diff options
author | Yao Qi <yao@codesourcery.com> | 2014-06-25 11:52:52 +0800 |
---|---|---|
committer | Yao Qi <yao@codesourcery.com> | 2014-06-27 20:06:56 +0800 |
commit | b67a2c6fd4862b79c04c254fe2ba37c180b73d60 (patch) | |
tree | 3cc8038e76d5d036c97f20c3fe7be92ed8078156 /gdb/dummy-frame.c | |
parent | 9393ab1c00601a01ec25bbe0d8dc8430f62c9c13 (diff) | |
download | fsf-binutils-gdb-b67a2c6fd4862b79c04c254fe2ba37c180b73d60.zip fsf-binutils-gdb-b67a2c6fd4862b79c04c254fe2ba37c180b73d60.tar.gz fsf-binutils-gdb-b67a2c6fd4862b79c04c254fe2ba37c180b73d60.tar.bz2 |
Associate dummy_frame with ptid
This patch is to add ptid into dummy_frame and extend frame_id to
dummy_frame_id (which has a ptid field). With this change, GDB uses
dummy_frame_id (thread ptid and frame_id) to find the dummy frames.
Currently, dummy frames are looked up by frame_id, which isn't
accurate in non-stop or multi-process mode. The test case
gdb.multi/dummy-frame-restore.exp shows the problem and this patch can
fix it.
Test dummy-frame-restore.exp makes two inferiors stop at
different functions, say, inferior 1 stops at f1 while inferior 2
stops at f2. Set a breakpoint to a function, do the inferior call
in two inferiors, and GDB has two dummy frames of the same frame_id.
When the inferior call is finished, GDB will look up a dummy frame
from its stack/list and restore the inferior's regcache. Two
inferiors are finished in different orders, the inferiors' states are
restored differently, which is wrong. Running dummy-frame-restore.exp
under un-patched GDB, we'll get two fails:
FAIL: gdb.multi/dummy-frame-restore.exp: inf 2 first: after infcall: bt in inferior 2
FAIL: gdb.multi/dummy-frame-restore.exp: inf 2 first: after infcall: bt in inferior 1
With this patch applied, GDB will choose the correct dummy_frame to
restore for a given inferior, because ptid is considered when looking up
dummy frames. Two fails above are fixed.
Regression tested on x86_64-linux, both native and gdbserver.
gdb:
2014-06-27 Yao Qi <yao@codesourcery.com>
* breakpoint.c (check_longjmp_breakpoint_for_call_dummy):
Change parameter type to 'struct thread_info *'. Caller
updated.
* breakpoint.h (check_longjmp_breakpoint_for_call_dummy):
Update declaration.
* dummy-frame.c (struct dummy_frame_id): New.
(dummy_frame_id_eq): New function.
(struct dummy_frame) <id>: Change its type to 'struct
dummy_frame_id'.
(dummy_frame_push): Add parameter ptid and save it in
dummy_frame_id.
(pop_dummy_frame_bpt): Use ptid of dummy_frame instead of
inferior_ptid.
(pop_dummy_frame): Assert that the ptid of dummy_frame equals
to inferior_ptid.
(lookup_dummy_frame): Change parameter type to 'struct
dummy_frame_id *'. Callers updated. Call dummy_frame_id_eq
instead of frame_id_eq.
(dummy_frame_pop): Add parameter ptid. Callers updated.
Update comments. Compose dummy_frame_id and pass it to
lookup_dummy_frame.
(dummy_frame_discard): Add parameter ptid.
(dummy_frame_sniffer): Compose dummy_frame_id and call
dummy_frame_id_eq instead of frame_id_eq.
(fprint_dummy_frames): Print ptid.
* dummy-frame.h: Remove comments.
(dummy_frame_push): Add ptid in declaration.
(dummy_frame_pop, dummy_frame_discard): Likewise.
gdb/testsuite:
2014-06-27 Yao Qi <yao@codesourcery.com>
* gdb.multi/dummy-frame-restore.exp: New.
* gdb.multi/dummy-frame-restore.c: New.
gdb/doc:
2014-06-27 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (Maintenance Commands): Update the output of
'maint print dummy-frames' command.
Diffstat (limited to 'gdb/dummy-frame.c')
-rw-r--r-- | gdb/dummy-frame.c | 72 |
1 files changed, 48 insertions, 24 deletions
diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index dd2ff12..35d78e9 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -31,6 +31,25 @@ #include "observer.h" #include "gdbthread.h" +struct dummy_frame_id +{ + /* This frame's ID. Must match the value returned by + gdbarch_dummy_id. */ + struct frame_id id; + + /* The thread this dummy_frame relates to. */ + ptid_t ptid; +}; + +/* Return whether dummy_frame_id *ID1 and *ID2 are equal. */ + +static int +dummy_frame_id_eq (struct dummy_frame_id *id1, + struct dummy_frame_id *id2) +{ + return frame_id_eq (id1->id, id2->id) && ptid_equal (id1->ptid, id2->ptid); +} + /* Dummy frame. This saves the processor state just prior to setting up the inferior function call. Older targets save the registers on the target stack (but that really slows down function calls). */ @@ -38,9 +57,10 @@ struct dummy_frame { struct dummy_frame *next; - /* This frame's ID. Must match the value returned by - gdbarch_dummy_id. */ - struct frame_id id; + + /* An id represents a dummy frame. */ + struct dummy_frame_id id; + /* The caller's state prior to the call. */ struct infcall_suspend_state *caller_state; }; @@ -52,13 +72,14 @@ static struct dummy_frame *dummy_frame_stack = NULL; void dummy_frame_push (struct infcall_suspend_state *caller_state, - const struct frame_id *dummy_id) + const struct frame_id *dummy_id, ptid_t ptid) { struct dummy_frame *dummy_frame; dummy_frame = XCNEW (struct dummy_frame); dummy_frame->caller_state = caller_state; - dummy_frame->id = (*dummy_id); + dummy_frame->id.id = (*dummy_id); + dummy_frame->id.ptid = ptid; dummy_frame->next = dummy_frame_stack; dummy_frame_stack = dummy_frame; } @@ -83,8 +104,8 @@ pop_dummy_frame_bpt (struct breakpoint *b, void *dummy_voidp) { struct dummy_frame *dummy = dummy_voidp; - if (b->thread == pid_to_thread_id (inferior_ptid) - && b->disposition == disp_del && frame_id_eq (b->frame_id, dummy->id)) + if (b->thread == pid_to_thread_id (dummy->id.ptid) + && b->disposition == disp_del && frame_id_eq (b->frame_id, dummy->id.id)) { while (b->related_breakpoint != b) delete_breakpoint (b->related_breakpoint); @@ -107,6 +128,7 @@ pop_dummy_frame (struct dummy_frame **dummy_ptr) { struct dummy_frame *dummy = *dummy_ptr; + gdb_assert (ptid_equal (dummy->id.ptid, inferior_ptid)); restore_infcall_suspend_state (dummy->caller_state); iterate_over_breakpoints (pop_dummy_frame_bpt, dummy); @@ -125,48 +147,47 @@ pop_dummy_frame (struct dummy_frame **dummy_ptr) Return NULL if not found. */ static struct dummy_frame ** -lookup_dummy_frame (struct frame_id dummy_id) +lookup_dummy_frame (struct dummy_frame_id *dummy_id) { struct dummy_frame **dp; for (dp = &dummy_frame_stack; *dp != NULL; dp = &(*dp)->next) { - if (frame_id_eq ((*dp)->id, dummy_id)) + if (dummy_frame_id_eq (&(*dp)->id, dummy_id)) return dp; } return NULL; } -/* Pop the dummy frame DUMMY_ID, restoring program state to that before the - frame was created. +/* Find the dummy frame by DUMMY_ID and PTID, and pop it, restoring + program state to that before the frame was created. On return reinit_frame_cache has been called. - If the frame isn't found, flag an internal error. - - NOTE: This can only pop the one frame, even if it is in the middle of the - stack, because the other frames may be for different threads, and there's - currently no way to tell which stack frame is for which thread. */ + If the frame isn't found, flag an internal error. */ void -dummy_frame_pop (struct frame_id dummy_id) +dummy_frame_pop (struct frame_id dummy_id, ptid_t ptid) { struct dummy_frame **dp; + struct dummy_frame_id id = { dummy_id, ptid }; - dp = lookup_dummy_frame (dummy_id); + dp = lookup_dummy_frame (&id); gdb_assert (dp != NULL); pop_dummy_frame (dp); } -/* Drop dummy frame DUMMY_ID. Do nothing if it is not found. Do not restore - its state into inferior, just free its memory. */ +/* Find the dummy frame by DUMMY_ID and PTID and drop it. Do nothing + if it is not found. Do not restore its state into inferior, just + free its memory. */ void -dummy_frame_discard (struct frame_id dummy_id) +dummy_frame_discard (struct frame_id dummy_id, ptid_t ptid) { struct dummy_frame **dp; + struct dummy_frame_id id = { dummy_id, ptid }; - dp = lookup_dummy_frame (dummy_id); + dp = lookup_dummy_frame (&id); if (dp) remove_dummy_frame (dp); } @@ -211,13 +232,14 @@ dummy_frame_sniffer (const struct frame_unwind *self, dummy ID, assuming it is a dummy frame. */ struct frame_id this_id = gdbarch_dummy_id (get_frame_arch (this_frame), this_frame); + struct dummy_frame_id dummy_id = { this_id, inferior_ptid }; /* Use that ID to find the corresponding cache entry. */ for (dummyframe = dummy_frame_stack; dummyframe != NULL; dummyframe = dummyframe->next) { - if (frame_id_eq (dummyframe->id, this_id)) + if (dummy_frame_id_eq (&dummyframe->id, &dummy_id)) { struct dummy_frame_cache *cache; @@ -297,7 +319,9 @@ fprint_dummy_frames (struct ui_file *file) gdb_print_host_address (s, file); fprintf_unfiltered (file, ":"); fprintf_unfiltered (file, " id="); - fprint_frame_id (file, s->id); + fprint_frame_id (file, s->id.id); + fprintf_unfiltered (file, ", ptid=%s", + target_pid_to_str (s->id.ptid)); fprintf_unfiltered (file, "\n"); } } |