From patchwork Thu Jun 28 14:50:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 28102 Received: (qmail 952 invoked by alias); 28 Jun 2018 14:50:42 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 830 invoked by uid 89); 28 Jun 2018 14:50:40 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=pc, sk:palves, sk:palves@, presenting X-HELO: mx1.redhat.com Received: from mx3-rdu2.redhat.com (HELO mx1.redhat.com) (66.187.233.73) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 28 Jun 2018 14:50:39 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D53544076063 for ; Thu, 28 Jun 2018 14:50:36 +0000 (UTC) Received: from localhost.localdomain (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6D6A11C71C for ; Thu, 28 Jun 2018 14:50:36 +0000 (UTC) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 1/2] Fix running to breakpoint set in inline function by lineno/address Date: Thu, 28 Jun 2018 15:50:34 +0100 Message-Id: <20180628145035.24713-1-palves@redhat.com> In-Reply-To: <77528608-be2c-5a21-e250-36e7d56ba950@redhat.com> References: <77528608-be2c-5a21-e250-36e7d56ba950@redhat.com> Commit 61b04dd04ac2 ("Change inline frame breakpoint skipping logic (fix gdb.gdb/selftest.exp)") caused a GDB crash when you set a breakpoint by line number in an inline function, and then run to the breakpoint: $ gdb -q test Reading symbols from test...done. (gdb) b inline-break.c:32 Breakpoint 1 at 0x40062f: file inline-break.c, line 32. (gdb) run Starting program: /[...]/test [1] 75618 segmentation fault /[...]/gdb -q test The problem occurs because we assume that a bp_location's symbol is not NULL, which is not true when we set the breakpoint with a linespec location: Program received signal SIGSEGV, Segmentation fault. 0x00000000006f42bb in stopped_by_user_bp_inline_frame ( stop_chain=, frame_block=) at gdb/inline-frame.c:305 305 && frame_block == SYMBOL_BLOCK_VALUE (loc->symbol)) (gdb) p loc->symbol $1 = (const symbol *) 0x0 The same thing happens if you run to a breakpoint set in an inline function by address: (gdb) b *0x40062f Breakpoint 3 at 0x40062f: file inline-break.c, line 32. To fix this, add a null pointer check, to avoid the crash, and make it so that if there's not symbol for the location, then we present the stop at the inline function. This preserves the previous behavior when e.g., setting a breakpoint by address, with "b *ADDRESS". gdb/ChangeLog: yyyy-mm-dd Pedro Alves * inline-frame.c (stopped_by_user_bp_inline_frame): Return true if the the location has no symbol. gdb/testsuite/ChangeLog: yyyy-mm-dd Pedro Alves * gdb.opt/inline-break.c (func1): Add "break here" marker. * gdb.opt/inline-break.exp: Test setting breakpoints by line number and address and running to them. --- gdb/inline-frame.c | 16 +++++++++---- gdb/testsuite/gdb.opt/inline-break.c | 2 +- gdb/testsuite/gdb.opt/inline-break.exp | 42 ++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c index 896b0004e4a..c6caf9d0c6e 100644 --- a/gdb/inline-frame.c +++ b/gdb/inline-frame.c @@ -300,10 +300,18 @@ stopped_by_user_bp_inline_frame (const block *frame_block, bpstat stop_chain) bp_location *loc = s->bp_location_at; enum bp_loc_type t = loc->loc_type; - if ((t == bp_loc_software_breakpoint - || t == bp_loc_hardware_breakpoint) - && frame_block == SYMBOL_BLOCK_VALUE (loc->symbol)) - return true; + if (t == bp_loc_software_breakpoint + || t == bp_loc_hardware_breakpoint) + { + /* If the location has a function symbol, check whether + the frame was for that inlined function. If it has + no function symbol, then assume it is. I.e., default + to presenting the stop at the innermost inline + function. */ + if (loc->symbol == nullptr + || frame_block == SYMBOL_BLOCK_VALUE (loc->symbol)) + return true; + } } } diff --git a/gdb/testsuite/gdb.opt/inline-break.c b/gdb/testsuite/gdb.opt/inline-break.c index f64a81af939..d4779299fa2 100644 --- a/gdb/testsuite/gdb.opt/inline-break.c +++ b/gdb/testsuite/gdb.opt/inline-break.c @@ -29,7 +29,7 @@ static inline ATTR int func1 (int x) { - return x * 23; + return x * 23; /* break here */ } /* A non-static inlined function that is called once. */ diff --git a/gdb/testsuite/gdb.opt/inline-break.exp b/gdb/testsuite/gdb.opt/inline-break.exp index bae76254905..68b7b89ef31 100644 --- a/gdb/testsuite/gdb.opt/inline-break.exp +++ b/gdb/testsuite/gdb.opt/inline-break.exp @@ -256,4 +256,46 @@ foreach_with_prefix func { "breakpoint hit presents stop at breakpointed function" } +# Test setting a breakpoint in an inline function by line number and +# by address, and that GDB presents the stop there. + +set line [gdb_get_line_number "break here"] + +with_test_prefix "line number" { + clean_restart $binfile + + if {![runto main]} { + untested "could not run to main" + continue + } + + # Set the breakpoint by line number, and check that GDB reports + # the breakpoint location being the inline function. + gdb_breakpoint "$srcfile:$line" + gdb_test "continue" "Breakpoint .*, func1 \\(x=1\\) at .*$srcfile:$line.*break here.*" \ + "breakpoint hit presents stop at inlined function" + + # Save the PC for the following by-address test. + set address [get_hexadecimal_valueof "\$pc" "0"] +} + +# Test setting a breakpoint in an inline function by address, and that +# GDB presents the stop there. + +with_test_prefix "address" { + + clean_restart $binfile + + if {![runto main]} { + untested "could not run to main" + continue + } + + # Set the breakpoint by address, and check that GDB reports the + # breakpoint location being the inline function. + gdb_test "break *$address" ".*Breakpoint .* at $address: file .*$srcfile, line $line." + gdb_test "continue" "Breakpoint .*, func1 \\(x=1\\) at .*$srcfile:$line.*break here.*" \ + "breakpoint hit presents stop at inlined function" +} + unset -nocomplain results