From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 109240 invoked by alias); 28 Feb 2018 17:11:11 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 109226 invoked by uid 89); 28 Feb 2018 17:11:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,MIME_BASE64_BLANKS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=personal, Tel X-HELO: mga07.intel.com Received: from mga07.intel.com (HELO mga07.intel.com) (134.134.136.100) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 28 Feb 2018 17:11:04 +0000 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Feb 2018 09:10:55 -0800 X-ExtLoop1: 1 Received: from irsmsx109.ger.corp.intel.com ([163.33.3.23]) by fmsmga007.fm.intel.com with ESMTP; 28 Feb 2018 09:10:54 -0800 Received: from irsmsx156.ger.corp.intel.com (10.108.20.68) by IRSMSX109.ger.corp.intel.com (163.33.3.23) with Microsoft SMTP Server (TLS) id 14.3.319.2; Wed, 28 Feb 2018 17:10:53 +0000 Received: from irsmsx104.ger.corp.intel.com ([169.254.5.101]) by IRSMSX156.ger.corp.intel.com ([169.254.3.24]) with mapi id 14.03.0319.002; Wed, 28 Feb 2018 17:10:53 +0000 From: "Metzger, Markus T" To: Yao Qi CC: "gdb-patches@sourceware.org" Subject: RE: [PATCH] btrace, gdbserver: check btrace target pointers Date: Wed, 28 Feb 2018 17:11:00 -0000 Message-ID: References: <1519727985-17914-1-git-send-email-markus.t.metzger@intel.com> <86sh9lgjxt.fsf@gmail.com> In-Reply-To: <86sh9lgjxt.fsf@gmail.com> x-ctpclassification: CTP_NT x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiM2RhNDQ0ZjUtOWI0OC00MTBjLTk4YmEtOTc0MzJiNDg1NDgyIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjIuNS4xOCIsIlRydXN0ZWRMYWJlbEhhc2giOiJ2dHZrKzFtSkxBRmRXSDJNdG9FaVkxM25yNEljXC9uT2JBSm1DbWZvU0tJdG9tV3VGMjFJV2YyNW9TS0paY1ZjMSJ9 dlp-product: dlpe-windows dlp-version: 11.0.0.116 dlp-reaction: no-action Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 X-IsSubscribed: yes X-SW-Source: 2018-02/txt/msg00472.txt.bz2 SGVsbG8gWWFvLA0KDQpUaGFua3MgZm9yIHlvdXIgcmV2aWV3Lg0KDQoNCj4g PiAtI2RlZmluZSB0YXJnZXRfZW5hYmxlX2J0cmFjZShwdGlkLCBjb25mKSBc DQo+ID4gLSAgKCp0aGVfdGFyZ2V0LT5lbmFibGVfYnRyYWNlKSAocHRpZCwg Y29uZikNCj4gPiArc3RhdGljIGlubGluZSBzdHJ1Y3QgYnRyYWNlX3Rhcmdl dF9pbmZvICoNCj4gPiArdGFyZ2V0X2VuYWJsZV9idHJhY2UgKHB0aWRfdCBw dGlkLCBjb25zdCBzdHJ1Y3QgYnRyYWNlX2NvbmZpZyAqY29uZikNCj4gPiAr ew0KPiA+ICsgIGlmICh0aGVfdGFyZ2V0LT5lbmFibGVfYnRyYWNlID09IG51 bGxwdHIpDQo+ID4gKyAgICBlcnJvciAoIlRhcmdldCBkb2VzIG5vdCBzdXBw b3J0IGJyYW5jaCB0cmFjaW5nLiIpOw0KPiA+ICsNCj4gPiArICByZXR1cm4g KCp0aGVfdGFyZ2V0LT5lbmFibGVfYnRyYWNlKSAocHRpZCwgY29uZik7DQo+ ID4gK30NCj4gDQo+IEl0IGlzIHJlYXNvbmFibGUgdG8gbWUgdGhhdCAoKnRo ZV90YXJnZXQtPmVuYWJsZV9idHJhY2UpIG1heSB0aHJvdw0KPiB2YXJpb3Vz IGV4Y2VwdGlvbnMgZHVlIHRvIGRpZmZlcmVudCByZWFzb25zLCBidXQgSSBh bSBub3QgY29udmluY2VkIHRoYXQNCj4gd2Ugc2hvdWxkIGVycm9yIG9uICh0 aGVfdGFyZ2V0LT5lbmFibGVfYnRyYWNlID09IG51bGxwdHIpLiAgSSBkb24n dCBsaWtlDQo+IHJlcGxhY2luZyBjb250cm9sIGZsb3cgbG9naWMgd2l0aCBl eGNlcHRpb24uICBUaGlzIGlzIG15IHBlcnNvbmFsDQo+IGZsYXZvci4gIElu c3RlYWQsIGNhbiB3ZSBjaGVjaw0KPiAodGhlX3RhcmdldC0+ZW5hYmxlX2J0 cmFjZSA9PSBudWxscHRyKSBiZWZvcmUgdXNpbmcNCj4gdGFyZ2V0X2VuYWJs ZV9idHJhY2UsIGFuZCBlcnJvciBpbiBoYW5kbGVfYnRyYWNlX2dlbmVyYWxf c2V0IGlmDQo+IHRocmVhZC0+YnRyYWNlIGlzIE5VTEwuICBXaGF0IGRvIHlv dSB0aGluaz8NCg0KSSBtb3ZlZCB0d28gb2YgdGhvc2UgY2hlY2tzIGludG8g dGhlIHRhcmdldF8qIG1ldGhvZCBzaW5jZSBJIHRob3VnaHQNCml0IHdvdWxk IGJlIGEgZ29vZCBpZGVhIHRvIGJlIGFibGUgdG8gaGFuZGxlIGV4Y2VwdGlv bnMgYW5kIHNpbmNlIEkgaGFkDQp0byBhZGQgdGhlIFRSWS9DQVRDSC9DQVRD SF9FTkQsIGFueXdheSwgSSB0aG91Z2h0IGl0IG1hZGUgc2Vuc2UNCnRvIGhh bmRsZSB0aGUgbnVsbHB0ciBjYXNlIGFsc28gdmlhIGV4Y2VwdGlvbnMuDQoN CklmIHdlJ3JlIG5vdCBkb2luZyBpdCB0aGF0IHdheSwgdGhlIGNhbGxlciB3 b3VsZCBuZWVkIHRvIGNoZWNrIHRoZSBwb2ludGVyDQooZWl0aGVyIGRpcmVj dGx5IG9yIHZpYSBhICpfcCAoKSBmdW5jdGlvbiBsaWtlIHdlIGRvIHdpdGgg Z2RiYXJjaCkgYW5kIHN0aWxsDQpiZSBwcmVwYXJlZCB0byBoYW5kbGUgZXhj ZXB0aW9ucyBmcm9tIHRoZSBhY3R1YWwgY2FsbC4NCg0KTXkgbW90aXZhdGlv biB3YXMgdG8gc2ltcGxpZnkgdGhlIGNhbGxlciBidXQgaWYgeW91IHRoaW5r IHRoZSBvdGhlciB3YXkNCmlzIGNsZWFyZXIgSSBjYW4gbW92ZSB0aGUgY2hl Y2sgYmFjayBpbnRvIHRoZSBjYWxsZXJzLiAgSXMgdGhhdCB5b3VyIHByZWZl cmVuY2U/DQoNClJlZ2FyZHMsDQpNYXJrdXMuDQoNCkludGVsIERldXRzY2hs YW5kIEdtYkgKUmVnaXN0ZXJlZCBBZGRyZXNzOiBBbSBDYW1wZW9uIDEwLTEy LCA4NTU3OSBOZXViaWJlcmcsIEdlcm1hbnkKVGVsOiArNDkgODkgOTkgODg1 My0wLCB3d3cuaW50ZWwuZGUKTWFuYWdpbmcgRGlyZWN0b3JzOiBDaHJpc3Rp biBFaXNlbnNjaG1pZCwgQ2hyaXN0aWFuIExhbXByZWNodGVyCkNoYWlycGVy c29uIG9mIHRoZSBTdXBlcnZpc29yeSBCb2FyZDogTmljb2xlIExhdQpSZWdp c3RlcmVkIE9mZmljZTogTXVuaWNoCkNvbW1lcmNpYWwgUmVnaXN0ZXI6IEFt dHNnZXJpY2h0IE11ZW5jaGVuIEhSQiAxODY5MjgK >From gdb-patches-return-145670-listarch-gdb-patches=sources.redhat.com@sourceware.org Wed Feb 28 20:33:30 2018 Return-Path: Delivered-To: listarch-gdb-patches@sources.redhat.com Received: (qmail 116041 invoked by alias); 28 Feb 2018 20:33:29 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 116031 invoked by uid 89); 28 Feb 2018 20:33:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=Hide, 17534 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 28 Feb 2018 20:33:26 +0000 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 304BDCFEA3 for ; Wed, 28 Feb 2018 20:33:25 +0000 (UTC) Received: from theo.uglyboxes.com (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id D3AA260BE3; Wed, 28 Feb 2018 20:33:24 +0000 (UTC) From: Keith Seitz To: gdb-patches@sourceware.org Subject: [PATCH v2] Don't elide all inlined frames Date: Wed, 28 Feb 2018 20:33:00 -0000 Message-Id: <20180228203324.17579-1-keiths@redhat.com> X-IsSubscribed: yes X-SW-Source: 2018-02/txt/msg00473.txt.bz2 Content-length: 19442 This is v2 of (one of) my original patches to fix some inline function breakpoint problems. The first patch dealing with "info break" has already been committed. What remains is the second of the two patches on which Pedro last commented on Dec. 1. This patch deals with reporting stop locations in inlined functions. [For more, read the commit log below.] Changes since v1: - Removed breakpoint_for_stop entirely - Removed changes from bpstat_explains_signal (no longer necessary) - Rewrote skip_inline_frames to walk stop chain and locations (no more calling decode_line_full) - Updated all (code) documentation - Updated new gdb.ada/bp_inlined_func.exp test (test originally stopped in calling frame) - Updated gdb.dwarf2/implptr.exp (same reason as bp_inlined_func.exp) Keith ---------- This patch essentially causes GDB to treat inlined frames like "normal" frames from the user's perspective. This means, for example, that when a user hits a breakpoint in an inlined function, GDB will now actually stop "in" that function. Using the test case from breakpoints/17534, 3 static inline void NVIC_EnableIRQ(int IRQn) 4 { 5 volatile int y; 6 y = IRQn; 7 } 8 9 __attribute__( ( always_inline ) ) static inline void __WFI(void) 10 { 11 __asm volatile ("nop"); 12 } 13 14 int main(void) { 15 16 x= 42; 17 18 if (x) 19 NVIC_EnableIRQ(16); 20 else 21 NVIC_EnableIRQ(18); (gdb) b NVIC_EnableIRQ Breakpoint 1 at 0x4003e4: NVIC_EnableIRQ. (2 locations) (gdb) r Starting program: 17534 Breakpoint 1, main () at 17534.c:19 19 NVIC_EnableIRQ(16); Because skip_inline_frames currently skips every inlined frame, GDB "stops" in the caller. This patch adds a new parameter to skip_inline_frames that allows us to pass in a bpstat stop chain. The breakpoint locations on the stop chain can be used to determine if we've stopped inside an inline function (due to a user breakpoint). If we have, we do not elide the frame. With this patch, GDB now reports that the inferior has stopped inside the inlined function: (gdb) r Starting program: 17534 Breakpoint 1, NVIC_EnableIRQ (IRQn=16) at 17534.c:6 6 y = IRQn; My thanks to Jan and Pedro for guidance on this. gdb/ChangeLog: * breakpoint.c (build_bpstat_chain): New function, moved from bpstat_stop_status. (bpstat_stop_status): Add optional parameter, `stop_chain'. If no stop chain is passed, call build_bpstat_chain to build it. * breakpoint.h (build_bpstat_chain): Declare. (bpstat_stop_status): Move documentation here from breakpoint.c. * infrun.c (handle_signal_stop): Before eliding inlined frames, build the stop chain and pass it to skip_inline_frames. Pass this stop chain to bpstat_stop_status. * inline-frame.c: Include breakpoint.h. (skip_inline_frames): Add parameter `stop_chain'. Move documention to inline-frame.h. If non-NULL, walk all locations to determine if the inlined frame caused the stop. If it did, do not elide it. * inline-frame.h (skip_inline_frames): Add parameter `stop-chain'. Add moved documentation and update for new parameter. gdb/testsuite/ChangeLog: * gdb.ada/bp_inlined_func.exp: Update inlined frame locations in expected breakpoint stop locations. * gdb.dwarf2/implptr.exp (implptr_test_baz): Use up/down to move to proper scope to test variable values. * gdb.opt/inline-break.c (inline_func1, not_inline_func1) (inline_func2, not_inline_func2, inline_func3, not_inline_func3): New functions. (main): Call not_inline_func3. * gdb.opt/inline-break.exp: Start inferior and set breakpoints at inline_func1, inline_func2, and inline_func3. Test that when each breakpoint is hit, GDB properly reports both the stop location and the backtrace. --- gdb/breakpoint.c | 79 +++++++++++++++---------------- gdb/breakpoint.h | 30 +++++++++++- gdb/infrun.c | 6 ++- gdb/inline-frame.c | 37 +++++++++++++-- gdb/inline-frame.h | 11 +++-- gdb/testsuite/gdb.ada/bp_inlined_func.exp | 20 ++------ gdb/testsuite/gdb.dwarf2/implptr.exp | 6 ++- gdb/testsuite/gdb.opt/inline-break.c | 50 +++++++++++++++++++ gdb/testsuite/gdb.opt/inline-break.exp | 35 ++++++++++++++ 9 files changed, 207 insertions(+), 67 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index c56084cce3..c4d800ceca 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -5342,54 +5342,21 @@ need_moribund_for_location_type (struct bp_location *loc) && !target_supports_stopped_by_hw_breakpoint ())); } - -/* Get a bpstat associated with having just stopped at address - BP_ADDR in thread PTID. - - Determine whether we stopped at a breakpoint, etc, or whether we - don't understand this stop. Result is a chain of bpstat's such - that: - - if we don't understand the stop, the result is a null pointer. - - if we understand why we stopped, the result is not null. - - Each element of the chain refers to a particular breakpoint or - watchpoint at which we have stopped. (We may have stopped for - several reasons concurrently.) - - Each element of the chain has valid next, breakpoint_at, - commands, FIXME??? fields. */ +/* See breakpoint.h. */ bpstat -bpstat_stop_status (const address_space *aspace, - CORE_ADDR bp_addr, ptid_t ptid, +build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr, const struct target_waitstatus *ws) { - struct breakpoint *b = NULL; - struct bp_location *bl; - struct bp_location *loc; - /* First item of allocated bpstat's. */ + struct breakpoint *b; bpstat bs_head = NULL, *bs_link = &bs_head; - /* Pointer to the last thing in the chain currently. */ - bpstat bs; - int ix; - int need_remove_insert; - int removed_any; - - /* First, build the bpstat chain with locations that explain a - target stop, while being careful to not set the target running, - as that may invalidate locations (in particular watchpoint - locations are recreated). Resuming will happen here with - breakpoint conditions or watchpoint expressions that include - inferior function calls. */ ALL_BREAKPOINTS (b) { if (!breakpoint_enabled (b)) continue; - for (bl = b->loc; bl != NULL; bl = bl->next) + for (bp_location *bl = b->loc; bl != NULL; bl = bl->next) { /* For hardware watchpoints, we look only at the first location. The watchpoint_check function will work on the @@ -5408,8 +5375,8 @@ bpstat_stop_status (const address_space *aspace, /* Come here if it's a watchpoint, or if the break address matches. */ - bs = new bpstats (bl, &bs_link); /* Alloc a bpstat to - explain stop. */ + bpstat bs = new bpstats (bl, &bs_link); /* Alloc a bpstat to + explain stop. */ /* Assume we stop. Should we find a watchpoint that is not actually triggered, or if the condition of the breakpoint @@ -5434,12 +5401,15 @@ bpstat_stop_status (const address_space *aspace, if (!target_supports_stopped_by_sw_breakpoint () || !target_supports_stopped_by_hw_breakpoint ()) { - for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) + bp_location *loc; + + for (int ix = 0; + VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix) { if (breakpoint_location_address_match (loc, aspace, bp_addr) && need_moribund_for_location_type (loc)) { - bs = new bpstats (loc, &bs_link); + bpstat bs = new bpstats (loc, &bs_link); /* For hits of moribund locations, we should just proceed. */ bs->stop = 0; bs->print = 0; @@ -5448,6 +5418,33 @@ bpstat_stop_status (const address_space *aspace, } } + return bs_head; +} + +/* See breakpoint.h. */ + +bpstat +bpstat_stop_status (const address_space *aspace, + CORE_ADDR bp_addr, ptid_t ptid, + const struct target_waitstatus *ws, + bpstat stop_chain) +{ + struct breakpoint *b = NULL; + /* First item of allocated bpstat's. */ + bpstat bs_head = stop_chain; + bpstat bs; + int need_remove_insert; + int removed_any; + + /* First, build the bpstat chain with locations that explain a + target stop, while being careful to not set the target running, + as that may invalidate locations (in particular watchpoint + locations are recreated). Resuming will happen here with + breakpoint conditions or watchpoint expressions that include + inferior function calls. */ + if (bs_head == NULL) + bs_head = build_bpstat_chain (aspace, bp_addr, ws); + /* A bit of special processing for shlib breakpoints. We need to process solib loading here, so that the lists of loaded and unloaded libraries are correct before we handle "catch load" and diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 8bb81d8d17..068c798b9d 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -917,9 +917,37 @@ extern void bpstat_clear (bpstat *); is part of the bpstat is copied as well. */ extern bpstat bpstat_copy (bpstat); +/* Build the (raw) bpstat chain for the stop information given by ASPACE, + BP_ADDR, and WS. Returns the head of the bpstat chain. */ + +extern bpstat build_bpstat_chain (const address_space *aspace, + CORE_ADDR bp_addr, + const struct target_waitstatus *ws); + +/* Get a bpstat associated with having just stopped at address + BP_ADDR in thread PTID. STOP_CHAIN may be supplied as a previously + computed stop chain or NULL, in which case the stop chain will be + computed using build_bpstat_chain. + + Determine whether we stopped at a breakpoint, etc, or whether we + don't understand this stop. Result is a chain of bpstat's such + that: + + if we don't understand the stop, the result is a null pointer. + + if we understand why we stopped, the result is not null. + + Each element of the chain refers to a particular breakpoint or + watchpoint at which we have stopped. (We may have stopped for + several reasons concurrently.) + + Each element of the chain has valid next, breakpoint_at, + commands, FIXME??? fields. */ + extern bpstat bpstat_stop_status (const address_space *aspace, CORE_ADDR pc, ptid_t ptid, - const struct target_waitstatus *ws); + const struct target_waitstatus *ws, + bpstat stop_chain = NULL); /* This bpstat_what stuff tells wait_for_inferior what to do with a breakpoint (a challenging task). diff --git a/gdb/infrun.c b/gdb/infrun.c index c663908568..f96c3c0374 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -5862,6 +5862,7 @@ handle_signal_stop (struct execution_control_state *ecs) ecs->event_thread->control.stop_step = 0; stop_print_frame = 1; stopped_by_random_signal = 0; + bpstat stop_chain = NULL; /* Hide inlined functions starting here, unless we just performed stepi or nexti. After stepi and nexti, always show the innermost frame (not any @@ -5893,7 +5894,8 @@ handle_signal_stop (struct execution_control_state *ecs) ecs->event_thread->prev_pc, &ecs->ws))) { - skip_inline_frames (ecs->ptid); + stop_chain = build_bpstat_chain (aspace, stop_pc, &ecs->ws); + skip_inline_frames (ecs->ptid, stop_chain); /* Re-fetch current thread's frame in case that invalidated the frame cache. */ @@ -5942,7 +5944,7 @@ handle_signal_stop (struct execution_control_state *ecs) handles this event. */ ecs->event_thread->control.stop_bpstat = bpstat_stop_status (get_current_regcache ()->aspace (), - stop_pc, ecs->ptid, &ecs->ws); + stop_pc, ecs->ptid, &ecs->ws, stop_chain); /* Following in case break condition called a function. */ diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c index a019619559..68467d0440 100644 --- a/gdb/inline-frame.c +++ b/gdb/inline-frame.c @@ -18,6 +18,7 @@ along with this program. If not, see . */ #include "defs.h" +#include "breakpoint.h" #include "inline-frame.h" #include "addrmap.h" #include "block.h" @@ -296,12 +297,10 @@ block_starting_point_at (CORE_ADDR pc, const struct block *block) return 1; } -/* Skip all inlined functions whose call sites are at the current PC. - Frames for the hidden functions will not appear in the backtrace until the - user steps into them. */ +/* See inline-frame.h. */ void -skip_inline_frames (ptid_t ptid) +skip_inline_frames (ptid_t ptid, bpstat stop_chain) { CORE_ADDR this_pc; const struct block *frame_block, *cur_block; @@ -327,6 +326,36 @@ skip_inline_frames (ptid_t ptid) if (BLOCK_START (cur_block) == this_pc || block_starting_point_at (this_pc, cur_block)) { + bool skip_this_frame = true; + + /* Loop over the stop chain and determine if execution + stopped in an inlined frame because of a user breakpoint. + If so do not skip the inlined frame. */ + for (bpstat s = stop_chain; s != NULL; s = s->next) + { + struct breakpoint *bpt = s->breakpoint_at; + + if (bpt != NULL && user_breakpoint_p (bpt)) + { + for (bp_location *loc = s->bp_location_at; + loc != NULL; loc = loc->next) + { + enum bp_loc_type t = loc->loc_type; + + if (loc->address == this_pc + && (t == bp_loc_software_breakpoint + || t == bp_loc_hardware_breakpoint)) + { + skip_this_frame = false; + break; + } + } + } + } + + if (!skip_this_frame) + break; + skip_count++; last_sym = BLOCK_FUNCTION (cur_block); } diff --git a/gdb/inline-frame.h b/gdb/inline-frame.h index 1d2e251cb1..d66ad44b7c 100644 --- a/gdb/inline-frame.h +++ b/gdb/inline-frame.h @@ -22,16 +22,21 @@ struct frame_info; struct frame_unwind; +struct bpstats; /* The inline frame unwinder. */ extern const struct frame_unwind inline_frame_unwind; /* Skip all inlined functions whose call sites are at the current PC. - Frames for the hidden functions will not appear in the backtrace until the - user steps into them. */ -void skip_inline_frames (ptid_t ptid); + If non-NULL, STOP_CHAIN is used to determine whether a stop was caused by + a user breakpoint. In that case, do not skip that inlined frame. This + allows the inlined frame to be treated as if it were non-inlined from the + user's perspective. GDB will stop "in" the inlined frame instead of + the caller. */ + +void skip_inline_frames (ptid_t ptid, struct bpstats *stop_chain); /* Forget about any hidden inlined functions in PTID, which is new or about to be resumed. If PTID is minus_one_ptid, forget about all diff --git a/gdb/testsuite/gdb.ada/bp_inlined_func.exp b/gdb/testsuite/gdb.ada/bp_inlined_func.exp index 37ef6af8ab..c220df7d33 100644 --- a/gdb/testsuite/gdb.ada/bp_inlined_func.exp +++ b/gdb/testsuite/gdb.ada/bp_inlined_func.exp @@ -38,21 +38,11 @@ gdb_test "break read_small" \ # We do not verify each breakpoint info, but use continue commands instead # to verify that we properly stop on each expected breakpoint. -gdb_test "continue" \ - "Breakpoint $decimal, b\\.doit \\(\\).*" \ - "Hitting first call of read_small" - -gdb_test "continue" \ - "Breakpoint $decimal, foo \\(\\).*" \ - "Hitting second call of read_small" - -gdb_test "continue" \ - "Breakpoint $decimal, c\\.c_doit \\(\\).*" \ - "Hitting third call of read_small" - -gdb_test "continue" \ - "Breakpoint $decimal, c\\.c_doit2 \\(\\).*" \ - "Hitting fourth call of read_small" +for {set i 0} {$i < 4} {incr i} { + gdb_test "continue" \ + "Breakpoint $decimal, b\\.read_small \\(\\).*" \ + "Stopped in read_small ($i)" +} gdb_test "continue" \ "Continuing\..*$inferior_exited_re.*" \ diff --git a/gdb/testsuite/gdb.dwarf2/implptr.exp b/gdb/testsuite/gdb.dwarf2/implptr.exp index 890598c9ff..92ca6d10e7 100644 --- a/gdb/testsuite/gdb.dwarf2/implptr.exp +++ b/gdb/testsuite/gdb.dwarf2/implptr.exp @@ -66,9 +66,13 @@ proc implptr_test_baz {} { gdb_test "break implptr.c:$line" "Breakpoint 3.*" \ "set baz breakpoint for implptr" gdb_continue_to_breakpoint "continue to baz breakpoint for implptr" + + # We are breaking in an inlined function. GDB used to stop in the + # calling frame, but it now stops "in" the inlined function. + gdb_test "up" "#1 foo .*" gdb_test {p p[0].y} " = 92" "sanity check element 0" gdb_test {p p[1].y} " = 46" "sanity check element 1" - gdb_test "step" "\r\nadd \\(.*" "enter the inlined function" + gdb_test "down" "#0 add .*" gdb_test "p a->y" " = 92" "check element 0 for the offset" gdb_test "p b->y" " = 46" "check element 1 for the offset" gdb_continue_to_breakpoint "ignore the second baz breakpoint" diff --git a/gdb/testsuite/gdb.opt/inline-break.c b/gdb/testsuite/gdb.opt/inline-break.c index c3d633810a..922102debb 100644 --- a/gdb/testsuite/gdb.opt/inline-break.c +++ b/gdb/testsuite/gdb.opt/inline-break.c @@ -128,6 +128,54 @@ func8a (int x) return func8b (x * 31); } +static inline ATTR int +inline_func1 (int x) +{ + int y = 1; /* inline_func1 */ + + return y + x; +} + +static int +not_inline_func1 (int x) +{ + int y = 2; /* not_inline_func1 */ + + return y + inline_func1 (x); +} + +inline ATTR int +inline_func2 (int x) +{ + int y = 3; /* inline_func2 */ + + return y + not_inline_func1 (x); +} + +int +not_inline_func2 (int x) +{ + int y = 4; /* not_inline_func2 */ + + return y + inline_func2 (x); +} + +static inline ATTR int +inline_func3 (int x) +{ + int y = 5; /* inline_func3 */ + + return y + not_inline_func2 (x); +} + +static int +not_inline_func3 (int x) +{ + int y = 6; /* not_inline_func3 */ + + return y + inline_func3 (x); +} + /* Entry point. */ int @@ -155,5 +203,7 @@ main (int argc, char *argv[]) x = func8a (x) + func8b (x); + x = not_inline_func3 (-21); + return x; } diff --git a/gdb/testsuite/gdb.opt/inline-break.exp b/gdb/testsuite/gdb.opt/inline-break.exp index c6b037d153..cc8d4bd53d 100644 --- a/gdb/testsuite/gdb.opt/inline-break.exp +++ b/gdb/testsuite/gdb.opt/inline-break.exp @@ -185,4 +185,39 @@ for {set i 1} {$i <= [array size results]} {incr i} { gdb_test "info break $i" $results($i) } +# Start us running. +if {![runto main]} { + untested "could not run to main" + return -1 +} + +# Insert breakpoints for all inline_func? and not_inline_func? and check +# that we actually stop where we think we should. + +for {set i 1} {$i < 4} {incr i} { + foreach inline {"not_inline" "inline"} { + gdb_breakpoint "${inline}_func$i" message + } +} + +set ws {[\r\n\t ]+} +set backtrace [list "(in|at)? main"] +for {set i 3} {$i > 0} {incr i -1} { + + foreach inline {"not_inline" "inline"} { + + # Check that we stop at the correct location and print out + # the (possibly) inlined frames. + set num [gdb_get_line_number "/* ${inline}_func$i */"] + set pattern ".*/$srcfile:$num${ws}.*$num${ws}int y = $decimal;" + append pattern "${ws}/\\\* ${inline}_func$i \\\*/" + send_log "Expecting $pattern\n" + gdb_continue_to_breakpoint "${inline}_func$i" $pattern + + # Also check for the correct backtrace. + set backtrace [linsert $backtrace 0 "(in|at)?${ws}${inline}_func$i"] + gdb_test_sequence "bt" "bt stopped in ${inline}_func$i" $backtrace + } +} + unset -nocomplain results -- 2.13.6