Add support to readelf to decode and display the contents of .debug_ranges
authorNick Clifton <nickc@redhat.com>
Wed, 3 Nov 2004 10:44:45 +0000 (10:44 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 3 Nov 2004 10:44:45 +0000 (10:44 +0000)
sections.

binutils/ChangeLog
binutils/NEWS
binutils/doc/binutils.texi
binutils/readelf.c

index 3a85a433224c6c79f7b85dffe5b45178676a0dfb..74bca2b63aa6fe8c433643e717b62131eebb25bc 100644 (file)
@@ -1,3 +1,64 @@
+2004-11-03  Nick Clifton  <nickc@redhat.com>
+
+       * readelf.c (do_debug_ranges): New variable.
+       (usage): Document new switch: -wR or --debug-dump=Ranges.
+       (parse_args): Handle new switch.  Replace switch statement for the
+       long options with a more compact table structure.
+       (process_section_headers): Allow the dumping of .debug_ranges
+       sections if so requested.
+       (debug_displays): Likewise.
+       (load_debug_range): New function: Grabs the contents of a
+       .debug_ranges section.
+       (free_debug_range): New function: Releases the grabbed
+       .debug_ranges section.
+       (decode_64bit_range): New function: Displays a 64-bit range in a
+       .debug_ranges section.
+       (decode_range): New function: Displays a 32-bit range in a
+       .debug_ranges section.
+       (read_and_display_attr_value): Record the value of DW_AT_low_pc
+       attributes.  Use decode_ranges() to display a DW_AT_ranges
+       attribute.
+       (display_debug_info): Use load_debug_range() and
+       free_debug_range().
+       (display_64bit_debug_ranges): New function.  Displays the contents
+       of a 64-bit format .debug_ranges section.
+       (display_debug_ranges): New function: Displays the contents of a
+       32-bit .debug_ranges section.
+       
+       (main): Move cmdline_dump_sects and num_cmdline_dump_sects into the
+       global scope.
+       (process_object): Initialise the dump_sects array from the
+       cmdline_dump_sects array before processing each object file.
+
+       (streq, strneq): New macros.  Use them to replace occurrences of
+       strcmp() and strncmp().
+
+       (debug_information): New structure array to replace
+       debug_line_pointer_sizes array.
+       (num_debug_info_entries): New variable to replace
+       num_debug_line_pointers.
+       (get_pointer_size_of_comp_unit): New function: Returns the pointer
+       size of a given compilation unit.
+       (get_debug_info): New function to replace
+       get_debug_line_pointer_sizes.
+       (display_debug_lines): Use the new functions.
+       (display_debug_loc): Likewise.
+       
+       (disassemble_section): Change return type to int.
+       (display_debug_lines): Move local variables to their
+       innermost scope.
+       (display_debug_section): Likewise.  Also record the return value
+       of functions called and pass this back to the parent.  Also only
+       warn about undumped sections when the user explicitly requested
+       their dumping.
+
+       (debug_apply_rela_addends): Allow relocations against STT_OBJECT
+       types as well.
+       
+       * NEWS: Mention the support for decoding .debug_ranges sections.
+       * doc/binutils.texi: Document the new command line switch to
+       readelf.
+
 2004-11-03  Randolph Chung  <tausq@debian.org>
 
        * readelf.c (ia64_unw_aux_info, ia64_unw_table_entry): Rename from
index f7c2dd7510ce2a8aa6802c4b9233858f4fcfbe33..f52b519730869239ae91e900459df2a0ae1a831f 100644 (file)
@@ -1,5 +1,10 @@
 -*- text -*-
 
+* readelf can now display address ranges from .debug_range sections.  This
+  happens automatically when a DW_AT_range attribute is encountered.  The
+  command line switch --debug-dump=Ranges (or -wR) can also be used to display
+  the contents of the .debug_range section.
+
 * nm and objdump now have a switch "--special-syms" to enable the displaying of
   symbols which the target considers to be special.  By default these symbols
   are no longer displayed.  Currently the only special symbols are the Mapping
index f2cd2d1a44debaaa8402f1177deedc4f0e2a93e6..683dd6126f8444eb156548339c7aef74d0b9ca6a 100644 (file)
@@ -3153,8 +3153,8 @@ readelf [@option{-a}|@option{--all}]
         [@option{-A}|@option{--arch-specific}]
         [@option{-D}|@option{--use-dynamic}]
         [@option{-x} <number>|@option{--hex-dump=}<number>]
-        [@option{-w[liaprmfFso]}|
-         @option{--debug-dump}[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=frames-interp,=str,=loc]]
+        [@option{-w[liaprmfFsoR]}|
+         @option{--debug-dump}[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]]
         [@option{-I}|@option{-histogram}]
         [@option{-v}|@option{--version}]
         [@option{-W}|@option{--wide}]
@@ -3271,8 +3271,8 @@ symbols section.
 @itemx --hex-dump=<number>
 Displays the contents of the indicated section as a hexadecimal dump.
 
-@item -w[liaprmfFso]
-@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=frames-interp,=str,=loc]
+@item -w[liaprmfFsoR]
+@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]
 Displays the contents of the debug sections in the file, if any are
 present.  If one of the optional letters or words follows the switch
 then only data found in those specific sections will be dumped.
index 69b8051a4909a5282f076ada21c9eefe4a4a2902..4cbbf88adf70e2a5bb0d70fb5517133cb076618d 100644 (file)
@@ -159,6 +159,7 @@ int do_debug_abbrevs;
 int do_debug_lines;
 int do_debug_pubnames;
 int do_debug_aranges;
+int do_debug_ranges;
 int do_debug_frames;
 int do_debug_frames_interp;
 int do_debug_macinfo;
@@ -185,7 +186,16 @@ size_t group_count = 0;
 
 struct group **section_headers_groups;
 
-/* A dynamic array of flags indicating which sections require dumping.  */
+/* A dynamic array of flags indicating for which sections a hex dump
+   has been requested (via the -x switch) and/or a disassembly dump
+   (via the -i switch).  */
+char *cmdline_dump_sects = NULL;
+unsigned num_cmdline_dump_sects = 0;
+
+/* A dynamic array of flags indicating for which sections a dump of
+   some kind has been requested.  It is reset on a per-object file
+   basis and then initialised from the cmdline_dump_sects array and
+   the results of interpreting the -w switch.  */
 char *dump_sects = NULL;
 unsigned int num_dump_sects = 0;
 
@@ -212,8 +222,8 @@ static void (*byte_put) (unsigned char *, bfd_vma, int);
 #define UNKNOWN -1
 
 #define SECTION_NAME(X)        ((X) == NULL ? "<none>" : \
-                                ((X)->sh_name >= string_table_length \
-                                 ? "<corrupt>" : string_table + (X)->sh_name))
+                        ((X)->sh_name >= string_table_length \
+                         ? "<corrupt>" : string_table + (X)->sh_name))
 
 /* Given st_shndx I, map to section_headers index.  */
 #define SECTION_HEADER_INDEX(I)                                \
@@ -259,6 +269,10 @@ static void (*byte_put) (unsigned char *, bfd_vma, int);
 /* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
    already been called and verified that the string exists.  */
 #define GET_DYNAMIC_NAME(offset)       (dynamic_strings + offset)
+
+/* This is just a bit of syntatic sugar.  */
+#define streq(a,b)     (strcmp ((a), (b)) == 0)
+#define strneq(a,b,n)  (strncmp ((a), (b), (n)) == 0)
 \f
 static void
 error (const char *message, ...)
@@ -566,8 +580,8 @@ byte_get_big_endian (unsigned char *field, int size)
 
 #ifndef BFD64
     case 8:
-      /* Although we are extracing data from an 8 byte wide field, we
-        are returning only 4 bytes of data.  */
+      /* Although we are extracing data from an 8 byte wide field,
+        we are returning only 4 bytes of data.  */
       return ((unsigned long) (field[7]))
        |   (((unsigned long) (field[6])) << 8)
        |   (((unsigned long) (field[5])) << 16)
@@ -743,7 +757,7 @@ slurp_rela_relocs (FILE *file,
 
       if (relas == NULL)
        {
-         error(_("out of memory parsing relocs"));
+         error (_("out of memory parsing relocs"));
          return 0;
        }
 
@@ -770,7 +784,7 @@ slurp_rela_relocs (FILE *file,
 
       if (relas == NULL)
        {
-         error(_("out of memory parsing relocs"));
+         error (_("out of memory parsing relocs"));
          return 0;
        }
 
@@ -813,7 +827,7 @@ slurp_rel_relocs (FILE *file,
 
       if (rels == NULL)
        {
-         error(_("out of memory parsing relocs"));
+         error (_("out of memory parsing relocs"));
          return 0;
        }
 
@@ -840,7 +854,7 @@ slurp_rel_relocs (FILE *file,
 
       if (rels == NULL)
        {
-         error(_("out of memory parsing relocs"));
+         error (_("out of memory parsing relocs"));
          return 0;
        }
 
@@ -1268,12 +1282,13 @@ dump_relocations (FILE *file,
        }
       else if (is_rela)
        {
-         printf ("%*c", is_32bit_elf ? (do_wide ? 34 : 28) : (do_wide ? 26 : 20), ' ');
+         printf ("%*c", is_32bit_elf ?
+                 (do_wide ? 34 : 28) : (do_wide ? 26 : 20), ' ');
          print_vma (rels[i].r_addend, LONG_HEX);
        }
 
       if (elf_header.e_machine == EM_SPARCV9
-         && !strcmp (rtype, "R_SPARC_OLO10"))
+         && streq (rtype, "R_SPARC_OLO10"))
        printf (" + %lx", (unsigned long) ELF64_R_TYPE_DATA (info));
 
       putchar ('\n');
@@ -1291,7 +1306,7 @@ dump_relocations (FILE *file,
          else
            printf ("%-17.17s", rtype2);
 
-         printf("\n                    Type3: ");
+         printf ("\n                    Type3: ");
 
          if (rtype3 == NULL)
 #ifdef _bfd_int64_low
@@ -2401,7 +2416,7 @@ get_parisc_section_type_name (unsigned int sh_type)
 static const char *
 get_ia64_section_type_name (unsigned int sh_type)
 {
-  /* If the top 8 bits are 0x78 the next 8 are the os/abi ID. */
+  /* If the top 8 bits are 0x78 the next 8 are the os/abi ID.  */
   if ((sh_type & 0xFF000000) == SHT_IA_64_LOPSREG)
     return get_osabi_name ((sh_type & 0x00FF0000) >> 16);
 
@@ -2576,8 +2591,8 @@ usage (void)
   -A --arch-specific     Display architecture specific information (if any).\n\
   -D --use-dynamic       Use the dynamic section info when displaying symbols\n\
   -x --hex-dump=<number> Dump the contents of section <number>\n\
-  -w[liaprmfFso] or\n\
-  --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str,=loc]\n\
+  -w[liaprmfFsoR] or\n\
+  --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
                          Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stdout, _("\
@@ -2594,6 +2609,11 @@ usage (void)
   exit (0);
 }
 
+/* Record the fact that the user wants the contents of section number
+   SECTION to be displayed using the method(s) encoded as flags bits
+   in TYPE.  Note, TYPE can be zero if we are creating the array for
+   the first time.  */
+
 static void
 request_dump (unsigned int section, int type)
 {
@@ -2744,10 +2764,13 @@ parse_args (int argc, char **argv)
                    break;
 
                  case 'r':
-                 case 'R':
                    do_debug_aranges = 1;
                    break;
 
+                 case 'R':
+                   do_debug_ranges = 1;
+                   break;
+
                  case 'F':
                    do_debug_frames_interp = 1;
                  case 'f':
@@ -2781,10 +2804,33 @@ parse_args (int argc, char **argv)
            do_debugging = 1;
          else
            {
-             static const char *debug_dump_opt[]
-               = { "line", "info", "abbrev", "pubnames", "ranges",
-                   "macro", "frames", "frames-interp", "str", "loc", NULL };
-             unsigned int index;
+             typedef struct
+             {
+               const char * option;
+               int *        variable;
+             }
+             debug_dump_long_opts;
+
+             debug_dump_long_opts opts_table [] =
+               {
+                 /* Please keep this table alpha- sorted.  */
+                 { "Ranges", & do_debug_ranges },
+                 { "abbrev", & do_debug_abbrevs },
+                 { "aranges", & do_debug_aranges },
+                 { "frames", & do_debug_frames },
+                 { "frames-interp", & do_debug_frames_interp },
+                 { "info", & do_debug_info },
+                 { "line", & do_debug_lines },
+                 { "loc",  & do_debug_loc },
+                 { "macro", & do_debug_macinfo },
+                 { "pubnames", & do_debug_pubnames },
+                 /* This entry is for compatability
+                    with earlier versions of readelf.  */
+                 { "ranges", & do_debug_aranges },
+                 { "str", & do_debug_str },
+                 { NULL, NULL }
+               };
+
              const char *p;
 
              do_debugging = 0;
@@ -2792,59 +2838,28 @@ parse_args (int argc, char **argv)
              p = optarg;
              while (*p)
                {
-                 for (index = 0; debug_dump_opt[index]; index++)
+                 debug_dump_long_opts * entry;
+
+                 for (entry = opts_table; entry->option; entry++)
                    {
-                     size_t len = strlen (debug_dump_opt[index]);
+                     size_t len = strlen (entry->option);
 
-                     if (strncmp (p, debug_dump_opt[index], len) == 0
+                     if (strneq (p, entry->option, len)
                          && (p[len] == ',' || p[len] == '\0'))
                        {
-                         switch (p[0])
-                           {
-                           case 'i':
-                             do_debug_info = 1;
-                             break;
-
-                           case 'a':
-                             do_debug_abbrevs = 1;
-                             break;
-
-                           case 'l':
-                             if (p[1] == 'i')
-                               do_debug_lines = 1;
-                             else
-                               do_debug_loc = 1;
-                             break;
-
-                           case 'p':
-                             do_debug_pubnames = 1;
-                             break;
-
-                           case 'r':
-                             do_debug_aranges = 1;
-                             break;
-
-                           case 'f':
-                             if (len > 6)
-                               do_debug_frames_interp = 1;
-                             do_debug_frames = 1;
-                             break;
-
-                           case 'm':
-                             do_debug_macinfo = 1;
-                             break;
-
-                           case 's':
-                             do_debug_str = 1;
-                             break;
-                           }
+                         * entry->variable = 1;
+
+                         /* The --debug-dump=frames-interp option also
+                            enables the --debug-dump=frames option.  */
+                         if (do_debug_frames_interp)
+                           do_debug_frames = 1;
 
                          p += len;
                          break;
                        }
                    }
 
-                 if (debug_dump_opt[index] == NULL)
+                 if (entry->option == NULL)
                    {
                      warn (_("Unrecognized debug option '%s'\n"), p);
                      p = strchr (p, ',');
@@ -2895,7 +2910,7 @@ parse_args (int argc, char **argv)
   else if (argc < 3)
     {
       warn (_("Nothing to do.\n"));
-      usage();
+      usage ();
     }
 }
 
@@ -3271,7 +3286,7 @@ process_program_headers (FILE *file)
              for (j = 0, sec = section_headers;
                   j < elf_header.e_shnum;
                   j++, sec++)
-               if (strcmp (SECTION_NAME (sec), ".dynamic") == 0)
+               if (streq (SECTION_NAME (sec), ".dynamic"))
                  break;
 
              if (j == elf_header.e_shnum || sec->sh_size == 0)
@@ -3716,7 +3731,7 @@ process_section_headers (FILE *file)
          dynamic_symbols = GET_ELF_SYMBOLS (file, section);
        }
       else if (section->sh_type == SHT_STRTAB
-              && strcmp (name, ".dynstr") == 0)
+              && streq (name, ".dynstr"))
        {
          if (dynamic_strings != NULL)
            {
@@ -3740,29 +3755,30 @@ process_section_headers (FILE *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_macinfo || do_debug_str
-               || do_debug_loc)
-              && strncmp (name, ".debug_", 7) == 0)
+               || do_debug_loc || do_debug_ranges)
+              && strneq (name, ".debug_", 7))
        {
          name += 7;
 
          if (do_debugging
-             || (do_debug_info     && (strcmp (name, "info") == 0))
-             || (do_debug_abbrevs  && (strcmp (name, "abbrev") == 0))
-             || (do_debug_lines    && (strcmp (name, "line") == 0))
-             || (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))
-             || (do_debug_str      && (strcmp (name, "str") == 0))
-             || (do_debug_loc      && (strcmp (name, "loc") == 0))
+             || (do_debug_info     && streq (name, "info"))
+             || (do_debug_abbrevs  && streq (name, "abbrev"))
+             || (do_debug_lines    && streq (name, "line"))
+             || (do_debug_pubnames && streq (name, "pubnames"))
+             || (do_debug_aranges  && streq (name, "aranges"))
+             || (do_debug_ranges   && streq (name, "ranges"))
+             || (do_debug_frames   && streq (name, "frame"))
+             || (do_debug_macinfo  && streq (name, "macinfo"))
+             || (do_debug_str      && streq (name, "str"))
+             || (do_debug_loc      && streq (name, "loc"))
              )
            request_dump (i, DEBUG_DUMP);
        }
       /* linkonce section to be combined with .debug_info at link time.  */
       else if ((do_debugging || do_debug_info)
-              && strncmp (name, ".gnu.linkonce.wi.", 17) == 0)
+              && strneq (name, ".gnu.linkonce.wi.", 17))
        request_dump (i, DEBUG_DUMP);
-      else if (do_debug_frames && strcmp (name, ".eh_frame") == 0)
+      else if (do_debug_frames && streq (name, ".eh_frame"))
        request_dump (i, DEBUG_DUMP);
     }
 
@@ -4071,6 +4087,7 @@ struct
 };
 
 /* Process the reloc section.  */
+
 static int
 process_relocs (FILE *file)
 {
@@ -4434,7 +4451,7 @@ slurp_ia64_unwind_table (FILE *file,
              sym = aux->symtab + ELF64_R_SYM (rp->r_info);
            }
 
-         if (strncmp (relname, "R_IA64_SEGREL", 13) != 0)
+         if (! strneq (relname, "R_IA64_SEGREL", 13))
            {
              warn (_("Skipping unexpected relocation type %s\n"), relname);
              continue;
@@ -4522,42 +4539,38 @@ ia64_process_unwind (FILE *file)
          for (; g != NULL; g = g->next)
            {
              sec = SECTION_HEADER (g->section_index);
-             if (strcmp (SECTION_NAME (sec),
-                         ELF_STRING_ia64_unwind_info) == 0)
+
+             if (streq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info))
                break;
            }
 
          if (g == NULL)
            i = elf_header.e_shnum;
        }
-      else if (strncmp (SECTION_NAME (unwsec),
-                       ELF_STRING_ia64_unwind_once, len) == 0)
+      else if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once, len))
        {
-         /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO */
+         /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.ia64unwi.FOO */
          len2 = sizeof (ELF_STRING_ia64_unwind_info_once) - 1;
          suffix = SECTION_NAME (unwsec) + len;
          for (i = 0, sec = section_headers; i < elf_header.e_shnum;
               ++i, ++sec)
-           if (strncmp (SECTION_NAME (sec),
-                        ELF_STRING_ia64_unwind_info_once, len2) == 0
-               && strcmp (SECTION_NAME (sec) + len2, suffix) == 0)
+           if (strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info_once, len2)
+               && streq (SECTION_NAME (sec) + len2, suffix))
              break;
        }
       else
        {
          /* .IA_64.unwindFOO -> .IA_64.unwind_infoFOO
-            .IA_64.unwind or BAR -> .IA_64.unwind_info */
+            .IA_64.unwind or BAR -> .IA_64.unwind_info */
          len = sizeof (ELF_STRING_ia64_unwind) - 1;
          len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
          suffix = "";
-         if (strncmp (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind,
-                      len) == 0)
+         if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind, len))
            suffix = SECTION_NAME (unwsec) + len;
          for (i = 0, sec = section_headers; i < elf_header.e_shnum;
               ++i, ++sec)
-           if (strncmp (SECTION_NAME (sec),
-                        ELF_STRING_ia64_unwind_info, len2) == 0
-               && strcmp (SECTION_NAME (sec) + len2, suffix) == 0)
+           if (strneq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info, len2)
+               && streq (SECTION_NAME (sec) + len2, suffix))
              break;
        }
 
@@ -4689,12 +4702,12 @@ dump_hppa_unwind (struct hppa_unw_aux_info *aux)
       print_vma (tp->end.offset, PREFIX_HEX);
       printf ("]\n\t");
 
-#define PF(_m) if (tp->_m) printf(#_m " ");
-#define PV(_m) if (tp->_m) printf(#_m "=%d ", tp->_m);
+#define PF(_m) if (tp->_m) printf (#_m " ");
+#define PV(_m) if (tp->_m) printf (#_m "=%d ", tp->_m);
       PF(Cannot_unwind);
       PF(Millicode);
       PF(Millicode_save_sr0);
-      /* PV(Region_description); */
+      /* PV(Region_description);  */
       PF(Entry_SR);
       PV(Entry_FR);
       PV(Entry_GR);
@@ -4722,7 +4735,7 @@ dump_hppa_unwind (struct hppa_unw_aux_info *aux)
 #undef PV
     }
 
-  printf("\n");
+  printf ("\n");
 }
 
 static int
@@ -4897,9 +4910,12 @@ slurp_hppa_unwind_table (FILE *file,
 static int
 hppa_process_unwind (FILE *file)
 {
-  Elf_Internal_Shdr *sec, *unwsec = NULL, *strsec;
-  unsigned long i, addr_size;
   struct hppa_unw_aux_info aux;
+  Elf_Internal_Shdr *unwsec = NULL;
+  Elf_Internal_Shdr *strsec;
+  Elf_Internal_Shdr *sec;
+  unsigned long addr_size;
+  unsigned long i;
 
   memset (& aux, 0, sizeof (aux));
 
@@ -4918,7 +4934,7 @@ hppa_process_unwind (FILE *file)
          aux.strtab = get_data (NULL, file, strsec->sh_offset,
                                 aux.strtab_size, _("string table"));
        }
-      else if (strcmp (SECTION_NAME(sec), ".PARISC.unwind") == 0)
+      else if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
        unwsec = sec;
     }
 
@@ -4927,9 +4943,8 @@ hppa_process_unwind (FILE *file)
 
   for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
     {
-      if (strcmp (SECTION_NAME(sec), ".PARISC.unwind") == 0)
+      if (streq (SECTION_NAME (sec), ".PARISC.unwind"))
        {
-
          printf (_("\nUnwind section "));
          printf (_("'%s'"), SECTION_NAME (sec));
 
@@ -4973,7 +4988,7 @@ process_unwind (FILE *file)
 
   for (i = 0; handlers[i].handler != NULL; i++)
     if (elf_header.e_machine == handlers[i].machtype)
-      return handlers[i].handler(file);
+      return handlers[i].handler (file);
 
   printf (_("\nThere are no unwind sections in this file.\n"));
   return 1;
@@ -5669,7 +5684,7 @@ process_dynamic_section (FILE *file)
                    case DT_NEEDED:
                      printf (_("Shared library: [%s]"), name);
 
-                     if (strcmp (name, program_interpreter) == 0)
+                     if (streq (name, program_interpreter))
                        printf (_(" program interpreter"));
                      break;
 
@@ -6811,7 +6826,7 @@ process_syminfo (FILE *file ATTRIBUTE_UNUSED)
 }
 
 #ifdef SUPPORT_DISASSEMBLY
-static void
+static int
 disassemble_section (Elf_Internal_Shdr *section, FILE *file)
 {
   printf (_("\nAssembly dump of section %s\n"),
@@ -6972,6 +6987,7 @@ reset_state_machine (int is_stmt)
 
 /* Handled an extend line op.  Returns true if this is the end
    of sequence.  */
+
 static int
 process_extended_line_op (unsigned char *data, int is_stmt, int pointer_size)
 {
@@ -7042,7 +7058,7 @@ find_section (const char * name)
 
   for (i = elf_header.e_shnum, sec = section_headers + i - 1;
        i; --i, --sec)
-    if (strcmp (SECTION_NAME (sec), name) == 0)
+    if (streq (SECTION_NAME (sec), name))
       break;
 
   if (i && sec && sec->sh_size != 0)
@@ -7051,11 +7067,27 @@ find_section (const char * name)
   return NULL;
 }
 
-/* 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 unsigned int * debug_line_pointer_sizes = NULL;
-static unsigned int   num_debug_line_pointer_sizes = 0;
+/* This could just be an array of unsigned integers, but I expect
+   that we will want to extend the structure to contain other
+   information.  */
+typedef struct
+{
+  unsigned int pointer_size;
+}
+debug_info;
+
+static debug_info *   debug_information = NULL;
+static unsigned int   num_debug_info_entries = 0;
+
+static unsigned int
+get_pointer_size_of_comp_unit (unsigned int comp_unit)
+{
+  if (num_debug_info_entries == 0
+      || comp_unit >= num_debug_info_entries)
+    return 0;
+
+  return debug_information [comp_unit].pointer_size;
+}
 
 /* Locate and scan the .debug_info section in the file and record the pointer
    sizes for the compilation units in it.  Usually an executable will have
@@ -7064,7 +7096,7 @@ static unsigned int   num_debug_line_pointer_sizes = 0;
    compilation units upon success.  */
 
 static unsigned int
-get_debug_line_pointer_sizes (FILE * file)
+get_debug_info (FILE * file)
 {
   Elf_Internal_Shdr * section;
   unsigned char *     start;
@@ -7074,13 +7106,17 @@ get_debug_line_pointer_sizes (FILE * file)
   unsigned int        num_units;
   unsigned int        unit;
 
+  /* If we already have the information there is nothing else to do.  */
+  if (num_debug_info_entries > 0)
+    return num_debug_info_entries;
+
   section = find_section (".debug_info");
   if (section == NULL)
     return 0;
 
   length = section->sh_size;
   start = get_data (NULL, file, section->sh_offset, section->sh_size,
-                   _("extracting pointer sizes from .debug_info section"));
+                   _("extracting information from .debug_info section"));
   if (start == NULL)
     return 0;
 
@@ -7109,11 +7145,11 @@ get_debug_line_pointer_sizes (FILE * file)
       return 0;
     }
 
-  /* Then allocate an array to hold the pointer sizes.  */
-  debug_line_pointer_sizes = malloc (num_units * sizeof * debug_line_pointer_sizes);
-  if (debug_line_pointer_sizes == NULL)
+  /* Then allocate an array to hold the information.  */
+  debug_information = malloc (num_units * sizeof * debug_information);
+  if (debug_information == NULL)
     {
-      error (_("Not enough memory for a pointer size array of %u entries"),
+      error (_("Not enough memory for a debug info array of %u entries"),
             num_units);
       free (start);
       return 0;
@@ -7134,7 +7170,7 @@ get_debug_line_pointer_sizes (FILE * file)
             -----------------------------
             Total:               22 bytes  */
 
-         debug_line_pointer_sizes [unit] = byte_get (begin + 22, 1);
+         debug_information [unit].pointer_size = byte_get (begin + 22, 1);
          length = byte_get (begin + 4, 8);
          begin += length + 12;
        }
@@ -7149,40 +7185,39 @@ get_debug_line_pointer_sizes (FILE * file)
             -----------------------------
             Total:               10 bytes  */
 
-         debug_line_pointer_sizes [unit] = byte_get (begin + 10, 1);
+         debug_information [unit].pointer_size = byte_get (begin + 10, 1);
          begin += length + 4;
        }
     }
 
   free (start);
-  num_debug_line_pointer_sizes = num_units;
-  return num_units;
+
+  return num_debug_info_entries = num_units;
 }
 
 static int
 display_debug_lines (Elf_Internal_Shdr *section,
                     unsigned char *start, FILE *file)
 {
-  unsigned char *hdrptr;
-  DWARF2_Internal_LineInfo info;
-  unsigned char *standard_opcodes;
   unsigned char *data = start;
   unsigned char *end = start + section->sh_size;
-  unsigned char *end_of_sequence;
-  int i;
-  int offset_size;
-  int initial_length_size;
   unsigned int comp_unit = 0;
 
   printf (_("\nDump of debug contents of section %s:\n\n"),
          SECTION_NAME (section));
 
-  if (num_debug_line_pointer_sizes == 0)
-    get_debug_line_pointer_sizes (file);
+  get_debug_info (file);
 
   while (data < end)
     {
+      DWARF2_Internal_LineInfo info;
+      unsigned char *standard_opcodes;
+      unsigned char *end_of_sequence;
+      unsigned char *hdrptr;
       unsigned int pointer_size;
+      int initial_length_size;
+      int offset_size;
+      int i;
 
       hdrptr = data;
 
@@ -7239,16 +7274,13 @@ display_debug_lines (Elf_Internal_Shdr *section,
 
       /* Get the pointer size from the comp unit associated
         with this block of line number information.  */
-      if (comp_unit >= num_debug_line_pointer_sizes)
+      pointer_size = get_pointer_size_of_comp_unit (comp_unit);
+      if (pointer_size == 0)
        {
          error (_("Not enough comp units for .debug_line section\n"));
          return 0;
        }
-      else
-       {
-         pointer_size = debug_line_pointer_sizes [comp_unit];
-         comp_unit ++;
-       }
+      comp_unit ++;
 
       printf (_("  Length:                      %ld\n"), info.li_length);
       printf (_("  DWARF Version:               %d\n"), info.li_version);
@@ -7326,7 +7358,6 @@ display_debug_lines (Elf_Internal_Shdr *section,
       /* Now display the statements.  */
       printf (_("\n Line Number Statements:\n"));
 
-
       while (data < end_of_sequence)
        {
          unsigned char op_code;
@@ -7433,16 +7464,14 @@ display_debug_lines (Elf_Internal_Shdr *section,
 
            default:
              printf (_("  Unknown opcode %d with operands: "), op_code);
-             {
-               int i;
-               for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
-                 {
-                   printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0),
-                           i == 1 ? "" : ", ");
-                   data += bytes_read;
-                 }
-               putchar ('\n');
-             }
+
+             for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
+               {
+                 printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0),
+                         i == 1 ? "" : ", ");
+                 data += bytes_read;
+               }
+             putchar ('\n');
              break;
            }
        }
@@ -7952,7 +7981,8 @@ display_debug_macinfo (Elf_Internal_Shdr *section,
            filenum = read_leb128 (curr, & bytes_read, 0);
            curr += bytes_read;
 
-           printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"), lineno, filenum);
+           printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"),
+                   lineno, filenum);
          }
          break;
 
@@ -7965,7 +7995,8 @@ display_debug_macinfo (Elf_Internal_Shdr *section,
          curr += bytes_read;
          string = curr;
          curr += strlen (string) + 1;
-         printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"), lineno, string);
+         printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
+                 lineno, string);
          break;
 
        case DW_MACINFO_undef:
@@ -7973,7 +8004,8 @@ display_debug_macinfo (Elf_Internal_Shdr *section,
          curr += bytes_read;
          string = curr;
          curr += strlen (string) + 1;
-         printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"), lineno, string);
+         printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
+                 lineno, string);
          break;
 
        case DW_MACINFO_vendor_ext:
@@ -7984,7 +8016,8 @@ display_debug_macinfo (Elf_Internal_Shdr *section,
            curr += bytes_read;
            string = curr;
            curr += strlen (string) + 1;
-           printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"), constant, string);
+           printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
+                   constant, string);
          }
          break;
        }
@@ -8023,11 +8056,9 @@ display_debug_abbrev (Elf_Internal_Shdr *section,
                  entry->children ? _("has children") : _("no children"));
 
          for (attr = entry->first_attr; attr; attr = attr->next)
-           {
-             printf (_("    %-18s %s\n"),
-                     get_AT_name (attr->attribute),
-                     get_FORM_name (attr->form));
-           }
+           printf (_("    %-18s %s\n"),
+                   get_AT_name (attr->attribute),
+                   get_FORM_name (attr->form));
        }
 
       free_abbrevs ();
@@ -8438,8 +8469,7 @@ display_debug_loc (Elf_Internal_Shdr *section,
       return 0;
     }
 
-  if (num_debug_line_pointer_sizes == 0)
-    get_debug_line_pointer_sizes (file);
+  get_debug_info (file);
 
   printf (_("Contents of the .debug_loc section:\n\n"));
   printf (_("\n    Offset   Begin    End      Expression\n"));
@@ -8456,16 +8486,13 @@ display_debug_loc (Elf_Internal_Shdr *section,
 
       /* Get the pointer size from the comp unit associated
         with this block of location information.  */
-      if (comp_unit >= num_debug_line_pointer_sizes)
+      pointer_size = get_pointer_size_of_comp_unit (comp_unit);
+      if (pointer_size == 0)
        {
          error (_("Not enough comp units for .debug_loc section\n"));
          return 0;
        }
-      else
-       {
-         pointer_size = debug_line_pointer_sizes [comp_unit];
-         comp_unit ++;
-       }
+      comp_unit ++;
 
       while (1)
        {
@@ -8603,6 +8630,156 @@ display_debug_str (Elf_Internal_Shdr *section,
   return 1;
 }
 
+static const char *   debug_range_contents;
+static unsigned long  debug_range_size;
+
+static void
+load_debug_range (FILE *file)
+{
+  Elf_Internal_Shdr *sec;
+
+  /* If it is already loaded, do nothing.  */
+  if (debug_range_contents != NULL)
+    return;
+
+  /* Locate the .debug_str section.  */
+  sec = find_section (".debug_ranges");
+  if (sec == NULL)
+    return;
+
+  debug_range_size = sec->sh_size;
+
+  debug_range_contents = get_data (NULL, file, sec->sh_offset, sec->sh_size,
+                                  _("debug_range section data"));
+}
+
+static void
+free_debug_range (void)
+{
+  if (debug_range_contents == NULL)
+    return;
+
+  free ((char *) debug_range_contents);
+  debug_range_contents = NULL;
+  debug_range_size = 0;
+}
+
+
+/* Decode a DW_AT_ranges attribute for 64bit DWARF3 .  */
+
+static void
+decode_64bit_range (unsigned long offset, bfd_vma base_address)
+{
+  const char * start = debug_range_contents + offset;
+  const char * end   = debug_range_contents + debug_range_size;
+
+  do
+    {
+      bfd_vma a;
+      bfd_vma b;
+
+      a = byte_get ((unsigned char *) start, 8);
+      b = byte_get ((unsigned char *) start + 8, 8);
+
+      if (a == 0xffffffff)
+       {
+         base_address = b;
+       }
+      else if (a == 0 && b == 0)
+       break;
+      else if (a > b)
+       printf (_(" [corrupt: start > end]"));
+      else
+       {
+         printf (" ");
+         print_vma (base_address + a, PREFIX_HEX);
+         printf (" - ");
+         print_vma (base_address + b, PREFIX_HEX);
+         printf (", ");
+       }
+
+      start += 16;
+    }
+  while (start < end);
+}
+
+/* Decode a DW_AT_ranges attribute.  */
+
+static void
+decode_range (unsigned long offset, bfd_vma base_address)
+{
+  const char * start;
+  const char * end;
+
+  if (offset >= (debug_range_size - 8))
+    {
+      printf (_("[corrupt: offset is outside the .debug_ranges section]"));
+      return;
+    }
+
+  /* Since all entries in the .debug_ranges section are pairs of either
+     4-byte integers (32-bit DWARF3) or 8-byte integers (64-bit DWARF3)
+     the offset should always be a multiple of 8 bytes.  */
+  if (offset % 8)
+    {
+      printf (_("[corrupt: offset is not a multiple of 8]"));
+      return;
+    }  
+
+  start = debug_range_contents + offset;
+
+  if (offset > 0
+      /* Be paranoid - check to see if the previous
+        two words were and end-of-range marker.  */
+      && (byte_get ((unsigned char *) start - 4, 4) != 0
+         || byte_get ((unsigned char *) start - 8, 4) != 0))
+    {
+      printf (_("[corrupt: offset is not at the start of a range]"));
+      return;
+    }  
+
+  end = debug_range_contents + debug_range_size;
+
+  printf ("(");
+  do
+    {
+      unsigned long a;
+      unsigned long b;
+
+      a = byte_get ((unsigned char *) start, 4);
+      b = byte_get ((unsigned char *) start + 4, 4);
+
+      if (a == 0xffffffff)
+       {
+         if (b == 0xffffffff)
+           {
+             decode_64bit_range (offset, base_address);
+             return;
+           }
+
+         base_address = b;
+       }
+      else if (a == 0 && b == 0)
+       break;
+      else if (a > b)
+       printf (_("[corrupt: start > end]"));
+      else
+       {
+         if (start > debug_range_contents + offset)
+           printf (", ");
+
+         printf (_("0x%lx - 0x%lx"),
+                 (unsigned long) base_address + a,
+                 (unsigned long) base_address + b);
+       }
+
+      start += 8;
+    }
+  while (start < end);
+  printf (")");
+}
+
+
 static unsigned char *
 read_and_display_attr_value (unsigned long attribute,
                             unsigned long form,
@@ -8612,6 +8789,7 @@ read_and_display_attr_value (unsigned long attribute,
                             unsigned long offset_size,
                             int dwarf_version)
 {
+  static unsigned long saved_DW_AT_low_pc = 0;
   unsigned long uvalue = 0;
   unsigned char *block_start = NULL;
   int bytes_read;
@@ -8925,11 +9103,20 @@ read_and_display_attr_value (unsigned long attribute,
          printf (")");
        }
       else if (form == DW_FORM_data4 || form == DW_FORM_data8)
-       {
-         printf ("(");
-         printf ("location list");
-         printf (")");
-       }
+       printf (_("(location list)"));
+
+      break;
+
+    case DW_AT_low_pc:
+      /* This is a hack.  We keep track of the DW_AT_low_pc attributes
+        and use them when decoding DW_AT_ranges attributes.  The
+        assumption here is that we are decoding the attributes in order
+        and so the correct base address for the range is the low_pc.  */
+      saved_DW_AT_low_pc = uvalue;
+      break;
+
+    case DW_AT_ranges:
+      decode_range (uvalue, saved_DW_AT_low_pc);
       break;
 
     default:
@@ -9007,10 +9194,15 @@ debug_apply_rela_addends (FILE *file,
              sym = symtab + ELF32_R_SYM (rp->r_info);
 
              if (ELF32_R_SYM (rp->r_info) != 0
-                 && ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
+                 && ELF32_ST_TYPE (sym->st_info) != STT_SECTION
+                 /* Relocations against object symbols can happen,
+                    eg when referencing a global array.  For an
+                    example of this see the _clz.o binary in libgcc.a.  */
+                 && ELF32_ST_TYPE (sym->st_info) != STT_OBJECT)
                {
-                 warn (_("Skipping unexpected symbol type %u\n"),
-                       ELF32_ST_TYPE (sym->st_info));
+                 warn (_("%s: skipping unexpected symbol type %s in relocation in section .rela%s\n"),
+                       get_symbol_type (ELF32_ST_TYPE (sym->st_info)),
+                       SECTION_NAME (section));
                  continue;
                }
            }
@@ -9019,10 +9211,12 @@ debug_apply_rela_addends (FILE *file,
              sym = symtab + ELF64_R_SYM (rp->r_info);
 
              if (ELF64_R_SYM (rp->r_info) != 0
-                 && ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
+                 && ELF64_ST_TYPE (sym->st_info) != STT_SECTION
+                 && ELF64_ST_TYPE (sym->st_info) != STT_OBJECT)
                {
-                 warn (_("Skipping unexpected symbol type %u\n"),
-                       ELF64_ST_TYPE (sym->st_info));
+                 warn (_("skipping unexpected symbol type %s in relocation in section .rela.%s\n"),
+                       get_symbol_type (ELF64_ST_TYPE (sym->st_info)),
+                       SECTION_NAME (section));
                  continue;
                }
            }
@@ -9049,6 +9243,7 @@ display_debug_info (Elf_Internal_Shdr *section,
 
   load_debug_str (file);
   load_debug_loc (file);
+  load_debug_range (file);
 
   while (start < end)
     {
@@ -9188,6 +9383,7 @@ display_debug_info (Elf_Internal_Shdr *section,
        }
     }
 
+  free_debug_range ();
   free_debug_str ();
   free_debug_loc ();
 
@@ -9292,6 +9488,95 @@ display_debug_aranges (Elf_Internal_Shdr *section,
   return 1;
 }
 
+static int
+display_64bit_debug_ranges (unsigned char * start, unsigned char * end)
+{
+  bfd_vma base_address = 0;
+
+  while (start < end)
+    {
+      bfd_vma a, b;
+
+      a = byte_get (start, 8);
+      b = byte_get (start + 8, 8);
+
+      if (a == 0xffffffffffffffffLL)
+       {
+         printf (_(" set base address to "));
+         print_vma (b, PREFIX_HEX);
+         base_address = b;
+       }
+      else if (a == 0 && b == 0)
+       printf ( _("end of range"));
+      else if (a > b)
+       printf (_(" <corrupt range entry, start is greater than end>"));
+      else if (base_address == 0)
+       {
+         printf ("range from base address + ");
+         print_vma (a, PREFIX_HEX);
+         printf (" to base address + ");
+         print_vma (b, PREFIX_HEX);
+       }
+      else
+       {
+         printf ("range from ");
+         print_vma (base_address + a, PREFIX_HEX);
+         printf (" to ");
+         print_vma (base_address + b, PREFIX_HEX);
+       }
+
+      start += 16;
+      printf ("\n");
+    }
+
+  return 1;
+}
+
+static int
+display_debug_ranges (Elf_Internal_Shdr *section,
+                     unsigned char *start,
+                     FILE *file ATTRIBUTE_UNUSED)
+{
+  unsigned long base_address = 0;
+  unsigned char *end = start + section->sh_size;
+
+  printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
+
+  while (start < end)
+    {
+      unsigned long a;
+      unsigned long b;
+
+      a = byte_get (start, 4);
+      b = byte_get (start + 4, 4);
+
+      if (a == 0xffffffff)
+       {
+         /* Attempt to handle 64-bit DWARF3 format.  This assumes
+            that in a 32-bit DWARF3 file the base address will
+            never be 0xffffffff, and that the .debug_ranges section
+            will never contain a mixture of 32-bit and 64-bit entries.  */
+         if (b == 0xffffffff)
+           return display_64bit_debug_ranges (start, end);
+      
+         printf (_(" set base address to 0x%lx\n"), b);
+         base_address = b;
+       }
+      else if (a == 0 && b == 0)
+       printf (_(" end of range\n"));
+      else if (a > b)
+       printf (_(" <corrupt range entry, start is greater than end>\n"));
+      else if (base_address == 0)
+       printf (_(" range from base address + 0x%lx to base address + 0x%lx\n"), a, b);
+      else
+       printf (_(" range from 0x%lx to 0x%lx\n"), base_address + a, base_address + b);
+
+      start += 8;
+    }
+
+  return 1;
+}
+
 typedef struct Frame_Chunk
 {
   struct Frame_Chunk *next;
@@ -9439,7 +9724,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
   Frame_Chunk *chunks = 0;
   Frame_Chunk *remembered_state = 0;
   Frame_Chunk *rs;
-  int is_eh = (strcmp (SECTION_NAME (section), ".eh_frame") == 0);
+  int is_eh = streq (SECTION_NAME (section), ".eh_frame");
   int length_return;
   int max_regs = 0;
   int addr_size = is_32bit_elf ? 4 : 8;
@@ -9528,7 +9813,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
              augmentation_data = start;
              start += augmentation_data_len;
            }
-         else if (strcmp (fc->augmentation, "eh") == 0)
+         else if (streq (fc->augmentation, "eh"))
            {
              start += addr_size;
              fc->code_factor = LEB ();
@@ -9687,8 +9972,8 @@ display_debug_frames (Elf_Internal_Shdr *section,
            }
        }
 
-      /* At this point, fc is the current chunk, cie (if any) is set, and we're
-        about to interpret instructions for the chunk.  */
+      /* At this point, fc is the current chunk, cie (if any) is set, and
+        we're about to interpret instructions for the chunk.  */
       /* ??? At present we need to do this always, since this sizes the
         fc->col_type and fc->col_offset arrays, which we write into always.
         We should probably split the interpreted and non-interpreted bits
@@ -10089,7 +10374,7 @@ display_debug_frames (Elf_Internal_Shdr *section,
              break;
 
            default:
-             fprintf (stderr, "unsupported or unknown DW_CFA_%d\n", op);
+             warn (_("unsupported or unknown DW_CFA_%d\n"), op);
              start = block_end;
            }
        }
@@ -10140,7 +10425,7 @@ debug_displays[] =
   { ".debug_str",              display_debug_str },
   { ".debug_loc",              display_debug_loc },
   { ".debug_pubtypes",         display_debug_pubnames },
-  { ".debug_ranges",           display_debug_not_supported },
+  { ".debug_ranges",           display_debug_ranges },
   { ".debug_static_func",      display_debug_not_supported },
   { ".debug_static_vars",      display_debug_not_supported },
   { ".debug_types",            display_debug_not_supported },
@@ -10152,7 +10437,7 @@ display_debug_section (Elf_Internal_Shdr *section, FILE *file)
 {
   char *name = SECTION_NAME (section);
   bfd_size_type length;
-  unsigned char *start;
+  int result = 1;
   int i;
 
   length = section->sh_size;
@@ -10162,42 +10447,50 @@ display_debug_section (Elf_Internal_Shdr *section, FILE *file)
       return 0;
     }
 
-  start = get_data (NULL, file, section->sh_offset, length,
-                   _("debug section data"));
-  if (!start)
-    return 0;
-
-  /* See if we know how to display the contents of this section.  */
-  if (strncmp (name, ".gnu.linkonce.wi.", 17) == 0)
+  if (strneq (name, ".gnu.linkonce.wi.", 17))
     name = ".debug_info";
 
+  /* See if we know how to display the contents of this section.  */
   for (i = NUM_ELEM (debug_displays); i--;)
-    if (strcmp (debug_displays[i].name, name) == 0)
+    if (streq (debug_displays[i].name, name))
       {
-       debug_displays[i].display (section, start, file);
+       unsigned char *start;
+
+       start = get_data (NULL, file, section->sh_offset, length,
+                         _("debug section data"));
+       if (start == NULL)
+         {
+           result = 0;
+           break;
+         }
+
+       result &= debug_displays[i].display (section, start, file);
+       free (start);
+
+       /* If we loaded in the abbrev section
+          at some point, we must release it here.  */
+       free_abbrevs ();
+
        break;
       }
 
   if (i == -1)
-    printf (_("Unrecognized debug section: %s\n"), name);
-
-  free (start);
-
-  /* If we loaded in the abbrev section at some point,
-     we must release it here.  */
-  free_abbrevs ();
+    {
+      printf (_("Unrecognized debug section: %s\n"), name);
+      result = 0;
+    }
 
-  return 1;
+  return result;
 }
 
-static int
+static void
 process_section_contents (FILE *file)
 {
   Elf_Internal_Shdr *section;
   unsigned int i;
 
   if (! do_dump)
-    return 1;
+    return;
 
   for (i = 0, section = section_headers;
        i < elf_header.e_shnum && i < num_dump_sects;
@@ -10214,10 +10507,11 @@ process_section_contents (FILE *file)
        display_debug_section (section, file);
     }
 
-  if (i < num_dump_sects)
-    warn (_("Some sections were not dumped because they do not exist!\n"));
-
-  return 1;
+  /* Check to see if the user requested a
+     dump of a section that does not exist.  */
+  while (i++ < num_dump_sects)
+    if (dump_sects[i])
+      warn (_("Section %d was not dumped because it does not exist!\n"), i);
 }
 
 static void
@@ -10835,7 +11129,7 @@ process_note (Elf_Internal_Note *pnote)
        note type strings.  */
     nt = get_note_type (pnote->type);
 
-  else if (strncmp (pnote->namedata, "NetBSD-CORE", 11) == 0)
+  else if (strneq (pnote->namedata, "NetBSD-CORE", 11))
     /* NetBSD-specific core file notes.  */
     nt = get_netbsd_elfcore_note_type (pnote->type);
 
@@ -11129,6 +11423,23 @@ process_object (char *file_name, FILE *file)
   if (show_name)
     printf (_("\nFile: %s\n"), file_name);
 
+  /* Initialise the dump_sects array from the cmdline_dump_sects array.
+     Note we do this even if cmdline_dump_sects is empty because we
+     must make sure that the dump_sets array is zeroed out before each
+     object file is processed.  */
+  if (num_dump_sects > num_cmdline_dump_sects)
+    memset (dump_sects, 0, num_dump_sects);
+
+  if (num_cmdline_dump_sects > 0)
+    {
+      if (num_dump_sects == 0)
+       /* A sneaky way of allocating the dump_sects array.  */
+       request_dump (num_cmdline_dump_sects, 0);
+
+      assert (num_dump_sects >= num_cmdline_dump_sects);
+      memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects);
+    }
+  
   if (! process_file_header ())
     return 1;
 
@@ -11226,6 +11537,13 @@ process_object (char *file_name, FILE *file)
       section_groups = NULL;
     }
 
+  if (debug_information)
+    {
+      free (debug_information);
+      debug_information = NULL;
+      num_debug_info_entries = 0;
+    }
+
   return 0;
 }
 
@@ -11294,7 +11612,7 @@ process_archive (char *file_name, FILE *file)
       if (fread (longnames, longnames_size, 1, file) != 1)
        {
          free (longnames);
-         error(_("%s: failed to read string table\n"), file_name);
+         error (_("%s: failed to read string table\n"), file_name);
          return 1;
        }
 
@@ -11367,7 +11685,7 @@ process_archive (char *file_name, FILE *file)
 
       archive_file_offset = ftell (file);
       archive_file_size = strtoul (arhdr.ar_size, NULL, 10);
-
+      
       ret |= process_object (namealc, file);
 
       free (namealc);
@@ -11476,8 +11794,6 @@ int
 main (int argc, char **argv)
 {
   int err;
-  char *cmdline_dump_sects = NULL;
-  unsigned num_cmdline_dump_sects = 0;
 
 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
   setlocale (LC_MESSAGES, "");
@@ -11490,13 +11806,9 @@ main (int argc, char **argv)
 
   parse_args (argc, argv);
 
-  if (optind < (argc - 1))
-    show_name = 1;
-
-  /* When processing more than one file remember the dump requests
-     issued on command line to reset them after each file.  */
-  if (optind + 1 < argc && dump_sects != NULL)
+  if (num_dump_sects > 0)
     {
+      /* Make a copy of the dump_sects array.  */
       cmdline_dump_sects = malloc (num_dump_sects);
       if (cmdline_dump_sects == NULL)
        error (_("Out of memory allocating dump request table."));
@@ -11507,19 +11819,12 @@ main (int argc, char **argv)
        }
     }
 
+  if (optind < (argc - 1))
+    show_name = 1;
+
   err = 0;
   while (optind < argc)
-    {
-      err |= process_file (argv[optind++]);
-
-      /* Reset dump requests.  */
-      if (optind < argc && dump_sects != NULL)
-       {
-         num_dump_sects = num_cmdline_dump_sects;
-         if (num_cmdline_dump_sects > 0)
-           memcpy (dump_sects, cmdline_dump_sects, num_cmdline_dump_sects);
-       }
-    }
+    err |= process_file (argv[optind++]);
 
   if (dump_sects != NULL)
     free (dump_sects);
This page took 0.05949 seconds and 4 git commands to generate.