2002-03-20 Daniel Berlin <dan@dberlin.org>
authorDaniel Berlin <dberlin@dberlin.org>
Thu, 21 Mar 2002 05:00:58 +0000 (05:00 +0000)
committerDaniel Berlin <dberlin@dberlin.org>
Thu, 21 Mar 2002 05:00:58 +0000 (05:00 +0000)
* readelf.c: Add support for displaying dwarf2 location lists.
(do_debug_loc, debug_loc_section, debug_loc_size): New.
(parse_args): Use 'O' as shorthand for displaying location list
section.
(process_section_headers): Handle debug_loc as well.
(load_debug_loc): New.
(free_debug_loc): New.
(fetch_location_list): New.
(display_debug_loc): New.
(display_debug_info): Call load_debug_loc and free_debug_loc.
(debug_displays): We can display .debug_loc now, too.
(usage): Update usage string.
(read_and_display_attr_value): Note location lists, but don't
display them inline.

binutils/ChangeLog
binutils/readelf.c

index e2ddf9361eec608a6e4d9eebbd4d849f777d94e6..ab5604cfd5b5aacc87a33bedc5ffeb9d03709828 100644 (file)
@@ -1,3 +1,20 @@
+2002-03-20  Daniel Berlin  <dan@dberlin.org>
+
+       * readelf.c: Add support for displaying dwarf2 location lists.
+       (do_debug_loc, debug_loc_section, debug_loc_size): New.
+       (parse_args): Use 'O' as shorthand for displaying location list
+       section.
+       (process_section_headers): Handle debug_loc as well.
+       (load_debug_loc): New.
+       (free_debug_loc): New.
+       (fetch_location_list): New.
+       (display_debug_loc): New.
+       (display_debug_info): Call load_debug_loc and free_debug_loc.
+       (debug_displays): We can display .debug_loc now, too.
+       (usage): Update usage string.
+       (read_and_display_attr_value): Note location lists, but don't
+       display them inline.
+
 2002-03-18  Tom Rix  <trix@redhat.com>
 
        * Makefile.am: Add binutils emulation support.
index 1f96f1069f52e0cbd0a28fe0d04c058807675a81..2c19d61d91352944c2bbca5baa55061eeeb631d8 100644 (file)
@@ -127,6 +127,7 @@ int                     do_debug_frames;
 int                     do_debug_frames_interp;
 int                    do_debug_macinfo;
 int                    do_debug_str;
+int                     do_debug_loc;
 int                     do_arch;
 int                     do_notes;
 int                    is_32bit_elf;
@@ -227,10 +228,14 @@ static int                display_debug_aranges       PARAMS ((Elf32_Internal_Sh
 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 int                display_debug_loc           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 void               load_debug_loc              PARAMS ((FILE *));
+static void               free_debug_loc              PARAMS ((void));
+static const char *       fetch_location_list         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));
@@ -2248,7 +2253,7 @@ usage ()
   -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 --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str]\n\
+  -w --debug-dump[=line,=info,=abbrev,=pubnames,=ranges,=macro,=frames,=str,=loc]\n\
                          Display the contents of DWARF2 debug sections\n"));
 #ifdef SUPPORT_DISASSEMBLY
   fprintf (stdout, _("\
@@ -2435,6 +2440,11 @@ parse_args (argc, argv)
                    do_debug_str = 1;
                    break;
 
+                 case 'o':
+                 case 'O':
+                   do_debug_loc = 1;
+                   break;
+                   
                  default:
                    warn (_("Unrecognized debug option '%s'\n"), optarg);
                    break;
@@ -3301,7 +3311,8 @@ 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_str)
+               || do_debug_frames || do_debug_macinfo || do_debug_str
+               || do_debug_loc)
               && strncmp (name, ".debug_", 7) == 0)
        {
          name += 7;
@@ -3315,6 +3326,7 @@ process_section_headers (file)
              || (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))
              )
            request_dump (i, DEBUG_DUMP);
        }
@@ -7187,6 +7199,123 @@ decode_location_expression (data, pointer_size, length)
     }
 }
 
+static const char * debug_loc_contents;
+static bfd_vma      debug_loc_size;
+
+static void
+load_debug_loc (file)
+     FILE * file;
+{
+  Elf32_Internal_Shdr * sec;
+  unsigned int          i;
+
+  /* If it is already loaded, do nothing.  */
+  if (debug_loc_contents != NULL)
+    return;
+
+  /* Locate the .debug_loc section.  */
+  for (i = 0, sec = section_headers;
+       i < elf_header.e_shnum;
+       i ++, sec ++)
+    if (strcmp (SECTION_NAME (sec), ".debug_loc") == 0)
+      break;
+
+  if (i == elf_header.e_shnum || sec->sh_size == 0)
+    return;
+
+  debug_loc_size = sec->sh_size;
+
+  debug_loc_contents = ((char *)
+                       get_data (NULL, file, sec->sh_offset, sec->sh_size,
+                                 _("debug_loc section data")));
+}
+
+static void
+free_debug_loc ()
+{
+  if (debug_loc_contents == NULL)
+    return;
+
+  free ((char *) debug_loc_contents);
+  debug_loc_contents = NULL;
+  debug_loc_size = 0;
+}
+
+static const char *
+fetch_location_list (offset)
+     unsigned long offset;
+{
+  if (debug_loc_contents == NULL)
+    return _("<no .debug_loc section>");
+
+  if (offset > debug_loc_size)
+    return _("<offset is too big>");
+
+  return debug_loc_contents + offset;
+}
+static int
+display_debug_loc (section, start, file)
+     Elf32_Internal_Shdr * section;
+     unsigned char * start;
+     FILE * file ATTRIBUTE_UNUSED;
+{
+  unsigned char *section_end;
+  unsigned long bytes;
+  unsigned char *section_begin = start;
+  bfd_vma addr;
+  
+  addr = section->sh_addr;
+  bytes = section->sh_size;
+  section_end = start + bytes;
+  if (bytes == 0)
+    {
+      printf (_("\nThe .debug_loc section is empty.\n"));
+      return 0;
+    }
+  printf (_("Contents of the .debug_loc section:\n\n"));
+  printf (_("\n    Offset   Begin    End      Expression\n"));
+  while (start < section_end)
+    {
+      unsigned long begin;
+      unsigned long end;
+      unsigned short length;
+      unsigned long offset;
+
+      offset = start - section_begin;
+
+      while (1)
+       {
+          /* Normally, the lists in  the debug_loc section are related to a
+            given compilation unit, and thus, we would use the
+            pointer size of that compilation unit.  However, since we are
+            displaying it seperately here, we either have to store
+            pointer sizes of all compilation units, or assume they don't
+            change.   We assume, like the debug_line display, that
+            it doesn't change.  */
+         begin = byte_get (start, debug_line_pointer_size);
+         start += debug_line_pointer_size;
+         end = byte_get (start, debug_line_pointer_size);
+         start += debug_line_pointer_size;
+         
+         if (begin == 0 && end == 0)
+           break;
+         
+         begin += addr;
+         end += addr;
+         
+         length = byte_get (start, 2);
+         start += 2;
+         
+         printf ("    %8.8lx %8.8lx %8.8lx (", offset, begin, end);
+         decode_location_expression (start, debug_line_pointer_size, length);
+         printf (")\n");
+         
+         start += length;
+       }
+      printf ("\n");
+    }
+  return 1;
+}
 
 static const char * debug_str_contents;
 static bfd_vma      debug_str_size;
@@ -7591,6 +7720,12 @@ read_and_display_attr_value (attribute, form, data, cu_offset, pointer_size)
          decode_location_expression (block_start, pointer_size, uvalue);
          printf (")");
        }
+      else if (form == DW_FORM_data4)
+       {
+         printf ("(");
+         printf ("location list");
+         printf (")");
+       }
       break;
 
     default:
@@ -7627,6 +7762,7 @@ display_debug_info (section, start, file)
   printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
 
   load_debug_str (file);
+  load_debug_loc (file);
 
   while (start < end)
     {
@@ -7811,6 +7947,7 @@ display_debug_info (section, start, file)
     }
 
   free_debug_str ();
+  free_debug_loc ();
 
   printf ("\n");
 
@@ -8622,7 +8759,7 @@ debug_displays[] =
   { ".eh_frame",          display_debug_frames, NULL },
   { ".debug_macinfo",     display_debug_macinfo, NULL },
   { ".debug_str",         display_debug_str, NULL },
-  
+  { ".debug_loc",         display_debug_loc, NULL },
   { ".debug_pubtypes",    display_debug_not_supported, NULL },
   { ".debug_ranges",      display_debug_not_supported, NULL },
   { ".debug_static_func", display_debug_not_supported, NULL },