Add R_X86_64_RELATIVE64.
[deliverable/binutils-gdb.git] / binutils / readelf.c
index c975189241961a3784a328df4cedddb595a1c346..a9064c541f7fda48daa70b8323edf0e7fbd3800a 100644 (file)
 #include "elf/sparc.h"
 #include "elf/spu.h"
 #include "elf/tic6x.h"
+#include "elf/tilegx.h"
+#include "elf/tilepro.h"
 #include "elf/v850.h"
 #include "elf/vax.h"
 #include "elf/x86-64.h"
@@ -286,6 +288,12 @@ print_mode;
     }                                          \
   while (0)
 \f
+/* Retrieve NMEMB structures, each SIZE bytes long from FILE starting at OFFSET.
+   Put the retrieved data into VAR, if it is not NULL.  Otherwise allocate a buffer
+   using malloc and fill that.  In either case return the pointer to the start of
+   the retrieved data or NULL if something went wrong.  If something does go wrong
+   emit an error message using REASON as part of the context.  */
+
 static void *
 get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb,
          const char * reason)
@@ -592,11 +600,14 @@ guess_is_rela (unsigned int e_machine)
     case EM_SPARCV9:
     case EM_SPU:
     case EM_TI_C6000:
+    case EM_TILEGX:
+    case EM_TILEPRO:
     case EM_V850:
     case EM_CYGNUS_V850:
     case EM_VAX:
     case EM_X86_64:
     case EM_L1OM:
+    case EM_K1OM:
     case EM_XSTORMY16:
     case EM_XTENSA:
     case EM_XTENSA_OLD:
@@ -1128,6 +1139,7 @@ dump_relocations (FILE * file,
 
        case EM_X86_64:
        case EM_L1OM:
+       case EM_K1OM:
          rtype = elf_x86_64_reloc_type (type);
          break;
 
@@ -1213,6 +1225,14 @@ dump_relocations (FILE * file,
        case EM_TI_C6000:
          rtype = elf_tic6x_reloc_type (type);
          break;
+
+       case EM_TILEGX:
+         rtype = elf_tilegx_reloc_type (type);
+         break;
+
+       case EM_TILEPRO:
+         rtype = elf_tilepro_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -1313,7 +1333,8 @@ dump_relocations (FILE * file,
                               && psym->st_shndx == SHN_MIPS_SUNDEFINED)
                        sec_name = "SUNDEF";
                      else if ((elf_header.e_machine == EM_X86_64
-                               || elf_header.e_machine == EM_L1OM)
+                               || elf_header.e_machine == EM_L1OM
+                               || elf_header.e_machine == EM_K1OM)
                               && psym->st_shndx == SHN_X86_64_LCOMMON)
                        sec_name = "LARGE_COMMON";
                      else if (elf_header.e_machine == EM_IA_64
@@ -1881,6 +1902,7 @@ get_machine_name (unsigned e_machine)
     case EM_PRISM:             return "Vitesse Prism";
     case EM_X86_64:            return "Advanced Micro Devices X86-64";
     case EM_L1OM:              return "Intel L1OM";
+    case EM_K1OM:              return "Intel K1OM";
     case EM_S390_OLD:
     case EM_S390:              return "IBM S/390";
     case EM_SCORE:             return "SUNPLUS S+Core";
@@ -1959,6 +1981,7 @@ get_machine_name (unsigned e_machine)
     case EM_STM8:              return "STMicroeletronics STM8 8-bit microcontroller";
     case EM_TILE64:            return "Tilera TILE64 multicore architecture family";
     case EM_TILEPRO:           return "Tilera TILEPro multicore architecture family";
+    case EM_TILEGX:            return "Tilera TILE-Gx multicore architecture family";
     case EM_CUDA:              return "NVIDIA CUDA architecture";
     default:
       snprintf (buff, sizeof (buff), _("<unknown>: 0x%x"), e_machine);
@@ -2405,6 +2428,9 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
          if (e_flags & EF_MIPS_ARCH_ASE_M16)
            strcat (buf, ", mips16");
 
+         if (e_flags & EF_MIPS_ARCH_ASE_MICROMIPS)
+           strcat (buf, ", micromips");
+
          switch ((e_flags & EF_MIPS_ARCH))
            {
            case E_MIPS_ARCH_1: strcat (buf, ", mips1"); break;
@@ -2593,8 +2619,7 @@ get_osabi_name (unsigned int osabi)
     case ELFOSABI_NONE:                return "UNIX - System V";
     case ELFOSABI_HPUX:                return "UNIX - HP-UX";
     case ELFOSABI_NETBSD:      return "UNIX - NetBSD";
-    case ELFOSABI_LINUX:       return "UNIX - Linux";
-    case ELFOSABI_HURD:                return "GNU/Hurd";
+    case ELFOSABI_GNU:         return "UNIX - GNU";
     case ELFOSABI_SOLARIS:     return "UNIX - Solaris";
     case ELFOSABI_AIX:         return "UNIX - AIX";
     case ELFOSABI_IRIX:                return "UNIX - IRIX";
@@ -3025,6 +3050,7 @@ get_section_type_name (unsigned int sh_type)
              break;
            case EM_X86_64:
            case EM_L1OM:
+           case EM_K1OM:
              result = get_x86_64_section_type_name (sh_type);
              break;
            case EM_ARM:
@@ -3065,7 +3091,9 @@ get_section_type_name (unsigned int sh_type)
       else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER))
        sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER);
       else
-       snprintf (buff, sizeof (buff), _("<unknown>: %x"), sh_type);
+       /* This message is probably going to be displayed in a 15
+          character wide field, so put the hex value first.  */
+       snprintf (buff, sizeof (buff), _("%08x: <unknown>"), sh_type);
 
       return buff;
     }
@@ -3073,6 +3101,8 @@ get_section_type_name (unsigned int sh_type)
 
 #define OPTION_DEBUG_DUMP      512
 #define OPTION_DYN_SYMS                513
+#define OPTION_DWARF_DEPTH     514
+#define OPTION_DWARF_START     515
 
 static struct option options[] =
 {
@@ -3106,6 +3136,9 @@ static struct option options[] =
 #endif
   {"debug-dump",       optional_argument, 0, OPTION_DEBUG_DUMP},
 
+  {"dwarf-depth",      required_argument, 0, OPTION_DWARF_DEPTH},
+  {"dwarf-start",      required_argument, 0, OPTION_DWARF_START},
+
   {"version",         no_argument, 0, 'v'},
   {"wide",            no_argument, 0, 'W'},
   {"help",            no_argument, 0, 'H'},
@@ -3149,6 +3182,10 @@ usage (FILE * stream)
                =frames-interp,=str,=loc,=Ranges,=pubtypes,\n\
                =gdb_index,=trace_info,=trace_abbrev,=trace_aranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
+  fprintf (stream, _("\
+  --dwarf-depth=N        Do not display DIEs at depth N or greater\n\
+  --dwarf-start=N        Display DIEs starting with N, at the same depth\n\
+                         or deeper\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stream, _("\
   -i --instruction-dump=<number|name>\n\
@@ -3355,6 +3392,20 @@ parse_args (int argc, char ** argv)
              dwarf_select_sections_by_names (optarg);
            }
          break;
+       case OPTION_DWARF_DEPTH:
+         {
+           char *cp;
+
+           dwarf_cutoff_level = strtoul (optarg, & cp, 0);
+         }
+         break;
+       case OPTION_DWARF_START:
+         {
+           char *cp;
+
+           dwarf_start_die = strtoul (optarg, & cp, 0);
+         }
+         break;
        case OPTION_DYN_SYMS:
          do_dyn_syms++;
          break;
@@ -4251,6 +4302,7 @@ get_elf_section_flags (bfd_vma sh_flags)
                case EM_486:
                case EM_X86_64:
                case EM_L1OM:
+               case EM_K1OM:
                case EM_OLD_SPARCV9:
                case EM_SPARC32PLUS:
                case EM_SPARCV9:
@@ -4302,7 +4354,8 @@ get_elf_section_flags (bfd_vma sh_flags)
 
            default:
              if ((elf_header.e_machine == EM_X86_64
-                  || elf_header.e_machine == EM_L1OM)
+                  || elf_header.e_machine == EM_L1OM
+                  || elf_header.e_machine == EM_K1OM)
                  && flag == SHF_X86_64_LARGE)
                *p = 'l';
              else if (flag & SHF_MASKOS)
@@ -4525,7 +4578,7 @@ process_section_headers (FILE * file)
          dynamic_strings = (char *) get_data (NULL, file, section->sh_offset,
                                                1, section->sh_size,
                                                _("dynamic strings"));
-         dynamic_strings_length = section->sh_size;
+         dynamic_strings_length = dynamic_strings == NULL ? 0 : section->sh_size;
        }
       else if (section->sh_type == SHT_SYMTAB_SHNDX)
        {
@@ -4567,6 +4620,7 @@ process_section_headers (FILE * file)
              || (do_debug_ranges   && streq (name, "ranges"))
              || (do_debug_frames   && streq (name, "frame"))
              || (do_debug_macinfo  && streq (name, "macinfo"))
+             || (do_debug_macinfo  && streq (name, "macro"))
              || (do_debug_str      && streq (name, "str"))
              || (do_debug_loc      && streq (name, "loc"))
              )
@@ -4692,6 +4746,7 @@ process_section_headers (FILE * file)
                case EM_486:
                case EM_X86_64:
                case EM_L1OM:
+               case EM_K1OM:
                case EM_OLD_SPARCV9:
                case EM_SPARC32PLUS:
                case EM_SPARCV9:
@@ -4820,7 +4875,8 @@ process_section_headers (FILE * file)
   if (!do_section_details)
     {
       if (elf_header.e_machine == EM_X86_64
-         || elf_header.e_machine == EM_L1OM)
+         || elf_header.e_machine == EM_L1OM
+         || elf_header.e_machine == EM_K1OM)
        printf (_("Key to Flags:\n\
   W (write), A (alloc), X (execute), M (merge), S (strings), l (large)\n\
   I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)\n\
@@ -5006,6 +5062,8 @@ process_section_groups (FILE * file)
          start = (unsigned char *) get_data (NULL, file, section->sh_offset,
                                               1, section->sh_size,
                                               _("section data"));
+         if (start == NULL)
+           continue;
 
          indices = start;
          size = (section->sh_size / section->sh_entsize) - 1;
@@ -5711,6 +5769,7 @@ ia64_process_unwind (FILE * file)
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
          strsec = section_headers + sec->sh_link;
+         assert (aux.strtab == NULL);
          aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset,
                                           1, strsec->sh_size,
                                           _("string table"));
@@ -5793,11 +5852,11 @@ ia64_process_unwind (FILE * file)
        }
       else
        {
-         aux.info_size = sec->sh_size;
          aux.info_addr = sec->sh_addr;
          aux.info = (unsigned char *) get_data (NULL, file, sec->sh_offset, 1,
-                                                 aux.info_size,
+                                                 sec->sh_size,
                                                  _("unwind info"));
+         aux.info_size = aux.info == NULL ? 0 : sec->sh_size;
 
          printf (_("\nUnwind section "));
 
@@ -6124,6 +6183,7 @@ hppa_process_unwind (FILE * file)
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
          strsec = section_headers + sec->sh_link;
+         assert (aux.strtab == NULL);
          aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset,
                                           1, strsec->sh_size,
                                           _("string table"));
@@ -6250,7 +6310,6 @@ arm_section_get_word (struct arm_unw_aux_info *aux,
       arm_sec->sec = sec;
       arm_sec->data = get_data (NULL, aux->file, sec->sh_offset, 1,
                                sec->sh_size, _("unwind data"));
-
       arm_sec->rela = NULL;
       arm_sec->nrelas = 0;
 
@@ -6311,12 +6370,26 @@ arm_section_get_word (struct arm_unw_aux_info *aux,
       if (rp->r_offset < word_offset)
        continue;
 
-      relname = elf_arm_reloc_type (ELF32_R_TYPE (rp->r_info));
+      switch (elf_header.e_machine)
+       {
+       case EM_ARM:
+         relname = elf_arm_reloc_type (ELF32_R_TYPE (rp->r_info));
+         break;
+
+       case EM_TI_C6000:
+         relname = elf_tic6x_reloc_type (ELF32_R_TYPE (rp->r_info));
+         break;
+
+       default:
+           abort();
+       }
 
-      if (streq (relname, "R_ARM_NONE"))
+      if (streq (relname, "R_ARM_NONE")
+         || streq (relname, "R_C6000_NONE"))
        continue;
 
-      if (! streq (relname, "R_ARM_PREL31"))
+      if (!(streq (relname, "R_ARM_PREL31")
+           || streq (relname, "R_C6000_PREL31")))
        {
          warn (_("Skipping unexpected relocation type %s\n"), relname);
          continue;
@@ -6336,6 +6409,9 @@ arm_section_get_word (struct arm_unw_aux_info *aux,
       offset += sym->st_value;
       prelval = offset - (arm_sec->sec->sh_addr + rp->r_offset);
 
+      if (streq (relname, "R_C6000_PREL31"))
+       prelval >>= 1;
+
       word = (word & ~ (bfd_vma) 0x7fffffff) | (prelval & 0x7fffffff);
       addr->section = sym->st_shndx;
       addr->offset = offset;
@@ -6348,15 +6424,26 @@ arm_section_get_word (struct arm_unw_aux_info *aux,
   return 1;
 }
 
+static const char *tic6x_unwind_regnames[16] = {
+    "A15", "B15", "B14", "B13", "B12", "B11", "B10", "B3", 
+    "A14", "A13", "A12", "A11", "A10", 
+    "[invalid reg 13]", "[invalid reg 14]", "[invalid reg 15]"};
+
 static void
-decode_arm_unwind (struct arm_unw_aux_info *aux,
-                  unsigned int word, unsigned int remaining,
-                  bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
-                  struct arm_section *data_arm_sec)
+decode_tic6x_unwind_regmask (unsigned int mask)
 {
-  int per_index;
-  unsigned int more_words;
-  struct absaddr addr;
+  int i;
+
+  for (i = 12; mask; mask >>= 1, i--)
+    {
+      if (mask & 1)
+       {
+         fputs (tic6x_unwind_regnames[i], stdout);
+         if (mask > 1)
+           fputs (", ", stdout);
+       }
+    }
+}
 
 #define ADVANCE                                                        \
   if (remaining == 0 && more_words)                            \
@@ -6384,77 +6471,14 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
     }                                  \
   printf ("0x%02x ", OP)
 
-  if (remaining == 0)
-    {
-      /* Fetch the first word.  */
-      if (!arm_section_get_word (aux, data_arm_sec, data_sec, data_offset,
-                                &word, &addr))
-       return;
-      remaining = 4;
-    }
-
-  if ((word & 0x80000000) == 0)
-    {
-      /* Expand prel31 for personality routine.  */
-      bfd_vma fn;
-      const char *procname;
-
-      fn = word;
-      if (fn & 0x40000000)
-       fn |= ~ (bfd_vma) 0x7fffffff;
-      fn = fn + data_sec->sh_addr + data_offset;
-
-      printf (_("  Personality routine: "));
-      procname = arm_print_vma_and_name (aux, fn, addr);
-      fputc ('\n', stdout);
-
-      /* The GCC personality routines use the standard compact
-        encoding, starting with one byte giving the number of
-        words.  */
-      if (procname != NULL
-         && (const_strneq (procname, "__gcc_personality_v0")
-             || const_strneq (procname, "__gxx_personality_v0")
-             || const_strneq (procname, "__gcj_personality_v0")
-             || const_strneq (procname, "__gnu_objc_personality_v0")))
-       {
-         remaining = 0;
-         more_words = 1;
-         ADVANCE;
-         if (!remaining)
-           {
-             printf (_("  [Truncated data]\n"));
-             return;
-           }
-         more_words = word >> 24;
-         word <<= 8;
-         remaining--;
-       }
-      else
-       return;
-    }
-  else
-    {
-      per_index = (word >> 24) & 0x7f;
-      if (per_index != 0 && per_index != 1 && per_index != 2)
-       {
-         printf (_("  [reserved compact index %d]\n"), per_index);
-         return;
-       }
-
-      printf (_("  Compact model %d\n"), per_index);
-      if (per_index == 0)
-       {
-         more_words = 0;
-         word <<= 8;
-         remaining--;
-       }
-      else
-       {
-         more_words = (word >> 16) & 0xff;
-         word <<= 16;
-         remaining -= 2;
-       }
-    }
+static void
+decode_arm_unwind_bytecode (struct arm_unw_aux_info *aux,
+                           unsigned int word, unsigned int remaining,
+                           unsigned int more_words,
+                           bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
+                           struct arm_section *data_arm_sec)
+{
+  struct absaddr addr;
 
   /* Decode the unwinding instructions.  */
   while (1)
@@ -6652,6 +6676,271 @@ decode_arm_unwind (struct arm_unw_aux_info *aux,
        printf (_("     [unsupported opcode]"));
       printf ("\n");
     }
+}
+
+static void
+decode_tic6x_unwind_bytecode (struct arm_unw_aux_info *aux,
+                           unsigned int word, unsigned int remaining,
+                           unsigned int more_words,
+                           bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
+                           struct arm_section *data_arm_sec)
+{
+  struct absaddr addr;
+
+  /* Decode the unwinding instructions.  */
+  while (1)
+    {
+      unsigned int op, op2;
+
+      ADVANCE;
+      if (remaining == 0)
+       break;
+      remaining--;
+      op = word >> 24;
+      word <<= 8;
+
+      printf (_("  0x%02x "), op);
+
+      if ((op & 0xc0) == 0x00)
+       {
+         int offset = ((op & 0x3f) << 3) + 8;
+         printf (_("     sp = sp + %d"), offset);
+       }
+      else if ((op & 0xc0) == 0x80)
+       {
+         GET_OP (op2);
+         if (op == 0x80 && op2 == 0)
+           printf (_("Refuse to unwind"));
+         else
+           {
+             unsigned int mask = ((op & 0x1f) << 8) | op2;
+             if (op & 0x20)
+               printf ("pop compact {");
+             else
+               printf ("pop {");
+
+             decode_tic6x_unwind_regmask (mask);
+             printf("}");
+           }
+       }
+      else if ((op & 0xf0) == 0xc0)
+       {
+         unsigned int reg;
+         unsigned int nregs;
+         unsigned int i;
+         const char *name;
+         struct {
+             unsigned int offset;
+             unsigned int reg;
+         } regpos[16];
+
+         /* Scan entire instruction first so that GET_OP output is not
+            interleaved with disassembly.  */
+         nregs = 0;
+         for (i = 0; nregs < (op & 0xf); i++)
+           {
+             GET_OP (op2);
+             reg = op2 >> 4;
+             if (reg != 0xf)
+               {
+                 regpos[nregs].offset = i * 2;
+                 regpos[nregs].reg = reg;
+                 nregs++;
+               }
+
+             reg = op2 & 0xf;
+             if (reg != 0xf)
+               {
+                 regpos[nregs].offset = i * 2 + 1;
+                 regpos[nregs].reg = reg;
+                 nregs++;
+               }
+           }
+
+         printf (_("pop frame {"));
+         reg = nregs - 1;
+         for (i = i * 2; i > 0; i--)
+           {
+             if (regpos[reg].offset == i - 1)
+               {
+                 name = tic6x_unwind_regnames[regpos[reg].reg];
+                 if (reg > 0)
+                   reg--;
+               }
+             else
+               name = _("[pad]");
+
+             fputs (name, stdout);
+             if (i > 1)
+               printf (", ");
+           }
+
+         printf ("}");
+       }
+      else if (op == 0xd0)
+       printf ("     MOV FP, SP");
+      else if (op == 0xd1)
+       printf ("     __c6xabi_pop_rts");
+      else if (op == 0xd2)
+       {
+         unsigned char buf[9];
+         unsigned int i, len;
+         unsigned long offset;
+         for (i = 0; i < sizeof (buf); i++)
+           {
+             GET_OP (buf[i]);
+             if ((buf[i] & 0x80) == 0)
+               break;
+           }
+         assert (i < sizeof (buf));
+         offset = read_uleb128 (buf, &len);
+         assert (len == i + 1);
+         offset = offset * 8 + 0x408;
+         printf (_("sp = sp + %ld"), offset);
+       }
+      else if ((op & 0xf0) == 0xe0)
+       {
+         if ((op & 0x0f) == 7)
+           printf ("     RETURN");
+         else
+           printf ("     MV %s, B3", tic6x_unwind_regnames[op & 0x0f]);
+       }
+      else
+       {
+         printf (_("     [unsupported opcode]"));
+       }
+      putchar ('\n');
+    }
+}
+
+static bfd_vma
+expand_prel31 (bfd_vma word, bfd_vma where)
+{
+  bfd_vma offset;
+
+  offset = word & 0x7fffffff;
+  if (offset & 0x40000000)
+    offset |= ~ (bfd_vma) 0x7fffffff;
+
+  if (elf_header.e_machine == EM_TI_C6000)
+    offset <<= 1;
+
+  return offset + where;
+}
+
+static void
+decode_arm_unwind (struct arm_unw_aux_info *aux,
+                  unsigned int word, unsigned int remaining,
+                  bfd_vma data_offset, Elf_Internal_Shdr *data_sec,
+                  struct arm_section *data_arm_sec)
+{
+  int per_index;
+  unsigned int more_words = 0;
+  struct absaddr addr;
+
+  if (remaining == 0)
+    {
+      /* Fetch the first word.  */
+      if (!arm_section_get_word (aux, data_arm_sec, data_sec, data_offset,
+                                &word, &addr))
+       return;
+      remaining = 4;
+    }
+
+  if ((word & 0x80000000) == 0)
+    {
+      /* Expand prel31 for personality routine.  */
+      bfd_vma fn;
+      const char *procname;
+
+      fn = expand_prel31 (word, data_sec->sh_addr + data_offset);
+      printf (_("  Personality routine: "));
+      procname = arm_print_vma_and_name (aux, fn, addr);
+      fputc ('\n', stdout);
+
+      /* The GCC personality routines use the standard compact
+        encoding, starting with one byte giving the number of
+        words.  */
+      if (procname != NULL
+         && (const_strneq (procname, "__gcc_personality_v0")
+             || const_strneq (procname, "__gxx_personality_v0")
+             || const_strneq (procname, "__gcj_personality_v0")
+             || const_strneq (procname, "__gnu_objc_personality_v0")))
+       {
+         remaining = 0;
+         more_words = 1;
+         ADVANCE;
+         if (!remaining)
+           {
+             printf (_("  [Truncated data]\n"));
+             return;
+           }
+         more_words = word >> 24;
+         word <<= 8;
+         remaining--;
+         per_index = -1;
+       }
+      else
+       return;
+    }
+  else
+    {
+      
+      per_index = (word >> 24) & 0x7f;
+      printf (_("  Compact model %d\n"), per_index);
+      if (per_index == 0)
+       {
+         more_words = 0;
+         word <<= 8;
+         remaining--;
+       }
+      else if (per_index < 3)
+       {
+         more_words = (word >> 16) & 0xff;
+         word <<= 16;
+         remaining -= 2;
+       }
+    }
+
+  switch (elf_header.e_machine)
+    {
+    case EM_ARM:
+      if (per_index < 3)
+       {
+         decode_arm_unwind_bytecode (aux, word, remaining, more_words,
+                                     data_offset, data_sec, data_arm_sec);
+       }
+      else
+       printf ("  [reserved]\n");
+      break;
+
+    case EM_TI_C6000:
+      if (per_index < 3)
+       {
+         decode_tic6x_unwind_bytecode (aux, word, remaining, more_words,
+                                     data_offset, data_sec, data_arm_sec);
+       }
+      else if (per_index < 5)
+       {
+         if (((word >> 17) & 0x7f) == 0x7f)
+           printf (_("  Restore stack from frame pointer\n"));
+         else
+           printf (_("  Stack increment %d\n"), (word >> 14) & 0x1fc);
+         printf (_("  Registers restored: "));
+         if (per_index == 4)
+           printf (" (compact) ");
+         decode_tic6x_unwind_regmask ((word >> 4) & 0x1fff);
+         putchar ('\n');
+         printf (_("  Return register: %s\n"),
+                 tic6x_unwind_regnames[word & 0xf]);
+       }
+      else
+       printf ("  [reserved]\n");
+      break;
+
+    default:
+      abort ();
+    }
 
   /* Decode the descriptors.  Not implemented.  */
 }
@@ -6684,10 +6973,7 @@ dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
          return;
        }
 
-      fn = exidx_fn & 0x7fffffff;
-      if (fn & 0x40000000)
-       fn |= ~ (bfd_vma) 0x7fffffff;
-      fn = fn + exidx_sec->sh_addr + 8 * i;
+      fn = expand_prel31 (exidx_fn, exidx_sec->sh_addr + 8 * i);
 
       arm_print_vma_and_name (aux, fn, entry_addr);
       fputs (": ", stdout);
@@ -6709,10 +6995,7 @@ dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
          Elf_Internal_Shdr *table_sec;
 
          fputs ("@", stdout);
-         table = exidx_entry;
-         if (table & 0x40000000)
-           table |= ~ (bfd_vma) 0x7fffffff;
-         table = table + exidx_sec->sh_addr + 8 * i + 4;
+         table = expand_prel31 (exidx_entry, exidx_sec->sh_addr + 8 * i + 4);
          print_vma (table, PREFIX_HEX);
          printf ("\n");
 
@@ -6746,6 +7029,7 @@ dump_arm_unwind (struct arm_unw_aux_info *aux, Elf_Internal_Shdr *exidx_sec)
   arm_free_section (&extab_arm_sec);
 }
 
+/* Used for both ARM and C6X unwinding tables.  */
 static int
 arm_process_unwind (FILE *file)
 {
@@ -6754,10 +7038,25 @@ arm_process_unwind (FILE *file)
   Elf_Internal_Shdr *strsec;
   Elf_Internal_Shdr *sec;
   unsigned long i;
+  unsigned int sec_type;
 
   memset (& aux, 0, sizeof (aux));
   aux.file = file;
 
+  switch (elf_header.e_machine)
+    {
+    case EM_ARM:
+      sec_type = SHT_ARM_EXIDX;
+      break;
+
+    case EM_TI_C6000:
+      sec_type = SHT_C6000_UNWIND;
+      break;
+
+    default:
+       abort();
+    }
+
   if (string_table == NULL)
     return 1;
 
@@ -6769,11 +7068,12 @@ arm_process_unwind (FILE *file)
          aux.symtab = GET_ELF_SYMBOLS (file, sec);
 
          strsec = section_headers + sec->sh_link;
+         assert (aux.strtab == NULL);
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
                                 1, strsec->sh_size, _("string table"));
          aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0;
        }
-      else if (sec->sh_type == SHT_ARM_EXIDX)
+      else if (sec->sh_type == sec_type)
        unwsec = sec;
     }
 
@@ -6782,7 +7082,7 @@ arm_process_unwind (FILE *file)
 
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
-      if (sec->sh_type == SHT_ARM_EXIDX)
+      if (sec->sh_type == sec_type)
        {
          printf (_("\nUnwind table index '%s' at offset 0x%lx contains %lu entries:\n"),
                  SECTION_NAME (sec),
@@ -6813,6 +7113,7 @@ process_unwind (FILE * file)
     { EM_ARM, arm_process_unwind },
     { EM_IA_64, ia64_process_unwind },
     { EM_PARISC, hppa_process_unwind },
+    { EM_TI_C6000, arm_process_unwind },
     { 0, 0 }
   };
   int i;
@@ -7277,7 +7578,7 @@ process_dynamic_section (FILE * file)
          dynamic_strings = (char *) get_data (NULL, file, offset, 1,
                                                str_tab_len,
                                                _("dynamic string table"));
-         dynamic_strings_length = str_tab_len;
+         dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len;
          break;
        }
     }
@@ -7815,9 +8116,9 @@ process_version_sections (FILE * file)
            edefs = (Elf_External_Verdef *)
                 get_data (NULL, file, section->sh_offset, 1,section->sh_size,
                           _("version definition section"));
-           endbuf = (char *) edefs + section->sh_size;
            if (!edefs)
              break;
+           endbuf = (char *) edefs + section->sh_size;
 
            for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
              {
@@ -7934,9 +8235,9 @@ process_version_sections (FILE * file)
                                                        section->sh_offset, 1,
                                                        section->sh_size,
                                                        _("version need section"));
-           endbuf = (char *) eneed + section->sh_size;
            if (!eneed)
              break;
+           endbuf = (char *) eneed + section->sh_size;
 
            for (idx = cnt = 0; cnt < section->sh_info; ++cnt)
              {
@@ -8152,9 +8453,10 @@ process_version_sections (FILE * file)
                              Elf_External_Vernaux evna;
                              unsigned long a_off;
 
-                             get_data (&evn, file, offset, sizeof (evn), 1,
-                                       _("version need"));
-
+                             if (get_data (&evn, file, offset, sizeof (evn), 1,
+                                           _("version need")) == NULL)
+                               break;
+                             
                              ivn.vn_aux  = BYTE_GET (evn.vn_aux);
                              ivn.vn_next = BYTE_GET (evn.vn_next);
 
@@ -8162,11 +8464,17 @@ process_version_sections (FILE * file)
 
                              do
                                {
-                                 get_data (&evna, file, a_off, sizeof (evna),
-                                           1, _("version need aux (2)"));
-
-                                 ivna.vna_next  = BYTE_GET (evna.vna_next);
-                                 ivna.vna_other = BYTE_GET (evna.vna_other);
+                                 if (get_data (&evna, file, a_off, sizeof (evna),
+                                               1, _("version need aux (2)")) == NULL)
+                                   {
+                                     ivna.vna_next  = 0;
+                                     ivna.vna_other = 0;
+                                   }
+                                 else
+                                   {
+                                     ivna.vna_next  = BYTE_GET (evna.vna_next);
+                                     ivna.vna_other = BYTE_GET (evna.vna_other);
+                                   }
 
                                  a_off += ivna.vna_next;
                                }
@@ -8207,11 +8515,17 @@ process_version_sections (FILE * file)
 
                          do
                            {
-                             get_data (&evd, file, offset, sizeof (evd), 1,
-                                       _("version def"));
-
-                             ivd.vd_next = BYTE_GET (evd.vd_next);
-                             ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
+                             if (get_data (&evd, file, offset, sizeof (evd), 1,
+                                           _("version def")) == NULL)
+                               {
+                                 ivd.vd_next = 0;
+                                 ivd.vd_ndx  = 0;
+                               }
+                             else
+                               {
+                                 ivd.vd_next = BYTE_GET (evd.vd_next);
+                                 ivd.vd_ndx  = BYTE_GET (evd.vd_ndx);
+                               }
 
                              offset += ivd.vd_next;
                            }
@@ -8225,10 +8539,11 @@ process_version_sections (FILE * file)
 
                              ivd.vd_aux = BYTE_GET (evd.vd_aux);
 
-                             get_data (&evda, file,
-                                       offset - ivd.vd_next + ivd.vd_aux,
-                                       sizeof (evda), 1,
-                                       _("version def aux"));
+                             if (get_data (&evda, file,
+                                           offset - ivd.vd_next + ivd.vd_aux,
+                                           sizeof (evda), 1,
+                                           _("version def aux")) == NULL)
+                               break;
 
                              ivda.vda_name = BYTE_GET (evda.vda_name);
 
@@ -8284,8 +8599,8 @@ get_symbol_binding (unsigned int binding)
       else if (binding >= STB_LOOS && binding <= STB_HIOS)
        {
          if (binding == STB_GNU_UNIQUE
-             && (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX
-                 /* GNU/Linux is still using the default value 0.  */
+             && (elf_header.e_ident[EI_OSABI] == ELFOSABI_GNU
+                 /* GNU is still using the default value 0.  */
                  || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE))
            return "UNIQUE";
          snprintf (buff, sizeof (buff), _("<OS specific>: %d"), binding);
@@ -8337,8 +8652,8 @@ get_symbol_type (unsigned int type)
            }
 
          if (type == STT_GNU_IFUNC
-             && (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX
-                 /* GNU/Linux is still using the default value 0.  */
+             && (elf_header.e_ident[EI_OSABI] == ELFOSABI_GNU
+                 /* GNU is still using the default value 0.  */
                  || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE))
            return "IFUNC";
 
@@ -8368,11 +8683,20 @@ get_mips_symbol_other (unsigned int other)
 {
   switch (other)
     {
-    case STO_OPTIONAL:  return "OPTIONAL";
-    case STO_MIPS16:    return "MIPS16";
-    case STO_MIPS_PLT: return "MIPS PLT";
-    case STO_MIPS_PIC: return "MIPS PIC";
-    default:           return NULL;
+    case STO_OPTIONAL:
+      return "OPTIONAL";
+    case STO_MIPS_PLT:
+      return "MIPS PLT";
+    case STO_MIPS_PIC:
+      return "MIPS PIC";
+    case STO_MICROMIPS:
+      return "MICROMIPS";
+    case STO_MICROMIPS | STO_MIPS_PIC:
+      return "MICROMIPS, MIPS PIC";
+    case STO_MIPS16:
+      return "MIPS16";
+    default:
+      return NULL;
     }
 }
 
@@ -8481,7 +8805,8 @@ get_symbol_index_type (unsigned int type)
          && elf_header.e_ident[EI_OSABI] == ELFOSABI_HPUX)
        return "ANSI_COM";
       else if ((elf_header.e_machine == EM_X86_64
-               || elf_header.e_machine == EM_L1OM)
+               || elf_header.e_machine == EM_L1OM
+               || elf_header.e_machine == EM_K1OM)
               && type == SHN_X86_64_LCOMMON)
        return "LARGE_COM";
       else if ((type == SHN_MIPS_SCOMMON
@@ -8889,8 +9214,8 @@ process_symbol_table (FILE * file)
              print_symbol (25, psym->st_name < strtab_size
                            ? strtab + psym->st_name : _("<corrupt>"));
 
-             if (section->sh_type == SHT_DYNSYM &&
-                 version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
+             if (section->sh_type == SHT_DYNSYM
+                 && version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
                {
                  unsigned char data[2];
                  unsigned short vers_data;
@@ -8902,8 +9227,9 @@ process_symbol_table (FILE * file)
                    (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
                     sizeof data + si * sizeof (vers_data));
 
-                 get_data (&data, file, offset + si * sizeof (vers_data),
-                           sizeof (data), 1, _("version data"));
+                 if (get_data (&data, file, offset + si * sizeof (vers_data),
+                               sizeof (data), 1, _("version data")) == NULL)
+                   break;
 
                  vers_data = byte_get (data, 2);
 
@@ -8931,8 +9257,14 @@ process_symbol_table (FILE * file)
                            {
                              unsigned long vna_off;
 
-                             get_data (&evn, file, offset, sizeof (evn), 1,
-                                       _("version need"));
+                             if (get_data (&evn, file, offset, sizeof (evn), 1,
+                                           _("version need")) == NULL)
+                               {
+                                 ivna.vna_next = 0;
+                                 ivna.vna_other = 0;
+                                 ivna.vna_name = 0;
+                                 break;
+                               }
 
                              ivn.vn_aux  = BYTE_GET (evn.vn_aux);
                              ivn.vn_next = BYTE_GET (evn.vn_next);
@@ -8943,13 +9275,20 @@ process_symbol_table (FILE * file)
                                {
                                  Elf_External_Vernaux evna;
 
-                                 get_data (&evna, file, vna_off,
-                                           sizeof (evna), 1,
-                                           _("version need aux (3)"));
-
-                                 ivna.vna_other = BYTE_GET (evna.vna_other);
-                                 ivna.vna_next  = BYTE_GET (evna.vna_next);
-                                 ivna.vna_name  = BYTE_GET (evna.vna_name);
+                                 if (get_data (&evna, file, vna_off,
+                                               sizeof (evna), 1,
+                                               _("version need aux (3)")) == NULL)
+                                   {
+                                     ivna.vna_next = 0;
+                                     ivna.vna_other = 0;
+                                     ivna.vna_name = 0;
+                                   }
+                                 else
+                                   {
+                                     ivna.vna_other = BYTE_GET (evna.vna_other);
+                                     ivna.vna_next  = BYTE_GET (evna.vna_next);
+                                     ivna.vna_name  = BYTE_GET (evna.vna_name);
+                                   }
 
                                  vna_off += ivna.vna_next;
                                }
@@ -8996,12 +9335,19 @@ process_symbol_table (FILE * file)
                                {
                                  Elf_External_Verdef evd;
 
-                                 get_data (&evd, file, off, sizeof (evd),
-                                           1, _("version def"));
-
-                                 ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
-                                 ivd.vd_aux = BYTE_GET (evd.vd_aux);
-                                 ivd.vd_next = BYTE_GET (evd.vd_next);
+                                 if (get_data (&evd, file, off, sizeof (evd),
+                                               1, _("version def")) == NULL)
+                                   {
+                                     ivd.vd_ndx = 0;
+                                     ivd.vd_aux = 0;
+                                     ivd.vd_next = 0;
+                                   }
+                                 else
+                                   {
+                                     ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
+                                     ivd.vd_aux = BYTE_GET (evd.vd_aux);
+                                     ivd.vd_next = BYTE_GET (evd.vd_next);
+                                   }
 
                                  off += ivd.vd_next;
                                }
@@ -9011,8 +9357,9 @@ process_symbol_table (FILE * file)
                              off -= ivd.vd_next;
                              off += ivd.vd_aux;
 
-                             get_data (&evda, file, off, sizeof (evda),
-                                       1, _("version def aux"));
+                             if (get_data (&evda, file, off, sizeof (evda),
+                                           1, _("version def aux")) == NULL)
+                               break;
 
                              ivda.vda_name = BYTE_GET (evda.vda_name);
 
@@ -9421,6 +9768,10 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 6; /* R_SPU_ADDR32 */
     case EM_TI_C6000:
       return reloc_type == 1; /* R_C6000_ABS32.  */
+    case EM_TILEGX:
+      return reloc_type == 2; /* R_TILEGX_32.  */
+    case EM_TILEPRO:
+      return reloc_type == 1; /* R_TILEPRO_32.  */
     case EM_CYGNUS_V850:
     case EM_V850:
       return reloc_type == 6; /* R_V850_ABS32.  */
@@ -9428,6 +9779,7 @@ is_32bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 1; /* R_VAX_32.  */
     case EM_X86_64:
     case EM_L1OM:
+    case EM_K1OM:
       return reloc_type == 10; /* R_X86_64_32.  */
     case EM_XC16X:
     case EM_C166:
@@ -9480,8 +9832,13 @@ is_32bit_pcrel_reloc (unsigned int reloc_type)
       return reloc_type == 6;  /* R_SPARC_DISP32.  */
     case EM_SPU:
       return reloc_type == 13; /* R_SPU_REL32.  */
+    case EM_TILEGX:
+      return reloc_type == 6; /* R_TILEGX_32_PCREL.  */
+    case EM_TILEPRO:
+      return reloc_type == 4; /* R_TILEPRO_32_PCREL.  */
     case EM_X86_64:
     case EM_L1OM:
+    case EM_K1OM:
       return reloc_type == 2;  /* R_X86_64_PC32.  */
     case EM_XTENSA_OLD:
     case EM_XTENSA:
@@ -9518,12 +9875,15 @@ is_64bit_abs_reloc (unsigned int reloc_type)
       return reloc_type == 54; /* R_SPARC_UA64.  */
     case EM_X86_64:
     case EM_L1OM:
+    case EM_K1OM:
       return reloc_type == 1; /* R_X86_64_64.  */
     case EM_S390_OLD:
     case EM_S390:
-      return reloc_type == 22; /* R_S390_64 */
+      return reloc_type == 22; /* R_S390_64.  */
+    case EM_TILEGX:
+      return reloc_type == 1; /* R_TILEGX_64.  */
     case EM_MIPS:
-      return reloc_type == 18; /* R_MIPS_64 */
+      return reloc_type == 18; /* R_MIPS_64 */
     default:
       return FALSE;
     }
@@ -9538,23 +9898,26 @@ is_64bit_pcrel_reloc (unsigned int reloc_type)
   switch (elf_header.e_machine)
     {
     case EM_ALPHA:
-      return reloc_type == 11; /* R_ALPHA_SREL64 */
+      return reloc_type == 11; /* R_ALPHA_SREL64 */
     case EM_IA_64:
-      return reloc_type == 0x4f; /* R_IA64_PCREL64LSB */
+      return reloc_type == 0x4f; /* R_IA64_PCREL64LSB */
     case EM_PARISC:
-      return reloc_type == 72; /* R_PARISC_PCREL64 */
+      return reloc_type == 72; /* R_PARISC_PCREL64 */
     case EM_PPC64:
-      return reloc_type == 44; /* R_PPC64_REL64 */
+      return reloc_type == 44; /* R_PPC64_REL64 */
     case EM_SPARC32PLUS:
     case EM_SPARCV9:
     case EM_SPARC:
-      return reloc_type == 46; /* R_SPARC_DISP64 */
+      return reloc_type == 46; /* R_SPARC_DISP64 */
     case EM_X86_64:
     case EM_L1OM:
-      return reloc_type == 24; /* R_X86_64_PC64 */
+    case EM_K1OM:
+      return reloc_type == 24; /* R_X86_64_PC64.  */
     case EM_S390_OLD:
     case EM_S390:
-      return reloc_type == 23; /* R_S390_PC64 */
+      return reloc_type == 23; /* R_S390_PC64.  */
+    case EM_TILEGX:
+      return reloc_type == 5;  /* R_TILEGX_64_PCREL.  */
     default:
       return FALSE;
     }
@@ -9642,10 +10005,13 @@ is_none_reloc (unsigned int reloc_type)
     case EM_CRIS:    /* R_CRIS_NONE.  */
     case EM_X86_64:  /* R_X86_64_NONE.  */
     case EM_L1OM:    /* R_X86_64_NONE.  */
+    case EM_K1OM:    /* R_X86_64_NONE.  */
     case EM_MN10300: /* R_MN10300_NONE.  */
     case EM_MOXIE:   /* R_MOXIE_NONE.  */
     case EM_M32R:    /* R_M32R_NONE.  */
     case EM_TI_C6000:/* R_C6000_NONE.  */
+    case EM_TILEGX:  /* R_TILEGX_NONE.  */
+    case EM_TILEPRO: /* R_TILEPRO_NONE.  */
     case EM_XC16X:
     case EM_C166:    /* R_XC16X_NONE.  */
       return reloc_type == 0;
@@ -10097,12 +10463,17 @@ load_specific_debug_section (enum dwarf_section_display_enum debug,
 
   snprintf (buf, sizeof (buf), _("%s section data"), section->name);
   section->address = sec->sh_addr;
-  section->size = sec->sh_size;
   section->start = (unsigned char *) get_data (NULL, (FILE *) file,
                                                sec->sh_offset, 1,
                                                sec->sh_size, buf);
-  if (uncompress_section_contents (&section->start, &section->size))
-    sec->sh_size = section->size;
+  if (section->start == NULL)
+    section->size = 0;
+  else
+    {
+      section->size = sec->sh_size;
+      if (uncompress_section_contents (&section->start, &section->size))
+       sec->sh_size = section->size;
+    }
 
   if (section->start == NULL)
     return 0;
@@ -11670,6 +12041,9 @@ process_mips_specific (FILE * file)
       offset = offset_from_vma (file, pltgot, global_end - pltgot);
       data = (unsigned char *) get_data (NULL, file, offset,
                                          global_end - pltgot, 1, _("GOT"));
+      if (data == NULL)
+       return 0;
+
       printf (_("\nPrimary GOT:\n"));
       printf (_(" Canonical gp value: "));
       print_vma (pltgot + 0x7ff0, LONG_HEX);
@@ -11766,6 +12140,9 @@ process_mips_specific (FILE * file)
       offset = offset_from_vma (file, mips_pltgot, end - mips_pltgot);
       data = (unsigned char *) get_data (NULL, file, offset, end - mips_pltgot,
                                          1, _("PLT GOT"));
+      if (data == NULL)
+       return 0;
+
       printf (_("\nPLT GOT:\n\n"));
       printf (_(" Reserved entries:\n"));
       printf (_("  %*s %*s Purpose\n"),
@@ -11844,8 +12221,6 @@ process_gnu_liblist (FILE * file)
          strtab = (char *) get_data (NULL, file, string_sec->sh_offset, 1,
                                       string_sec->sh_size,
                                       _("liblist string table"));
-         strtab_size = string_sec->sh_size;
-
          if (strtab == NULL
              || section->sh_entsize != sizeof (Elf32_External_Lib))
            {
@@ -11853,6 +12228,7 @@ process_gnu_liblist (FILE * file)
              free (strtab);
              break;
            }
+         strtab_size = string_sec->sh_size;
 
          printf (_("\nLibrary list section '%s' contains %lu entries:\n"),
                  SECTION_NAME (section),
@@ -11937,6 +12313,8 @@ get_note_type (unsigned e_type)
        return _("NT_S390_CTRS (s390 control registers)");
       case NT_S390_PREFIX:
        return _("NT_S390_PREFIX (s390 prefix register)");
+      case NT_ARM_VFP:
+       return _("NT_ARM_VFP (arm VFP registers)");
       case NT_PSTATUS:
        return _("NT_PSTATUS (pstatus structure)");
       case NT_FPREGS:
@@ -11990,6 +12368,63 @@ get_gnu_elf_note_type (unsigned e_type)
   return buff;
 }
 
+static int
+print_gnu_note (Elf_Internal_Note *pnote)
+{
+  switch (pnote->type)
+    {
+    case NT_GNU_BUILD_ID:
+      {
+       unsigned long i;
+
+       printf (_("    Build ID: "));
+       for (i = 0; i < pnote->descsz; ++i)
+         printf ("%02x", pnote->descdata[i] & 0xff);
+       printf (_("\n"));
+      }
+      break;
+
+    case NT_GNU_ABI_TAG:
+      {
+       unsigned long os, major, minor, subminor;
+       const char *osname;
+
+       os = byte_get ((unsigned char *) pnote->descdata, 4);
+       major = byte_get ((unsigned char *) pnote->descdata + 4, 4);
+       minor = byte_get ((unsigned char *) pnote->descdata + 8, 4);
+       subminor = byte_get ((unsigned char *) pnote->descdata + 12, 4);
+
+       switch (os)
+         {
+         case GNU_ABI_TAG_LINUX:
+           osname = "Linux";
+           break;
+         case GNU_ABI_TAG_HURD:
+           osname = "Hurd";
+           break;
+         case GNU_ABI_TAG_SOLARIS:
+           osname = "Solaris";
+           break;
+         case GNU_ABI_TAG_FREEBSD:
+           osname = "FreeBSD";
+           break;
+         case GNU_ABI_TAG_NETBSD:
+           osname = "NetBSD";
+           break;
+         default:
+           osname = "Unknown";
+           break;
+         }
+
+       printf (_("    OS: %s, ABI: %ld.%ld.%ld\n"), osname,
+               major, minor, subminor);
+      }
+      break;
+    }
+
+  return 1;
+}
+
 static const char *
 get_netbsd_elfcore_note_type (unsigned e_type)
 {
@@ -12052,6 +12487,61 @@ get_netbsd_elfcore_note_type (unsigned e_type)
   return buff;
 }
 
+static const char *
+get_stapsdt_note_type (unsigned e_type)
+{
+  static char buff[64];
+
+  switch (e_type)
+    {
+    case NT_STAPSDT:
+      return _("NT_STAPSDT (SystemTap probe descriptors)");
+
+    default:
+      break;
+    }
+
+  snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+  return buff;
+}
+
+static int
+print_stapsdt_note (Elf_Internal_Note *pnote)
+{
+  int addr_size = is_32bit_elf ? 4 : 8;
+  char *data = pnote->descdata;
+  char *data_end = pnote->descdata + pnote->descsz;
+  bfd_vma pc, base_addr, semaphore;
+  char *provider, *probe, *arg_fmt;
+
+  pc = byte_get ((unsigned char *) data, addr_size);
+  data += addr_size;
+  base_addr = byte_get ((unsigned char *) data, addr_size);
+  data += addr_size;
+  semaphore = byte_get ((unsigned char *) data, addr_size);
+  data += addr_size;
+
+  provider = data;
+  data += strlen (data) + 1;
+  probe = data;
+  data += strlen (data) + 1;
+  arg_fmt = data;
+  data += strlen (data) + 1;
+
+  printf (_("    Provider: %s\n"), provider);
+  printf (_("    Name: %s\n"), probe);
+  printf (_("    Location: "));
+  print_vma (pc, FULL_HEX);
+  printf (_(", Base: "));
+  print_vma (base_addr, FULL_HEX);
+  printf (_(", Semaphore: "));
+  print_vma (semaphore, FULL_HEX);
+  printf (_("\n"));
+  printf (_("    Arguments: %s\n"), arg_fmt);
+
+  return data == data_end;
+}
+
 static const char *
 get_ia64_vms_note_type (unsigned e_type)
 {
@@ -12198,15 +12688,22 @@ process_note (Elf_Internal_Note * pnote)
     /* VMS/ia64-specific file notes.  */
     nt = get_ia64_vms_note_type (pnote->type);
 
+  else if (const_strneq (pnote->namedata, "stapsdt"))
+    nt = get_stapsdt_note_type (pnote->type);
+
   else
     /* Don't recognize this note name; just use the default set of
        note type strings.  */
     nt = get_note_type (pnote->type);
 
-  printf ("  %-10s\t0x%08lx\t%s\n", name, pnote->descsz, nt);
+  printf ("  %-20s 0x%08lx\t%s\n", name, pnote->descsz, nt);
 
   if (const_strneq (pnote->namedata, "IPF/VMS"))
     return print_ia64_vms_note (pnote);
+  else if (const_strneq (pnote->namedata, "GNU"))
+    return print_gnu_note (pnote);
+  else if (const_strneq (pnote->namedata, "stapsdt"))
+    return print_stapsdt_note (pnote);
   else
     return 1;
 }
@@ -12231,7 +12728,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length)
 
   printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"),
          (unsigned long) offset, (unsigned long) length);
-  printf (_("  Owner\t\tData size\tDescription\n"));
+  printf (_("  %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
 
   while (external < (Elf_External_Note *) ((char *) pnotes + length))
     {
This page took 0.040134 seconds and 4 git commands to generate.