• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修訂83b9557361c2d79479e17d5967f5180c371fa138 (tree)
時間2017-11-29 05:39:19
作者Keith Seitz <keiths@redh...>
CommiterKeith Seitz

Log Message

Report stop locations in inlined functions

This is a patch for a very related inline function problem. 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);

This happens because skip_inline_frames automatically skips every inlined
frame. Based on a suggestion by Jan, this patch introduces a new function,
breakpoint_for_stop, which attempts to ascertain which breakpoint, if any,
caused a particular stop in the inferior. That breakpoint is then passed
to skip_inline_frames so that it can decide if a particular inlined frame
should be skipped.

I've had to separate the bpstat chain building from bpstat_stop_status --
py-finish-breakpoint.exp did not like me calling bpstat_stop_status multiple
times. So I've added the ability to allocate the chain separately and
optionally pass it to bpstat_stop_status, which remains otherwise unchanged.

With this patch, GDB now correctly 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;

gdb/ChangeLog:

* breakpoint.c (bpstat_explains_signal): Add output parameter for
breakpoint and save the breakpoint if one is found to explain
the signal.
All callers updated.
(build_bpstat_chain): New function, moved from bpstat_stop_status.
(breakpoint_for_stop): New function.
(bpstat_stop_status): Add new optional parameter for the bpstat chain.
If this new parameter is NULL, call build_bpstat_chain.
All callers updated.
* breakpoint.h (breakpoint_for_stop): Declare.
(bpstat_explains_signal): Update declaration.
* infrun.c (handle_signal_stop): Before calling skip_inline_frames,
use breakpoint_for_stop to find the breakpoint that caused us
to stop.
Save the bpstat chain for later invocation of bpstat_stop_status.
* inline-frame.c: Include linespec.h.
(skip_inline_frames): Add struct breakpoint parameter.
Re-parse the location of the breakpoint causing the stop, if any,
and only skip frames that did not cause the stop.
* inline-frame.h (skip_inline_frames): Update declaration.

gdb/testsuite/ChangeLog:

* 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.

Change Summary

差異

--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -5357,58 +5357,25 @@ need_moribund_for_location_type (struct bp_location *loc)
53575357 && !target_supports_stopped_by_hw_breakpoint ()));
53585358 }
53595359
5360-
5361-/* Get a bpstat associated with having just stopped at address
5362- BP_ADDR in thread PTID.
5363-
5364- Determine whether we stopped at a breakpoint, etc, or whether we
5365- don't understand this stop. Result is a chain of bpstat's such
5366- that:
5367-
5368- if we don't understand the stop, the result is a null pointer.
5369-
5370- if we understand why we stopped, the result is not null.
5371-
5372- Each element of the chain refers to a particular breakpoint or
5373- watchpoint at which we have stopped. (We may have stopped for
5374- several reasons concurrently.)
5375-
5376- Each element of the chain has valid next, breakpoint_at,
5377- commands, FIXME??? fields. */
5360+/* See breakpoint.h. */
53785361
53795362 bpstat
5380-bpstat_stop_status (const address_space *aspace,
5381- CORE_ADDR bp_addr, ptid_t ptid,
5363+build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
53825364 const struct target_waitstatus *ws)
53835365 {
5384- struct breakpoint *b = NULL;
5385- struct bp_location *bl;
5386- struct bp_location *loc;
5387- /* First item of allocated bpstat's. */
5366+ struct breakpoint *b;
53885367 bpstat bs_head = NULL, *bs_link = &bs_head;
5389- /* Pointer to the last thing in the chain currently. */
5390- bpstat bs;
5391- int ix;
5392- int need_remove_insert;
5393- int removed_any;
5394-
5395- /* First, build the bpstat chain with locations that explain a
5396- target stop, while being careful to not set the target running,
5397- as that may invalidate locations (in particular watchpoint
5398- locations are recreated). Resuming will happen here with
5399- breakpoint conditions or watchpoint expressions that include
5400- inferior function calls. */
54015368
54025369 ALL_BREAKPOINTS (b)
54035370 {
54045371 if (!breakpoint_enabled (b))
54055372 continue;
54065373
5407- for (bl = b->loc; bl != NULL; bl = bl->next)
5374+ for (bp_location *bl = b->loc; bl != NULL; bl = bl->next)
54085375 {
54095376 /* For hardware watchpoints, we look only at the first
54105377 location. The watchpoint_check function will work on the
5411- entire expression, not the individual locations. For
5378+
54125379 read watchpoints, the watchpoints_triggered function has
54135380 checked all locations already. */
54145381 if (b->type == bp_hardware_watchpoint && bl != b->loc)
@@ -5423,8 +5390,8 @@ bpstat_stop_status (const address_space *aspace,
54235390 /* Come here if it's a watchpoint, or if the break address
54245391 matches. */
54255392
5426- bs = new bpstats (bl, &bs_link); /* Alloc a bpstat to
5427- explain stop. */
5393+ bpstat bs = new bpstats (bl, &bs_link); /* Alloc a bpstat to
5394+ explain stop. */
54285395
54295396 /* Assume we stop. Should we find a watchpoint that is not
54305397 actually triggered, or if the condition of the breakpoint
@@ -5449,12 +5416,15 @@ bpstat_stop_status (const address_space *aspace,
54495416 if (!target_supports_stopped_by_sw_breakpoint ()
54505417 || !target_supports_stopped_by_hw_breakpoint ())
54515418 {
5452- for (ix = 0; VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
5419+ struct bp_location *loc;
5420+
5421+ for (int ix = 0;
5422+ VEC_iterate (bp_location_p, moribund_locations, ix, loc); ++ix)
54535423 {
54545424 if (breakpoint_location_address_match (loc, aspace, bp_addr)
54555425 && need_moribund_for_location_type (loc))
54565426 {
5457- bs = new bpstats (loc, &bs_link);
5427+ bpstat bs = new bpstats (loc, &bs_link);
54585428 /* For hits of moribund locations, we should just proceed. */
54595429 bs->stop = 0;
54605430 bs->print = 0;
@@ -5463,6 +5433,49 @@ bpstat_stop_status (const address_space *aspace,
54635433 }
54645434 }
54655435
5436+ return bs_head;
5437+}
5438+
5439+/* Get a bpstat associated with having just stopped at address
5440+ BP_ADDR in thread PTID.
5441+
5442+ Determine whether we stopped at a breakpoint, etc, or whether we
5443+ don't understand this stop. Result is a chain of bpstat's such
5444+ that:
5445+
5446+ if we don't understand the stop, the result is a null pointer.
5447+
5448+ if we understand why we stopped, the result is not null.
5449+
5450+ Each element of the chain refers to a particular breakpoint or
5451+ watchpoint at which we have stopped. (We may have stopped for
5452+ several reasons concurrently.)
5453+
5454+ Each element of the chain has valid next, breakpoint_at,
5455+ commands, FIXME??? fields. */
5456+
5457+bpstat
5458+bpstat_stop_status (const address_space *aspace,
5459+ CORE_ADDR bp_addr, ptid_t ptid,
5460+ const struct target_waitstatus *ws,
5461+ bpstat stop_chain)
5462+{
5463+ struct breakpoint *b = NULL;
5464+ /* First item of allocated bpstat's. */
5465+ bpstat bs_head = stop_chain;
5466+ bpstat bs;
5467+ int need_remove_insert;
5468+ int removed_any;
5469+
5470+ /* First, build the bpstat chain with locations that explain a
5471+ target stop, while being careful to not set the target running,
5472+ as that may invalidate locations (in particular watchpoint
5473+ locations are recreated). Resuming will happen here with
5474+ breakpoint conditions or watchpoint expressions that include
5475+ inferior function calls. */
5476+ if (bs_head == NULL)
5477+ bs_head = build_bpstat_chain (aspace, bp_addr, ws);
5478+
54665479 /* A bit of special processing for shlib breakpoints. We need to
54675480 process solib loading here, so that the lists of loaded and
54685481 unloaded libraries are correct before we handle "catch load" and
@@ -6780,22 +6793,9 @@ describe_other_breakpoints (struct gdbarch *gdbarch,
67806793 }
67816794
67826795
6783-/* Return true iff it is meaningful to use the address member of
6784- BPT locations. For some breakpoint types, the locations' address members
6785- are irrelevant and it makes no sense to attempt to compare them to other
6786- addresses (or use them for any other purpose either).
6787-
6788- More specifically, each of the following breakpoint types will
6789- always have a zero valued location address and we don't want to mark
6790- breakpoints of any of these types to be a duplicate of an actual
6791- breakpoint location at address zero:
6792-
6793- bp_watchpoint
6794- bp_catchpoint
6795-
6796-*/
6796+/* See breakpoint.h. */
67976797
6798-static int
6798+bool
67996799 breakpoint_address_is_meaningful (struct breakpoint *bpt)
68006800 {
68016801 enum bptype type = bpt->type;
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -917,9 +917,35 @@ extern void bpstat_clear (bpstat *);
917917 is part of the bpstat is copied as well. */
918918 extern bpstat bpstat_copy (bpstat);
919919
920+/* Build the bstat chain for the stop information given by ASPACE,
921+ BP_ADDR, and WS. Returns the head of the bpstat chain. */
922+
923+extern bpstat build_bpstat_chain (const address_space *aspace,
924+ CORE_ADDR bp_addr,
925+ const struct target_waitstatus *ws);
926+
920927 extern bpstat bpstat_stop_status (const address_space *aspace,
921928 CORE_ADDR pc, ptid_t ptid,
922- const struct target_waitstatus *ws);
929+ const struct target_waitstatus *ws,
930+ bpstat stop_chain = NULL);
931+
932+/* Return true iff it is meaningful to use the address member of
933+ BPT locations. For some breakpoint types, the locations' address members
934+ are irrelevant and it makes no sense to attempt to compare them to other
935+ addresses (or use them for any other purpose either).
936+
937+ More specifically, each of the following breakpoint types will
938+ always have a zero valued location address and we don't want to mark
939+ breakpoints of any of these types to be a duplicate of an actual
940+ breakpoint location at address zero:
941+
942+ bp_watchpoint
943+ bp_catchpoint
944+
945+*/
946+
947+extern bool breakpoint_address_is_meaningful (struct breakpoint *bpt);
948+
923949
924950 /* This bpstat_what stuff tells wait_for_inferior what to do with a
925951 breakpoint (a challenging task).
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5839,6 +5839,7 @@ handle_signal_stop (struct execution_control_state *ecs)
58395839 ecs->event_thread->control.stop_step = 0;
58405840 stop_print_frame = 1;
58415841 stopped_by_random_signal = 0;
5842+ bpstat stop_chain = NULL;
58425843
58435844 /* Hide inlined functions starting here, unless we just performed stepi or
58445845 nexti. After stepi and nexti, always show the innermost frame (not any
@@ -5870,7 +5871,13 @@ handle_signal_stop (struct execution_control_state *ecs)
58705871 ecs->event_thread->prev_pc,
58715872 &ecs->ws)))
58725873 {
5873- skip_inline_frames (ecs->ptid);
5874+ struct breakpoint *bpt = NULL;
5875+
5876+ stop_chain = build_bpstat_chain (aspace, stop_pc, &ecs->ws);
5877+ if (stop_chain != NULL)
5878+ bpt = stop_chain->breakpoint_at;
5879+
5880+ skip_inline_frames (ecs->ptid, bpt);
58745881
58755882 /* Re-fetch current thread's frame in case that invalidated
58765883 the frame cache. */
@@ -5919,7 +5926,7 @@ handle_signal_stop (struct execution_control_state *ecs)
59195926 handles this event. */
59205927 ecs->event_thread->control.stop_bpstat
59215928 = bpstat_stop_status (get_current_regcache ()->aspace (),
5922- stop_pc, ecs->ptid, &ecs->ws);
5929+ stop_pc, ecs->ptid, &ecs->ws, stop_chain);
59235930
59245931 /* Following in case break condition called a
59255932 function. */
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -301,7 +301,7 @@ block_starting_point_at (CORE_ADDR pc, const struct block *block)
301301 user steps into them. */
302302
303303 void
304-skip_inline_frames (ptid_t ptid)
304+skip_inline_frames (ptid_t ptid, struct breakpoint *bpt)
305305 {
306306 CORE_ADDR this_pc;
307307 const struct block *frame_block, *cur_block;
@@ -327,7 +327,25 @@ skip_inline_frames (ptid_t ptid)
327327 if (BLOCK_START (cur_block) == this_pc
328328 || block_starting_point_at (this_pc, cur_block))
329329 {
330- skip_count++;
330+ bool skip_this_frame = true;
331+
332+ if (bpt != NULL
333+ && user_breakpoint_p (bpt)
334+ && breakpoint_address_is_meaningful (bpt))
335+ {
336+ for (bp_location *loc = bpt->loc; loc != NULL;
337+ loc = loc->next)
338+ {
339+ if (loc->address == this_pc)
340+ {
341+ skip_this_frame = false;
342+ break;
343+ }
344+ }
345+ }
346+
347+ if (skip_this_frame)
348+ skip_count++;
331349 last_sym = BLOCK_FUNCTION (cur_block);
332350 }
333351 else
--- a/gdb/inline-frame.h
+++ b/gdb/inline-frame.h
@@ -31,7 +31,7 @@ extern const struct frame_unwind inline_frame_unwind;
3131 Frames for the hidden functions will not appear in the backtrace until the
3232 user steps into them. */
3333
34-void skip_inline_frames (ptid_t ptid);
34+void skip_inline_frames (ptid_t ptid, struct breakpoint *bpt);
3535
3636 /* Forget about any hidden inlined functions in PTID, which is new or
3737 about to be resumed. If PTID is minus_one_ptid, forget about all
--- a/gdb/testsuite/gdb.opt/inline-break.c
+++ b/gdb/testsuite/gdb.opt/inline-break.c
@@ -128,6 +128,54 @@ func8a (int x)
128128 return func8b (x * 31);
129129 }
130130
131+static inline ATTR int
132+inline_func1 (int x)
133+{
134+ int y = 1; /* inline_func1 */
135+
136+ return y + x;
137+}
138+
139+static int
140+not_inline_func1 (int x)
141+{
142+ int y = 2; /* not_inline_func1 */
143+
144+ return y + inline_func1 (x);
145+}
146+
147+inline ATTR int
148+inline_func2 (int x)
149+{
150+ int y = 3; /* inline_func2 */
151+
152+ return y + not_inline_func1 (x);
153+}
154+
155+int
156+not_inline_func2 (int x)
157+{
158+ int y = 4; /* not_inline_func2 */
159+
160+ return y + inline_func2 (x);
161+}
162+
163+static inline ATTR int
164+inline_func3 (int x)
165+{
166+ int y = 5; /* inline_func3 */
167+
168+ return y + not_inline_func2 (x);
169+}
170+
171+static int
172+not_inline_func3 (int x)
173+{
174+ int y = 6; /* not_inline_func3 */
175+
176+ return y + inline_func3 (x);
177+}
178+
131179 /* Entry point. */
132180
133181 int
@@ -155,5 +203,7 @@ main (int argc, char *argv[])
155203
156204 x = func8a (x) + func8b (x);
157205
206+ x = not_inline_func3 (-21);
207+
158208 return x;
159209 }
--- 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} {
185185 gdb_test "info break $i" $results($i)
186186 }
187187
188+# Start us running.
189+if {![runto main]} {
190+ untested "could not run to main"
191+ return -1
192+}
193+
194+# Insert breakpoints for all inline_func? and not_inline_func? and check
195+# that we actually stop where we think we should.
196+
197+for {set i 1} {$i < 4} {incr i} {
198+ foreach inline {"not_inline" "inline"} {
199+ gdb_breakpoint "${inline}_func$i" message
200+ }
201+}
202+
203+set ws {[\r\n\t ]+}
204+set backtrace [list "(in|at)? main"]
205+for {set i 3} {$i > 0} {incr i -1} {
206+
207+ foreach inline {"not_inline" "inline"} {
208+
209+ # Check that we stop at the correct location and print out
210+ # the (possibly) inlined frames.
211+ set num [gdb_get_line_number "/* ${inline}_func$i */"]
212+ set pattern ".*/$srcfile:$num${ws}.*$num${ws}int y = $decimal;"
213+ append pattern "${ws}/\\\* ${inline}_func$i \\\*/"
214+ send_log "Expecting $pattern\n"
215+ gdb_continue_to_breakpoint "${inline}_func$i" $pattern
216+
217+ # Also check for the correct backtrace.
218+ set backtrace [linsert $backtrace 0 "(in|at)?${ws}${inline}_func$i"]
219+ gdb_test_sequence "bt" "bt stopped in ${inline}_func$i" $backtrace
220+ }
221+}
222+
188223 unset -nocomplain results