]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
Change sources over to using GPLv3
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index 359ddbefdecdbc55dc2d367860c7796cc09be55a..9305d04ffac3ce06114df17cd1c6a29cf32319ce 100644 (file)
@@ -9,7 +9,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
   ELF file than is provided by objdump.  In particular it can display DWARF
   debugging information which (at the moment) objdump cannot.  */
 \f
+#include "sysdep.h"
 #include <assert.h>
-#include <sys/types.h>
 #include <sys/stat.h>
-#include <stdio.h>
 #include <time.h>
 
 /* for PATH_MAX */
@@ -74,6 +73,8 @@
 #define BFD64
 #endif
 
+#include "bfd.h"
+#include "bucomm.h"
 #include "dwarf.h"
 
 #include "elf/common.h"
 
 #include "aout/ar.h"
 
-#include "bucomm.h"
 #include "getopt.h"
 #include "libiberty.h"
 
@@ -3516,6 +3516,9 @@ process_program_headers (FILE *file)
                  break;
                }
 
+             if (sec->sh_type == SHT_NOBITS)
+               break;
+
              dynamic_addr = sec->sh_offset;
              dynamic_size = sec->sh_size;
 
@@ -7803,6 +7806,10 @@ debug_apply_rela_addends (void *file,
   if (!is_relocatable)
     return 1;
 
+  /* SH uses RELA but uses in place value instead of the addend field.  */
+  if (elf_header.e_machine == EM_SH)
+    return 0;
+
   for (relsec = section_headers;
        relsec < section_headers + elf_header.e_shnum;
        ++relsec)
@@ -8290,8 +8297,166 @@ display_arm_attribute (unsigned char *p)
   return p;
 }
 
+
+static unsigned char *
+display_gnu_attribute (unsigned char *p,
+                      unsigned char *(*display_proc_gnu_attribute)
+                           (unsigned char *, int))
+{
+  int tag;
+  unsigned int len;
+  int val;
+  int type;
+
+  tag = read_uleb128 (p, &len);
+  p += len;
+
+  /* Tag_compatibility is the only generic GNU attribute defined at
+     present.  */
+  if (tag == 32)
+    {
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("flag = %d, vendor = %s\n", val, p);
+      p += strlen((char *)p) + 1;
+      return p;
+    }
+
+  if ((tag & 2) == 0 && display_proc_gnu_attribute)
+    return display_proc_gnu_attribute (p, tag);
+
+  if (tag & 1)
+    type = 1; /* String.  */
+  else
+    type = 2; /* uleb128.  */
+  printf ("  Tag_unknown_%d: ", tag);
+
+  if (type == 1)
+    {
+      printf ("\"%s\"\n", p);
+      p += strlen ((char *)p) + 1;
+    }
+  else
+    {
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("%d (0x%x)\n", val, val);
+    }
+
+  return p;
+}
+
+static unsigned char *
+display_power_gnu_attribute (unsigned char *p, int tag)
+{
+  int type;
+  unsigned int len;
+  int val;
+
+  if (tag == Tag_GNU_Power_ABI_FP)
+    {
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_GNU_Power_ABI_FP: ");
+      switch (val)
+       {
+       case 0:
+         printf ("Hard or soft float\n");
+         break;
+       case 1:
+         printf ("Hard float\n");
+         break;
+       case 2:
+         printf ("Soft float\n");
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+   }
+
+  if (tag & 1)
+    type = 1; /* String.  */
+  else
+    type = 2; /* uleb128.  */
+  printf ("  Tag_unknown_%d: ", tag);
+
+  if (type == 1)
+    {
+      printf ("\"%s\"\n", p);
+      p += strlen ((char *)p) + 1;
+    }
+  else
+    {
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("%d (0x%x)\n", val, val);
+    }
+
+  return p;
+}
+
+static unsigned char *
+display_mips_gnu_attribute (unsigned char *p, int tag)
+{
+  int type;
+  unsigned int len;
+  int val;
+
+  if (tag == Tag_GNU_MIPS_ABI_FP)
+    {
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("  Tag_GNU_MIPS_ABI_FP: ");
+      switch (val)
+       {
+       case 0:
+         printf ("Hard or soft float\n");
+         break;
+       case 1:
+         printf ("Hard float (-mdouble-float)\n");
+         break;
+       case 2:
+         printf ("Hard float (-msingle-float)\n");
+         break;
+       case 3:
+         printf ("Soft float\n");
+         break;
+       default:
+         printf ("??? (%d)\n", val);
+         break;
+       }
+      return p;
+   }
+
+  if (tag & 1)
+    type = 1; /* String.  */
+  else
+    type = 2; /* uleb128.  */
+  printf ("  Tag_unknown_%d: ", tag);
+
+  if (type == 1)
+    {
+      printf ("\"%s\"\n", p);
+      p += strlen ((char *)p) + 1;
+    }
+  else
+    {
+      val = read_uleb128 (p, &len);
+      p += len;
+      printf ("%d (0x%x)\n", val, val);
+    }
+
+  return p;
+}
+
 static int
-process_arm_specific (FILE *file)
+process_attributes (FILE *file, const char *public_name,
+                   unsigned int proc_type,
+                   unsigned char *(*display_pub_attribute) (unsigned char *),
+                   unsigned char *(*display_proc_gnu_attribute)
+                        (unsigned char *, int))
 {
   Elf_Internal_Shdr *sect;
   unsigned char *contents;
@@ -8306,7 +8471,7 @@ process_arm_specific (FILE *file)
        i < elf_header.e_shnum;
        i++, sect++)
     {
-      if (sect->sh_type != SHT_ARM_ATTRIBUTES)
+      if (sect->sh_type != proc_type && sect->sh_type != SHT_GNU_ATTRIBUTES)
        continue;
 
       contents = get_data (NULL, file, sect->sh_offset, 1, sect->sh_size,
@@ -8323,6 +8488,7 @@ process_arm_specific (FILE *file)
            {
              int namelen;
              bfd_boolean public_section;
+             bfd_boolean gnu_section;
 
              section_len = byte_get (p, 4);
              p += 4;
@@ -8334,10 +8500,14 @@ process_arm_specific (FILE *file)
                }
              len -= section_len;
              printf ("Attribute Section: %s\n", p);
-             if (strcmp ((char *)p, "aeabi") == 0)
+             if (public_name && strcmp ((char *)p, public_name) == 0)
                public_section = TRUE;
              else
                public_section = FALSE;
+             if (strcmp ((char *)p, "gnu") == 0)
+               gnu_section = TRUE;
+             else
+               gnu_section = FALSE;
              namelen = strlen ((char *)p) + 1;
              p += namelen;
              section_len -= namelen + 4;
@@ -8386,7 +8556,13 @@ process_arm_specific (FILE *file)
                  if (public_section)
                    {
                      while (p < end)
-                       p = display_arm_attribute(p);
+                       p = display_pub_attribute (p);
+                   }
+                 else if (gnu_section)
+                   {
+                     while (p < end)
+                       p = display_gnu_attribute (p,
+                                                  display_proc_gnu_attribute);
                    }
                  else
                    {
@@ -8407,6 +8583,20 @@ process_arm_specific (FILE *file)
   return 1;
 }
 
+static int
+process_arm_specific (FILE *file)
+{
+  return process_attributes (file, "aeabi", SHT_ARM_ATTRIBUTES,
+                            display_arm_attribute, NULL);
+}
+
+static int
+process_power_specific (FILE *file)
+{
+  return process_attributes (file, NULL, SHT_GNU_ATTRIBUTES, NULL,
+                            display_power_gnu_attribute);
+}
+
 static int
 process_mips_specific (FILE *file)
 {
@@ -8417,6 +8607,9 @@ process_mips_specific (FILE *file)
   size_t options_offset = 0;
   size_t conflicts_offset = 0;
 
+  process_attributes (file, NULL, SHT_GNU_ATTRIBUTES, NULL,
+                     display_mips_gnu_attribute);
+
   /* We have a lot of special sections.  Thanks SGI!  */
   if (dynamic_section == NULL)
     /* No information available.  */
@@ -9182,6 +9375,9 @@ process_arch_specific (FILE *file)
     case EM_MIPS_RS3_LE:
       return process_mips_specific (file);
       break;
+    case EM_PPC:
+      return process_power_specific (file);
+      break;
     default:
       break;
     }