Reinstate readelf decoding of i860, i960 and i370 relocs
[deliverable/binutils-gdb.git] / binutils / readelf.c
index f221cce32a948b489977cc3199f5da1a66413fb3..cf395dbe2d6998abc481a918d9f5370441c02200 100644 (file)
@@ -655,7 +655,8 @@ find_section (Filedata * filedata, const char * name)
 {
   unsigned int i;
 
-  assert (filedata->section_headers != NULL);
+  if (filedata->section_headers == NULL)
+    return NULL;
 
   for (i = 0; i < filedata->file_header.e_shnum; i++)
     if (streq (SECTION_NAME (filedata->section_headers + i), name))
@@ -672,6 +673,9 @@ find_section_by_address (Filedata * filedata, bfd_vma addr)
 {
   unsigned int i;
 
+  if (filedata->section_headers == NULL)
+    return NULL;
+
   for (i = 0; i < filedata->file_header.e_shnum; i++)
     {
       Elf_Internal_Shdr *sec = filedata->section_headers + i;
@@ -688,6 +692,9 @@ find_section_by_type (Filedata * filedata, unsigned int type)
 {
   unsigned int i;
 
+  if (filedata->section_headers == NULL)
+    return NULL;
+
   for (i = 0; i < filedata->file_header.e_shnum; i++)
     {
       Elf_Internal_Shdr *sec = filedata->section_headers + i;
@@ -707,6 +714,9 @@ find_section_in_set (Filedata * filedata, const char * name, unsigned int * set)
 {
   unsigned int i;
 
+  if (filedata->section_headers == NULL)
+    return NULL;
+
   if (set != NULL)
     {
       while ((i = *set++) > 0)
@@ -2263,7 +2273,7 @@ get_machine_name (unsigned e_machine)
     case EM_PARISC:            return "HPPA";
     case EM_VPP550:            return "Fujitsu VPP500";
     case EM_SPARC32PLUS:       return "Sparc v8+" ;
-    case EM_960:               return "Intel 90860";
+    case EM_960:               return "Intel 80960";
     case EM_PPC:               return "PowerPC";
       /* 20 */
     case EM_PPC64:             return "PowerPC64";
@@ -9643,7 +9653,7 @@ process_dynamic_section (Filedata * filedata)
          if (archive_file_offset != 0)
            str_tab_len = archive_file_size - offset;
          else
-           str_tab_len = filedata->file_size;
+           str_tab_len = filedata->file_size - offset;
 
          if (str_tab_len < 1)
            {
@@ -9999,6 +10009,21 @@ process_dynamic_section (Filedata * filedata)
                      printf (" PIE");
                      val ^= DF_1_PIE;
                    }
+                 if (val & DF_1_KMOD)
+                   {
+                     printf (" KMOD");
+                     val ^= DF_1_KMOD;
+                   }
+                 if (val & DF_1_WEAKFILTER)
+                   {
+                     printf (" WEAKFILTER");
+                     val ^= DF_1_WEAKFILTER;
+                   }
+                 if (val & DF_1_NOCOMMON)
+                   {
+                     printf (" NOCOMMON");
+                     val ^= DF_1_NOCOMMON;
+                   }
                  if (val != 0)
                    printf (" %lx", val);
                  puts ("");
@@ -10202,7 +10227,7 @@ process_dynamic_section (Filedata * filedata)
 static char *
 get_ver_flags (unsigned int flags)
 {
-  static char buff[32];
+  static char buff[128];
 
   buff[0] = 0;
 
@@ -16594,9 +16619,9 @@ get_note_type (Filedata * filedata, unsigned e_type)
       case NT_ARCH:
        return _("NT_ARCH (architecture)");
       case NT_GNU_BUILD_ATTRIBUTE_OPEN:
-       return _("NT_GNU_BUILD_ATTRIBUTE_OPEN");
+       return _("OPEN");
       case NT_GNU_BUILD_ATTRIBUTE_FUNC:
-       return _("NT_GNU_BUILD_ATTRIBUTE_FUNC");
+       return _("func");
       default:
        break;
       }
@@ -17416,13 +17441,16 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
   return TRUE;
 }
 
-/* Print the name of the symbol associated with a build attribute
-   that is attached to address OFFSET.  */
+/* Find the symbol associated with a build attribute that is attached
+   to address OFFSET.  If PNAME is non-NULL then store the name of
+   the symbol (if found) in the provided pointer,  Returns NULL if a
+   symbol could not be found.  */
 
-static bfd_boolean
-print_symbol_for_build_attribute (Filedata *     filedata,
-                                 unsigned long  offset,
-                                 bfd_boolean    is_open_attr)
+static Elf_Internal_Sym *
+get_symbol_for_build_attribute (Filedata *       filedata,
+                               unsigned long    offset,
+                               bfd_boolean      is_open_attr,
+                               const char **    pname)
 {
   static Filedata *         saved_filedata = NULL;
   static char *             strtab;
@@ -17461,10 +17489,7 @@ print_symbol_for_build_attribute (Filedata *     filedata,
     }
 
   if (symtab == NULL || strtab == NULL)
-    {
-      printf ("\n");
-      return FALSE;
-    }
+    return NULL;
 
   /* Find a symbol whose value matches offset.  */
   for (sym = symtab; sym < symtab + nsyms; sym ++)
@@ -17477,6 +17502,13 @@ print_symbol_for_build_attribute (Filedata *     filedata,
        if (strtab[sym->st_name] == 0)
          continue;
 
+       /* The AArch64 and ARM architectures define mapping symbols
+          (eg $d, $x, $t) which we want to ignore.  */
+       if (strtab[sym->st_name] == '$'
+           && strtab[sym->st_name + 1] != 0
+           && strtab[sym->st_name + 2] == 0)
+         continue;
+
        if (is_open_attr)
          {
            /* For OPEN attributes we prefer GLOBAL over LOCAL symbols
@@ -17484,14 +17516,15 @@ print_symbol_for_build_attribute (Filedata *     filedata,
               FUNC symbols entirely.  */
            switch (ELF_ST_TYPE (sym->st_info))
              {
-             case STT_FILE:
-               saved_sym = sym;
-               /* We can stop searching now.  */
-               sym = symtab + nsyms;
-               continue;
-
              case STT_OBJECT:
+             case STT_FILE:
                saved_sym = sym;
+               if (sym->st_size)
+                 {
+                   /* If the symbol has a size associated
+                      with it then we can stop searching.  */
+                   sym = symtab + nsyms;
+                 }
                continue;
 
              case STT_FUNC:
@@ -17529,55 +17562,124 @@ print_symbol_for_build_attribute (Filedata *     filedata,
          }
       }
 
-  printf (" (%s: %s)\n",
-         is_open_attr ? _("file") : _("func"),
-         saved_sym ? strtab + saved_sym->st_name : _("<no symbol found>)"));
-  return TRUE;
+  if (saved_sym && pname)
+    * pname = strtab + saved_sym->st_name;
+
+  return saved_sym;
 }
 
 static bfd_boolean
 print_gnu_build_attribute_description (Elf_Internal_Note *  pnote,
                                       Filedata *           filedata)
 {
-  static unsigned long global_offset = 0;
-  unsigned long        offset;
-  unsigned int         desc_size = is_32bit_elf ? 4 : 8;
-  bfd_boolean          is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
+  static unsigned long  global_offset = 0;
+  static unsigned long  global_end = 0;
+  static unsigned long  func_offset = 0;
+  static unsigned long  func_end = 0;
+
+  Elf_Internal_Sym *    sym;
+  const char *          name;
+  unsigned long         start;
+  unsigned long         end;
+  bfd_boolean           is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
 
-  if (pnote->descsz == 0)
+  switch (pnote->descsz)
     {
+    case 0:
+      /* A zero-length description means that the range of
+        the previous note of the same type should be used.  */
       if (is_open_attr)
        {
-         printf (_("    Applies from offset %#lx\n"), global_offset);
-         return TRUE;
+         if (global_end > global_offset)
+           printf (_("    Applies to region from %#lx to %#lx\n"),
+                   global_offset, global_end);
+         else
+           printf (_("    Applies to region from %#lx\n"), global_offset);
        }
       else
        {
-         printf (_("    Applies to func at %#lx"), global_offset);
-         return print_symbol_for_build_attribute (filedata, global_offset, is_open_attr);
+         if (func_end > func_offset)
+           printf (_("    Applies to region from %#lx to %#lx\n"), func_offset, func_end);
+         else
+           printf (_("    Applies to region from %#lx\n"), func_offset);
        }
-    }
+      return TRUE;
 
-  if (pnote->descsz != desc_size)
-    {
+    case 4:
+      start = byte_get ((unsigned char *) pnote->descdata, 4);
+      end = 0;
+      break;
+
+    case 8:
+      if (is_32bit_elf)
+       {
+         /* FIXME: We should check that version 3+ notes are being used here...  */
+         start = byte_get ((unsigned char *) pnote->descdata, 4);
+         end = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       }
+      else
+       {
+         start = byte_get ((unsigned char *) pnote->descdata, 8);
+         end = 0;
+       }
+      break;
+
+    case 16:
+      start = byte_get ((unsigned char *) pnote->descdata, 8);
+      end = byte_get ((unsigned char *) pnote->descdata + 8, 8);
+      break;
+      
+    default:
       error (_("    <invalid description size: %lx>\n"), pnote->descsz);
       printf (_("    <invalid descsz>"));
       return FALSE;
     }
 
-  offset = byte_get ((unsigned char *) pnote->descdata, desc_size);
+  name = NULL;
+  sym = get_symbol_for_build_attribute (filedata, start, is_open_attr, & name);
+  /* As of version 5 of the annobin plugin, filename symbols are biased by 2
+     in order to avoid them being confused with the start address of the
+     first function in the file...  */
+  if (sym == NULL && is_open_attr)
+    sym = get_symbol_for_build_attribute (filedata, start + 2, is_open_attr,
+                                         & name);
+
+  if (end == 0 && sym != NULL && sym->st_size > 0)
+    end = start + sym->st_size;
 
   if (is_open_attr)
     {
-      printf (_("    Applies from offset %#lx"), offset);
-      global_offset = offset;
+      /* FIXME: Need to properly allow for section alignment.  16 is just the alignment used on x86_64.  */
+      if (global_end > 0 && start > BFD_ALIGN (global_end, 16))
+       warn (_("Gap in build notes detected from %#lx to %#lx\n"),
+             global_end + 1, start - 1);
+
+      printf (_("    Applies to region from %#lx"), start);
+      global_offset = start;
+
+      if (end)
+       {
+         printf (_(" to %#lx"), end);
+         global_end = end;
+       }
     }
   else
     {
-      printf (_("    Applies to func at %#lx"), offset);
+      printf (_("    Applies to region from %#lx"), start);
+      func_offset = start;
+
+      if (end)
+       {
+         printf (_(" to %#lx"), end);
+         func_end = end;
+       }
     }
 
-  return print_symbol_for_build_attribute (filedata, offset, is_open_attr);
+  if (sym && name)
+    printf (_(" (%s)"), name);
+
+  printf ("\n");
+  return TRUE;
 }
 
 static bfd_boolean
@@ -17600,11 +17702,21 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
       return FALSE;
     }
 
-  left = 20;
+  if (do_wide)
+    left = 28;
+  else
+    left = 20;
 
   /* Version 2 of the spec adds a "GA" prefix to the name field.  */
   if (name[0] == 'G' && name[1] == 'A')
     {
+      if (pnote->namesz < 4)
+       {
+         error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
+         print_symbol (-20, _("  <corrupt name>"));
+         return FALSE;
+       }
+
       printf ("GA");
       name += 2;
       left -= 2;
This page took 0.031737 seconds and 4 git commands to generate.