This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] decoded output of .debug_line from readelf -wL


>  I see it now : )
>  Thanks to Caro for pointing it out in the first place, and to Daniel
>  for pointing out the obvious.

It seems that subtracting 1 from the directory index was wrong after all:

>From section 6.2.5.3 of the dwarf 3 standard document:
"The directory index represents an entry in the include_directories
section of the line
number program header. The index is LEB128(0) if the file was found in
the current
directory of the compilation, LEB128(1) if it was found in the first
directory in the
include_directories section, and so on. The directory index is ignored
for file names that
represent full path names."

So 0 means the compilation directory and directory indices start counting at 1.

I think I got it right this time

Cary: Sorry for misspelling your name in my last post.

Torleif
? config.log
? decodedline.patch
? serdep.tmp
? bfd/.libs
? bfd/Makefile
? bfd/aout32.lo
? bfd/archive.lo
? bfd/archures.lo
? bfd/bfd-in3.h
? bfd/bfd.h
? bfd/bfd.lo
? bfd/bfd_stdint.h
? bfd/bfdio.lo
? bfd/bfdver.h
? bfd/bfdwin.lo
? bfd/binary.lo
? bfd/cache.lo
? bfd/coffgen.lo
? bfd/cofflink.lo
? bfd/config.cache
? bfd/config.h
? bfd/config.log
? bfd/config.status
? bfd/corefile.lo
? bfd/cpu-i386.lo
? bfd/dwarf1.lo
? bfd/dwarf2.lo
? bfd/efi-app-ia32.lo
? bfd/efi-bsdrv-ia32.lo
? bfd/efi-rtdrv-ia32.lo
? bfd/elf-attrs.lo
? bfd/elf-eh-frame.lo
? bfd/elf-strtab.lo
? bfd/elf-vxworks.lo
? bfd/elf.lo
? bfd/elf32-gen.lo
? bfd/elf32-i386.lo
? bfd/elf32-target.h
? bfd/elf32.lo
? bfd/elflink.lo
? bfd/format.lo
? bfd/hash.lo
? bfd/i386linux.lo
? bfd/ihex.lo
? bfd/init.lo
? bfd/libbfd.la
? bfd/libbfd.lo
? bfd/libtool
? bfd/libtool-soversion
? bfd/linker.lo
? bfd/merge.lo
? bfd/ofiles
? bfd/opncls.lo
? bfd/peigen.c
? bfd/peigen.lo
? bfd/reloc.lo
? bfd/section.lo
? bfd/simple.lo
? bfd/srec.lo
? bfd/stab-syms.lo
? bfd/stabs.lo
? bfd/stamp-h1
? bfd/stamp-lib
? bfd/stamp-ofiles
? bfd/stmp-bfd-h
? bfd/syms.lo
? bfd/targets.lo
? bfd/targmatch.h
? bfd/tekhex.lo
? bfd/trad-core.lo
? bfd/doc/Makefile
? bfd/doc/aoutx.texi
? bfd/doc/archive.texi
? bfd/doc/archures.texi
? bfd/doc/bfd.info
? bfd/doc/bfdio.texi
? bfd/doc/bfdt.texi
? bfd/doc/bfdver.texi
? bfd/doc/bfdwin.texi
? bfd/doc/cache.texi
? bfd/doc/chew
? bfd/doc/coffcode.texi
? bfd/doc/core.texi
? bfd/doc/elf.texi
? bfd/doc/elfcode.texi
? bfd/doc/format.texi
? bfd/doc/hash.texi
? bfd/doc/init.texi
? bfd/doc/libbfd.texi
? bfd/doc/linker.texi
? bfd/doc/mmo.texi
? bfd/doc/opncls.texi
? bfd/doc/reloc.texi
? bfd/doc/section.texi
? bfd/doc/syms.texi
? bfd/doc/targets.texi
? bfd/po/BLD-POTFILES
? bfd/po/Makefile
? bfd/po/Makefile.in
? bfd/po/SRC-POTFILES
? binutils/.libs
? binutils/Makefile
? binutils/arlex.c
? binutils/arparse.c
? binutils/arparse.h
? binutils/config.cache
? binutils/config.h
? binutils/config.log
? binutils/config.status
? binutils/libtool
? binutils/objdump
? binutils/readelf
? binutils/size
? binutils/stamp-h1
? binutils/doc/Makefile
? binutils/doc/addr2line.1
? binutils/doc/ar.1
? binutils/doc/binutils.info
? binutils/doc/c++filt.1
? binutils/doc/cxxfilt.man
? binutils/doc/dlltool.1
? binutils/doc/nlmconv.1
? binutils/doc/nm.1
? binutils/doc/objcopy.1
? binutils/doc/objdump.1
? binutils/doc/ranlib.1
? binutils/doc/readelf.1
? binutils/doc/size.1
? binutils/doc/strings.1
? binutils/doc/strip.1
? binutils/doc/windmc.1
? binutils/doc/windres.1
? binutils/po/Makefile
? binutils/po/Makefile.in
? binutils/po/POTFILES
? intl/Makefile
? intl/config.cache
? intl/config.h
? intl/config.intl
? intl/config.log
? intl/config.status
? libiberty/Makefile
? libiberty/config.cache
? libiberty/config.h
? libiberty/config.log
? libiberty/config.status
? libiberty/needed-list
? libiberty/required-list
? libiberty/stamp-h
? libiberty/stamp-picdir
? libiberty/xhost-mkfrag
? libiberty/testsuite/Makefile
? opcodes/.libs
? opcodes/Makefile
? opcodes/config.cache
? opcodes/config.h
? opcodes/config.log
? opcodes/config.status
? opcodes/dis-buf.lo
? opcodes/dis-init.lo
? opcodes/disassemble.lo
? opcodes/i386-dis.lo
? opcodes/i386-opc.lo
? opcodes/libopcodes.la
? opcodes/libtool
? opcodes/stamp-h1
? opcodes/stamp-lib
? opcodes/po/Makefile
? opcodes/po/Makefile.in
? opcodes/po/POTFILES
Index: binutils/NEWS
===================================================================
RCS file: /cvs/src/src/binutils/NEWS,v
retrieving revision 1.69
diff -r1.69 NEWS
1a2,3
> * Added -wL switch to dump decoded contents of .debug_line.
> 
Index: binutils/dwarf.c
===================================================================
RCS file: /cvs/src/src/binutils/dwarf.c,v
retrieving revision 1.32
diff -r1.32 dwarf.c
46a47
> int do_debug_lines_addresses;
54a56
> int do_wide;
2054,2068c2056,2060
< display_debug_lines (struct dwarf_section *section, void *file)
< {
<   unsigned char *start = section->start;
<   unsigned char *data = start;
<   unsigned char *end = start + section->size;
< 
<   printf (_("\nDump of debug contents of section %s:\n\n"),
< 	  section->name);
< 
<   if (load_debug_info (file) == 0)
<     {
<       warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"),
< 	    section->name);
<       return 0;
<     }
---
> display_debug_lines_raw (struct dwarf_section *section, unsigned char *data,
>                          unsigned char *end)
> { 
>   printf (_("Raw dump of debug contents of section %s:\n\n"),
>           section->name);
2069a2062
>   unsigned char *start = section->start;
2334a2328,2754
> typedef struct
> {
>     unsigned char *name;
>     unsigned int directory_index;
>     unsigned int modification_date;
>     unsigned int length;
> } File_Entry;
> 
> /* Output a decoded representation of the .debug_line section.  */
> static int 
> display_debug_lines_decoded(struct dwarf_section *section, unsigned char *data,
>                             unsigned char *end)
> {
>   printf (_("Decoded dump of debug contents of section %s:\n\n"), 
>           section->name);
> 
>   while (data < end)
>     {
>       /* This loop amounts to one iteration per compilation unit.  */
>       DWARF2_Internal_LineInfo info;
>       unsigned char *standard_opcodes;
>       unsigned char *end_of_sequence;
>       unsigned char *hdrptr;
>       int initial_length_size;
>       int offset_size;
>       int i;
>       File_Entry *file_table = NULL;
>       unsigned char **directory_table = NULL;
>       unsigned int prev_line = 0;
> 
>       hdrptr = data;
> 
>       /* Extract information from the Line Number Program Header, */
>       /* (section 6.2.4 in the Dwarf3 doc).  */
> 
>       /* Get the length of this CU's line number information block.  */
>       info.li_length = byte_get (hdrptr, 4);
>       hdrptr += 4;
> 
>       if (info.li_length == 0xffffffff)
>         {
>           /* This section is 64-bit DWARF 3.  */
>           info.li_length = byte_get (hdrptr, 8);
>           hdrptr += 8;
>           offset_size = 8;
>           initial_length_size = 12;
>         }
>       else
>         {
>           offset_size = 4;
>           initial_length_size = 4;
>         }
>       
>       if (info.li_length + initial_length_size > section->size)
>         {
>           warn (_("The line info appears to be corrupt - "
>                   "the section is too small\n"));
>           return 0;
>         }
> 
>       /* Get this CU's Line Number Block version number.  */
>       info.li_version = byte_get (hdrptr, 2);
>       hdrptr += 2;
>       if (info.li_version != 2 && info.li_version != 3)
>         {
>           warn (_("Only DWARF version 2 and 3 line info is currently "
>                 "supported.\n"));
>           return 0;
>         }
>       
>       info.li_prologue_length = byte_get (hdrptr, offset_size);
>       hdrptr += offset_size;
>       info.li_min_insn_length = byte_get (hdrptr, 1);
>       hdrptr++;
>       info.li_default_is_stmt = byte_get (hdrptr, 1);
>       hdrptr++;
>       info.li_line_base = byte_get (hdrptr, 1);
>       hdrptr++;
>       info.li_line_range = byte_get (hdrptr, 1);
>       hdrptr++;
>       info.li_opcode_base = byte_get (hdrptr, 1);
>       hdrptr++;
> 
>       /* Sign extend the line base field.  */
>       info.li_line_base <<= 24;
>       info.li_line_base >>= 24;
>       
>       /* Find the end of this CU's Line Number Information Block. */
>       end_of_sequence = data + info.li_length + initial_length_size;
> 
>       reset_state_machine (info.li_default_is_stmt);
> 
>       /* Save a pointer to the contents of the Opcodes table.  */
>       standard_opcodes = hdrptr;
>       
>       /* Traverse the Directory table just to count entries.  */
>       data = standard_opcodes + info.li_opcode_base - 1;
>       if (*data != 0)
>         {
>           unsigned int n_directories = 0;
>           unsigned char *ptr_directory_table = data;
>           int i;
>           while (*data != 0)
>           {
> 	        data += strlen ((char *) data) + 1;
>             n_directories++;
>           }
>           /* Go through the directory table again to save the directories. */
>           directory_table = (unsigned char **)xmalloc (n_directories*sizeof(unsigned char *));
> 
>           i = 0;
>           while (*ptr_directory_table != 0)
>             {
>               directory_table[i] = ptr_directory_table;
>               ptr_directory_table += strlen ((char *) ptr_directory_table) + 1;
>               i++;
>             }
>         }
>       /* Skip the NUL at the end of the table.  */
>       data++;
> 
>       /* Traverse the File Name table just to count the entries.  */
>       if (*data != 0)
>         {
>           unsigned int n_files = 0;
>           unsigned char *ptr_file_name_table = data;
>           int i;
>           while (*data != 0)
>             {
> 	          unsigned int bytes_read;
>               /* Skip Name, directory index, last modification time and length 
>                  of file.  */
>               data += strlen ((char *) data) + 1;
>               read_leb128 (data, & bytes_read, 0);
>               data += bytes_read;
>               read_leb128 (data, & bytes_read, 0);
>               data += bytes_read;
>               read_leb128 (data, & bytes_read, 0);
>               data += bytes_read;
>               
>               n_files++;
>             }
>         
>           /* Go through the file table again to save the strings. */
>           file_table = xmalloc (n_files*sizeof(File_Entry));
> 
>           i = 0;
>           while (*ptr_file_name_table != 0)
>             {
>               unsigned int bytes_read;
> 
>               file_table[i].name = ptr_file_name_table;
>               ptr_file_name_table += strlen ((char *) ptr_file_name_table) + 1;
>               
>               /* We are not interested in directory, time or size.  */
>               file_table[i].directory_index = read_leb128 (ptr_file_name_table, 
>                                                            & bytes_read, 0);
>               ptr_file_name_table += bytes_read;
>               file_table[i].modification_date = read_leb128 (ptr_file_name_table, & bytes_read, 0);
>               ptr_file_name_table += bytes_read;
>               file_table[i].length = read_leb128 (ptr_file_name_table, & bytes_read, 0);
>               ptr_file_name_table += bytes_read;
>               i++;
>             }
>           i = 0;
> 
>           /* Print the Compilation Unit's name and a header.  */
>           if (directory_table == NULL)
>             {
>               printf (_("CU: %s:\n"), file_table[0].name);
>               printf (_("File name                            Line number    Starting address\n"));
>             }
>           else 
>             {
>               if(strlen((char *)directory_table[0]) < 76)
>                 {
>                   printf (_("CU: %s/%s:\n"), directory_table[0], 
>                           file_table[0].name);
>                 }
>               else
>                 {
>                   printf (_("%s:\n"), file_table[0].name);
>                 }
>               printf (_("File name                            Line number    Starting address\n"));
>             }
>         }
> 
>       /* Skip the NUL at the end of the table.  */
>       data++;
>       
>       /* This loop iterates through the Dwarf Line Number Program.  */
>       while (data < end_of_sequence)
>         {
> 	      unsigned char op_code;
>           int adv;
>           unsigned long int uladv;
>           unsigned int bytes_read;
>           int is_special_opcode = 0;
>           
>           op_code = *data++;
>           prev_line = state_machine_regs.line;
>           
>           if (op_code >= info.li_opcode_base)
> 	        {
> 	          op_code -= info.li_opcode_base;
>               uladv = (op_code / info.li_line_range) * info.li_min_insn_length;
>               state_machine_regs.address += uladv;
>               
>               adv = (op_code % info.li_line_range) + info.li_line_base;
>               state_machine_regs.line += adv;
>               is_special_opcode = 1;
>             }
>           else switch (op_code)
>             {
>             case DW_LNS_extended_op:
>               {
>                 unsigned int ext_op_code_len;
>                 unsigned int bytes_read;
>                 unsigned char ext_op_code;
>                 unsigned char *op_code_data = data;
> 
>                 ext_op_code_len = read_leb128 (op_code_data, &bytes_read, 0);
>                 op_code_data += bytes_read;
>         
>                 if(ext_op_code_len == 0)
>                   {
>                     warn (_("badly formed extended line op encountered!\n"));
>                     break;
>                   }
>                 ext_op_code_len += bytes_read;
>                 ext_op_code = *op_code_data++;
>                 switch (ext_op_code)
>                   {
>                   case DW_LNE_end_sequence:
>                     reset_state_machine (info.li_default_is_stmt);
>                     break;
>                   case DW_LNE_set_address:
>                     state_machine_regs.address = 
>                     byte_get (op_code_data, ext_op_code_len - bytes_read - 1);
>                     break;
>                   case DW_LNE_define_file:
>                     {
>                       unsigned int dir_index = 0;
>                       ++state_machine_regs.last_file_entry;
>                       op_code_data += strlen ((char *) op_code_data) + 1;
>                       dir_index = read_leb128 (op_code_data, & bytes_read, 0);
>                       op_code_data += bytes_read;
>                       read_leb128 (op_code_data, & bytes_read, 0);
>                       op_code_data += bytes_read;
>                       read_leb128 (op_code_data, & bytes_read, 0);
>                   
>                       printf (_("%s:\n"), directory_table[dir_index]);
>                       break;
>                     }
>                   default:
>                     printf (_("UNKNOWN: length %d\n"), ext_op_code_len - bytes_read);
>                     break;
>                   }
>                 data += ext_op_code_len;
>                 break;
>               }
>             case DW_LNS_copy:
>               break;
> 
>             case DW_LNS_advance_pc:
>               uladv = read_leb128 (data, & bytes_read, 0);
>               uladv *= info.li_min_insn_length;
>               data += bytes_read;
>               state_machine_regs.address += uladv;
>               break;
> 
>             case DW_LNS_advance_line:
>               adv = read_leb128 (data, & bytes_read, 1);
>               data += bytes_read;
>               state_machine_regs.line += adv;
>               break;
> 
>             case DW_LNS_set_file:
>               adv = read_leb128 (data, & bytes_read, 0);
>               data += bytes_read;
>               state_machine_regs.file = adv;
>               if (file_table[state_machine_regs.file - 1].directory_index == 0)
>                 {
>                   /* if index is 0, that means current directory. */
>                   printf (_("\n./%s:\n"), 
>                           file_table[state_machine_regs.file - 1].name);
>                 }
>               else
>                 {
>                   /* The directory index starts counting at 1 */
>                   printf (_("\n%s/%s:\n"), 
>                           directory_table[file_table[state_machine_regs.file - 1].directory_index], 
>                           file_table[state_machine_regs.file - 1].name);
>                 }
>               break;
> 
>             case DW_LNS_set_column:
>               uladv = read_leb128 (data, & bytes_read, 0);
>               data += bytes_read;
>               state_machine_regs.column = uladv;
>               break;
> 
>             case DW_LNS_negate_stmt:
>               adv = state_machine_regs.is_stmt;
>               adv = ! adv;
>               state_machine_regs.is_stmt = adv;
>               break;
> 
>             case DW_LNS_set_basic_block:
>               state_machine_regs.basic_block = 1;
>               break;
> 
>             case DW_LNS_const_add_pc:
>               uladv = (((255 - info.li_opcode_base) / info.li_line_range)
>                        * info.li_min_insn_length);
>               state_machine_regs.address += uladv;
>               break;
> 
>             case DW_LNS_fixed_advance_pc:
>               uladv = byte_get (data, 2);
>               data += 2;
>               state_machine_regs.address += uladv;
>               break;
> 
>             case DW_LNS_set_prologue_end:
>               break;
> 
>             case DW_LNS_set_epilogue_begin:
>               break;
> 
>             case DW_LNS_set_isa:
>               uladv = read_leb128 (data, & bytes_read, 0);
>               data += bytes_read;
>               printf (_("  Set ISA to %lu\n"), uladv);
>               break;
> 
>             default:
>               printf (_("  Unknown opcode %d with operands: "), op_code);
> 
>               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;
>             }
>         
>           /* Only Special opcodes, DW_LNS_copy and DW_LNE_end_sequence adds a row
>              to the DWARF address/line matrix.  */
>           if( (is_special_opcode) || (op_code == DW_LNE_end_sequence) ||
>               (op_code == DW_LNS_copy) )
>             {
>               const unsigned int MAX_FILENAME_LENGTH = 35;
>               char *fileName = (char *)file_table[state_machine_regs.file - 1].name;
>               char *newFileName = NULL;
>               size_t fileNameLength = strlen (fileName);
>               if( (fileNameLength > MAX_FILENAME_LENGTH) && (!do_wide) )
>                 {
>                   newFileName = xmalloc (MAX_FILENAME_LENGTH + 1);
>                   /* Truncate file name */
>                   strncpy (newFileName, 
>                            fileName + fileNameLength - MAX_FILENAME_LENGTH,
>                            MAX_FILENAME_LENGTH + 1);
>                 }
>               else
>                 {
>                   newFileName = xmalloc (fileNameLength + 1);
>                   strncpy (newFileName, fileName, fileNameLength + 1);
>                 }
>               if( !do_wide || (fileNameLength <= MAX_FILENAME_LENGTH) )
>                 {
>                   printf (_("%-35s  %11d  %#18lx\n"), newFileName, 
>                           state_machine_regs.line, state_machine_regs.address);
>                 }
>               else
>                 {
>                   printf (_("%s  %11d  %#18lx\n"), newFileName, 
>                           state_machine_regs.line, state_machine_regs.address);
>                 }
>               free (newFileName);
>               if(op_code == DW_LNE_end_sequence)
>               {
>                   printf("\n");
>               }
>             }
>         }
>       free (file_table);
>       file_table = NULL;
>       free (directory_table);
>       directory_table = NULL;
>       putchar ('\n');
>     }
> 
>   return 1;
> }
> 
> static int
> display_debug_lines (struct dwarf_section *section, void *file)
> {
>   unsigned char *data = section->start;
>   unsigned char *end = data + section->size;
>   int retValRaw = 0;
>   int retValDecoded = 0;
> 
>   if (load_debug_info (file) == 0)
>     {
>       warn (_("Unable to load/parse the .debug_info section, so cannot interpret the %s section.\n"),
>             section->name);
>       return 0;
>     }
>   
>   if (do_debug_lines)
>       retValRaw = display_debug_lines_raw (section, data, end);
>   if (do_debug_lines_addresses)
>     retValDecoded = display_debug_lines_decoded (section, data, end);
>   
>   if ( (do_debug_lines && !retValRaw) || 
>      (do_debug_lines_addresses && !retValDecoded) )
>     {
>       return 0;
>     }
>   else
>     return 1;   
> }
> 
Index: binutils/dwarf.h
===================================================================
RCS file: /cvs/src/src/binutils/dwarf.h,v
retrieving revision 1.5
diff -r1.5 dwarf.h
98a99
> extern int do_debug_lines_addresses;
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.405
diff -r1.405 readelf.c
163a164
> int do_wide;
200d200
< static int do_wide;
2884c2884
<   --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
---
>   --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=str,=loc,=Ranges]\n\
3085a3086,3089
>           case 'L':
>             do_debug_lines_addresses = 1;
>             break;
> 
4306,4308c4310,4312
< 		|| do_debug_lines || do_debug_pubnames || do_debug_aranges
< 		|| do_debug_frames || do_debug_macinfo || do_debug_str
< 		|| do_debug_loc || do_debug_ranges)
---
> 		|| do_debug_lines || do_debug_lines_addresses || do_debug_pubnames 
>         || do_debug_aranges || do_debug_frames || do_debug_macinfo 
>         || do_debug_str || do_debug_loc || do_debug_ranges)
4316c4320,4321
< 	      || (do_debug_lines    && streq (name, "line"))
---
> 	      || ( (do_debug_lines || do_debug_lines_addresses) 
>                && streq (name, "line"))
Index: binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.126
diff -r1.126 binutils.texi
3708,3709c3708,3709
<         [@option{-w[liaprmfFsoR]}|
<          @option{--debug-dump}[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]]
---
>         [@option{-w[lLiaprmfFsoR]}|
>          @option{--debug-dump}[=rawline,=decodedline,line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]]
3846,3847c3846,3847
< @item -w[liaprmfFsoR]
< @itemx --debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]
---
> @item -w[lLiaprmfFsoR]
> @itemx --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]