[PATCH]: Add support for displaying location lists to readelf

Daniel Berlin dan@dberlin.org
Wed Mar 20 09:07:00 GMT 2002


We don't display them inline, because they can get very long.

This patch was tested against a gcc that can generate location lists for variables.

The output looks like this:
Contents of the .debug_loc section:


    Offset   Begin    End      Expression
    00000000 00000024 00000028 (DW_OP_fbreg: 8; )
    00000000 00000028 0000003c (DW_OP_reg0; )
    00000000 0000003c 00000040 (DW_OP_fbreg: 8; )
    00000000 00000040 00000080 (DW_OP_reg0; )
    00000000 00000080 00000084 (DW_OP_fbreg: 8; )
    00000000 00000084 0000008c (DW_OP_reg9; )
    00000000 0000008c 00000090 (DW_OP_fbreg: 8; )
    00000000 00000090 000000a0 (DW_OP_reg0; )
    00000000 000000a0 000000a4 (DW_OP_fbreg: 8; )
    00000000 000000a4 000000d0 (DW_OP_reg4; )

    0000007b 0000004c 00000050 (DW_OP_fbreg: 12; )
    0000007b 00000050 00000090 (DW_OP_reg0; )
    0000007b 00000090 00000094 (DW_OP_fbreg: 12; )
    0000007b 00000094 000000a4 (DW_OP_reg0; )
    0000007b 000000a4 000000a8 (DW_OP_fbreg: 12; )
    0000007b 000000a8 000000d0 (DW_OP_reg5; )

    000000c8 00000048 00000070 (DW_OP_fbreg: 16; )
    000000c8 00000070 000000a8 (DW_OP_reg9; )
    000000c8 000000a8 000000ac (DW_OP_fbreg: 16; )
    000000c8 000000ac 000000d0 (DW_OP_reg6; )


 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.
 
Index: readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.153
diff -c -3 -p -w -B -b -r1.153 readelf.c
*** readelf.c	2002/02/21 22:39:19	1.153
--- readelf.c	2002/03/20 17:03:45
*************** int                     do_debug_frames;
*** 127,132 ****
--- 127,133 ----
  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;
*************** static int                display_debug_
*** 227,236 ****
--- 228,241 ----
  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));
*************** usage ()
*** 2248,2254 ****
    -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\
                           Display the contents of DWARF2 debug sections\n"));
  #ifdef SUPPORT_DISASSEMBLY
    fprintf (stdout, _("\
--- 2253,2259 ----
    -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,=loc]\n\
                           Display the contents of DWARF2 debug sections\n"));
  #ifdef SUPPORT_DISASSEMBLY
    fprintf (stdout, _("\
*************** parse_args (argc, argv)
*** 2435,2440 ****
--- 2440,2450 ----
  		    do_debug_str = 1;
  		    break;
  
+ 		  case 'o':
+ 		  case 'O':
+ 		    do_debug_loc = 1;
+ 		    break;
+ 		    
  		  default:
  		    warn (_("Unrecognized debug option '%s'\n"), optarg);
  		    break;
*************** process_section_headers (file)
*** 3301,3307 ****
  	}
        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)
  	       && strncmp (name, ".debug_", 7) == 0)
  	{
  	  name += 7;
--- 3311,3318 ----
  	}
        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)
  	{
  	  name += 7;
*************** process_section_headers (file)
*** 3315,3320 ****
--- 3326,3332 ----
  	      || (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);
  	}
*************** decode_location_expression (data, pointe
*** 7187,7193 ****
--- 7199,7322 ----
      }
  }
  
+ 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;
  
*************** read_and_display_attr_value (attribute, 
*** 7591,7596 ****
--- 7720,7731 ----
  	  decode_location_expression (block_start, pointer_size, uvalue);
  	  printf (")");
  	}
+       else if (form == DW_FORM_data4)
+ 	{
+ 	  printf ("(");
+ 	  printf ("location list");
+ 	  printf (")");
+ 	}
        break;
  
      default:
*************** display_debug_info (section, start, file
*** 7627,7632 ****
--- 7762,7768 ----
    printf (_("The section %s contains:\n\n"), SECTION_NAME (section));
  
    load_debug_str (file);
+   load_debug_loc (file);
  
    while (start < end)
      {
*************** display_debug_info (section, start, file
*** 7811,7816 ****
--- 7947,7953 ----
      }
  
    free_debug_str ();
+   free_debug_loc ();
  
    printf ("\n");
  
*************** debug_displays[] =
*** 8622,8628 ****
    { ".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_ranges",      display_debug_not_supported, NULL },
    { ".debug_static_func", display_debug_not_supported, NULL },
--- 8759,8765 ----
    { ".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 },




More information about the Binutils mailing list