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


Hi again Nick.
I finally sat down to implement your proposals:

>   *) Please use xmalloc() rather than malloc().  That way you also do
>      not need to check for a NULL return pointer.
Done. I wasn't aware of xmalloc().

>   *) Please read the GNU Coding Standard:
Done. It would have been nice if

>   *) The -wL and -wl command line options ought to display different
>      comments at the start of their output, and if both switches are
>      used then both comments should be displayed.  eg:
Done.

>    *) The new command line option needs to be documented in
>       binutils/binutils.texi and mentioned in binutils/NEWS.
Done.

>    *) It would be nice to have an option to suppress the output of the
>       column number, as this can be rather confusing.  It would be
>       especially nice if this was done automatically if the column is
>       always zero, unless the user has used a command line option to
>       specifically request column numbers.
I just removed the column number from the output as gcc doesn't seem
to support it yet anyway.

>    *) It would be nice if there were headings at the start of the
>       decoded information for each compilation unit, and if you used a
>       little more white space.  eg:
Done.

>       You might also want to restrict the number of characters printed
>       for the file name unless the --wide command line option has been
>       enabled.
Done

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,2740
> 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;
>               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);
>             }
>         }
>       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]