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 > >
From 1f0ae2c9643a0871109f53ec8506bf5697d67a70 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 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..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