>From b0da0a6f6c9a57a37a144a806ecd219a76c66b54 Mon Sep 17 00:00:00 2001 From: Di Chen <dic...@redhat.com> Date: Tue, 1 Mar 2022 20:44:38 +0800 Subject: [PATCH] readelf: Don't consider padding DT_NULL as dynamic section entry
when using `$ eu-readelf -d {FILE}` to get the number of dynamic section entris, it wrongly counts the padding DT_NULLs as dynamic section entries. However, DT_NULL Marks end of dynamic section. They should not be considered as dynamic section entries. https://sourceware.org/bugzilla/show_bug.cgi?id=28928 Signed-off-by: Di Chen <dic...@redhat.com> --- src/readelf.c | 49 ++++++++++++++++++++++++++++++++++++------ tests/alldts.c | 5 +++-- tests/run-alldts.sh | 2 +- tests/run-readelf-d.sh | 7 +----- 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/readelf.c b/src/readelf.c index 93fb5989..0d70bb47 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -296,6 +296,7 @@ static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr); static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr); static void print_scngrp (Ebl *ebl); static void print_dynamic (Ebl *ebl); +static void handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr); static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr); @@ -1781,16 +1782,54 @@ print_dt_posflag_1 (int class, GElf_Xword d_val) } +static GElf_Phdr * +get_dyn_phdr (Elf *elf) +{ + GElf_Phdr *phdr = NULL; + for (size_t i = 0; i < phnum; ++i) { + GElf_Phdr phdr_mem; + phdr = gelf_getphdr(elf, i, &phdr_mem); + if (phdr->p_type == PT_DYNAMIC) { + break; + } + } + return phdr; +} + + +static size_t +get_dyn_scnents (Elf *elf, GElf_Phdr * dyn_phdr) +{ + Elf_Data *data = elf_getdata_rawchunk( + elf, dyn_phdr->p_offset, dyn_phdr->p_filesz, ELF_T_DYN); + GElf_Dyn *dyn; + size_t dyn_idx = 0; + do + { + GElf_Dyn dyn_mem; + dyn = gelf_getdyn(data, dyn_idx, &dyn_mem); + ++dyn_idx; + } while (dyn->d_tag != DT_NULL); + + return dyn_idx; +} + + static void handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) { int class = gelf_getclass (ebl->elf); + GElf_Phdr *dyn_phdr; GElf_Shdr glink_mem; GElf_Shdr *glink; Elf_Data *data; size_t cnt; size_t shstrndx; - size_t sh_entsize; + size_t dyn_scnents; + + /* Get the dynamic section entry number */ + dyn_phdr = get_dyn_phdr (ebl->elf); + dyn_scnents = get_dyn_scnents (ebl->elf, dyn_phdr); /* Get the data of the section. */ data = elf_getdata (scn, NULL); @@ -1802,8 +1841,6 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) error (EXIT_FAILURE, 0, _("cannot get section header string table index")); - sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT); - glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem); if (glink == NULL) error (EXIT_FAILURE, 0, _("invalid sh_link value in section %zu"), @@ -1813,15 +1850,15 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", "\ \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", - shdr->sh_size / sh_entsize), - (unsigned long int) (shdr->sh_size / sh_entsize), + dyn_scnents), + (unsigned long int) dyn_scnents, class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, shdr->sh_offset, (int) shdr->sh_link, elf_strptr (ebl->elf, shstrndx, glink->sh_name)); fputs_unlocked (_(" Type Value\n"), stdout); - for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) + for (cnt = 0; cnt < dyn_scnents; ++cnt) { GElf_Dyn dynmem; GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem); diff --git a/tests/alldts.c b/tests/alldts.c index 3e9f9fe6..d0fe4f24 100644 --- a/tests/alldts.c +++ b/tests/alldts.c @@ -44,7 +44,7 @@ main (void) Dwelf_Strent *shstrtabse; const Elf32_Sword dtflags[] = { - DT_NULL, DT_NEEDED, DT_PLTRELSZ, DT_PLTGOT, + 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, @@ -61,7 +61,8 @@ main (void) 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 + DT_VERNEED, DT_VERNEEDNUM, DT_AUXILIARY, DT_FILTER, + DT_NULL }; const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]); diff --git a/tests/run-alldts.sh b/tests/run-alldts.sh index 6a9a9ece..ce3630b0 100755 --- a/tests/run-alldts.sh +++ b/tests/run-alldts.sh @@ -27,7 +27,6 @@ testrun_compare ${abs_top_builddir}/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 @@ -93,6 +92,7 @@ Dynamic segment contains 66 entries: VERNEEDNUM 3735928559 AUXILIARY 0xdeadbeef FILTER 0xdeadbeef + NULL EOF exit 0 diff --git a/tests/run-readelf-d.sh b/tests/run-readelf-d.sh index d0b6ed24..69b01c49 100755 --- a/tests/run-readelf-d.sh +++ b/tests/run-readelf-d.sh @@ -34,7 +34,7 @@ testfiles testlib_dynseg.so testrun_compare ${abs_top_builddir}/src/readelf -d testlib_dynseg.so <<\EOF -Dynamic segment contains 28 entries: +Dynamic segment contains 23 entries: Addr: 0x00000000000017e0 Offset: 0x0007e0 Link to section: [ 3] '.dynstr' Type Value PLTGOT 0x00000000000019c8 @@ -60,11 +60,6 @@ Dynamic segment contains 28 entries: VERNEED 0x0000000000000498 VERNEEDNUM 2 NULL - NULL - NULL - NULL - NULL - NULL EOF exit 0 -- 2.35.1 On Tue, Mar 22, 2022 at 9:47 PM Di Chen <dic...@redhat.com> wrote: > Hey team, > I made some changes for this patch: > (1) update the commit message to make it more clear > (2) tests/alldts.c needs the padding spaces for output comparison > > On Tue, Mar 1, 2022 at 8:54 PM Di Chen <dic...@redhat.com> wrote: > >> commit 978663c5323cf402cd35b8614e41f24b587cbdd8 (HEAD -> dichen/DT_NULL, >> origin/dichen/DT_NULL) >> Author: Di Chen <dic...@redhat.com> >> Date: Tue Mar 1 20:44:38 2022 +0800 >> >> readelf: PR28928 - wrong dynamic section entry number >> >> when using `$ eu-readelf -d {file}` to get the number of dynamic >> section entris, It wrongly counts the padding DT_NULLs as dynamic >> section entries. However, DT_NULL Marks end of dynamic section. >> They should not be counted as dynamic section entries. >> >> https://sourceware.org/bugzilla/show_bug.cgi?id=28928 >> >> Signed-off-by: Di Chen <dic...@redhat.com> >> >> diff --git a/src/readelf.c b/src/readelf.c >> index 93fb5989..1bec3aa6 100644 >> --- a/src/readelf.c >> +++ b/src/readelf.c >> @@ -296,6 +296,7 @@ static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr); >> static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr); >> static void print_scngrp (Ebl *ebl); >> static void print_dynamic (Ebl *ebl); >> +static void handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); >> static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr); >> static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, >> GElf_Shdr *shdr); >> @@ -1781,16 +1782,54 @@ print_dt_posflag_1 (int class, GElf_Xword d_val) >> [dichen@arpeggio elfutils]$ git format-patch -1 HEAD >> 0001-readelf-PR28928-wrong-dynamic-section-entry-number.patch >> [dichen@arpeggio elfutils]$ vim >> 0001-readelf-PR28928-wrong-dynamic-section-entry-number.patch >> [dichen@arpeggio elfutils]$ cat >> 0001-readelf-PR28928-wrong-dynamic-section-entry-number.patch >> From 978663c5323cf402cd35b8614e41f24b587cbdd8 Mon Sep 17 00:00:00 2001 >> From: Di Chen <dic...@redhat.com> >> Date: Tue, 1 Mar 2022 20:44:38 +0800 >> Subject: [PATCH] readelf: PR28928 - wrong dynamic section entry number >> >> when using `$ eu-readelf -d {file}` to get the number of dynamic >> section entris, It wrongly counts the padding DT_NULLs as dynamic >> section entries. However, DT_NULL Marks end of dynamic section. >> They should not be counted as dynamic section entries. >> >> https://sourceware.org/bugzilla/show_bug.cgi?id=28928 >> >> Signed-off-by: Di Chen <dic...@redhat.com> >> --- >> src/readelf.c | 49 ++++++++++++++++++++++++++++++++++++------ >> tests/alldts.c | 5 +++-- >> tests/run-alldts.sh | 2 +- >> tests/run-readelf-d.sh | 7 +----- >> 4 files changed, 48 insertions(+), 15 deletions(-) >> >> diff --git a/src/readelf.c b/src/readelf.c >> index 93fb5989..1bec3aa6 100644 >> --- a/src/readelf.c >> +++ b/src/readelf.c >> @@ -296,6 +296,7 @@ static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr); >> static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr); >> static void print_scngrp (Ebl *ebl); >> static void print_dynamic (Ebl *ebl); >> +static void handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); >> static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr); >> static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, >> GElf_Shdr *shdr); >> @@ -1781,16 +1782,54 @@ print_dt_posflag_1 (int class, GElf_Xword d_val) >> } >> >> >> +static GElf_Phdr * >> +get_dyn_phdr (Elf *elf) >> +{ >> + GElf_Phdr *phdr = NULL; >> + for (size_t i = 0; i < phnum; ++i) { >> + GElf_Phdr phdr_mem; >> + phdr = gelf_getphdr(elf, i, &phdr_mem); >> + if (phdr->p_type == PT_DYNAMIC) { >> + break; >> + } >> + } >> + return phdr; >> +} >> + >> + >> +static size_t >> +get_dyn_scnents (Elf *elf, GElf_Phdr * dyn_phdr) >> +{ >> + Elf_Data *data = elf_getdata_rawchunk( >> + elf, dyn_phdr->p_offset, dyn_phdr->p_filesz, ELF_T_DYN); >> + GElf_Dyn *dyn; >> + size_t dyn_idx = 0; >> + do >> + { >> + GElf_Dyn dyn_mem; >> + dyn = gelf_getdyn(data, dyn_idx, &dyn_mem); >> + ++dyn_idx; >> + } while (dyn->d_tag != DT_NULL); >> + >> + return dyn_idx; >> +} >> + >> + >> static void >> handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) >> { >> int class = gelf_getclass (ebl->elf); >> + GElf_Phdr *dyn_phdr; >> GElf_Shdr glink_mem; >> GElf_Shdr *glink; >> Elf_Data *data; >> size_t cnt; >> size_t shstrndx; >> - size_t sh_entsize; >> + size_t dyn_scnents; >> + >> + /* Calculate the dynamic section entry number */ >> + dyn_phdr = get_dyn_phdr (ebl->elf); >> + dyn_scnents = get_dyn_scnents (ebl->elf, dyn_phdr); >> >> /* Get the data of the section. */ >> data = elf_getdata (scn, NULL); >> @@ -1802,8 +1841,6 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr >> *shdr) >> error (EXIT_FAILURE, 0, >> _("cannot get section header string table index")); >> >> - sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT); >> - >> glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), >> &glink_mem); >> if (glink == NULL) >> error (EXIT_FAILURE, 0, _("invalid sh_link value in section %zu"), >> @@ -1813,15 +1850,15 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr >> *shdr) >> \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: >> %#08" PRIx64 " Link to section: [%2u] '%s'\n", >> "\ >> \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: >> %#08" PRIx64 " Link to section: [%2u] '%s'\n", >> - shdr->sh_size / sh_entsize), >> - (unsigned long int) (shdr->sh_size / sh_entsize), >> + dyn_scnents), >> + (unsigned long int) dyn_scnents, >> class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, >> shdr->sh_offset, >> (int) shdr->sh_link, >> elf_strptr (ebl->elf, shstrndx, glink->sh_name)); >> fputs_unlocked (_(" Type Value\n"), stdout); >> >> - for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) >> + for (cnt = 0; cnt < dyn_scnents; ++cnt) >> { >> GElf_Dyn dynmem; >> GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem); >> diff --git a/tests/alldts.c b/tests/alldts.c >> index 3e9f9fe6..d0fe4f24 100644 >> --- a/tests/alldts.c >> +++ b/tests/alldts.c >> @@ -44,7 +44,7 @@ main (void) >> Dwelf_Strent *shstrtabse; >> const Elf32_Sword dtflags[] = >> { >> - DT_NULL, DT_NEEDED, DT_PLTRELSZ, DT_PLTGOT, >> + 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, >> @@ -61,7 +61,8 @@ main (void) >> 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 >> + DT_VERNEED, DT_VERNEEDNUM, DT_AUXILIARY, DT_FILTER, >> + DT_NULL >> }; >> const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]); >> >> diff --git a/tests/run-alldts.sh b/tests/run-alldts.sh >> index 6a9a9ece..bd750a35 100755 >> --- a/tests/run-alldts.sh >> +++ b/tests/run-alldts.sh >> @@ -27,7 +27,6 @@ testrun_compare ${abs_top_builddir}/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 >> @@ -93,6 +92,7 @@ Dynamic segment contains 66 entries: >> VERNEEDNUM 3735928559 >> AUXILIARY 0xdeadbeef >> FILTER 0xdeadbeef >> + NULL >> EOF >> >> exit 0 >> diff --git a/tests/run-readelf-d.sh b/tests/run-readelf-d.sh >> index d0b6ed24..69b01c49 100755 >> --- a/tests/run-readelf-d.sh >> +++ b/tests/run-readelf-d.sh >> @@ -34,7 +34,7 @@ testfiles testlib_dynseg.so >> >> testrun_compare ${abs_top_builddir}/src/readelf -d testlib_dynseg.so >> <<\EOF >> >> -Dynamic segment contains 28 entries: >> +Dynamic segment contains 23 entries: >> Addr: 0x00000000000017e0 Offset: 0x0007e0 Link to section: [ 3] >> '.dynstr' >> Type Value >> PLTGOT 0x00000000000019c8 >> @@ -60,11 +60,6 @@ Dynamic segment contains 28 entries: >> VERNEED 0x0000000000000498 >> VERNEEDNUM 2 >> NULL >> - NULL >> - NULL >> - NULL >> - NULL >> - NULL >> EOF >> >> exit 0 >> -- >> 2.34.1 >> >>