diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/ChangeLog | 7 | ||||
| -rw-r--r-- | tests/Makefile.am | 6 | ||||
| -rw-r--r-- | tests/emptyfile.c | 277 |
3 files changed, 288 insertions, 2 deletions
diff --git a/tests/ChangeLog b/tests/ChangeLog index 1504d487..73aad091 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2016-06-24 Mark Wielaard <[email protected]> + + * Makefile.am (check_PROGRAMS): Add emptyfile. + (TESTS): Likewise. + (emptyfile_LDADD): New variable. + * emptyfile.c: New test. + 2016-06-28 Richard Henderson <[email protected]> * Makefile.am (TESTS): Add run-disasm-bpf.sh, conditionally. diff --git a/tests/Makefile.am b/tests/Makefile.am index 274356fb..9c22c4d7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -53,7 +53,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ buildid deleted deleted-lib.so aggregate_size vdsosyms \ getsrc_die strptr newdata elfstrtab dwfl-proc-attach \ elfshphehdr elfstrmerge dwelfgnucompressed elfgetchdr \ - elfgetzdata elfputzdata zstrptr + elfgetzdata elfputzdata zstrptr emptyfile asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9 @@ -126,7 +126,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-elfgetchdr.sh \ run-elfgetzdata.sh run-elfputzdata.sh run-zstrptr.sh \ run-compress-test.sh \ - run-readelf-zdebug.sh run-readelf-zdebug-rel.sh + run-readelf-zdebug.sh run-readelf-zdebug-rel.sh \ + emptyfile if !BIARCH export ELFUTILS_DISABLE_BIARCH = 1 @@ -481,6 +482,7 @@ elfgetchdr_LDADD = $(libelf) $(libdw) elfgetzdata_LDADD = $(libelf) elfputzdata_LDADD = $(libelf) zstrptr_LDADD = $(libelf) +emptyfile_LDADD = $(libelf) # We want to test the libelf header against the system elf.h header. # Don't include any -I CPPFLAGS. diff --git a/tests/emptyfile.c b/tests/emptyfile.c new file mode 100644 index 00000000..6d086246 --- /dev/null +++ b/tests/emptyfile.c @@ -0,0 +1,277 @@ +/* Test program for adding a section to an empty ELF file. + Copyright (C) 2016 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include ELFUTILS_HEADER(elf) +#include <gelf.h> + + +/* Index of last string added. Returned by add_string (). */ +static size_t stridx = 0; + +/* Adds a string and returns the offset in the section. */ +static size_t +add_string (Elf_Scn *scn, char *str) +{ + size_t lastidx = stridx; + size_t size = strlen (str) + 1; + + Elf_Data *data = elf_newdata (scn); + if (data == NULL) + { + printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1)); + exit (1); + } + + data->d_buf = str; + data->d_type = ELF_T_BYTE; + data->d_size = size; + data->d_align = 1; + data->d_version = EV_CURRENT; + + stridx += size; + printf ("add_string: '%s', stridx: %zd, lastidx: %zd\n", + str, stridx, lastidx); + return lastidx; +} + +static void +check_elf (const char *fname, int class, int use_mmap) +{ + printf ("\nfname: %s\n", fname); + stridx = 0; // Reset strtab strings index + + int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, 0666); + if (fd == -1) + { + printf ("cannot open `%s': %s\n", fname, strerror (errno)); + exit (1); + } + + Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); + exit (1); + } + + // Create an ELF header. + if (gelf_newehdr (elf, class) == 0) + { + printf ("cannot create ELF header: %s\n", elf_errmsg (-1)); + exit (1); + } + + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr == NULL) + { + printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); + exit (1); + } + + // Initialize header. + ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB; + ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU; + ehdr->e_type = ET_NONE; + ehdr->e_machine = EM_X86_64; + ehdr->e_version = EV_CURRENT; + + if (gelf_update_ehdr (elf, ehdr) == 0) + { + printf ("cannot update ELF header: %s\n", elf_errmsg (-1)); + exit (1); + } + + // Write everything to disk. + if (elf_update (elf, ELF_C_WRITE) < 0) + { + printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1)); + exit (1); + } + + if (elf_end (elf) != 0) + { + printf ("failure in elf_end: %s\n", elf_errmsg (-1)); + exit (1); + } + + close (fd); + + /* Reread the ELF from disk now. */ + fd = open (fname, O_RDWR, 0666); + if (fd == -1) + { + printf ("cannot (re)open `%s': %s\n", fname, strerror (errno)); + exit (1); + } + + elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1)); + exit (1); + } + + // There are no sections yet. + if (elf_nextscn (elf, NULL) != NULL) + { + printf ("Empty elf had a section???\n"); + exit (1); + } + + // Create strtab section. + Elf_Scn *scn = elf_newscn (elf); + if (scn == NULL) + { + printf ("cannot create strings section: %s\n", elf_errmsg (-1)); + exit (1); + } + + // Add an empty string to the table as NUL entry for section zero. + add_string (scn, ""); + + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr == NULL) + { + printf ("cannot get header for strings section: %s\n", elf_errmsg (-1)); + exit (1); + } + + shdr->sh_type = SHT_STRTAB; + shdr->sh_flags = 0; + shdr->sh_addr = 0; + shdr->sh_link = SHN_UNDEF; + shdr->sh_info = SHN_UNDEF; + shdr->sh_addralign = 1; + shdr->sh_entsize = 0; + shdr->sh_name = add_string (scn, ".strtab"); + + // We have to store the section strtab index in the ELF header. + // So sections have actual names. + int ndx = elf_ndxscn (scn); + ehdr->e_shstrndx = ndx; + + if (gelf_update_ehdr (elf, ehdr) == 0) + { + printf ("cannot update ELF header: %s\n", elf_errmsg (-1)); + exit (1); + } + + // Finished strtab section, update the header. + if (gelf_update_shdr (scn, shdr) == 0) + { + printf ("cannot update STRTAB section header: %s\n", elf_errmsg (-1)); + exit (1); + } + + // Write everything to disk. + if (elf_update (elf, ELF_C_WRITE) < 0) + { + printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1)); + exit (1); + } + + if (elf_end (elf) != 0) + { + printf ("failure in elf_end: %s\n", elf_errmsg (-1)); + exit (1); + } + + close (fd); + + // And read it in one last time. + fd = open (fname, O_RDONLY, 0666); + if (fd == -1) + { + printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno)); + exit (1); + } + + elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1)); + exit (1); + } + + // Is our new section there? + scn = elf_nextscn (elf, NULL); + if (scn == NULL) + { + printf ("cannot get new section: %s\n", elf_errmsg (-1)); + exit (1); + } + + shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr == NULL) + { + printf ("cannot get header for new section: %s\n", elf_errmsg (-1)); + exit (1); + } + + size_t shstrndx; + if (elf_getshdrstrndx (elf, &shstrndx) < 0) + { + printf ("elf_getshdrstrndx: %s\n", elf_errmsg (-1)); + exit (1); + } + + const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name); + if (sname == NULL || strcmp (sname, ".strtab") != 0) + { + printf ("Bad section name: %s\n", sname); + exit (1); + } + + if (elf_end (elf) != 0) + { + printf ("failure in elf_end: %s\n", elf_errmsg (-1)); + exit (1); + } + + close (fd); + + unlink (fname); +} + +int +main (int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + elf_version (EV_CURRENT); + + check_elf ("empty.elf.32", ELFCLASS32, 0); + check_elf ("empty.elf.32.mmap", ELFCLASS32, 1); + check_elf ("empty.elf.64", ELFCLASS64, 0); + check_elf ("empty.elf.64.mmap", ELFCLASS64, 1); + + return 0; +} |
