* cris.h (R_CRIS_32_IE): New relocation.
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 02de84c43ad7b18043d088de02015c6bb8400809..81cde343e593d202ddf28c1df71e444af431e864 100644 (file)
@@ -414,35 +414,31 @@ print_vma (bfd_vma vma, print_mode mode)
   return 0;
 }
 
-/* Display a symbol on stdout.  Handles the display of
-   non-printing characters.
-   If DO_WIDE is not true then format the symbol to be
-   at most WIDTH characters, truncating as necessary.
-   If WIDTH is negative then format the string to be
-   exactly - WIDTH characters, truncating or padding
-   as necessary.  */
+/* Display a symbol on stdout.  Handles the display of non-printing characters.
 
-static void
+   If DO_WIDE is not true then format the symbol to be at most WIDTH characters,
+   truncating as necessary.  If WIDTH is negative then format the string to be
+   exactly - WIDTH characters, truncating or padding as necessary.
+
+   Returns the number of emitted characters.  */
+
+static unsigned int
 print_symbol (int width, const char *symbol)
 {
-  const char * format_string;
   const char * c;
+  bfd_boolean extra_padding = FALSE;
+  unsigned int num_printed = 0;
 
   if (do_wide)
     {
-      format_string = "%.*s";
       /* Set the width to a very large value.  This simplifies the code below.  */
       width = INT_MAX;
     }
   else if (width < 0)
     {
-      format_string = "%-*.*2s";
       /* Keep the width positive.  This also helps.  */
       width = - width;
-    }
-  else
-    {
-      format_string = "%-.*s";
+      extra_padding = TRUE;
     }
 
   while (width)
@@ -464,9 +460,10 @@ print_symbol (int width, const char *symbol)
          if (len > width)
            len = width;
 
-         printf (format_string, len, symbol);
+         printf ("%.*s", len, symbol);
 
          width -= len;
+         num_printed += len;
        }
 
       if (* c == 0 || width == 0)
@@ -482,6 +479,7 @@ print_symbol (int width, const char *symbol)
          printf ("^%c", *c + 0x40);
 
          width -= 2;
+         num_printed += 2;
        }
       else
        {
@@ -491,10 +489,20 @@ print_symbol (int width, const char *symbol)
          printf ("<0x%.2x>", *c);
 
          width -= 6;
+         num_printed += 6;
        }
 
       symbol = c + 1;
     }
+
+  if (extra_padding && width > 0)
+    {
+      /* Fill in the remaining spaces.  */
+      printf ("%-*s", width, " ");
+      num_printed += 2;
+    }
+
+  return num_printed;
 }
 
 static void
@@ -1242,8 +1250,39 @@ dump_relocations (FILE *file,
              psym = symtab + symtab_index;
 
              printf (" ");
-             print_vma (psym->st_value, LONG_HEX);
-             printf (is_32bit_elf ? "   " : " ");
+
+             if (ELF_ST_TYPE (psym->st_info) == STT_IFUNC)
+               {
+                 const char * name;
+                 unsigned int len;
+                 unsigned int width = is_32bit_elf ? 8 : 14;
+
+                 /* Relocations against IFUNC symbols do not use the value of
+                    the symbol as the address to relocate against.  Instead
+                    they invoke the function named by the symbol and use its
+                    result as the address for relocation.
+
+                    To indicate this to the user, do not display the value of
+                    the symbol in the "Symbols's Value" field.  Instead show
+                    its name followed by () as a hint that the symbol is
+                    invoked.  */
+
+                 if (strtab == NULL
+                     || psym->st_name == 0
+                     || psym->st_name >= strtablen)
+                   name = "??";
+                 else
+                   name = strtab + psym->st_name;
+
+                 len = print_symbol (width, name);
+                 printf ("()%-*s", len <= width ? (width + 1) - len : 1, " ");
+               }
+             else
+               {
+                 print_vma (psym->st_value, LONG_HEX);
+
+                 printf (is_32bit_elf ? "   " : " ");
+               }
 
              if (psym->st_name == 0)
                {
@@ -1294,7 +1333,14 @@ dump_relocations (FILE *file,
                print_symbol (22, strtab + psym->st_name);
 
              if (is_rela)
-               printf (" + %lx", (unsigned long) rels[i].r_addend);
+               {
+                 long offset = (long) (bfd_signed_vma) rels[i].r_addend;
+
+                 if (offset < 0)
+                   printf (" - %lx", - offset);
+                 else
+                   printf (" + %lx", offset);
+               }
            }
        }
       else if (is_rela)
@@ -7019,6 +7065,14 @@ get_symbol_type (unsigned int type)
              if (type == STT_HP_STUB)
                return "HP_STUB";
            }
+         else if (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX
+                  || elf_header.e_ident[EI_OSABI] == ELFOSABI_HURD
+                  /* GNU/Linux is still using the default value 0.  */
+                  || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE)
+           {
+             if (type == STT_IFUNC)
+               return "IFUNC";
+           }
 
          snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type);
        }
@@ -8740,29 +8794,30 @@ typedef struct
 
 static const char *arm_attr_tag_CPU_arch[] =
   {"Pre-v4", "v4", "v4T", "v5T", "v5TE", "v5TEJ", "v6", "v6KZ", "v6T2",
-   "v6K", "v7"};
+   "v6K", "v7", "v6-M", "v6S-M"};
 static const char *arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
 static const char *arm_attr_tag_THUMB_ISA_use[] =
   {"No", "Thumb-1", "Thumb-2"};
 static const char *arm_attr_tag_VFP_arch[] =
   {"No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16"};
-static const char *arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1"};
-static const char *arm_attr_tag_NEON_arch[] = {"No", "NEONv1"};
-static const char *arm_attr_tag_ABI_PCS_config[] =
+static const char *arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1", "WMMXv2"};
+static const char *arm_attr_tag_Advanced_SIMD_arch[] = {"No", "NEONv1"};
+static const char *arm_attr_tag_PCS_config[] =
   {"None", "Bare platform", "Linux application", "Linux DSO", "PalmOS 2004",
    "PalmOS (reserved)", "SymbianOS 2004", "SymbianOS (reserved)"};
 static const char *arm_attr_tag_ABI_PCS_R9_use[] =
   {"V6", "SB", "TLS", "Unused"};
 static const char *arm_attr_tag_ABI_PCS_RW_data[] =
   {"Absolute", "PC-relative", "SB-relative", "None"};
-static const char *arm_attr_tag_ABI_PCS_RO_DATA[] =
+static const char *arm_attr_tag_ABI_PCS_RO_data[] =
   {"Absolute", "PC-relative", "None"};
 static const char *arm_attr_tag_ABI_PCS_GOT_use[] =
   {"None", "direct", "GOT-indirect"};
 static const char *arm_attr_tag_ABI_PCS_wchar_t[] =
   {"None", "??? 1", "2", "??? 3", "4"};
 static const char *arm_attr_tag_ABI_FP_rounding[] = {"Unused", "Needed"};
-static const char *arm_attr_tag_ABI_FP_denormal[] = {"Unused", "Needed"};
+static const char *arm_attr_tag_ABI_FP_denormal[] =
+  {"Unused", "Needed", "Sign only"};
 static const char *arm_attr_tag_ABI_FP_exceptions[] = {"Unused", "Needed"};
 static const char *arm_attr_tag_ABI_FP_user_exceptions[] = {"Unused", "Needed"};
 static const char *arm_attr_tag_ABI_FP_number_model[] =
@@ -8784,10 +8839,15 @@ static const char *arm_attr_tag_ABI_optimization_goals[] =
 static const char *arm_attr_tag_ABI_FP_optimization_goals[] =
   {"None", "Prefer Speed", "Aggressive Speed", "Prefer Size",
     "Aggressive Size", "Prefer Accuracy", "Aggressive Accuracy"};
+static const char *arm_attr_tag_CPU_unaligned_access[] = {"None", "v6"};
 static const char *arm_attr_tag_VFP_HP_extension[] =
   {"Not Allowed", "Allowed"};
 static const char *arm_attr_tag_ABI_FP_16bit_format[] =
   {"None", "IEEE 754", "Alternative Format"};
+static const char *arm_attr_tag_T2EE_use[] = {"Not Allowed", "Allowed"};
+static const char *arm_attr_tag_Virtualization_use[] =
+  {"Not Allowed", "Allowed"};
+static const char *arm_attr_tag_MPextension_use[] = {"Not Allowed", "Allowed"};
 
 #define LOOKUP(id, name) \
   {id, #name, 0x80 | ARRAY_SIZE(arm_attr_tag_##name), arm_attr_tag_##name}
@@ -8801,11 +8861,11 @@ static arm_attr_public_tag arm_attr_public_tags[] =
   LOOKUP(9, THUMB_ISA_use),
   LOOKUP(10, VFP_arch),
   LOOKUP(11, WMMX_arch),
-  LOOKUP(12, NEON_arch),
-  LOOKUP(13, ABI_PCS_config),
+  LOOKUP(12, Advanced_SIMD_arch),
+  LOOKUP(13, PCS_config),
   LOOKUP(14, ABI_PCS_R9_use),
   LOOKUP(15, ABI_PCS_RW_data),
-  LOOKUP(16, ABI_PCS_RO_DATA),
+  LOOKUP(16, ABI_PCS_RO_data),
   LOOKUP(17, ABI_PCS_GOT_use),
   LOOKUP(18, ABI_PCS_wchar_t),
   LOOKUP(19, ABI_FP_rounding),
@@ -8822,8 +8882,15 @@ static arm_attr_public_tag arm_attr_public_tags[] =
   LOOKUP(30, ABI_optimization_goals),
   LOOKUP(31, ABI_FP_optimization_goals),
   {32, "compatibility", 0, NULL},
+  LOOKUP(34, CPU_unaligned_access),
   LOOKUP(36, VFP_HP_extension),
   LOOKUP(38, ABI_FP_16bit_format),
+  {64, "nodefaults", 0, NULL},
+  {65, "also_compatible_with", 0, NULL},
+  LOOKUP(66, T2EE_use),
+  {67, "conformance", 1, NULL},
+  LOOKUP(68, Virtualization_use),
+  LOOKUP(70, MPextension_use)
 };
 #undef LOOKUP
 
@@ -8903,6 +8970,28 @@ display_arm_attribute (unsigned char *p)
              p += strlen((char *)p) + 1;
              break;
 
+           case 64: /* Tag_nodefaults.  */
+             p++;
+             printf ("True\n");
+             break;
+
+           case 65: /* Tag_also_compatible_with.  */
+             val = read_uleb128 (p, &len);
+             p += len;
+             if (val == 6 /* Tag_CPU_arch.  */)
+               {
+                 val = read_uleb128 (p, &len);
+                 p += len;
+                 if ((unsigned int)val >= ARRAY_SIZE(arm_attr_tag_CPU_arch))
+                   printf ("??? (%d)\n", val);
+                 else
+                   printf ("%s\n", arm_attr_tag_CPU_arch[val]);
+               }
+             else
+               printf ("???\n");
+             while (*(p++) != '\0' /* NUL terminator.  */);
+             break;
+
            default:
              abort();
            }
This page took 0.042075 seconds and 4 git commands to generate.