readelf: Don't consider padding DT_NULL as dynamic section entry
authorDi Chen <dichen@redhat.com>
Tue, 1 Mar 2022 12:44:38 +0000 (20:44 +0800)
committerMark Wielaard <mark@klomp.org>
Tue, 19 Apr 2022 08:13:11 +0000 (10:13 +0200)
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 <dichen@redhat.com>
src/ChangeLog
src/readelf.c
tests/ChangeLog
tests/alldts.c
tests/run-alldts.sh
tests/run-readelf-d.sh

index c0a3db3..f563e99 100644 (file)
@@ -1,3 +1,9 @@
+2022-03-01  Di Chen  <dichen@redhat.com>
+
+       * readelf.c (get_dyn_ents): New function.
+       (handle_dynamic): Use get_dyn_ents to get the actual number of
+       Dynamic entries in the section.
+
 2022-03-27  Mark Wielaard  <mark@klomp.org>
 
        * addr2line.c: Replace error (EXIT_FAILURE, ...) with error_exit(...).
index 41d64d3..4b275ec 100644 (file)
@@ -1772,6 +1772,24 @@ print_dt_posflag_1 (int class, GElf_Xword d_val)
 }
 
 
+static size_t
+get_dyn_ents (Elf_Data * dyn_data)
+{
+  GElf_Dyn *dyn;
+  size_t dyn_idx = 0;
+  do
+    {
+      GElf_Dyn dyn_mem;
+      dyn = gelf_getdyn(dyn_data, dyn_idx, &dyn_mem);
+      if (dyn != NULL)
+       ++dyn_idx;
+    }
+  while (dyn != NULL && dyn->d_tag != DT_NULL);
+
+  return dyn_idx;
+}
+
+
 static void
 handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
 {
@@ -1781,19 +1799,20 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
   Elf_Data *data;
   size_t cnt;
   size_t shstrndx;
-  size_t sh_entsize;
+  size_t dyn_ents;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
   if (data == NULL)
     return;
 
+  /* Get the dynamic section entry number */
+  dyn_ents = get_dyn_ents (data);
+
   /* Get the section header string table index.  */
   if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
     error_exit (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 (0, _("invalid sh_link value in section %zu"),
@@ -1803,15 +1822,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_ents),
+         (unsigned long int) dyn_ents,
          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_ents; ++cnt)
     {
       GElf_Dyn dynmem;
       GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
index e49bff0..c734b26 100644 (file)
@@ -1,3 +1,10 @@
+2022-03-01  Di Chen <dichen@redhat.com>
+
+       * alldts.c (dtflags): Put DT_NULL last.
+       * run-alldts.sh: NULL comes last.
+       * run-readelf-d.sh: Adjust Dynamic entries, remove DT_NULL
+       padding.
+
 2022-04-14  Mark Wielaard  <mark@klomp.org>
 
        * run-debuginfod-federation-sqlite.sh: Don't try to corrupt
index 3e9f9fe..d0fe4f2 100644 (file)
@@ -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]);
 
index 6a9a9ec..ce3630b 100755 (executable)
@@ -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
index d0b6ed2..69b01c4 100755 (executable)
@@ -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