I've just pushed another test for function ebl_dynamic_tag_name. This function is used mainly in elflint, but also in readelf. Test is quite simple--just print all the possible strings the function can return. Now the ebl_dynamic_tag_name is fully covered.
I've also fixed last ChangeLog entry which contained wrong month number. All is available in branch mpolacek/ebl_dynamic_tag_name.
Please review. Thanks,
Marek
On Mon, 2011-03-14 at 21:12 +0100, Marek Polacek wrote:
I've just pushed another test for function ebl_dynamic_tag_name. This function is used mainly in elflint, but also in readelf. Test is quite simple--just print all the possible strings the function can return. Now the ebl_dynamic_tag_name is fully covered.
I've also fixed last ChangeLog entry which contained wrong month number. All is available in branch mpolacek/ebl_dynamic_tag_name.
This looks fine to me. But note that libebl isn't a stable interface. So I wouldn't spend too much time adding specific tests for it, unless higher level functions really depend on it. So in this case, why not (also) actually read the dynamic segment of the testfile you open and check the tag names found in there?
Since we are adding more and more tests, it would be good to have a bit more structured framework for it. Maybe using autoconf autotest? But I don't really have a suggestion/preference for what/which framework would be nicest (but please something simple without external dependencies except regular build infrastructure tools). Would you be willing to look into that?
Thanks,
Mark
This looks fine to me. But note that libebl isn't a stable interface. So I wouldn't spend too much time adding specific tests for it, unless higher level functions really depend on it. So in this case, why not (also) actually read the dynamic segment of the testfile you open and check the tag names found in there?
That's a good point. It's arguably anti-useful to have tests like this that make someone think the ebl interface must not be broken. The right way to test this function is just to run readelf. You can just choose a test file synthesized to contain all the known names and then run readelf -d on it to check the output, there is no need to write a unit test like this.
Since we are adding more and more tests, it would be good to have a bit more structured framework for it. Maybe using autoconf autotest? But I don't really have a suggestion/preference for what/which framework would be nicest (but please something simple without external dependencies except regular build infrastructure tools). Would you be willing to look into that?
I have long been intending to convert our tests to autotest. I just never got around to it. I think it would be a good thing to do. This is an excellent suggestion for a new volunteer like Marek to look into. I'm glad you reminded me about it.
It would start with some macros to replace what test-subr.sh provides, making it simple to write tests. The hairy thing there is to do them so that they serve correctly for both 'make check' and 'make installcheck'. The other nice thing I'd planned to do was integrate into the test macros some magic that emits the right magic data for lcov to delineate the coverage data between tests. I have some macro magic kicking around somewhere from another old project for that.
Thanks, Roland
On 03/15/2011 05:23 PM, Roland McGrath wrote:
This looks fine to me. But note that libebl isn't a stable interface. So I wouldn't spend too much time adding specific tests for it, unless higher level functions really depend on it. So in this case, why not (also) actually read the dynamic segment of the testfile you open and check the tag names found in there?
That's a good point. It's arguably anti-useful to have tests like this that make someone think the ebl interface must not be broken. The right way to test this function is just to run readelf. You can just choose a test file synthesized to contain all the known names and then run readelf -d on it to check the output, there is no need to write a unit test like this.
Aha, OK, thanks for explaining. I'll remove that branch and hopefully will come up with just .sh test.
Since we are adding more and more tests, it would be good to have a bit more structured framework for it. Maybe using autoconf autotest? But I don't really have a suggestion/preference for what/which framework would be nicest (but please something simple without external dependencies except regular build infrastructure tools). Would you be willing to look into that?
Sure!
I have long been intending to convert our tests to autotest. I just never got around to it. I think it would be a good thing to do. This is an excellent suggestion for a new volunteer like Marek to look into. I'm glad you reminded me about it.
It would start with some macros to replace what test-subr.sh provides, making it simple to write tests. The hairy thing there is to do them so that they serve correctly for both 'make check' and 'make installcheck'. The other nice thing I'd planned to do was integrate into the test macros some magic that emits the right magic data for lcov to delineate the coverage data between tests. I have some macro magic kicking around somewhere from another old project for that.
Fine. I have no experience with autotest and only a little with whole autoconf beast, but this looks like something cool to learn, so I'll dig into it right off when time allows. We'll see how it turns out.
Thank you.
Marek
Ok, another try. I've constructed an ELF file with all the DT_* flags set, it is named testfile58. The .sh file just runs readelf -d like you suggested, so there isn't any .c file. With this test the function ebl_dynamic_tag_name is 100% covered. The unlovely thing is that the test depends on printf ("%s", NULL) printing "(null)" because this way it is a way simpler.
I've also fixed date in the last ChangeLog entry. All is available in branch mpolacek/ebl_dynamic_tag_name. Tested on x86_64. The patch is also attached. Ok?
Marek
Signed-off-by: Marek Polacek mpolacek@redhat.com --- tests/ChangeLog | 8 +++- tests/Makefile.am | 5 +- tests/run-ebl-dynamic-tag-name.sh | 103 +++++++++++++++++++++++++++++++++++++ tests/testfile58.bz2 | Bin 0 -> 299 bytes 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100755 tests/run-ebl-dynamic-tag-name.sh create mode 100644 tests/testfile58.bz2
diff --git a/tests/ChangeLog b/tests/ChangeLog index 4ec3853..3c11635 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,4 +1,10 @@ -2011-04-02 Marek Polacek mpolacek@redhat.com +2011-03-25 Marek Polacek mpolacek@redhat.com + + * run-ebl-dynamic-tag-name.sh: New test. + * testfile58.bz2: New file, all DT_* flags set. + * Makefile.am (EXTRA_DIST): Add and update all. + +2011-03-02 Marek Polacek mpolacek@redhat.com
* dwarf-getstring.c: New test. * run-dwarf-getstring.sh: And its wrapper. diff --git a/tests/Makefile.am b/tests/Makefile.am index 70029f7..f1de41d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -84,7 +84,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-disasm-x86.sh run-disasm-x86-64.sh \ run-early-offscn.sh run-dwarf-getmacros.sh \ run-test-flag-nobits.sh run-prelink-addr-test.sh \ - run-dwarf-getstring.sh run-rerequest_tag.sh + run-dwarf-getstring.sh run-rerequest_tag.sh \ + run-ebl-dynamic-tag-name.sh # run-show-ciefde.sh
if !STANDALONE @@ -118,7 +119,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ run-addrname-test.sh run-dwfl-bug-offline-rel.sh \ run-dwfl-addr-sect.sh run-early-offscn.sh \ run-dwarf-getmacros.sh run-test-flag-nobits.sh \ - run-dwarf-getstring.sh \ + run-dwarf-getstring.sh run-ebl-dynamic-tag-name.sh \ testfile15.bz2 testfile15.debug.bz2 \ testfile16.bz2 testfile16.debug.bz2 \ testfile17.bz2 testfile17.debug.bz2 \ diff --git a/tests/run-ebl-dynamic-tag-name.sh b/tests/run-ebl-dynamic-tag-name.sh new file mode 100755 index 0000000..4e872fd --- /dev/null +++ b/tests/run-ebl-dynamic-tag-name.sh @@ -0,0 +1,103 @@ +#! /bin/sh +# Copyright (C) 2011 Red Hat, Inc. +# This file is part of Red Hat elfutils. +# +# Red Hat elfutils 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; version 2 of the License. +# +# Red Hat 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 Red Hat elfutils; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. +# +# Red Hat elfutils is an included package of the Open Invention Network. +# An included package of the Open Invention Network is a package for which +# Open Invention Network licensees cross-license their patents. No patent +# license is granted, either expressly or impliedly, by designation as an +# included package. Should you wish to participate in the Open Invention +# Network licensing program, please visit www.openinventionnetwork.com +# http://www.openinventionnetwork.com. + +. $srcdir/test-subr.sh + +testfiles testfile58 + +testrun_compare ../src/readelf -d testfile58 <<\EOF + +Dynamic segment contains 66 entries: + Addr: 0x000001a0 Offset: 0x000078 Link to section: [ 0] '' + Type Value + NULL + NEEDED Shared library: [(null)] + PLTRELSZ 3735928559 (bytes) + PLTGOT 0xdeadbeef + HASH 0xdeadbeef + STRTAB 0xdeadbeef + SYMTAB 0xdeadbeef + RELA 0xdeadbeef + RELASZ 3735928559 (bytes) + RELAENT 3735928559 (bytes) + STRSZ 3735928559 (bytes) + SYMENT 3735928559 (bytes) + INIT 0xdeadbeef + FINI 0xdeadbeef + SONAME Library soname: [(null)] + RPATH Library rpath: [(null)] + SYMBOLIC 0xdeadbeef + REL 0xdeadbeef + RELSZ 3735928559 (bytes) + RELENT 3735928559 (bytes) + PLTREL ??? + DEBUG + TEXTREL + JMPREL 0xdeadbeef + BIND_NOW + INIT_ARRAY 0xdeadbeef + FINI_ARRAY 0xdeadbeef + INIT_ARRAYSZ 3735928559 (bytes) + FINI_ARRAYSZ 3735928559 (bytes) + RUNPATH Library runpath: [(null)] + FLAGS ORIGIN SYMBOLIC TEXTREL BIND_NOW 0xdeadbee0 + PREINIT_ARRAY 0xdeadbeef + PREINIT_ARRAY 0xdeadbeef + PREINIT_ARRAYSZ 0xdeadbeef + VERSYM 0xdeadbeef + GNU_PRELINKED 0xdeadbeef + GNU_CONFLICTSZ 3735928559 (bytes) + GNU_LIBLISTSZ 3735928559 (bytes) + CHECKSUM 0xdeadbeef + PLTPADSZ 3735928559 (bytes) + MOVEENT 3735928559 (bytes) + MOVESZ 3735928559 (bytes) + FEATURE_1 PARINIT CONFEXP 0xdeadbeec + POSFLAG_1 LAZYLOAD GROUPPERM 0xdeadbeec + SYMINSZ 3735928559 (bytes) + SYMINENT 3735928559 (bytes) + GNU_HASH 0xdeadbeef + TLSDESC_PLT 0xdeadbeef + TLSDESC_GOT 0xdeadbeef + GNU_CONFLICT 0xdeadbeef + GNU_LIBLIST 0xdeadbeef + CONFIG 0xdeadbeef + DEPAUDIT 0xdeadbeef + AUDIT 0xdeadbeef + PLTPAD 0xdeadbeef + MOVETAB 0xdeadbeef + SYMINFO 0xdeadbeef + RELACOUNT 3735928559 + RELCOUNT 3735928559 + FLAGS_1 NOW GLOBAL GROUP NODELETE INITFIRST NOOPEN ORIGIN TRANS INTERPOSE NODEFLIB NODUMP CONFALT DISPRELDNE DISPRELPND 0xdeac0000 + VERDEF 0xdeadbeef + VERDEFNUM 3735928559 + VERNEED 0xdeadbeef + VERNEEDNUM 3735928559 + AUXILIARY 0xdeadbeef + FILTER 0xdeadbeef +EOF + +exit 0 diff --git a/tests/testfile58.bz2 b/tests/testfile58.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..a74bed6ecb84319c5b8a11f31a3ee6a68db5fc32 GIT binary patch literal 299 zcmV+`0o49NT4*^jL0KkKS+@7zuK)nCef$6a|Nmk^1OP(>JY$?-fIt8QKmq^(00961 z!~d`V_8Sp0kT&&D28Nmd00E(<KmY+1J?bg8l=U8<00000000096oQ_hXagbYHj~se z9-*KIwL{bZ01_lAm(cxd3=Fg!f+a6XQ*53@CI~A^lGdA>4kMz*kE^Y(e+CVWovL>C zFx888vwF0QEhkfepwnpqQ%-0pcpxY-6}VaDAd)D>0!XQBjWf>zIORmF8*CeG7~rg8 zku=&9Z7nO%Ba<b)-CezQ_sbvQB}Df4(Rho>DS&y10^tB$APq^TKo<!qFR4l>-FtWO x=hwfVe*z_~YXATMioq~uW@bich=_;)AOHdKOYxbT#$XwL7ji{7P>{Cw->(lCcs>9C
literal 0 HcmV?d00001
On 03/25/2011 04:27 PM, Marek Polacek wrote:
Ok, another try. I've constructed an ELF file with all the DT_* flags set, it is named testfile58.
FWIW, here is source code of program which constructs an ELF file like this:
/* Create an ELF file with all the DT_* flags set. Copyright (C) 2011 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Marek Polacek mpolacek@redhat.com, 2011.
Red Hat elfutils 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; version 2 of the License.
Red Hat 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 Red Hat elfutils; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
Red Hat elfutils is an included package of the Open Invention Network. An included package of the Open Invention Network is a package for which Open Invention Network licensees cross-license their patents. No patent license is granted, either expressly or impliedly, by designation as an included package. Should you wish to participate in the Open Invention Network licensing program, please visit www.openinventionnetwork.com http://www.openinventionnetwork.com. */
#include <elf.h> #include <gelf.h> #include <fcntl.h> #include <libelf.h> #include <libebl.h> #include <stdio.h> #include <stdio_ext.h> #include <stdint.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> #include <unistd.h>
int main (void) { static const char fname[] = "testfile58"; struct Ebl_Strtab *shst; struct Ebl_Strent *dynscn; struct Ebl_Strent *shstrtabse; const Elf32_Sword dtflags[] = { DT_NULL, DT_NEEDED, DT_PLTRELSZ, DT_PLTGOT, DT_HASH, DT_STRTAB, DT_SYMTAB, DT_RELA, DT_RELASZ, DT_RELAENT, DT_STRSZ, DT_SYMENT, DT_INIT, DT_FINI, DT_SONAME, DT_RPATH, DT_SYMBOLIC, DT_REL, DT_RELSZ, DT_RELENT, DT_PLTREL, DT_DEBUG, DT_TEXTREL, DT_JMPREL, DT_BIND_NOW, DT_INIT_ARRAY, DT_FINI_ARRAY, DT_INIT_ARRAYSZ, DT_FINI_ARRAYSZ, DT_RUNPATH, DT_FLAGS, DT_ENCODING, DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ, DT_VERSYM, DT_GNU_PRELINKED, DT_GNU_CONFLICTSZ, DT_GNU_LIBLISTSZ, DT_CHECKSUM, DT_PLTPADSZ, DT_MOVEENT, DT_MOVESZ, DT_FEATURE_1, DT_POSFLAG_1, DT_SYMINSZ, DT_SYMINENT, DT_GNU_HASH, DT_TLSDESC_PLT, DT_TLSDESC_GOT, DT_GNU_CONFLICT, DT_GNU_LIBLIST, DT_CONFIG, DT_DEPAUDIT, DT_AUDIT, DT_PLTPAD, DT_MOVETAB, DT_SYMINFO, DT_RELACOUNT, DT_RELCOUNT, DT_FLAGS_1, DT_VERDEF, DT_VERDEFNUM, DT_VERNEED, DT_VERNEEDNUM, DT_AUXILIARY, DT_FILTER }; const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]);
/* We use no threads here which can interfere with handling a stream. */ (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
/* Open the file. */ int fd = open64 (fname, O_RDWR | O_CREAT | O_TRUNC, 0666); if (fd == -1) { printf ("cannot open `%s': %m\n", fname); return 1; }
/* Tell the library which version are we expecting. */ elf_version (EV_CURRENT);
/* Create an ELF descriptor. */ Elf *elf = elf_begin (fd, ELF_C_WRITE, NULL); if (elf == NULL) { printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); return 1; }
/* Create an ELF header. */ Elf32_Ehdr *ehdr = elf32_newehdr (elf); if (ehdr == NULL) { printf ("cannot create ELF header: %s\n", elf_errmsg (-1)); return 1; }
ehdr->e_ident[0] = 42; ehdr->e_ident[5] = 1; ehdr->e_ident[6] = 2; ehdr->e_type = ET_EXEC; ehdr->e_machine = EM_386; ehdr->e_version = 1; ehdr->e_ehsize = 1; ehdr->e_shnum = 3;
elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
/* Create the program headers. */ Elf32_Phdr *phdr = elf32_newphdr (elf, 2); if (phdr == NULL) { printf ("cannot create program headers: %s\n", elf_errmsg (-1)); return 1; }
phdr[0].p_type = PT_PHDR; phdr[1].p_type = PT_DYNAMIC;
elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY); shst = ebl_strtabinit (true);
/* Create the .dynamic section. */ Elf_Scn *scn = elf_newscn (elf); if (scn == NULL) { printf ("cannot create DYNAMIC section: %s\n", elf_errmsg (-1)); return 1; }
Elf32_Shdr *shdr = elf32_getshdr (scn); if (shdr == NULL) { printf ("cannot get header for DYNAMIC section: %s\n", elf_errmsg (-1)); return 1; }
dynscn = ebl_strtabadd (shst, ".dynamic", 0);
/* We'll need to know the section offset. But this will be set up by elf_update later, so for now just store the address. */ const Elf32_Off *const dynscn_offset = &shdr->sh_offset; shdr->sh_type = SHT_DYNAMIC; shdr->sh_flags = SHF_ALLOC | SHF_WRITE; shdr->sh_link = SHN_UNDEF; shdr->sh_info = SHN_UNDEF; /* This section will start here. */ shdr->sh_addr = 0x1a0;
/* Create new section data. */ Elf_Data *data = elf_newdata (scn); if (data == NULL) { printf ("cannot create data for DYNAMIC section: %s\n", elf_errmsg (-1)); return 1; }
/* Allocate memory for all the .dynamic entries. */ Elf32_Dyn *dyn = malloc (ndtflags * sizeof (Elf32_Dyn)); if (dyn == NULL) { printf ("malloc failed: %m\n"); return 1; }
/* Now write all the DT_* flags. */ for (int i = 0; i < ndtflags; ++i) { dyn[i].d_tag = dtflags[i]; dyn[i].d_un.d_val = 0xdeadbeef; }
/* Set the pointer to allocated memory. */ data->d_buf = dyn; data->d_type = ELF_T_DYN; data->d_version = EV_CURRENT; data->d_size = ndtflags * sizeof (Elf32_Dyn); data->d_align = 0x8;
/* Create .shstrtab section. */ scn = elf_newscn (elf); if (scn == NULL) { printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1)); return 1; }
shdr = elf32_getshdr (scn); if (shdr == NULL) { printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1)); return 1; }
shstrtabse = ebl_strtabadd (shst, ".shstrtab", 0);
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_entsize = 1;
/* We have to store the section index in the ELF header. */ ehdr->e_shstrndx = elf_ndxscn (scn);
data = elf_newdata (scn); if (data == NULL) { printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1)); return 1; }
/* No more sections, finalize the section header string table. */ ebl_strtabfinalize (shst, data);
elf32_getshdr (elf_getscn (elf, 1))->sh_name = ebl_strtaboffset (dynscn); shdr->sh_name = ebl_strtaboffset (shstrtabse);
/* Let the library compute the internal structure information. */ if (elf_update (elf, ELF_C_NULL) < 0) { printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1)); return 1; }
ehdr = elf32_getehdr (elf);
phdr[0].p_offset = ehdr->e_phoff; phdr[0].p_vaddr = ehdr->e_phoff; phdr[0].p_paddr = ehdr->e_phoff; phdr[0].p_flags = PF_R | PF_X; phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT); phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT); phdr[0].p_align = sizeof (Elf32_Word);
phdr[1].p_flags = PF_W | PF_R; phdr[1].p_offset = *dynscn_offset; /* Set up the start of this segment to equal start address of the .dynamic section. */ phdr[1].p_vaddr = 0x1a0; phdr[1].p_paddr = 0x1a0; phdr[1].p_align = 2 * sizeof (Elf32_Word); phdr[1].p_filesz = ndtflags * sizeof (Elf32_Dyn); phdr[1].p_memsz = ndtflags * sizeof (Elf32_Dyn);
/* Write out the file. */ if (elf_update (elf, ELF_C_WRITE) < 0) { printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1)); return 1; }
/* We don't need the string table anymore. */ ebl_strtabfree (shst);
/* And the data allocated in the .shstrtab section. */ free (data->d_buf);
/* All done. */ if (elf_end (elf) != 0) { printf ("failure in elf_end: %s\n", elf_errmsg (-1)); return 1; }
return 0; }
On Fri, 2011-03-25 at 16:30 +0100, Marek Polacek wrote:
On 03/25/2011 04:27 PM, Marek Polacek wrote:
Ok, another try. I've constructed an ELF file with all the DT_* flags set, it is named testfile58.
FWIW, here is source code of program which constructs an ELF file like this:
I think you should include this and produce the ELF file during the test run instead of only including the binary. I realize that is stretching the testsuite support a little. But in this case the elf file is completely produced "synthetically" instead of depending on compiler versions/arch.
Cheers,
Mark
On 03/28/2011 12:57 PM, Mark Wielaard wrote:
I think you should include this and produce the ELF file during the test run instead of only including the binary. I realize that is stretching the testsuite support a little. But in this case the elf file is completely produced "synthetically" instead of depending on compiler versions/arch.
All right. Should be done now. Pushed to my branch.
Signed-off-by: Marek Polacek mpolacek@redhat.com --- tests/ChangeLog | 8 ++- tests/Makefile.am | 8 +- tests/alldts.c | 275 +++++++++++++++++++++++++++++++++++++++++++++++++++ tests/run-alldts.sh | 106 ++++++++++++++++++++ 4 files changed, 393 insertions(+), 4 deletions(-) create mode 100644 tests/alldts.c create mode 100755 tests/run-alldts.sh
diff --git a/tests/ChangeLog b/tests/ChangeLog index 4ec3853..bfdbf67 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,4 +1,10 @@ -2011-04-02 Marek Polacek mpolacek@redhat.com +2011-03-28 Marek Polacek mpolacek@redhat.com + + * alldts.c: New file. + * run-alldts.sh: Use it. + * Makefile.am (EXTRA_DIST): Add and update all. + +2011-03-02 Marek Polacek mpolacek@redhat.com
* dwarf-getstring.c: New test. * run-dwarf-getstring.sh: And its wrapper. diff --git a/tests/Makefile.am b/tests/Makefile.am index 70029f7..35f55e3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -57,7 +57,8 @@ noinst_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ dwfl-bug-addr-overflow arls dwfl-bug-fd-leak \ dwfl-addr-sect dwfl-bug-report early-offscn \ dwfl-bug-getmodules dwarf-getmacros addrcfi \ - test-flag-nobits dwarf-getstring rerequest_tag + test-flag-nobits dwarf-getstring rerequest_tag \ + alldts asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -70,7 +71,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-strip-test3.sh run-strip-test4.sh run-strip-test5.sh \ run-strip-test6.sh run-strip-test7.sh run-strip-test8.sh \ run-unstrip-test.sh run-unstrip-test2.sh \ - run-ecp-test.sh run-ecp-test2.sh \ + run-ecp-test.sh run-ecp-test2.sh run-alldts.sh \ run-elflint-test.sh run-elflint-self.sh run-ranlib-test.sh \ run-ranlib-test2.sh run-ranlib-test3.sh run-ranlib-test4.sh \ run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \ @@ -118,7 +119,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ run-addrname-test.sh run-dwfl-bug-offline-rel.sh \ run-dwfl-addr-sect.sh run-early-offscn.sh \ run-dwarf-getmacros.sh run-test-flag-nobits.sh \ - run-dwarf-getstring.sh \ + run-dwarf-getstring.sh run-alldts.sh \ testfile15.bz2 testfile15.debug.bz2 \ testfile16.bz2 testfile16.debug.bz2 \ testfile17.bz2 testfile17.debug.bz2 \ @@ -253,6 +254,7 @@ dwarf_getstring_LDADD = $(libdw) $(libmudflap) addrcfi_LDADD = $(libdw) $(libebl) $(libelf) $(libmudflap) -ldl test_flag_nobits_LDADD = $(libelf) $(libmudflap) rerequest_tag_LDADD = $(libdw) $(libmudflap) +alldts_LDADD = $(libebl) $(libelf) $(libmudflap)
if GCOV check: check-am coverage diff --git a/tests/alldts.c b/tests/alldts.c new file mode 100644 index 0000000..ed7624a --- /dev/null +++ b/tests/alldts.c @@ -0,0 +1,275 @@ +/* Create an ELF file with all the DT_* flags set. + Copyright (C) 2011 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Marek Polacek mpolacek@redhat.com, 2011. + + Red Hat elfutils 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; version 2 of the License. + + Red Hat 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 Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + http://www.openinventionnetwork.com. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include ELFUTILS_HEADER(ebl) +#include <elf.h> +#include <gelf.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +int +main (void) +{ + static const char fname[] = "testfile-alldts"; + struct Ebl_Strtab *shst; + struct Ebl_Strent *dynscn; + struct Ebl_Strent *shstrtabse; + const Elf32_Sword dtflags[] = + { + DT_NULL, DT_NEEDED, DT_PLTRELSZ, DT_PLTGOT, + DT_HASH, DT_STRTAB, DT_SYMTAB, DT_RELA, + DT_RELASZ, DT_RELAENT, DT_STRSZ, DT_SYMENT, + DT_INIT, DT_FINI, DT_SONAME, DT_RPATH, + DT_SYMBOLIC, DT_REL, DT_RELSZ, DT_RELENT, + DT_PLTREL, DT_DEBUG, DT_TEXTREL, DT_JMPREL, + DT_BIND_NOW, DT_INIT_ARRAY, DT_FINI_ARRAY, + DT_INIT_ARRAYSZ, DT_FINI_ARRAYSZ, DT_RUNPATH, + DT_FLAGS, DT_ENCODING, DT_PREINIT_ARRAY, + DT_PREINIT_ARRAYSZ, DT_VERSYM, DT_GNU_PRELINKED, + DT_GNU_CONFLICTSZ, DT_GNU_LIBLISTSZ, DT_CHECKSUM, + DT_PLTPADSZ, DT_MOVEENT, DT_MOVESZ, DT_FEATURE_1, + DT_POSFLAG_1, DT_SYMINSZ, DT_SYMINENT, DT_GNU_HASH, + DT_TLSDESC_PLT, DT_TLSDESC_GOT, DT_GNU_CONFLICT, + DT_GNU_LIBLIST, DT_CONFIG, DT_DEPAUDIT, DT_AUDIT, + DT_PLTPAD, DT_MOVETAB, DT_SYMINFO, DT_RELACOUNT, + DT_RELCOUNT, DT_FLAGS_1, DT_VERDEF, DT_VERDEFNUM, + DT_VERNEED, DT_VERNEEDNUM, DT_AUXILIARY, DT_FILTER + }; + const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]); + + /* We use no threads here which can interfere with handling a stream. */ + (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); + + /* Open the file. */ + int fd = open64 (fname, O_RDWR | O_CREAT | O_TRUNC, 0666); + if (fd == -1) + { + printf ("cannot open `%s': %m\n", fname); + return 1; + } + + /* Tell the library which version are we expecting. */ + elf_version (EV_CURRENT); + + /* Create an ELF descriptor. */ + Elf *elf = elf_begin (fd, ELF_C_WRITE, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); + return 1; + } + + /* Create an ELF header. */ + Elf32_Ehdr *ehdr = elf32_newehdr (elf); + if (ehdr == NULL) + { + printf ("cannot create ELF header: %s\n", elf_errmsg (-1)); + return 1; + } + + ehdr->e_ident[0] = 42; + ehdr->e_ident[5] = 1; + ehdr->e_ident[6] = 2; + ehdr->e_type = ET_EXEC; + ehdr->e_machine = EM_386; + ehdr->e_version = 1; + ehdr->e_ehsize = 1; + ehdr->e_shnum = 3; + + elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY); + + /* Create the program headers. */ + Elf32_Phdr *phdr = elf32_newphdr (elf, 2); + if (phdr == NULL) + { + printf ("cannot create program headers: %s\n", elf_errmsg (-1)); + return 1; + } + + phdr[0].p_type = PT_PHDR; + phdr[1].p_type = PT_DYNAMIC; + + elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY); + shst = ebl_strtabinit (true); + + /* Create the .dynamic section. */ + Elf_Scn *scn = elf_newscn (elf); + if (scn == NULL) + { + printf ("cannot create DYNAMIC section: %s\n", elf_errmsg (-1)); + return 1; + } + + Elf32_Shdr *shdr = elf32_getshdr (scn); + if (shdr == NULL) + { + printf ("cannot get header for DYNAMIC section: %s\n", elf_errmsg (-1)); + return 1; + } + + dynscn = ebl_strtabadd (shst, ".dynamic", 0); + + /* We'll need to know the section offset. But this will be set up + by elf_update later, so for now just store the address. */ + const Elf32_Off *const dynscn_offset = &shdr->sh_offset; + shdr->sh_type = SHT_DYNAMIC; + shdr->sh_flags = SHF_ALLOC | SHF_WRITE; + shdr->sh_link = SHN_UNDEF; + shdr->sh_info = SHN_UNDEF; + /* This section will start here. */ + shdr->sh_addr = 0x1a0; + + /* Create new section data. */ + Elf_Data *data = elf_newdata (scn); + if (data == NULL) + { + printf ("cannot create data for DYNAMIC section: %s\n", elf_errmsg (-1)); + return 1; + } + + /* Allocate memory for all the .dynamic entries. */ + Elf32_Dyn *dyn = malloc (ndtflags * sizeof (Elf32_Dyn)); + if (dyn == NULL) + { + printf ("malloc failed: %m\n"); + return 1; + } + + /* Now write all the DT_* flags. */ + for (int i = 0; i < ndtflags; ++i) + { + dyn[i].d_tag = dtflags[i]; + dyn[i].d_un.d_val = 0xdeadbeef; + } + + /* Set the pointer to allocated memory. */ + data->d_buf = dyn; + data->d_type = ELF_T_DYN; + data->d_version = EV_CURRENT; + data->d_size = ndtflags * sizeof (Elf32_Dyn); + data->d_align = 0x8; + + /* Create .shstrtab section. */ + scn = elf_newscn (elf); + if (scn == NULL) + { + printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1)); + return 1; + } + + shdr = elf32_getshdr (scn); + if (shdr == NULL) + { + printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1)); + return 1; + } + + shstrtabse = ebl_strtabadd (shst, ".shstrtab", 0); + + 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_entsize = 1; + + /* We have to store the section index in the ELF header. */ + ehdr->e_shstrndx = elf_ndxscn (scn); + + data = elf_newdata (scn); + if (data == NULL) + { + printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1)); + return 1; + } + + /* No more sections, finalize the section header string table. */ + ebl_strtabfinalize (shst, data); + + elf32_getshdr (elf_getscn (elf, 1))->sh_name = ebl_strtaboffset (dynscn); + shdr->sh_name = ebl_strtaboffset (shstrtabse); + + /* Let the library compute the internal structure information. */ + if (elf_update (elf, ELF_C_NULL) < 0) + { + printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1)); + return 1; + } + + ehdr = elf32_getehdr (elf); + + phdr[0].p_offset = ehdr->e_phoff; + phdr[0].p_vaddr = ehdr->e_phoff; + phdr[0].p_paddr = ehdr->e_phoff; + phdr[0].p_flags = PF_R | PF_X; + phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT); + phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT); + phdr[0].p_align = sizeof (Elf32_Word); + + phdr[1].p_flags = PF_W | PF_R; + phdr[1].p_offset = *dynscn_offset; + /* Set up the start of this segment to equal start address of the + .dynamic section. */ + phdr[1].p_vaddr = 0x1a0; + phdr[1].p_paddr = 0x1a0; + phdr[1].p_align = 2 * sizeof (Elf32_Word); + phdr[1].p_filesz = ndtflags * sizeof (Elf32_Dyn); + phdr[1].p_memsz = ndtflags * sizeof (Elf32_Dyn); + + /* Write out the file. */ + if (elf_update (elf, ELF_C_WRITE) < 0) + { + printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1)); + return 1; + } + + /* We don't need the string table anymore. */ + ebl_strtabfree (shst); + + /* And the data allocated in the .shstrtab section. */ + free (data->d_buf); + + /* All done. */ + if (elf_end (elf) != 0) + { + printf ("failure in elf_end: %s\n", elf_errmsg (-1)); + return 1; + } + + return 0; +} diff --git a/tests/run-alldts.sh b/tests/run-alldts.sh new file mode 100755 index 0000000..327f2f1 --- /dev/null +++ b/tests/run-alldts.sh @@ -0,0 +1,106 @@ +#! /bin/sh +# Copyright (C) 2011 Red Hat, Inc. +# This file is part of Red Hat elfutils. +# +# Red Hat elfutils 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; version 2 of the License. +# +# Red Hat 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 Red Hat elfutils; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. +# +# Red Hat elfutils is an included package of the Open Invention Network. +# An included package of the Open Invention Network is a package for which +# Open Invention Network licensees cross-license their patents. No patent +# license is granted, either expressly or impliedly, by designation as an +# included package. Should you wish to participate in the Open Invention +# Network licensing program, please visit www.openinventionnetwork.com +# http://www.openinventionnetwork.com. + +. $srcdir/test-subr.sh + +# This will produce "testfile-alldts" file +./alldts + +testrun_compare ../src/readelf -d testfile-alldts <<\EOF + +Dynamic segment contains 66 entries: + Addr: 0x000001a0 Offset: 0x000078 Link to section: [ 0] '' + Type Value + NULL + NEEDED Shared library: [(null)] + PLTRELSZ 3735928559 (bytes) + PLTGOT 0xdeadbeef + HASH 0xdeadbeef + STRTAB 0xdeadbeef + SYMTAB 0xdeadbeef + RELA 0xdeadbeef + RELASZ 3735928559 (bytes) + RELAENT 3735928559 (bytes) + STRSZ 3735928559 (bytes) + SYMENT 3735928559 (bytes) + INIT 0xdeadbeef + FINI 0xdeadbeef + SONAME Library soname: [(null)] + RPATH Library rpath: [(null)] + SYMBOLIC 0xdeadbeef + REL 0xdeadbeef + RELSZ 3735928559 (bytes) + RELENT 3735928559 (bytes) + PLTREL ??? + DEBUG + TEXTREL + JMPREL 0xdeadbeef + BIND_NOW + INIT_ARRAY 0xdeadbeef + FINI_ARRAY 0xdeadbeef + INIT_ARRAYSZ 3735928559 (bytes) + FINI_ARRAYSZ 3735928559 (bytes) + RUNPATH Library runpath: [(null)] + FLAGS ORIGIN SYMBOLIC TEXTREL BIND_NOW 0xdeadbee0 + PREINIT_ARRAY 0xdeadbeef + PREINIT_ARRAY 0xdeadbeef + PREINIT_ARRAYSZ 0xdeadbeef + VERSYM 0xdeadbeef + GNU_PRELINKED 0xdeadbeef + GNU_CONFLICTSZ 3735928559 (bytes) + GNU_LIBLISTSZ 3735928559 (bytes) + CHECKSUM 0xdeadbeef + PLTPADSZ 3735928559 (bytes) + MOVEENT 3735928559 (bytes) + MOVESZ 3735928559 (bytes) + FEATURE_1 PARINIT CONFEXP 0xdeadbeec + POSFLAG_1 LAZYLOAD GROUPPERM 0xdeadbeec + SYMINSZ 3735928559 (bytes) + SYMINENT 3735928559 (bytes) + GNU_HASH 0xdeadbeef + TLSDESC_PLT 0xdeadbeef + TLSDESC_GOT 0xdeadbeef + GNU_CONFLICT 0xdeadbeef + GNU_LIBLIST 0xdeadbeef + CONFIG 0xdeadbeef + DEPAUDIT 0xdeadbeef + AUDIT 0xdeadbeef + PLTPAD 0xdeadbeef + MOVETAB 0xdeadbeef + SYMINFO 0xdeadbeef + RELACOUNT 3735928559 + RELCOUNT 3735928559 + FLAGS_1 NOW GLOBAL GROUP NODELETE INITFIRST NOOPEN ORIGIN TRANS INTERPOSE NODEFLIB NODUMP CONFALT DISPRELDNE DISPRELPND 0xdeac0000 + VERDEF 0xdeadbeef + VERDEFNUM 3735928559 + VERNEED 0xdeadbeef + VERNEEDNUM 3735928559 + AUXILIARY 0xdeadbeef + FILTER 0xdeadbeef +EOF + +rm -f testfile-alldts + +exit 0
On Mon, 2011-03-28 at 16:15 +0200, Marek Polacek wrote:
On 03/28/2011 12:57 PM, Mark Wielaard wrote:
I think you should include this and produce the ELF file during the test run instead of only including the binary. I realize that is stretching the testsuite support a little. But in this case the elf file is completely produced "synthetically" instead of depending on compiler versions/arch.
All right. Should be done now. Pushed to my branch.
+2011-03-28 Marek Polacek mpolacek@redhat.com
- alldts.c: New file.
- run-alldts.sh: Use it.
- Makefile.am (EXTRA_DIST): Add and update all.
Thanks, that way the test looks much nicer to me.
You did forget to mention the other changes in Makefile.am in your ChangeLog entry though.
Cheers,
Mark
On Wed, 2011-03-30 at 09:22 +0200, Marek Polacek wrote:
On 03/29/2011 03:15 PM, Mark Wielaard wrote:
You did forget to mention the other changes in Makefile.am in your ChangeLog entry though.
You're right. I've amended that commit. Should I push it to trunk now?
Yes. Sorry for the nitpicking.
Thanks,
Mark
elfutils-devel@lists.fedorahosted.org