This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[patch] better dwarf2 debug info for inlined functions


This patch improves the debug info generated for inlined function
calls.  This is related to the binutils bug 947 and the gcc bug 20967.

Currently, the debug info support for inlined functions is poor. 
Suppose you have a function A in file A.h inlined into main, and then
you use gdb or addr2line on an address inside the inlined function.  The
answer you get will be that you are in the function main in the file
A.h.  This is correct, but not very useful.

If gdb and/or addr2line are extended to handle DW_AT_inlined_subroutine,
then we can do better.  However, there is still one thing we can't
determine from the current debug info, and that is the line from which
an inlined function was called.  This can't be computed from surrounding
info.  We tried, and ran into numerous problems.  Instructions
scheduling, block reorg, etc may disturb the instruction chain so much
that this info can't be found.  Also, very short inline functions may
expand to 0 instructions after optimization, which means that they will
have no line number info of their own.  There is an easy solution
though, we just need to emit DW_AT_call_file and DW_AT_call_line info. 
These are part of the original DWARF2 spec, so there should be no
compatibility problems here.

With this extra info, we can now generate the same backtraces with
function inlining as we can generate without function inlining.  There
is a good description of the new result in the binutils message that
contains the addr2line patch to use this new info.  See
    http://lists.gnu.org/archive/html/bug-binutils/2005-05/msg00081.html
This has a C++ testcase using <vector>, with four levels of functions
inlined into main, and addr2line can now generate a complete backtrace
showing all four inlined functions and where they were called from.  The
stuff described here works only with this gcc patch installed.  This
binutils patch has already been installed.

We are working on an equivalent gdb patch to use this new info.

This was tested a month or so ago with an x86-linux bootstrap and make
check.  There were no regressions.  I am redoing the tests to make sure
it is still safe.  The bootstrap succeeded, the tests are still running.

I'll wait a day or two in case someone wants to comment, then I will
check it in.
-- 
Jim Wilson, GNU Tools Support, http://www.specifix.com
2005-07-06  James E Wilson  <wilson@specifixinc.com>

	* dwarf2out.c (add_call_src_coords_attributes): New.
	(gen_inlined_subroutine_die): Call it.
	(maybe_emit_file, init_file_table): Add comments.
	(prune_unused_types_walk_attribs): Pass DW_AT_call_file through
	maybe_emit_file.
	* tree-inline.c (expand_call_inline): Set BLOCK_SOURCE_LOCATION.
	* tree.h (BLOCK_SOURCE_LOCATION): New.
	(struct tree_block): New field locus.

Index: dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.602
diff -p -p -r1.602 dwarf2out.c
*** dwarf2out.c	25 Jun 2005 01:59:43 -0000	1.602
--- dwarf2out.c	7 Jul 2005 01:10:42 -0000
*************** gen_label_die (tree decl, dw_die_ref con
*** 11734,11739 ****
--- 11734,11753 ----
      }
  }
  
+ /* A helper function for gen_inlined_subroutine_die.  Add source coordinate
+    attributes to the DIE for a block STMT, to describe where the inlined
+    function was called from.  This is similar to add_src_coords_attributes.  */
+ 
+ static inline void
+ add_call_src_coords_attributes (tree stmt, dw_die_ref die)
+ {
+   expanded_location s = expand_location (BLOCK_SOURCE_LOCATION (stmt));
+   unsigned file_index = lookup_filename (s.file);
+ 
+   add_AT_unsigned (die, DW_AT_call_file, file_index);
+   add_AT_unsigned (die, DW_AT_call_line, s.line);
+ }
+ 
  /* A helper function for gen_lexical_block_die and gen_inlined_subroutine_die.
     Add low_pc and high_pc attributes to the DIE for a block STMT.  */
  
*************** gen_inlined_subroutine_die (tree stmt, d
*** 11801,11806 ****
--- 11815,11821 ----
  
        add_abstract_origin_attribute (subr_die, decl);
        add_high_low_attributes (stmt, subr_die);
+       add_call_src_coords_attributes (stmt, subr_die);
  
        decls_for_scope (stmt, subr_die, depth);
        current_function_has_inlines = 1;
*************** lookup_filename (const char *file_name)
*** 13224,13229 ****
--- 13239,13250 ----
    return i;
  }
  
+ /* If the assembler will construct the file table, then translate the compiler
+    internal file table number into the assembler file table number, and emit
+    a .file directive if we haven't already emitted one yet.  The file table
+    numbers are different because we prune debug info for unused variables and
+    types, which may include filenames.  */
+ 
  static int
  maybe_emit_file (int fileno)
  {
*************** maybe_emit_file (int fileno)
*** 13244,13249 ****
--- 13265,13272 ----
      return fileno;
  }
  
+ /* Initialize the compiler internal file table.  */
+ 
  static void
  init_file_table (void)
  {
*************** prune_unused_types_walk_attribs (dw_die_
*** 13621,13627 ****
  	     Make sure that it will get emitted.  */
  	  prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1);
  	}
!       else if (a->dw_attr == DW_AT_decl_file)
  	{
  	  /* A reference to a file.  Make sure the file name is emitted.  */
  	  a->dw_attr_val.v.val_unsigned =
--- 13644,13650 ----
  	     Make sure that it will get emitted.  */
  	  prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1);
  	}
!       else if (a->dw_attr == DW_AT_decl_file || a->dw_attr == DW_AT_call_file)
  	{
  	  /* A reference to a file.  Make sure the file name is emitted.  */
  	  a->dw_attr_val.v.val_unsigned =
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.200
diff -p -p -r1.200 tree-inline.c
*** tree-inline.c	28 Jun 2005 19:33:23 -0000	1.200
--- tree-inline.c	7 Jul 2005 01:10:42 -0000
*************** expand_call_inline (basic_block bb, tree
*** 2018,2026 ****
       statement expression is the return type of the function call.  */
    id->block = make_node (BLOCK);
    BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
    add_lexical_block (TREE_BLOCK (stmt), id->block);
  
- 
    /* Local declarations will be replaced by their equivalents in this
       map.  */
    st = id->decl_map;
--- 2019,2027 ----
       statement expression is the return type of the function call.  */
    id->block = make_node (BLOCK);
    BLOCK_ABSTRACT_ORIGIN (id->block) = fn;
+   BLOCK_SOURCE_LOCATION (id->block) = input_location;
    add_lexical_block (TREE_BLOCK (stmt), id->block);
  
    /* Local declarations will be replaced by their equivalents in this
       map.  */
    st = id->decl_map;
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.741
diff -p -p -r1.741 tree.h
*** tree.h	27 Jun 2005 12:17:16 -0000	1.741
--- tree.h	7 Jul 2005 01:10:43 -0000
*************** struct varray_head_tag;
*** 1489,1494 ****
--- 1489,1500 ----
  #define BLOCK_FRAGMENT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.fragment_origin)
  #define BLOCK_FRAGMENT_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.fragment_chain)
  
+ /* For an inlined function, this gives the location where it was called
+    from.  This is only set in the top level block, which corresponds to the
+    inlined function scope.  This is used in the debug output routines.  */
+ 
+ #define BLOCK_SOURCE_LOCATION(NODE) (BLOCK_CHECK (NODE)->block.locus)
+ 
  struct tree_block GTY(())
  {
    struct tree_common common;
*************** struct tree_block GTY(())
*** 1503,1508 ****
--- 1509,1515 ----
    tree abstract_origin;
    tree fragment_origin;
    tree fragment_chain;
+   location_t locus;
  };
  
  /* Define fields and accessors for nodes representing data types.  */

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