* hppa-dis.c (print_insn_hppa): Output a space after 'X' completer.
[deliverable/binutils-gdb.git] / binutils / readelf.c
index 84f73f13b73df8b3067bb52caee64c083d021b4b..9a85549b50d05e8e03376cc073f1354fc48f3a9a 100644 (file)
 #include <stdio.h>
 #include <time.h>
 
+#if __GNUC__ >= 2
 /* Define BFD64 here, even if our default architecture is 32 bit ELF
-   as this will allow us to read in and parse 64bit and 32bit ELF files.  */
+   as this will allow us to read in and parse 64bit and 32bit ELF files.
+   Only do this if we belive that the compiler can support a 64 bit
+   data type.  For now we only rely on GCC being able to do this.  */
 #define BFD64
+#endif
+
 #include "bfd.h"
 
 #include "elf/common.h"
@@ -62,6 +67,7 @@
 #include "elf/fr30.h"
 #include "elf/mcore.h"
 #include "elf/i960.h"
+#include "elf/pj.h"
 
 #include "bucomm.h"
 #include "getopt.h"
@@ -108,6 +114,8 @@ int                     do_debug_abbrevs;
 int                     do_debug_lines;
 int                     do_debug_pubnames;
 int                     do_debug_aranges;
+int                     do_arch;
+int                     do_notes;
 int                    is_32bit_elf;
 
 /* A dynamic array of flags indicating which sections require dumping.  */
@@ -123,6 +131,7 @@ static bfd_vma (*         byte_get)                   PARAMS ((unsigned char *,
 static bfd_vma            byte_get_little_endian      PARAMS ((unsigned char *, int));
 static bfd_vma            byte_get_big_endian         PARAMS ((unsigned char *, int));
 static const char *       get_mips_dynamic_type       PARAMS ((unsigned long));
+static const char *       get_sparc64_dynamic_type    PARAMS ((unsigned long));
 static const char *       get_dynamic_type            PARAMS ((unsigned long));
 static int                dump_relocations            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, unsigned long, char *, int));
 static char *             get_file_type               PARAMS ((unsigned));
@@ -170,7 +179,7 @@ static int                display_debug_abbrev        PARAMS ((Elf32_Internal_Sh
 static int                display_debug_aranges       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));
+static int                process_extended_line_op    PARAMS ((unsigned char *, int, int));
 static void               reset_state_machine         PARAMS ((int));
 static char *             get_TAG_name                PARAMS ((unsigned long));
 static char *             get_AT_name                 PARAMS ((unsigned long));
@@ -186,6 +195,11 @@ static const char *       get_elf_class               PARAMS ((unsigned char));
 static const char *       get_data_encoding           PARAMS ((unsigned char));
 static const char *       get_osabi_name              PARAMS ((unsigned char));
 static int               guess_is_rela               PARAMS ((unsigned long));
+static char *            get_note_type                  PARAMS ((unsigned int));
+static int               process_note                   PARAMS ((Elf_External_Note *));
+static int               process_corefile_note_segment  PARAMS ((FILE *, unsigned long, unsigned long));
+static int               process_corefile_note_segments PARAMS ((FILE *));
+static int               process_corefile_contents      PARAMS ((FILE *));
 
 typedef int Elf32_Word;
 
@@ -200,7 +214,20 @@ typedef int Elf32_Word;
 #define DT_VERSIONTAGIDX(tag)  (DT_VERNEEDNUM - (tag)) /* Reverse order! */
 
 #define BYTE_GET(field)        byte_get (field, sizeof (field))
+
+/* If we can support a 64 bit data type then BFD64 should be defined
+   and sizeof (bfd_vma) == 8.  In this case when translating from an
+   external 8 byte field to an internal field, we can assume that the
+   internal field is also 8 bytes wide and so we can extact all the data.
+   If, however, BFD64 is not defined, then we must assume that the
+   internal data structure only has 4 byte wide fields that are the
+   equivalent of the 8 byte wide external counterparts, and so we must
+   truncate the data.  */
+#ifdef  BFD64
 #define BYTE_GET8(field)       byte_get (field, -8)
+#else
+#define BYTE_GET8(field)       byte_get (field, 8)
+#endif
 
 #define NUM_ELEM(array)        (sizeof (array) / sizeof ((array)[0]))
 
@@ -326,6 +353,7 @@ byte_get_little_endian (field, size)
        |    (((unsigned long) (field [2])) << 16)
        |    (((unsigned long) (field [3])) << 24);
 
+#ifdef BFD64
     case -8:
       /* This is a special case, generated by the BYTE_GET8 macro.
         It means that we are loading an 8 byte value from a field
@@ -339,7 +367,7 @@ byte_get_little_endian (field, size)
        |    (((bfd_vma) (field [5])) << 40)
        |    (((bfd_vma) (field [6])) << 48)
        |    (((bfd_vma) (field [7])) << 56);
-
+#endif
     default:
       error (_("Unhandled data length: %d\n"), size);
       abort ();
@@ -373,6 +401,7 @@ byte_get_big_endian (field, size)
        |   (((unsigned long) (field [5])) << 16)
        |   (((unsigned long) (field [4])) << 24);
 
+#ifdef BFD64
     case -8:
       /* This is a special case, generated by the BYTE_GET8 macro.
         It means that we are loading an 8 byte value from a field
@@ -386,6 +415,7 @@ byte_get_big_endian (field, size)
        |   (((bfd_vma) (field [2])) << 40)
        |   (((bfd_vma) (field [1])) << 48)
        |   (((bfd_vma) (field [0])) << 56);
+#endif
       
     default:
       error (_("Unhandled data length: %d\n"), size);
@@ -611,7 +641,12 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
            type       = ELF64_R_TYPE_ID (info);
          else
            type       = ELF64_R_TYPE (info);
+         /* The #ifdef BFD64 below is to prevent a compile time warning.
+            We know that if we do not have a 64 bit data type that we
+            will never execute this code anyway.  */
+#ifdef BFD64 
          symtab_index = ELF64_R_SYM  (info);
+#endif
        }
 
 #ifdef _bfd_int64_low
@@ -706,6 +741,10 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        case EM_PARISC:
          rtype = elf_hppa_reloc_type (type);
          break;
+
+       case EM_PJ:
+         rtype = elf_pj_reloc_type (type);
+         break;
        }
 
       if (rtype == NULL)
@@ -813,6 +852,18 @@ get_mips_dynamic_type (type)
     }
 }
 
+static const char *
+get_sparc64_dynamic_type (type)
+     unsigned long type;
+{
+  switch (type)
+    {
+    case DT_SPARC_REGISTER: return "SPARC_REGISTER";
+    default:
+      return NULL;
+    }
+}    
+
 static const char *
 get_dynamic_type (type)
      unsigned long type;
@@ -887,6 +938,9 @@ get_dynamic_type (type)
            case EM_MIPS_RS4_BE:
              result = get_mips_dynamic_type (type);
              break;
+           case EM_SPARCV9:
+             result = get_sparc64_dynamic_type (type);
+             break;
            default:
              result = NULL;
              break;
@@ -983,7 +1037,7 @@ get_machine_name (e_machine)
     case EM_CYGNUS_MN10300:    return "mn10300";
     case EM_CYGNUS_MN10200:    return "mn10200";
     case EM_CYGNUS_FR30:       return "Fujitsu FR30";
-
+    case EM_PJ:                 return "picoJava";
     default:
       sprintf (buff, _("<unknown>: %x"), e_machine);
       return buff;
@@ -1077,7 +1131,10 @@ get_machine_flags (e_flags, e_machine)
            strcat (buf, ", v8+");
 
          if (e_flags & EF_SPARC_SUN_US1)
-           strcat (buf, ", ultrasparc");
+           strcat (buf, ", ultrasparcI");
+
+         if (e_flags & EF_SPARC_SUN_US3)
+           strcat (buf, ", ultrasparcIII");
 
          if (e_flags & EF_SPARC_HAL_R1)
            strcat (buf, ", halr1");
@@ -1094,6 +1151,14 @@ get_machine_flags (e_flags, e_machine)
          if ((e_flags & EF_SPARCV9_MM) == EF_SPARCV9_RMO)
            strcat (buf, ", rmo");
          break;
+
+       case EM_PJ:
+         if ((e_flags & EF_PICOJAVA_NEWCALLS) == EF_PICOJAVA_NEWCALLS)
+           strcat (buf, ", new calling convention");
+
+         if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS)
+           strcat (buf, ", gnu calling convention");
+         break;
        }
     }
 
@@ -1282,14 +1347,16 @@ struct option options [] =
   {"file-header",      no_argument, 0, 'h'},
   {"program-headers",  no_argument, 0, 'l'},
   {"headers",          no_argument, 0, 'e'},
-  {"histogram",        no_argument, & do_histogram, 1},
+  {"histogram",        no_argument, 0, 'I'},
   {"segments",         no_argument, 0, 'l'},
   {"sections",         no_argument, 0, 'S'},
   {"section-headers",  no_argument, 0, 'S'},
   {"symbols",          no_argument, 0, 's'},
   {"syms",             no_argument, 0, 's'},
   {"relocs",           no_argument, 0, 'r'},
+  {"notes",            no_argument, 0, 'n'},
   {"dynamic",          no_argument, 0, 'd'},
+  {"arch-specific",    no_argument, 0, 'A'},
   {"version-info",     no_argument, 0, 'V'},
   {"use-dynamic",      no_argument, 0, 'D'},
   {"hex-dump",         required_argument, 0, 'x'},
@@ -1308,7 +1375,7 @@ usage ()
 {
   fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
   fprintf (stdout, _("  Options are:\n"));
-  fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V --histogram\n"));
+  fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V -A -I\n"));
   fprintf (stdout, _("  -h or --file-header       Display the ELF file header\n"));
   fprintf (stdout, _("  -l or --program-headers or --segments\n"));
   fprintf (stdout, _("                            Display the program headers\n"));
@@ -1316,9 +1383,11 @@ usage ()
   fprintf (stdout, _("                            Display the sections' header\n"));
   fprintf (stdout, _("  -e or --headers           Equivalent to: -h -l -S\n"));
   fprintf (stdout, _("  -s or --syms or --symbols Display the symbol table\n"));
+  fprintf (stdout, _("  -n or --notes             Display the core notes (if present)\n"));
   fprintf (stdout, _("  -r or --relocs            Display the relocations (if present)\n"));
   fprintf (stdout, _("  -d or --dynamic           Display the dynamic segment (if present)\n"));
   fprintf (stdout, _("  -V or --version-info      Display the version sections (if present)\n"));
+  fprintf (stdout, _("  -A or --arch-specific     Display architecture specific information (if any).\n"));
   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"));
@@ -1328,7 +1397,7 @@ usage ()
   fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
   fprintf (stdout, _("                            Disassemble the contents of section <number>\n"));
 #endif
-  fprintf (stdout, _("        --histogram         Display histogram of bucket list lengths\n"));
+  fprintf (stdout, _("  -I or --histogram         Display histogram of bucket list lengths\n"));
   fprintf (stdout, _("  -v or --version           Display the version number of readelf\n"));
   fprintf (stdout, _("  -H or --help              Display this information\n"));
   fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
@@ -1378,7 +1447,7 @@ parse_args (argc, argv)
     usage ();
 
   while ((c = getopt_long
-         (argc, argv, "ersahldSDw::x:i:vV", options, NULL)) != EOF)
+         (argc, argv, "ersahnldSDAIw::x:i:vV", options, NULL)) != EOF)
     {
       char *    cp;
       int      section;
@@ -1401,12 +1470,17 @@ parse_args (argc, argv)
          do_segments ++;
          do_version ++;
          do_histogram ++;
+         do_arch ++;
+         do_notes ++;
          break;
        case 'e':
          do_header ++;
          do_sections ++;
          do_segments ++;
          break;
+       case 'A':
+         do_arch ++;
+         break;
        case 'D':
          do_using_dynamic ++;
          break;
@@ -1428,6 +1502,12 @@ parse_args (argc, argv)
        case 'd':
          do_dynamic ++;
          break;
+       case 'I':
+         do_histogram ++;
+         break;
+       case 'n':
+         do_notes ++;
+         break;
        case 'x':
          do_dump ++;
          section = strtoul (optarg, & cp, 0);
@@ -1506,7 +1586,7 @@ parse_args (argc, argv)
 
   if (!do_dynamic && !do_syms && !do_reloc && !do_sections
       && !do_segments && !do_header && !do_dump && !do_version
-      && !do_histogram && !do_debugging)
+      && !do_histogram && !do_debugging && !do_arch && !do_notes)
     usage ();
   else if (argc < 3)
     {
@@ -1844,7 +1924,7 @@ process_program_headers (file)
                      ? (section->sh_addr >= segment->p_vaddr
                         && section->sh_addr + section->sh_size
                         <= segment->p_vaddr + segment->p_memsz)
-                     : (section->sh_offset >= segment->p_offset
+                     : ((bfd_vma) section->sh_offset >= segment->p_offset
                         && (section->sh_offset + section->sh_size
                             <= segment->p_offset + segment->p_filesz))))
                printf ("%s ", SECTION_NAME (section));
@@ -2169,7 +2249,7 @@ process_relocs (file)
 
   if (do_using_dynamic)
     {
-      int is_rela;
+      int is_rela = FALSE;
 
       rel_size   = 0;
       rel_offset = 0;
@@ -3513,7 +3593,7 @@ process_symbol_table (file)
   Elf32_Internal_Shdr *   section;
   char   nb [4];
   char   nc [4];
-  int    nbuckets;
+  int    nbuckets = 0;
   int    nchains;
   int *  buckets = NULL;
   int *  chains = NULL;
@@ -3848,9 +3928,9 @@ process_symbol_table (file)
 
 static int
 process_syminfo (file)
-     FILE * file;
+     FILE * file ATTRIBUTE_UNUSED;
 {
-  int i;
+  unsigned int i;
 
   if (dynamic_syminfo == NULL
       || !do_dynamic)
@@ -4077,9 +4157,10 @@ reset_state_machine (is_stmt)
 /* Handled an extend line op.  Returns true if this is the end
    of sequence.  */
 static int
-process_extended_line_op (data, is_stmt)
+process_extended_line_op (data, is_stmt, pointer_size)
      unsigned char * data;
      int is_stmt;
+     int pointer_size;
 {
   unsigned char   op_code;
   int             bytes_read;
@@ -4109,8 +4190,7 @@ process_extended_line_op (data, is_stmt)
       break;
 
     case DW_LNE_set_address:
-      /* XXX - assumption here that address size is 4! */
-      adr = byte_get (data, 4);
+      adr = byte_get (data, pointer_size);
       printf (_("set Address to 0x%lx\n"), adr);
       state_machine_regs.address = adr;
       break;
@@ -4138,12 +4218,16 @@ process_extended_line_op (data, is_stmt)
   return len;
 }
 
+/* Size of pointers in the .debug_line section.  This information is not
+   really present in that section.  It's obtained before dumping the debug
+   sections by doing some pre-scan of the .debug_info section.  */
+static int debug_line_pointer_size = 4;
 
 static int
 display_debug_lines (section, start, file)
      Elf32_Internal_Shdr * section;
      unsigned char *       start;
-     FILE *                file;
+     FILE *                file ATTRIBUTE_UNUSED;
 {
   DWARF2_External_LineInfo * external;
   DWARF2_Internal_LineInfo   info;
@@ -4207,7 +4291,7 @@ display_debug_lines (section, start, file)
       printf (_("\n Opcodes:\n"));
       
       for (i = 1; i < info.li_opcode_base; i++)
-       printf (_("  Opcode %d has %d args\n"), i, standard_opcodes[i]);
+       printf (_("  Opcode %d has %d args\n"), i, standard_opcodes[i - 1]);
       
       /* Display the contents of the Directory table.  */
       data = standard_opcodes + info.li_opcode_base - 1;
@@ -4275,7 +4359,8 @@ display_debug_lines (section, start, file)
          switch (op_code)
            {
            case DW_LNS_extended_op:
-             data += process_extended_line_op (data, info.li_default_is_stmt);
+             data += process_extended_line_op (data, info.li_default_is_stmt,
+                                                debug_line_pointer_size);
              break;
              
            case DW_LNS_copy:
@@ -4326,7 +4411,8 @@ display_debug_lines (section, start, file)
              break;
              
            case DW_LNS_const_add_pc:
-             adv = (255 - info.li_opcode_base) / info.li_line_range;
+             adv = (((255 - info.li_opcode_base) / info.li_line_range)
+                    * info.li_min_insn_length);
              state_machine_regs.address += adv;
              printf (_("  Advance PC by constant %d to 0x%lx\n"), adv,
                      state_machine_regs.address);
@@ -4346,7 +4432,7 @@ display_debug_lines (section, start, file)
              state_machine_regs.address += adv;
              printf (_("  Special opcode %d: advance Address by %d to 0x%lx"),
                      op_code, adv, state_machine_regs.address);
-             adv    += (op_code % info.li_line_range) + info.li_line_base;
+             adv = (op_code % info.li_line_range) + info.li_line_base;
              state_machine_regs.line += adv;
              printf (_(" and Line by %d to %d\n"),
                      adv, state_machine_regs.line);
@@ -4363,7 +4449,7 @@ static int
 display_debug_pubnames (section, start, file)
      Elf32_Internal_Shdr * section;
      unsigned char *       start;
-     FILE *                file;
+     FILE *                file ATTRIBUTE_UNUSED;
 {
   DWARF2_External_PubNames * external;
   DWARF2_Internal_PubNames   pubnames;
@@ -4751,8 +4837,11 @@ process_abbrev_section (start, end)
       entry = read_leb128 (start, & bytes_read, 0);
       start += bytes_read;
 
+      /* A single zero is supposed to end the section according
+        to the standard.  If there's more, then signal that to
+        the caller.  */
       if (entry == 0)
-       return start;
+       return start == end ? NULL : start;
 
       tag = read_leb128 (start, & bytes_read, 0);
       start += bytes_read;
@@ -4785,7 +4874,7 @@ static int
 display_debug_abbrev (section, start, file)
      Elf32_Internal_Shdr * section;
      unsigned char *       start;
-     FILE *                file;
+     FILE *                file ATTRIBUTE_UNUSED;
 {
   abbrev_entry * entry;
   unsigned char * end = start + section->sh_size;
@@ -5307,8 +5396,8 @@ read_and_display_attr (attribute, form, data, pointer_size)
      unsigned char * data;
      unsigned long   pointer_size;
 {
-  unsigned long   uvalue;
-  unsigned char * block_start;
+  unsigned long   uvalue = 0;
+  unsigned char * block_start = NULL;
   int             bytes_read;
   int            is_ref = 0;
 
@@ -5629,7 +5718,7 @@ display_debug_info (section, start, file)
       while (tags < start)
        {
          int            bytes_read;
-         int            abbrev_number;
+         unsigned long  abbrev_number;
          abbrev_entry * entry;
          abbrev_attr  * attr;
 
@@ -5652,12 +5741,12 @@ display_debug_info (section, start, file)
 
          if (entry == NULL)
            {
-             warn (_("Unable to locate entry %d in the abbreviation table\n"),
+             warn (_("Unable to locate entry %lu in the abbreviation table\n"),
                    abbrev_number);
              return 0;
            }
 
-         printf (_(" <%d><%x>: Abbrev Number: %d (%s)\n"),
+         printf (_(" <%d><%x>: Abbrev Number: %lu (%s)\n"),
                  level, tags - section_begin - bytes_read,
                  abbrev_number,
                  get_TAG_name (entry->tag));
@@ -5682,7 +5771,7 @@ static int
 display_debug_aranges (section, start, file)
      Elf32_Internal_Shdr * section;
      unsigned char *       start;
-     FILE *                file;
+     FILE *                file ATTRIBUTE_UNUSED;
 {
   unsigned char * end = start + section->sh_size;
 
@@ -5695,6 +5784,7 @@ display_debug_aranges (section, start, file)
       unsigned char *          ranges;
       unsigned long            length;
       unsigned long            address;
+      int                     excess;
 
       external = (DWARF2_External_ARange *) start;
 
@@ -5714,19 +5804,25 @@ display_debug_aranges (section, start, file)
 
       ranges = start + sizeof (* external);
 
+      /* Must pad to an alignment boundary that is twice the pointer size.  */
+      excess = sizeof (*external) % (2 * arange.ar_pointer_size);
+      if (excess)
+       ranges += (2 * arange.ar_pointer_size) - excess;
+
       for (;;)
        {
          address = byte_get (ranges, arange.ar_pointer_size);
 
-         if (address == 0)
-           break;
-
          ranges += arange.ar_pointer_size;
 
          length  = byte_get (ranges, arange.ar_pointer_size);
 
          ranges += arange.ar_pointer_size;
 
+         /* A pair of zeros marks the end of the list.  */
+         if (address == 0 && length == 0)
+           break;
+         
          printf ("    %8.8lx %lu\n", address, length);
        }
 
@@ -5742,8 +5838,8 @@ display_debug_aranges (section, start, file)
 static int
 display_debug_not_supported (section, start, file)
      Elf32_Internal_Shdr * section;
-     unsigned char *       start;
-     FILE *                file;
+     unsigned char *       start ATTRIBUTE_UNUSED;
+     FILE *                file ATTRIBUTE_UNUSED;
 {
   printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
            SECTION_NAME (section));
@@ -5751,27 +5847,47 @@ display_debug_not_supported (section, start, file)
   return 1;
 }
 
+/* Pre-scan the .debug_info section to record the size of address.
+   When dumping the .debug_line, we use that size information, assuming
+   that all compilation units have the same address size.  */
+static int
+prescan_debug_info (section, start, file)
+     Elf32_Internal_Shdr * section ATTRIBUTE_UNUSED;
+     unsigned char *       start;
+     FILE *                file ATTRIBUTE_UNUSED;
+{
+  DWARF2_External_CompUnit * external;
+
+  external = (DWARF2_External_CompUnit *) start;
+
+  debug_line_pointer_size = BYTE_GET (external->cu_pointer_size);
+  return 0;
+}
+
   /* A structure containing the name of a debug section and a pointer
-     to a function that can decode it.  */
+     to a function that can decode it.  The third field is a prescan
+     function to be run over the section before displaying any of the
+     sections.  */
 struct
 {
   char * name;
-  int (* display) PARAMS((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+  int (* display) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
+  int (* prescan) PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 }
 debug_displays[] =
 {
-  { ".debug_info",        display_debug_info },
-  { ".debug_abbrev",      display_debug_abbrev },
-  { ".debug_line",        display_debug_lines },
-  { ".debug_aranges",     display_debug_aranges },
-  { ".debug_pubnames",    display_debug_pubnames },
-  { ".debug_macinfo",     display_debug_not_supported },
-  { ".debug_frame",       display_debug_not_supported },
-  { ".debug_str",         display_debug_not_supported },
-  { ".debug_static_func", display_debug_not_supported },
-  { ".debug_static_vars", display_debug_not_supported },
-  { ".debug_types",       display_debug_not_supported },
-  { ".debug_weaknames",   display_debug_not_supported }
+  { ".debug_info",        display_debug_info, prescan_debug_info },
+  { ".debug_abbrev",      display_debug_abbrev, NULL },
+  { ".debug_line",        display_debug_lines, NULL },
+  { ".debug_aranges",     display_debug_aranges, NULL },
+  { ".debug_pubnames",    display_debug_pubnames, NULL },
+  { ".debug_macinfo",     display_debug_not_supported, NULL },
+  { ".debug_frame",       display_debug_not_supported, NULL },
+  { ".debug_str",         display_debug_not_supported, NULL },
+  { ".debug_static_func", display_debug_not_supported, NULL },
+  { ".debug_static_vars", display_debug_not_supported, NULL },
+  { ".debug_types",       display_debug_not_supported, NULL },
+  { ".debug_weaknames",   display_debug_not_supported, NULL }
 };
 
 static int
@@ -5819,15 +5935,48 @@ static int
 process_section_contents (file)
      FILE * file;
 {
-  Elf32_Internal_Shdr *    section;
-  unsigned int  i;
+  Elf32_Internal_Shdr * section;
+  unsigned int         i;
 
   if (! do_dump)
     return 1;
 
+  /* Pre-scan the debug sections to find some debug information not
+     present in some of them.  For the .debug_line, we must find out the
+     size of address (specified in .debug_info and .debug_aranges).  */
+  for (i = 0, section = section_headers;
+       i < elf_header.e_shnum && i < num_dump_sects;
+       i ++, section ++)
+    {
+      char *   name = SECTION_NAME (section);
+      int       j;
+
+      if (section->sh_size == 0)
+        continue;
+
+      /* See if there is some pre-scan operation for this section.  */
+      for (j = NUM_ELEM (debug_displays); j--;)
+        if (strcmp (debug_displays[j].name, name) == 0)
+         {
+           if (debug_displays[j].prescan != NULL)
+             {
+               bfd_size_type   length;
+               unsigned char * start;
+
+               length = section->sh_size;
+               GET_DATA_ALLOC (section->sh_offset, length, start, unsigned char *,
+                               "debug section data");
+
+               debug_displays[j].prescan (section, start, file);
+               free (start);
+             }
+           
+            break;
+          }
+    }
+
   for (i = 0, section = section_headers;
-       i < elf_header.e_shnum
-       && i < num_dump_sects;
+       i < elf_header.e_shnum && i < num_dump_sects;
        i ++, section ++)
     {
 #ifdef SUPPORT_DISASSEMBLY
@@ -5955,7 +6104,7 @@ process_mips_specific (file)
                  { " DELTA", LL_DELTA }
                };
              int flags = liblist.l_flags;
-             int fcnt;
+             size_t fcnt;
 
              for (fcnt = 0;
                   fcnt < sizeof (l_flags_vals) / sizeof (l_flags_vals[0]);
@@ -6225,10 +6374,171 @@ process_mips_specific (file)
   return 1;
 }
 
+static char *
+get_note_type (e_type)
+     unsigned e_type;
+{
+  static char buff[64];
+  
+  switch (e_type)
+    {
+    case NT_PRSTATUS:  return _("NT_PRSTATUS (prstatus structure)");
+    case NT_FPREGSET:  return _("NT_FPREGSET (floating point registers)");
+    case NT_PRPSINFO:   return _("NT_PRPSINFO (prpsinfo structure)");
+    case NT_TASKSTRUCT: return _("NT_TASKSTRUCT (task structure)");
+    case NT_PSTATUS:   return _("NT_PSTATUS (pstatus structure)");
+    case NT_FPREGS:    return _("NT_FPREGS (floating point registers)");
+    case NT_PSINFO:    return _("NT_PSINFO (psinfo structure)");
+    case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)");
+    case NT_LWPSINFO:  return _("NT_LWPSINFO (lwpsinfo_t structure)");
+    default:
+      sprintf (buff, _("Unknown note type: (0x%08x)"), e_type);
+      return buff;
+    }
+}
+
+static int
+process_note (pnote)
+  Elf_External_Note * pnote;
+{
+  Elf32_Internal_Note * internal;
+  char * pname;
+  
+  internal = (Elf32_Internal_Note *) pnote;
+  pname = malloc (internal->namesz + 1);
+  
+  if (pname == NULL)
+    {
+      error (_("Out of memory\n"));
+      return 0;
+    }
+
+  memcpy (pname, pnote->name, internal->namesz);
+  pname[internal->namesz] = '\0';
+
+  printf ("  %s\t\t0x%08lx\t%s\n", 
+         pname, internal->descsz, get_note_type (internal->type));
+          
+  free (pname);
+
+  return 1;
+}
+
+static int
+process_corefile_note_segment (file, offset, length)
+     FILE * file;
+     unsigned long offset;
+     unsigned long length;
+{
+  Elf_External_Note *  pnotes;
+  Elf_External_Note *  external;
+  Elf32_Internal_Note* internal;
+  unsigned int        notesz;
+  unsigned int         nlength;
+  unsigned char *      p;
+  int                  res = 1;
+  
+  if (length <= 0)
+    return 0;
+    
+  GET_DATA_ALLOC (offset, length, pnotes, Elf_External_Note *, "notes");
+
+  external = pnotes; 
+  p = (unsigned char *) pnotes;
+  nlength = length;
+  printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"), offset, length);
+  printf (_("  Owner\t\tData size\tDescription\n"));
+  
+  while (nlength > 0)
+    {
+      res &= process_note (external);
+      
+      internal = (Elf32_Internal_Note *) p;
+      notesz   = 3 * sizeof(unsigned long) + internal->namesz + internal->descsz;
+      nlength -= notesz;
+      p       += notesz;
+      external = (Elf_External_Note *) p;
+    }
+
+  free (pnotes);
+  
+  return res;
+}
+
+static int
+process_corefile_note_segments (file)
+     FILE * file;
+{
+  Elf_Internal_Phdr * program_headers;
+  Elf_Internal_Phdr * segment;
+  unsigned int       i;
+  int                 res = 1;
+  
+  program_headers = (Elf_Internal_Phdr *) malloc
+    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+
+  if (program_headers == NULL)
+    {
+      error (_("Out of memory\n"));
+      return 0;
+    }
+
+  if (is_32bit_elf)
+    i = get_32bit_program_headers (file, program_headers);
+  else
+    i = get_64bit_program_headers (file, program_headers);
+
+  if (i == 0)
+    {
+      free (program_headers);
+      return 0;
+    }
+  
+  for (i = 0, segment = program_headers;
+       i < elf_header.e_phnum;
+       i ++, segment ++)
+    {
+      if (segment->p_type == PT_NOTE)
+       res &= process_corefile_note_segment (file, 
+                                             (unsigned long)segment->p_offset,
+                                             (unsigned long)segment->p_filesz);
+    }
+    
+  free (program_headers);
+
+  return res;
+}
+
+static int
+process_corefile_contents (file)
+     FILE * file;
+{
+  /* If we have not been asked to display the notes then do nothing.  */
+  if (! do_notes)
+    return 1;
+  
+  /* If file is not a core file then exit.  */
+  if (elf_header.e_type != ET_CORE)
+    return 1;
+    
+  /* No program headers means no NOTE segment.  */
+  if (elf_header.e_phnum == 0)
+    {
+      printf (_("No note segments present in the core file.\n"));
+      return 1;
+   }
+
+  return process_corefile_note_segments (file);
+}
+
 static int
 process_arch_specific (file)
      FILE * file;
 {
+  if (! do_arch)
+    return 1;
+
   switch (elf_header.e_machine)
     {
     case EM_MIPS:
@@ -6286,6 +6596,17 @@ get_file_header (file)
   else
     {
       Elf64_External_Ehdr ehdr64;
+
+      /* If we have been compiled with sizeof (bfd_vma) == 4, then
+        we will not be able to cope with the 64bit data found in
+        64 ELF files.  Detect this now and abort before we start
+        overwritting things.  */
+      if (sizeof (bfd_vma) < 8)
+       {
+         error (_("This instance of readelf has been built without support for a\n"));
+         error (_("64 bit data type and so it cannot read 64 bit ELF files.\n"));
+         return 0;
+       }
       
       if (fread (ehdr64.e_type, sizeof (ehdr64) - EI_NIDENT, 1, file) != 1)
        return 0;
@@ -6368,7 +6689,9 @@ process_file (file_name)
   process_version_sections (file);
 
   process_section_contents (file);
-
+  
+  process_corefile_contents (file);
+  
   process_arch_specific (file);
 
   fclose (file);
This page took 0.035025 seconds and 4 git commands to generate.