public inbox for binutils-cvs@sourceware.org
 help / color / mirror / Atom feed
* [binutils-gdb] Update readelf's display of RELR sections to include the number of locations relocated
@ 2024-04-24 11:45 Nick Clifton
  0 siblings, 0 replies; only message in thread
From: Nick Clifton @ 2024-04-24 11:45 UTC (permalink / raw)
  To: binutils-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=3b3e2090118966e3b885ae578440e380dc90e648

commit 3b3e2090118966e3b885ae578440e380dc90e648
Author: Nick Clifton <nickc@redhat.com>
Date:   Wed Apr 24 12:45:04 2024 +0100

    Update readelf's display of RELR sections to include the number of locations relocated

Diff:
---
 binutils/readelf.c                        | 135 +++++++++++++++++++++++++-----
 ld/testsuite/ld-elf/dt-relr-2b.d          |   2 +-
 ld/testsuite/ld-elf/dt-relr-2c.d          |   2 +-
 ld/testsuite/ld-elf/dt-relr-2d.d          |   2 +-
 ld/testsuite/ld-elf/dt-relr-2e.d          |   2 +-
 ld/testsuite/ld-elf/dt-relr-2i.d          |   2 +-
 ld/testsuite/ld-i386/dt-relr-1a.d         |   2 +-
 ld/testsuite/ld-i386/dt-relr-1b.d         |   2 +-
 ld/testsuite/ld-powerpc/abs-pie-relr.r    |   2 +-
 ld/testsuite/ld-powerpc/abs-shared-relr.r |   2 +-
 ld/testsuite/ld-x86-64/dt-relr-1a-x32.d   |   2 +-
 ld/testsuite/ld-x86-64/dt-relr-1a.d       |   2 +-
 ld/testsuite/ld-x86-64/dt-relr-1b-x32.d   |   2 +-
 ld/testsuite/ld-x86-64/dt-relr-1b.d       |   2 +-
 14 files changed, 128 insertions(+), 33 deletions(-)

diff --git a/binutils/readelf.c b/binutils/readelf.c
index e0cf718aa28..f8305b4715b 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -1548,6 +1548,10 @@ get_symbol_at (Elf_Internal_Sym *  symtab,
   Elf_Internal_Sym *  best = NULL;
   uint64_t            dist = 0x100000;
 
+  /* Paranoia.  */
+  if (symtab == NULL || nsyms == 0 || strtab == NULL || strtablen == 0)
+    return NULL;
+
   /* FIXME: Since this function is likely to be called repeatedly with
      slightly increasing addresses each time, we could speed things up by
      caching the last returned value and starting our search from there.  */
@@ -1624,6 +1628,69 @@ symcmp (const void *p, const void *q)
   return sp->st_value > sq->st_value ? 1 : (sp->st_value < sq->st_value ? -1 : 0);
 }
 
+static uint64_t
+count_relr_relocations (Filedata *          filedata,
+			Elf_Internal_Shdr * section)
+{
+  uint64_t *  relrs;
+  uint64_t    nentries;
+  uint64_t    i;
+  uint64_t    count;
+  int         entsize;
+
+  if (section == NULL
+      || section->sh_type != SHT_RELR
+      || section->sh_size == 0)
+    return 0;
+
+  entsize = section->sh_entsize;
+  if (entsize == 0)
+    entsize = is_32bit_elf
+      ? sizeof (Elf32_External_Relr) : sizeof (Elf64_External_Relr);
+  else if (entsize != sizeof (Elf32_External_Relr)
+	   && entsize != sizeof (Elf64_External_Relr))
+    return 0;
+
+  nentries = section->sh_size / entsize;
+  if (nentries == 0)
+    return 0;
+  
+  /* FIXME: This call to get_data duplicates one that follows in
+     dump_relr_relocations().  They could be combined into just
+     one call.  */
+  relrs = get_data (NULL, filedata, section->sh_offset, 1,
+		    section->sh_size, _("RELR relocation data"));
+  if (relrs == NULL)
+    return 0;
+
+  for (count = i = 0; i < nentries; i++)
+    {
+      uint64_t entry;
+
+      if (entsize == sizeof (Elf32_External_Relr))
+	entry = BYTE_GET (((Elf32_External_Relr *)relrs)[i].r_data);
+      else
+	entry = BYTE_GET (((Elf64_External_Relr *)relrs)[i].r_data);
+
+      if ((entry & 1) == 0)
+	{
+	  ++ count;
+	}
+      else
+	{
+	  if (entry == 1)
+	    continue;
+
+	  for (; entry >>= 1;)
+	    if ((entry & 1) == 1)
+	      ++ count;
+	}
+    }
+
+  free (relrs);
+  return count;
+}
+
 static bool
 dump_relr_relocations (Filedata *          filedata,
 		       Elf_Internal_Shdr * section,
@@ -1640,15 +1707,15 @@ dump_relr_relocations (Filedata *          filedata,
   uint64_t    where = 0;
   int         num_bits_in_entry;
 
-  relrs = get_data (NULL, filedata, relr_offset, 1, relr_size, _("RELR relocation data"));
-  if (relrs == NULL)
-    return false;
-
   if (relr_entsize == 0)
-    relr_entsize = is_32bit_elf ? 4 : 8;
+    relr_entsize = is_32bit_elf
+      ? sizeof (Elf32_External_Relr) : sizeof (Elf64_External_Relr);
 
   nentries = relr_size / relr_entsize;
 
+  if (nentries == 0)
+    return true;
+
   if (relr_entsize == sizeof (Elf32_External_Relr))
     num_bits_in_entry = 31;
   else if (relr_entsize == sizeof (Elf64_External_Relr))
@@ -1658,14 +1725,21 @@ dump_relr_relocations (Filedata *          filedata,
       warn (_("Unexpected entsize for RELR section\n"));
       return false;
     }
-  
-  /* Symbol tables are not sorted on address, but we want a quick lookup
-     for the symbol associated with each address computed below, so sort
-     the table now.  FIXME: This assumes that the symbol table will not
-     be used later on for some other purpose.  */
-  qsort (symtab, nsyms, sizeof (Elf_Internal_Sym), symcmp);
 
-  if (relr_entsize == 4)
+  relrs = get_data (NULL, filedata, relr_offset, 1, relr_size, _("RELR relocation data"));
+  if (relrs == NULL)
+    return false;
+
+  if (symtab != NULL)
+    {
+      /* Symbol tables are not sorted on address, but we want a quick lookup
+	 for the symbol associated with each address computed below, so sort
+	 the table now.  FIXME: This assumes that the symbol table will not
+	 be used later on for some other purpose.  */
+      qsort (symtab, nsyms, sizeof (Elf_Internal_Sym), symcmp);
+    }
+
+  if (relr_entsize == sizeof (Elf32_External_Relr))
     printf (_ ("Index: Entry    Address   Symbolic Address\n"));
   else
     printf (_ ("Index: Entry            Address           Symbolic Address\n"));
@@ -1674,7 +1748,7 @@ dump_relr_relocations (Filedata *          filedata,
     {
       uint64_t entry;
 
-      if (relr_entsize == 4)
+      if (relr_entsize == sizeof (Elf32_External_Relr))
 	entry = BYTE_GET (((Elf32_External_Relr *)relrs)[i].r_data);
       else
 	entry = BYTE_GET (((Elf64_External_Relr *)relrs)[i].r_data);
@@ -1698,7 +1772,9 @@ dump_relr_relocations (Filedata *          filedata,
 
 	  /* The least significant bit is ignored.  */
 	  if (entry == 1)
-	    warn (_("Malformed RELR bitmap - no significant bits are set\n"));
+	    /* This can actually happen when the linker is allowed to shrink
+	       RELR sections.  For more details see: https://reviews.llvm.org/D67164. */
+	    continue;
 	  else if (i == 0)
 	    warn (_("Unusual RELR bitmap - no previous entry to set the base address\n"));
 
@@ -9077,12 +9153,31 @@ display_relocations (Elf_Internal_Shdr *  section,
   uint64_t num_rela = rel_size / section->sh_entsize;
   uint64_t rel_offset = section->sh_offset;
 
-  printf (ngettext (" at offset %#" PRIx64
-		    " contains %" PRIu64 " entry:\n",
-		    " at offset %#" PRIx64
-		    " contains %" PRId64 " entries:\n",
-		    num_rela),
-	  rel_offset, num_rela);
+  if (rel_type == reltype_relr)
+    {
+      /* Just stating the 'number of entries' in a RELR section can be
+	 misleading, since this is not the number of locations relocated, but
+	 the number of words in the compressed RELR format.  So also provide
+	 the number of locations affected.  */
+      if (num_rela == 1)
+	/* This is unlikely, but possible.  */
+	printf (_(" at offset %#" PRIx64
+		  " contains 1 entry which relocates 1 location:\n"),
+		rel_offset);
+      else
+	printf (_(" at offset %#" PRIx64 " contains %" PRIu64
+		  " entries which relocate %" PRIu64 " locations:\n"),
+		rel_offset, num_rela, count_relr_relocations (filedata, section));
+    }
+  else
+    {
+      printf (ngettext (" at offset %#" PRIx64
+			" contains %" PRIu64 " entry:\n",
+			" at offset %#" PRIx64
+			" contains %" PRIu64 " entries:\n",
+			num_rela),
+	      rel_offset, num_rela);
+    }
 
   Elf_Internal_Shdr * symsec;
   Elf_Internal_Sym *  symtab = NULL;
diff --git a/ld/testsuite/ld-elf/dt-relr-2b.d b/ld/testsuite/ld-elf/dt-relr-2b.d
index f9c688087f9..6c66d56eade 100644
--- a/ld/testsuite/ld-elf/dt-relr-2b.d
+++ b/ld/testsuite/ld-elf/dt-relr-2b.d
@@ -12,7 +12,7 @@ Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
 #...
 [0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
 #...
-Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +data
 0001: +[0-9a-f]+ [0-9a-f]+ +data \+ 0x[0-9a-f]+
diff --git a/ld/testsuite/ld-elf/dt-relr-2c.d b/ld/testsuite/ld-elf/dt-relr-2c.d
index d9e3698a8f0..cc37375e4e5 100644
--- a/ld/testsuite/ld-elf/dt-relr-2c.d
+++ b/ld/testsuite/ld-elf/dt-relr-2c.d
@@ -12,7 +12,7 @@ Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
 #...
 [0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
 #...
-Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +.*
 0001: +[0-9a-f]+ [0-9a-f]+ +.*
diff --git a/ld/testsuite/ld-elf/dt-relr-2d.d b/ld/testsuite/ld-elf/dt-relr-2d.d
index 69863bddec4..d149e77bd68 100644
--- a/ld/testsuite/ld-elf/dt-relr-2d.d
+++ b/ld/testsuite/ld-elf/dt-relr-2d.d
@@ -12,7 +12,7 @@ Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
 #...
 [0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
 #...
-Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +data
 0001: +[0-9a-f]+ [0-9a-f]+ +data \+ 0x[0-9a-f]+
diff --git a/ld/testsuite/ld-elf/dt-relr-2e.d b/ld/testsuite/ld-elf/dt-relr-2e.d
index e047c0d6529..e6b478cb5f0 100644
--- a/ld/testsuite/ld-elf/dt-relr-2e.d
+++ b/ld/testsuite/ld-elf/dt-relr-2e.d
@@ -12,7 +12,7 @@ Relocation section '\.rel(a|)\.data' at offset 0x[0-9a-f]+ contains 1 entry:
 #...
 [0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
 #...
-Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +data
 0001: +[0-9a-f]+ [0-9a-f]+ +data \+ 0x[0-9a-f]+
diff --git a/ld/testsuite/ld-elf/dt-relr-2i.d b/ld/testsuite/ld-elf/dt-relr-2i.d
index a328ccb92e5..2a07fcb1a71 100644
--- a/ld/testsuite/ld-elf/dt-relr-2i.d
+++ b/ld/testsuite/ld-elf/dt-relr-2i.d
@@ -12,7 +12,7 @@ Relocation section '\.rel(a|)\.dyn' at offset 0x[0-9a-f]+ contains 1 entry:
 #...
 [0-9a-f]+ +[0-9a-f]+ +R_.*_(RELATIVE|UADDR.*) .*
 #...
-Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries:
+Relocation section '\.relr\.dyn' at offset 0x[0-9a-f]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +data
 0001: +[0-9a-f]+ [0-9a-f]+ +data \+ 0x[0-9a-f]+
diff --git a/ld/testsuite/ld-i386/dt-relr-1a.d b/ld/testsuite/ld-i386/dt-relr-1a.d
index 89cc636f4bc..282540b8b50 100644
--- a/ld/testsuite/ld-i386/dt-relr-1a.d
+++ b/ld/testsuite/ld-i386/dt-relr-1a.d
@@ -13,7 +13,7 @@ Relocation section '\.rel\.plt' at offset 0x[0-9a-f]+ contains 1 entry:
  +Offset +Info +Type +Sym. Value +Symbol's Name
 [0-9a-f]+ +[0-9a-f]+ +R_386_JUMP_SLOT +0+ +func1
 
-Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries:
+Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +.*
 0001: +[0-9a-f]+ [0-9a-f]+ +.*
diff --git a/ld/testsuite/ld-i386/dt-relr-1b.d b/ld/testsuite/ld-i386/dt-relr-1b.d
index 6e7f3ca0a25..ff027257e15 100644
--- a/ld/testsuite/ld-i386/dt-relr-1b.d
+++ b/ld/testsuite/ld-i386/dt-relr-1b.d
@@ -16,7 +16,7 @@ Relocation section '\.rel\.plt' at offset 0x[0-9a-f]+ contains 1 entry:
  +Offset +Info +Type +Sym. Value +Symbol's Name
 [0-9a-f]+ +[0-9a-f]+ +R_386_JUMP_SLOT +0+ +func1
 
-Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries:
+Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +.*
 0001: +[0-9a-f]+ [0-9a-f]+ +.*
diff --git a/ld/testsuite/ld-powerpc/abs-pie-relr.r b/ld/testsuite/ld-powerpc/abs-pie-relr.r
index e84b0af115b..37c64f38bc6 100644
--- a/ld/testsuite/ld-powerpc/abs-pie-relr.r
+++ b/ld/testsuite/ld-powerpc/abs-pie-relr.r
@@ -3,6 +3,6 @@
 #ld: -melf64ppc -pie --hash-style=sysv -z pack-relative-relocs --defsym a=1 --defsym 'HIDDEN(b=2)' --defsym c=0x123456789abcdef0
 #readelf: -rW
 
-Relocation section '\.relr\.dyn' at offset .* contains 1 entry:
+Relocation section '\.relr\.dyn' at offset .* contains 1 entry which relocates 1 location:
 Index: Entry            Address           Symbolic Address
 0000: +[0-9a-f]+ [0-9a-f]+ +x
diff --git a/ld/testsuite/ld-powerpc/abs-shared-relr.r b/ld/testsuite/ld-powerpc/abs-shared-relr.r
index ce1a7eee339..3f36c5d877f 100644
--- a/ld/testsuite/ld-powerpc/abs-shared-relr.r
+++ b/ld/testsuite/ld-powerpc/abs-shared-relr.r
@@ -12,7 +12,7 @@ Relocation section '\.rela\.dyn' at offset .* contains 6 entries:
 0+10428  0+400000014 R_PPC64_GLOB_DAT       123456789abcdef0 c \+ 0
 0+10450  0+400000026 R_PPC64_ADDR64         123456789abcdef0 c \+ 0
 
-Relocation section '\.relr\.dyn' at offset .* contains 1 entry:
+Relocation section '\.relr\.dyn' at offset .* contains 1 entry which relocates 1 location:
 Index: Entry            Address           Symbolic Address
 0000: +[0-9a-f]+ [0-9a-f]+ +x
 
diff --git a/ld/testsuite/ld-x86-64/dt-relr-1a-x32.d b/ld/testsuite/ld-x86-64/dt-relr-1a-x32.d
index 863e97a7980..dd2b73e1f5e 100644
--- a/ld/testsuite/ld-x86-64/dt-relr-1a-x32.d
+++ b/ld/testsuite/ld-x86-64/dt-relr-1a-x32.d
@@ -13,7 +13,7 @@ Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entry:
  +Offset +Info +Type +Sym. Value +Symbol's Name \+ Addend
 [0-9a-f]+ +[0-9a-f]+ +R_X86_64_JUMP_SLOT +0+ +func1 \+ 0
 
-Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries:
+Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +.*
 0001: +[0-9a-f]+ [0-9a-f]+ +.*
diff --git a/ld/testsuite/ld-x86-64/dt-relr-1a.d b/ld/testsuite/ld-x86-64/dt-relr-1a.d
index 30af87535c9..c7a74e398a5 100644
--- a/ld/testsuite/ld-x86-64/dt-relr-1a.d
+++ b/ld/testsuite/ld-x86-64/dt-relr-1a.d
@@ -13,7 +13,7 @@ Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entry:
  +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
 [0-9a-f]+ +[0-9a-f]+ +R_X86_64_JUMP_SLOT +0+ +func1 \+ 0
 
-Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries:
+Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +.*
 0001: +[0-9a-f]+ [0-9a-f]+ +.*
diff --git a/ld/testsuite/ld-x86-64/dt-relr-1b-x32.d b/ld/testsuite/ld-x86-64/dt-relr-1b-x32.d
index 3c37bcd5358..bc582aea1b0 100644
--- a/ld/testsuite/ld-x86-64/dt-relr-1b-x32.d
+++ b/ld/testsuite/ld-x86-64/dt-relr-1b-x32.d
@@ -16,7 +16,7 @@ Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entry:
  +Offset +Info +Type +Sym. Value +Symbol's Name \+ Addend
 [0-9a-f]+ +[0-9a-f]+ +R_X86_64_JUMP_SLOT +0+ +func1 \+ 0
 
-Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries:
+Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +.*
 0001: +[0-9a-f]+ [0-9a-f]+ +.*
diff --git a/ld/testsuite/ld-x86-64/dt-relr-1b.d b/ld/testsuite/ld-x86-64/dt-relr-1b.d
index bc07cf89b26..c3fddb08e20 100644
--- a/ld/testsuite/ld-x86-64/dt-relr-1b.d
+++ b/ld/testsuite/ld-x86-64/dt-relr-1b.d
@@ -16,7 +16,7 @@ Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entry:
  +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
 [0-9a-f]+ +[0-9a-f]+ +R_X86_64_JUMP_SLOT +0+ +func1 \+ 0
 
-Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries:
+Relocation section '.relr.dyn' at offset 0x[a-f0-9]+ contains 2 entries which relocate [0-9]+ locations:
 #...
 0000: +[0-9a-f]+ [0-9a-f]+ +.*
 0001: +[0-9a-f]+ [0-9a-f]+ +.*

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-04-24 11:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-24 11:45 [binutils-gdb] Update readelf's display of RELR sections to include the number of locations relocated Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).