MIPS/readelf: With `-A' also dump GOT in static binaries
authorMaciej W. Rozycki <macro@imgtec.com>
Mon, 24 Apr 2017 19:41:33 +0000 (20:41 +0100)
committerMaciej W. Rozycki <macro@imgtec.com>
Wed, 26 Apr 2017 12:11:20 +0000 (13:11 +0100)
A static, non-relocated global offset table will be embedded in static
binaries produced from objects containing any kind of GOT relocations,
generally PIC code.  All symbols will have been resolved in static link
in such binaries making all GOT entries local and their values final as
there is no run-time load processing further performed.

Dump such GOT with `readelf -A' like already done with regular GOT, to
make it easier to examine static code that uses accesses via the GOT
pointer.  There will be no dynamic segment or section in a static binary
to get the GOT pointer (DT_PLTGOT) from, so use section headers to find
a `.got' section instead.

binutils/
* readelf.c (process_mips_specific): Add static GOT support.

binutils/ChangeLog
binutils/readelf.c

index 7f8e29d9eeb031a8057a1b524546358c088b2a43..d2ddf41f8d37cb990e8887abe3984e07ffed1a10 100644 (file)
@@ -1,3 +1,7 @@
+2017-04-26  Maciej W. Rozycki  <macro@imgtec.com>
+
+       * readelf.c (process_mips_specific): Add static GOT support.
+
 2017-04-25  Maciej W. Rozycki  <macro@imgtec.com>
 
        * readelf.c (process_mips_specific): Remove error reporting from
index 1139f710becc2aaca216c464a3525e2e7b0896f9..2d3ef2709983ed0d98e78487325cc3a6c8bc7062 100644 (file)
@@ -15007,8 +15007,93 @@ process_mips_specific (FILE * file)
 
   /* We have a lot of special sections.  Thanks SGI!  */
   if (dynamic_section == NULL)
-    /* No information available.  */
-    return res;
+    {
+      /* No dynamic information available.  See if there is static GOT.  */
+      sect = find_section (".got");
+      if (sect != NULL)
+       {
+         unsigned char *data_end;
+         unsigned char *data;
+         bfd_vma ent, end;
+         int addr_size;
+
+         pltgot = sect->sh_addr;
+
+         ent = pltgot;
+         addr_size = (is_32bit_elf ? 4 : 8);
+         end = pltgot + sect->sh_size;
+
+         data = (unsigned char *) get_data (NULL, file, sect->sh_offset,
+                                            end - pltgot, 1,
+                                            _("Global Offset Table data"));
+         /* PR 12855: Null data is handled gracefully throughout.  */
+         data_end = data + (end - pltgot);
+
+         printf (_("\nStatic GOT:\n"));
+         printf (_(" Canonical gp value: "));
+         print_vma (ent + 0x7ff0, LONG_HEX);
+         printf ("\n\n");
+
+         /* In a dynamic binary GOT[0] is reserved for the dynamic
+            loader to store the lazy resolver pointer, however in
+            a static binary it may well have been omitted and GOT
+            reduced to a table of addresses.
+            PR 21344: Check for the entry being fully available
+            before fetching it.  */
+         if (data
+             && data + ent - pltgot + addr_size <= data_end
+             && byte_get (data + ent - pltgot, addr_size) == 0)
+           {
+             printf (_(" Reserved entries:\n"));
+             printf (_("  %*s %10s %*s\n"),
+                     addr_size * 2, _("Address"), _("Access"),
+                     addr_size * 2, _("Value"));
+             ent = print_mips_got_entry (data, pltgot, ent, data_end);
+             printf ("\n");
+             if (ent == (bfd_vma) -1)
+               goto sgot_print_fail;
+
+             /* Check for the MSB of GOT[1] being set, identifying a
+                GNU object.  This entry will be used by some runtime
+                loaders, to store the module pointer.  Otherwise this
+                is an ordinary local entry.
+                PR 21344: Check for the entry being fully available
+                before fetching it.  */
+             if (data
+                 && data + ent - pltgot + addr_size <= data_end
+                 && (byte_get (data + ent - pltgot, addr_size)
+                     >> (addr_size * 8 - 1)) != 0)
+               {
+                 ent = print_mips_got_entry (data, pltgot, ent, data_end);
+                 printf ("\n");
+                 if (ent == (bfd_vma) -1)
+                   goto sgot_print_fail;
+               }
+             printf ("\n");
+           }
+
+         if (ent < end)
+           {
+             printf (_(" Local entries:\n"));
+             printf ("  %*s %10s %*s\n",
+                     addr_size * 2, _("Address"), _("Access"),
+                     addr_size * 2, _("Value"));
+             while (ent < end)
+               {
+                 ent = print_mips_got_entry (data, pltgot, ent, data_end);
+                 printf ("\n");
+                 if (ent == (bfd_vma) -1)
+                   goto sgot_print_fail;
+               }
+             printf ("\n");
+           }
+
+       sgot_print_fail:
+         if (data)
+           free (data);
+       }
+      return res;
+    }
 
   for (entry = dynamic_section;
        /* PR 17531 file: 012-50589-0.004.  */