Add -ws switch to display contents of .debug_str sections
authorNick Clifton <nickc@redhat.com>
Mon, 19 Nov 2001 14:35:57 +0000 (14:35 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 19 Nov 2001 14:35:57 +0000 (14:35 +0000)
binutils/ChangeLog
binutils/doc/binutils.texi
binutils/readelf.c

index 5d09b39b378c070273b3b433f977f2773edc7ef1..1eb553ec9877b28037a241a5b19bd8ddc1a00c92 100644 (file)
@@ -1,3 +1,24 @@
+2001-11-19  Nick Clifton  <nickc@cambridge.redhat.com>
+
+       * readelf.c (do_debug_str): New variable.
+       (display_debug_str): New function: Display the contents of a
+       .debug_str section.
+       (load_debug_str): New function: Load in the contents of a
+       .debug_str section.
+       (free_debug_str): New function: Free the memory used by
+       load_debug_str().
+       (fetch_indirect_string): Retrieve a string from the .debug_str
+       section.
+       (usage): Add -ws.
+       (parse_args): Accept -ws.
+       (process_section_headers): Allow the display of the .debug_str
+       section.
+       (read_and_display_attr_value): Use fetch_indirect_string.  Show
+       offset into .debug_str section.
+       (display_debug_info): Use load_debug_str and free_debug_str.
+       (debug_displays): Add .debug_str.
+       * doc/binutils.texi: Document -ws.
+
 2001-11-19  Andreas Jaeger  <aj@suse.de>
 
        * testsuite/binutils-all/objdump.exp: Add x86-64.
index db166336bb2a2a348847f05ac7795f8844f0e51a..22c903c66f60815694226790bef929885d500234 100644 (file)
@@ -2851,7 +2851,7 @@ readelf [@option{-a}|@option{--all}]
         [@option{-V}|@option{--version-info}]
         [@option{-D}|@option{--use-dynamic}]
         [@option{-x} <number>|@option{--hex-dump=}<number>]
-        [@option{-w[liaprmf]}|@option{--debug-dump}[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames]]
+        [@option{-w[liaprmfs]}|@option{--debug-dump}[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]]
         [@option{-histogram}]
         [@option{-v}|@option{--version}]
         [@option{-W}|@option{--wide}]
@@ -2953,8 +2953,8 @@ symbols section.
 @itemx --hex-dump=<number>
 Displays the contents of the indicated section as a hexadecimal dump.
 
-@item -w[liaprmf]
-@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames]
+@item -w[liaprmfs]
+@itemx --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]
 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 fa98f7ab164a4e9831dccec0e89638779fa98e8a..a566cd26144acd523f6d9b5b13694ea23cceb05f 100644 (file)
@@ -123,6 +123,7 @@ int                     do_debug_aranges;
 int                     do_debug_frames;
 int                     do_debug_frames_interp;
 int                    do_debug_macinfo;
+int                    do_debug_str;
 int                     do_arch;
 int                     do_notes;
 int                    is_32bit_elf;
@@ -220,7 +221,11 @@ static int                display_debug_abbrev        PARAMS ((Elf32_Internal_Sh
 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 int                display_debug_str           PARAMS ((Elf32_Internal_Shdr *, unsigned char *, FILE *));
 static unsigned char *    process_abbrev_section      PARAMS ((unsigned char *, unsigned char *));
+static void               load_debug_str              PARAMS ((FILE *));
+static void               free_debug_str              PARAMS ((void));
+static const char *       fetch_indirect_string       PARAMS ((unsigned long));
 static unsigned long      read_leb128                 PARAMS ((unsigned char *, int *, int));
 static int                process_extended_line_op    PARAMS ((unsigned char *, int, int));
 static void               reset_state_machine         PARAMS ((int));
@@ -276,7 +281,7 @@ typedef int Elf32_Word;
 #define BYTE_GET8(field)       byte_get (field, 8)
 #endif
 
-#define NUM_ELEM(array)        (sizeof (array) / sizeof ((array)[0]))
+#define NUM_ELEM(array)        (sizeof (array) / sizeof ((array)[0]))
 
 #define GET_ELF_SYMBOLS(file, offset, size)                    \
   (is_32bit_elf ? get_32bit_elf_symbols (file, offset, size)   \
@@ -2072,7 +2077,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[liaprmf] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames]\n"));
+  fprintf (stdout, _("  -w[liaprmfs] or --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]\n"));
   fprintf (stdout, _("                            Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
@@ -2252,6 +2257,11 @@ parse_args (argc, argv)
                    do_debug_macinfo = 1;
                    break;
 
+                 case 's':
+                 case 'S':
+                   do_debug_str = 1;
+                   break;
+
                  default:
                    warn (_("Unrecognised debug option '%s'\n"), optarg);
                    break;
@@ -3046,7 +3056,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_macinfo)
+               || do_debug_frames || do_debug_macinfo || do_debug_str)
               && strncmp (name, ".debug_", 7) == 0)
        {
          name += 7;
@@ -3059,6 +3069,7 @@ process_section_headers (file)
              || (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))
              )
            request_dump (i, DEBUG_DUMP);
        }
@@ -4091,7 +4102,6 @@ process_dynamic_segment (file)
 
          dynamic_strings = (char *) get_data (NULL, file, offset, str_tab_len,
                                               _("dynamic string table"));
-
          break;
        }
     }
@@ -4740,12 +4750,12 @@ process_version_sections (file)
        case SHT_GNU_versym:
          {
            Elf32_Internal_Shdr *       link_section;
-           int         total;
-           int         cnt;
-           unsigned char *             edata;
-           unsigned short *            data;
-           char *              strtab;
-           Elf_Internal_Sym *          symbols;
+           int                         total;
+           int                         cnt;
+           unsigned char *             edata;
+           unsigned short *            data;
+           char *                      strtab;
+           Elf_Internal_Sym *          symbols;
            Elf32_Internal_Shdr *       string_sec;
 
            link_section = section_headers + section->sh_link;
@@ -6307,9 +6317,6 @@ get_FORM_name (form)
     }
 }
 
-static const char *debug_str;
-static bfd_vma debug_str_size;
-
 /* FIXME:  There are better and more effiecint ways to handle
    these structures.  For now though, I just want something that
    is simple to implement.  */
@@ -6933,6 +6940,123 @@ decode_location_expression (data, pointer_size, length)
 }
 
 
+static const char * debug_str_contents;
+static bfd_vma      debug_str_size;
+
+static void
+load_debug_str (file)
+     FILE * file;
+{
+  Elf32_Internal_Shdr * sec;
+  int                   i;
+
+  /* If it is already loaded, do nothing.  */
+  if (debug_str_contents != NULL)
+    return;
+
+  /* Locate the .debug_str section.  */
+  for (i = 0, sec = section_headers;
+       i < elf_header.e_shnum;
+       i ++, sec ++)
+    if (strcmp (SECTION_NAME (sec), ".debug_str") == 0)
+      break;
+
+  if (i == elf_header.e_shnum || sec->sh_size == 0)
+    return;
+
+  debug_str_size = sec->sh_size;
+
+  debug_str_contents = ((char *)
+                       get_data (NULL, file, sec->sh_offset, sec->sh_size,
+                                 _("debug_str section data")));
+}
+
+static void
+free_debug_str ()
+{
+  if (debug_str_contents == NULL)
+    return;
+
+  free ((char *) debug_str_contents);
+  debug_str_contents = NULL;
+  debug_str_size = 0;
+}
+
+static const char *
+fetch_indirect_string (offset)
+     unsigned long offset;
+{
+  if (debug_str_contents == NULL)
+    return _("<no .debug_str section>");
+
+  if (offset > debug_str_size)
+    return _("<offset is too big>");
+
+  return debug_str_contents + offset;
+}
+
+
+static int
+display_debug_str (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char *       start;
+     FILE *                file ATTRIBUTE_UNUSED;
+{
+  unsigned long   bytes;
+  bfd_vma         addr;
+
+  addr  = section->sh_addr;
+  bytes = section->sh_size;
+
+  if (bytes == 0)
+    {
+      printf (_("\nThe .debug_str section is empty.\n"));
+      return 0;
+    }
+
+  printf (_("Contents of the .debug_str section:\n\n"));
+
+  while (bytes)
+    {
+      int j;
+      int k;
+      int lbytes;
+
+      lbytes = (bytes > 16 ? 16 : bytes);
+
+      printf ("  0x%8.8lx ", (unsigned long) addr);
+
+      for (j = 0; j < 16; j++)
+       {
+         if (j < lbytes)
+           printf ("%2.2x", start [j]);
+         else
+           printf ("  ");
+
+         if ((j & 3) == 3)
+           printf (" ");
+       }
+
+      for (j = 0; j < lbytes; j++)
+       {
+         k = start [j];
+         if (k >= ' ' && k < 0x80)
+           printf ("%c", k);
+         else
+           printf (".");
+       }
+
+      putchar ('\n');
+
+      start += lbytes;
+      addr  += lbytes;
+      bytes -= lbytes;
+    }
+
+  return 1;
+}
+
+
 static unsigned char *
 read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
      unsigned long   attribute;
@@ -7061,13 +7185,8 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
       break;
 
     case DW_FORM_strp:
-      if (debug_str == NULL)
-       warn (_("DW_FORM_strp used but no .debug_str section\n"));
-      else if (uvalue >= debug_str_size)
-       warn (_("DW_FORM_strp %lx points outside of .debug_str section\n"),
-             uvalue);
-      else
-        printf (" %s", debug_str + uvalue);
+      printf (_(" (indirect string, offset: 0x%lx): "), uvalue);
+      printf (fetch_indirect_string (uvalue));
       break;
 
     case DW_FORM_indirect:
@@ -7259,23 +7378,7 @@ display_debug_info (section, start, file)
 
   printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
 
-  {
-    Elf32_Internal_Shdr * sec;
-    int i;
-
-    /* Locate the .debug_str section and read it.  */
-    for (i = 0, sec = section_headers;
-        i < elf_header.e_shnum;
-        i ++, sec ++)
-      if (strcmp (SECTION_NAME (sec), ".debug_str") == 0 && sec->sh_size != 0)
-       {
-         debug_str = (const char *)
-                     get_data (NULL, file, sec->sh_offset, sec->sh_size,
-                               _("debug_str section data"));
-         debug_str_size = sec->sh_size;
-         break;
-       }
-  }
+  load_debug_str (file);
 
   while (start < end)
     {
@@ -7378,8 +7481,7 @@ display_debug_info (section, start, file)
          continue;
        }
 
-      if (first_abbrev != NULL)
-       free_abbrevs ();
+      free_abbrevs ();
 
       /* Read in the abbrevs used by this compilation unit.  */
 
@@ -7461,11 +7563,7 @@ display_debug_info (section, start, file)
        }
     }
 
-  if (debug_str != NULL)
-    {
-      free ((char *) debug_str);
-      debug_str = NULL;
-    }
+  free_debug_str ();
 
   printf ("\n");
 
@@ -8262,22 +8360,24 @@ prescan_debug_info (section, start, file)
      sections.  */
 struct
 {
-  char * name;
+  const char * const name;
   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, 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_frame",       display_debug_frames, NULL },
+  { ".debug_info",        display_debug_info, prescan_debug_info },
+  { ".debug_line",        display_debug_lines, NULL },
+  { ".debug_pubnames",    display_debug_pubnames, NULL },
   { ".eh_frame",          display_debug_frames, NULL },
   { ".debug_macinfo",     display_debug_macinfo, NULL },
+  { ".debug_str",         display_debug_str, NULL },
+  
   { ".debug_pubtypes",    display_debug_not_supported, NULL },
-  { ".debug_str",         display_debug_not_supported, NULL },
+  { ".debug_ranges",      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 },
@@ -8324,8 +8424,7 @@ display_debug_section (section, file)
 
   /* If we loaded in the abbrev section at some point,
      we must release it here.  */
-  if (first_abbrev != NULL)
-    free_abbrevs ();
+  free_abbrevs ();
 
   return 1;
 }