* gdbint.texinfo: Bring the HTML `top' menu into sync with the
[binutils-gdb.git] / binutils / readelf.c
index cfa7c130b24c484a02acf0e66f2c5cd6be0f5aac..3c29c8dff101785b8b00632c79a278ed7348759a 100644 (file)
@@ -119,6 +119,7 @@ int                     do_debug_pubnames;
 int                     do_debug_aranges;
 int                     do_debug_frames;
 int                     do_debug_frames_interp;
+int                    do_debug_macinfo;
 int                     do_arch;
 int                     do_notes;
 int                    is_32bit_elf;
@@ -183,8 +184,11 @@ static void               dynamic_segment_mips_val    PARAMS ((Elf_Internal_Dyn
 static void               dynamic_segment_parisc_val  PARAMS ((Elf_Internal_Dyn *));
 static int                process_dynamic_segment     PARAMS ((FILE *));
 static int                process_symbol_table        PARAMS ((FILE *));
+static int                process_syminfo             PARAMS ((FILE *));
 static int                process_section_contents    PARAMS ((FILE *));
-static void               process_file                PARAMS ((char *));
+static void               process_mips_fpe_exception  PARAMS ((int));
+static int                process_mips_specific       PARAMS ((FILE *));
+static int                process_file                PARAMS ((char *));
 static int                process_relocs              PARAMS ((FILE *));
 static int                process_version_sections    PARAMS ((FILE *));
 static char *             get_ver_flags               PARAMS ((unsigned int));
@@ -206,10 +210,13 @@ static int                  dump_section                PARAMS ((Elf32_Internal_Shdr *,
 static int               display_debug_section       PARAMS ((Elf32_Internal_Shdr *, FILE *));
 static int                display_debug_info          PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_not_supported PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                prescan_debug_info          PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_lines         PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_pubnames      PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_abbrev        PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_aranges       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static int                display_debug_frames        PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+static int                display_debug_macinfo       PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static unsigned char *    process_abbrev_section      PARAMS ((unsigned char *, unsigned char *));
 static unsigned long      read_leb128                 PARAMS ((unsigned char *, int *, int));
 static int                process_extended_line_op    PARAMS ((unsigned char *, int, int));
@@ -233,6 +240,7 @@ static int            process_note                   PARAMS ((Elf32_Internal_Note *));
 static int               process_corefile_note_segment  PARAMS ((FILE *, bfd_vma, bfd_vma));
 static int               process_corefile_note_segments PARAMS ((FILE *));
 static int               process_corefile_contents      PARAMS ((FILE *));
+static int               process_arch_specific          PARAMS ((FILE *));
 
 typedef int Elf32_Word;
 
@@ -802,12 +810,24 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        return 0;
     }
 
-  if (is_rela)
-    printf
-      (_("  Offset    Info  Type            Symbol's Value  Symbol's Name          Addend\n"));
+  if (is_32bit_elf)
+    {
+      if (is_rela)
+       printf
+         (_(" Offset     Info    Type            Symbol's Value  Symbol's Name          Addend\n"));
+      else
+       printf
+         (_(" Offset     Info    Type            Symbol's Value  Symbol's Name\n"));
+    }
   else
-    printf
-      (_("  Offset    Info  Type            Symbol's Value  Symbol's Name\n"));
+    {
+      if (is_rela)
+       printf
+         (_("    Offset             Info            Type               Symbol's Value   Symbol's Name           Addend\n"));
+      else
+       printf
+         (_("    Offset             Info            Type               Symbol's Value   Symbol's Name\n"));
+    }
 
   for (i = 0; i < rel_size; i++)
     {
@@ -847,11 +867,26 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
 #endif
        }
 
+      if (is_32bit_elf)
+       {
 #ifdef _bfd_int64_low
-      printf ("  %8.8lx  %5.5lx ", _bfd_int64_low (offset), _bfd_int64_low (info));
+         printf ("%8.8lx  %8.8lx ", _bfd_int64_low (offset), _bfd_int64_low (info));
 #else
-      printf ("  %8.8lx  %5.5lx ", offset, info);
+         printf ("%8.8lx  %8.8lx ", offset, info);
 #endif
+       }
+      else
+       {
+#ifdef _bfd_int64_low
+         printf ("%8.8lx%8.8lx  %8.8lx%8.8lx ",
+                 _bfd_int64_high (offset),
+                 _bfd_int64_low (offset),
+                 _bfd_int64_high (info),
+                 _bfd_int64_low (info));
+#else
+         printf ("%16.16lx  %16.16lx ", offset, info);
+#endif
+       }
 
       switch (elf_header.e_machine)
        {
@@ -920,6 +955,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
          break;
 
        case EM_PPC:
+       case EM_PPC64:
          rtype = elf_ppc_reloc_type (type);
          break;
 
@@ -1566,9 +1602,15 @@ get_machine_flags (e_flags, e_machine)
          if (e_flags & EF_MIPS_CPIC)
            strcat (buf, ", cpic");
 
+         if (e_flags & EF_MIPS_UCODE)
+           strcat (buf, ", ugen_reserved");
+
          if (e_flags & EF_MIPS_ABI2)
            strcat (buf, ", abi2");
 
+         if (e_flags & EF_MIPS_32BITMODE)
+           strcat (buf, ", 32bitmode");
+
          if ((e_flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1)
            strcat (buf, ", mips1");
 
@@ -2019,7 +2061,7 @@ usage ()
   fprintf (stdout, _("  -D or --use-dynamic       Use the dynamic section info when displaying symbols\n"));
   fprintf (stdout, _("  -x <number> or --hex-dump=<number>\n"));
   fprintf (stdout, _("                            Dump the contents of section <number>\n"));
-  fprintf (stdout, _("  -w[liaprf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=frames]\n"));
+  fprintf (stdout, _("  -w[liaprmf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames]\n"));
   fprintf (stdout, _("                            Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
@@ -2189,6 +2231,11 @@ parse_args (argc, argv)
                  do_debug_frames = 1;
                  break;
 
+               case 'm':
+               case 'M':
+                 do_debug_macinfo = 1;
+                 break;
+
                default:
                  warn (_("Unrecognised debug option '%s'\n"), optarg);
                  break;
@@ -2935,7 +2982,7 @@ process_section_headers (file)
        }
       else if ((do_debugging || do_debug_info || do_debug_abbrevs
                || do_debug_lines || do_debug_pubnames || do_debug_aranges
-               || do_debug_frames)
+               || do_debug_frames || do_debug_macinfo)
               && strncmp (name, ".debug_", 7) == 0)
        {
          name += 7;
@@ -2947,6 +2994,7 @@ process_section_headers (file)
              || (do_debug_pubnames && (strcmp (name, "pubnames") == 0))
              || (do_debug_aranges  && (strcmp (name, "aranges") == 0))
              || (do_debug_frames   && (strcmp (name, "frame") == 0))
+             || (do_debug_macinfo  && (strcmp (name, "macinfo") == 0))
              )
            request_dump (i, DEBUG_DUMP);
        }
@@ -6264,6 +6312,80 @@ process_abbrev_section (start, end)
 }
 
 
+static int
+display_debug_macinfo (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file ATTRIBUTE_UNUSED;
+{
+  unsigned char * end = start + section->sh_size;
+  unsigned char * curr = start;
+  unsigned int bytes_read;
+  enum dwarf_macinfo_record_type op;
+
+  printf (_("Contents of the %s section:\n\n"), SECTION_NAME (section));
+
+  while (curr < end)
+    {
+      unsigned int lineno;
+      const char * string;
+
+      op = * curr;
+      curr ++;
+
+      switch (op)
+       {
+       case DW_MACINFO_start_file:
+         {
+           unsigned int filenum;
+
+           lineno = read_leb128 (curr, & bytes_read, 0);
+           curr += bytes_read;
+           filenum = read_leb128 (curr, & bytes_read, 0);
+           curr += bytes_read;
+
+           printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"), lineno, filenum);
+         }
+         break;
+
+       case DW_MACINFO_end_file:
+         printf (_(" DW_MACINFO_end_file\n"));
+         break;
+
+       case DW_MACINFO_define:
+         lineno = read_leb128 (curr, & bytes_read, 0);
+         curr += bytes_read;
+         string = curr;
+         curr += strlen (string) + 1;
+         printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"), lineno, string);
+         break;
+
+       case DW_MACINFO_undef:
+         lineno = read_leb128 (curr, & bytes_read, 0);
+         curr += bytes_read;
+         string = curr;
+         curr += strlen (string) + 1;
+         printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"), lineno, string);
+         break;
+
+       case DW_MACINFO_vendor_ext:
+         {
+           unsigned int constant;
+
+           constant = read_leb128 (curr, & bytes_read, 0);
+           curr += bytes_read;
+           string = curr;
+           curr += strlen (string) + 1;
+           printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"), constant, string);
+         }
+         break;
+       }
+    }
+
+  return 1;
+}
+  
+
 static int
 display_debug_abbrev (section, start, file)
      Elf32_Internal_Shdr * section;
@@ -6944,6 +7066,7 @@ display_debug_info (section, start, file)
     {
       DWARF2_External_CompUnit * external;
       DWARF2_Internal_CompUnit   compunit;
+      Elf32_Internal_Shdr *      relsec;
       unsigned char *            tags;
       int                        i;
       int                       level;
@@ -6956,6 +7079,68 @@ display_debug_info (section, start, file)
       compunit.cu_abbrev_offset = BYTE_GET (external->cu_abbrev_offset);
       compunit.cu_pointer_size  = BYTE_GET (external->cu_pointer_size);
 
+      /* Check for RELA relocations in the abbrev_offset address, and
+         apply them.  */
+      for (relsec = section_headers;
+          relsec < section_headers + elf_header.e_shnum;
+          ++relsec)
+       {
+         unsigned long nrelas, nsyms;
+         Elf_Internal_Rela *rela, *rp;
+         Elf32_Internal_Shdr *symsec;
+         Elf_Internal_Sym *symtab;
+         Elf_Internal_Sym *sym;
+
+         if (relsec->sh_type != SHT_RELA
+             || section_headers + relsec->sh_info != section)
+           continue;
+
+         if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
+                                 & rela, & nrelas))
+           return 0;
+
+         symsec = section_headers + relsec->sh_link;
+         nsyms = symsec->sh_size / symsec->sh_entsize;
+         symtab = GET_ELF_SYMBOLS (file, symsec->sh_offset, nsyms);
+
+         for (rp = rela; rp < rela + nrelas; ++rp)
+           {
+             if (rp->r_offset
+                 != (bfd_vma) ((unsigned char *) &external->cu_abbrev_offset
+                               - section_begin))
+               continue;
+             
+             if (is_32bit_elf)
+               {
+                 sym = symtab + ELF32_R_SYM (rp->r_info);
+
+                 if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
+                   {
+                     warn (_("Skipping unexpected symbol type %u"),
+                           ELF32_ST_TYPE (sym->st_info));
+                     continue;
+                   }
+               }
+             else
+               {
+                 sym = symtab + ELF64_R_SYM (rp->r_info);
+
+                 if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
+                   {
+                     warn (_("Skipping unexpected symbol type %u"),
+                           ELF64_ST_TYPE (sym->st_info));
+                     continue;
+                   }
+               }
+
+             compunit.cu_abbrev_offset += rp->r_addend;
+             break;
+           }
+
+         free (rela);
+         break;
+       }
+
       tags = start + sizeof (* external);
       cu_offset = start - section_begin;
       start += compunit.cu_length + sizeof (external->cu_length);
@@ -7038,8 +7223,9 @@ display_debug_info (section, start, file)
              return 0;
            }
 
-         printf (_(" <%d><%x>: Abbrev Number: %lu (%s)\n"),
-                 level, tags - section_begin - bytes_read,
+         printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"),
+                 level,
+                 (unsigned long) (tags - section_begin - bytes_read),
                  abbrev_number,
                  get_TAG_name (entry->tag));
 
@@ -7156,6 +7342,10 @@ Frame_Chunk;
    in the frame info.  */
 #define DW_CFA_unreferenced (-1)
 
+static void frame_need_space PARAMS ((Frame_Chunk *, int));
+static void frame_display_row PARAMS ((Frame_Chunk *, int *, int *));
+static int size_of_encoded_value PARAMS ((int));
+
 static void
 frame_need_space (fc, reg)
      Frame_Chunk * fc;
@@ -7454,10 +7644,10 @@ display_debug_frames (section, start, file)
              start += augmentation_data_len;
            }
 
-         printf ("\n%08lx %08lx %08lx FDE cie=%08x pc=%08lx..%08lx\n",
+         printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
                  (unsigned long)(saved_start - section_start), length, cie_id,
-                 cie->chunk_start - section_start, fc->pc_begin,
-                 fc->pc_begin + fc->pc_range);
+                 (unsigned long)(cie->chunk_start - section_start),
+                 fc->pc_begin, fc->pc_begin + fc->pc_range);
          if (! do_debug_frames_interp && augmentation_data_len)
            {
              unsigned long i;
@@ -7846,7 +8036,7 @@ debug_displays[] =
   { ".debug_pubnames",    display_debug_pubnames, NULL },
   { ".debug_frame",       display_debug_frames, NULL },
   { ".eh_frame",          display_debug_frames, NULL },
-  { ".debug_macinfo",     display_debug_not_supported, NULL },
+  { ".debug_macinfo",     display_debug_macinfo, NULL },
   { ".debug_str",         display_debug_not_supported, NULL },
   { ".debug_static_func", display_debug_not_supported, NULL },
   { ".debug_static_vars", display_debug_not_supported, NULL },
@@ -8356,7 +8546,8 @@ process_mips_specific (file)
          free (econf64);
        }
 
-      printf (_("\nSection '.conflict' contains %d entries:\n"), conflictsno);
+      printf (_("\nSection '.conflict' contains %ld entries:\n"),
+             (long) conflictsno);
       puts (_("  Num:    Index       Value  Name"));
 
       for (cnt = 0; cnt < conflictsno; ++cnt)
@@ -8652,7 +8843,7 @@ get_file_header (file)
   return 1;
 }
 
-static void
+static int
 process_file (file_name)
      char * file_name;
 {
@@ -8663,21 +8854,21 @@ process_file (file_name)
   if (stat (file_name, & statbuf) < 0)
     {
       error (_("Cannot stat input file %s.\n"), file_name);
-      return;
+      return 1;
     }
 
   file = fopen (file_name, "rb");
   if (file == NULL)
     {
       error (_("Input file %s not found.\n"), file_name);
-      return;
+      return 1;
     }
 
   if (! get_file_header (file))
     {
       error (_("%s: Failed to read file header\n"), file_name);
       fclose (file);
-      return;
+      return 1;
     }
 
   /* Initialise per file variables.  */
@@ -8694,7 +8885,7 @@ process_file (file_name)
   if (! process_file_header ())
     {
       fclose (file);
-      return;
+      return 1;
     }
 
   process_section_headers (file);
@@ -8752,6 +8943,8 @@ process_file (file_name)
       free (dynamic_syminfo);
       dynamic_syminfo = NULL;
     }
+
+  return 0;
 }
 
 #ifdef SUPPORT_DISASSEMBLY
@@ -8778,6 +8971,8 @@ main (argc, argv)
      int     argc;
      char ** argv;
 {
+  int err;
+
 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
   setlocale (LC_MESSAGES, "");
 #endif
@@ -8789,11 +8984,12 @@ main (argc, argv)
   if (optind < (argc - 1))
     show_name = 1;
 
+  err = 0;
   while (optind < argc)
-    process_file (argv [optind ++]);
+    err |= process_file (argv [optind ++]);
 
   if (dump_sects != NULL)
     free (dump_sects);
 
-  return 0;
+  return err;
 }