]> 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 000221e53b1f9d3303ddc0d309017c96ed88c531..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;
 
@@ -8294,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;
@@ -8310,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,
@@ -8327,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;
@@ -8338,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;
@@ -8390,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
                    {
@@ -8411,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)
 {
@@ -8421,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.  */
@@ -9186,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;
     }