This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB 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]

[binutils-gdb] out of line functions nested inside inline functions.


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0fa7fe506c242b459c4c05d331e7c7d66fb52390

commit 0fa7fe506c242b459c4c05d331e7c7d66fb52390
Author: Joel Brobecker <brobecker@adacore.com>
Date:   Tue Apr 21 10:34:04 2015 -0700

    out of line functions nested inside inline functions.
    
    This patch improves the handling of out-of-line functions nested
    inside functions that have been inlined.
    
    Consider for instance a situation where function Foo_O224_021
    has a function Child1 declared in it, which itself has a function
    Child2 nested inside Child1. After compiling the program with
    optimization on, Child1 gets inlined, but not Child2.
    
    After inserting a breakpoint on Child2, and running the program
    until reaching that breakpoint, we get the following backtrace:
    
        % gdb foo_o224_021
        (gdb) break foo_o224_021.child1.child2
        (gdb) run
        [...]
        Breakpoint 1, foo_o224_021 () at foo_o224_021.adb:28
        28          Child1;
        (gdb) bt
        #0  0x0000000000402400 in foo_o224_021 () at foo_o224_021.adb:28
        #1  0x00000000004027a4 in foo_o224_021.child1 () at foo_o224_021.adb:23
        #2  0x00000000004027a4 in foo_o224_021 () at foo_o224_021.adb:28
    
    GDB reports the wrong function name for frame #0. We also get the same
    kind of error in the "Breakpoint 1, foo_o224_021 () [...]" message.
    In both cases, the function name should be foo_o224_021.child1.child2,
    and the parameters should be "s=...".
    
    What happens is that the inlined frame handling does not handle well
    the case where an inlined function is calling an out-of-line function
    which was declared inside the inlined function's scope.
    
    In particular, looking first at the inlined-frame sniffer when applying
    to frame #0:
    
            /* Calculate DEPTH, the number of inlined functions at this
               location.  */
            depth = 0;
            cur_block = frame_block;
            while (BLOCK_SUPERBLOCK (cur_block))
              {
                if (block_inlined_p (cur_block))
                  depth++;
                cur_block = BLOCK_SUPERBLOCK (cur_block);
              }
    
    What happens is that cur_block starts as the block associated
    to child2, which is not inlined. We shoud be stopping here, but
    instead, we keep walking the superblock chain, which takes us
    all the way to Foo_O224_021's block, via Child2's block. And
    since Child1 was inlined, we end up with a depth count of 1,
    wrongly making GDB think that frame #0 is an inlined frame.
    
    Same kind of issue inside skip_inline_frames.
    
    The fix is to stop checking for inlined frames as soon as we see
    a block corresponding to a function which is not inlined.  This is
    the behavior we now obtain:
    
        (gdb) run
        [...]
        Breakpoint 1, foo_o224_021.child1.child2 (s=...) at foo_o224_021.adb:9
        9               function Child2 (S : String) return Boolean is
        (gdb) bt
        #0  0x0000000000402400 in foo_o224_021.child1.child2 (s=...)
            at foo_o224_021.adb:9
        #1  0x00000000004027a4 in foo_o224_021.child1 () at foo_o224_021.adb:23
        #2  0x00000000004027a4 in foo_o224_021 () at foo_o224_021.adb:28
    
    gdb/ChangeLog:
    
            * inline-frame.c (inline_frame_sniffer, skip_inline_frames):
            Stop counting inlined frames as soon as an out-of-line function
            is found.
    
    gdb/testsuite/ChangeLog:
    
            * gdb.ada/out_of_line_in_inlined.exp: Add run and "bt" tests.

Diff:
---
 gdb/ChangeLog                                    |  6 ++++++
 gdb/inline-frame.c                               |  5 +++++
 gdb/testsuite/ChangeLog                          |  4 ++++
 gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp | 12 ++++++++++++
 4 files changed, 27 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b4bcef1..f36a762 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2015-05-05  Joel Brobecker  <brobecker@adacore.com>
+
+	* inline-frame.c (inline_frame_sniffer, skip_inline_frames):
+	Stop counting inlined frames as soon as an out-of-line function
+	is found.
+
 2014-05-05  Pierre-Marie de Rodat  <derodat@adacore.com>
 
 	* dwarf2read.c (inherit_abstract_dies): Skip
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index eec44d8..e5d7360 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -225,6 +225,8 @@ inline_frame_sniffer (const struct frame_unwind *self,
     {
       if (block_inlined_p (cur_block))
 	depth++;
+      else if (BLOCK_FUNCTION (cur_block) != NULL)
+	break;
 
       cur_block = BLOCK_SUPERBLOCK (cur_block);
     }
@@ -331,6 +333,9 @@ skip_inline_frames (ptid_t ptid)
 	      else
 		break;
 	    }
+	  else if (BLOCK_FUNCTION (cur_block) != NULL)
+	    break;
+
 	  cur_block = BLOCK_SUPERBLOCK (cur_block);
 	}
     }
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 66a87c8..63c4bf3 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
 2015-05-05  Joel Brobecker  <brobecker@adacore.com>
 
+	* gdb.ada/out_of_line_in_inlined.exp: Add run and "bt" tests.
+
+2015-05-05  Joel Brobecker  <brobecker@adacore.com>
+
 	* gdb.ada/out_of_line_in_inlined: New testcase.
 
 2015-05-05  Joel Brobecker  <brobecker@adacore.com>
diff --git a/gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp b/gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp
index ebebb6c..5301b4f 100644
--- a/gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp
+++ b/gdb/testsuite/gdb.ada/out_of_line_in_inlined.exp
@@ -29,3 +29,15 @@ clean_restart ${testfile}
 setup_xfail "*-*-*"
 gdb_test "break foo_o224_021.child1.child2" \
          "Breakpoint \[0-9\]+ at.*: file .*foo_o224_021.adb, line \[0-9\]+."
+
+gdb_run_cmd
+setup_xfail "*-*-*"
+gdb_test "" \
+         "Breakpoint $decimal, foo_o224_021\\.child1\\.child2 \\(s=\\.\\.\\.\\).*"
+
+set opt_addr_in "($hex in)?"
+setup_xfail "*-*-*"
+gdb_test "bt" \
+    [multi_line "#0 +$opt_addr_in +foo_o224_021\\.child1\\.child2 \\(s=\\.\\.\\.\\).*" \
+                "#1 +$opt_addr_in +foo_o224_021\\.child1 \\(\\).*" \
+                "#2 +$opt_addr_in +foo_o224_021 \\(\\).*" ]


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