diff options
author | Doug Evans <dje@google.com> | 2009-01-19 19:05:01 +0000 |
---|---|---|
committer | Doug Evans <dje@google.com> | 2009-01-19 19:05:01 +0000 |
commit | b89667ebd42a3a59b8f17ec9153d07dd2fc7e5e1 (patch) | |
tree | 8789d7e1d5edcf4019b51d276a77fc5fe649d699 /gdb/dummy-frame.c | |
parent | 63f2573fe476336550cf141d09a62bc1a349eba2 (diff) | |
download | gdb-b89667ebd42a3a59b8f17ec9153d07dd2fc7e5e1.zip gdb-b89667ebd42a3a59b8f17ec9153d07dd2fc7e5e1.tar.gz gdb-b89667ebd42a3a59b8f17ec9153d07dd2fc7e5e1.tar.bz2 |
* dummy-frame.c (dummy_frame): Replace regcache member with
caller_state.
(dummy_frame_push): Replace caller_regcache arg with caller_state.
All callers updated.
(remove_dummy_frame,pop_dummy_frame,lookup_dummy_frame): New fns.
(dummy_frame_pop): Rewrite. Verify requested frame is in the
dummy frame stack. Restore program state.
(cleanup_dummy_frames): Rewrite.
(dummy_frame_sniffer): Update. Make static.
* dummy-frame.h (regcache,frame_info): Delete forward decls.
(inferior_thread_state): New forward decl.
(dummy_frame_push): Update prototype.
* frame.c (frame_pop): dummy_frame_pop now does all the work for
DUMMY_FRAMEs.
* infcall.c (breakpoint_auto_delete_contents): Delete.
(get_function_name,run_inferior_call): New fns.
(call_function_by_hand): Simplify by moving some code to
get_function_name, run_inferior_call. Inferior function call wrapped
in TRY_CATCH so there's less need for cleanups and all exits from
proceed are handled similarily. Detect program exit.
Detect program stopping in a different thread.
Make error messages more consistent.
* inferior.h (inferior_thread_state): Declare (opaque type).
(save_inferior_thread_state,restore_inferior_thread_state,
make_cleanup_restore_inferior_thread_state,
discard_inferior_thread_state, get_inferior_thread_state_regcache):
Declare.
(save_inferior_status): Update prototype.
* infrun.c: (normal_stop): When stopped for the completion of an
inferior function call, verify the expected stack frame kind.
(inferior_thread_state): New struct.
(save_inferior_thread_state,restore_inferior_thread_state,
do_restore_inferior_thread_state_cleanup,
make_cleanup_restore_inferior_thread_state,
discard_inferior_thread_state,
get_inferior_thread_state_regcache): New functions.
(inferior_status): Move stop_signal, stop_pc, registers to
inferior_thread_state. Remove restore_stack_info.
(save_inferior_status): Remove arg restore_stack_info.
All callers updated. Remove saving of state now saved by
save_inferior_thread_state.
(restore_inferior_status): Remove restoration of state now done by
restore_inferior_thread_state.
(discard_inferior_status): Remove freeing of registers, now done by
discard_inferior_thread_state.
* gdb.base/break.exp: Update expected gdb output.
* gdb.base/sepdebug.exp: Ditto.
* gdb.mi/mi-syn-frame.exp: Ditto.
* gdb.mi/mi2-syn-frame.exp: Ditto.
* gdb.base/call-signal-resume.exp: New file.
* gdb.base/call-signals.c: New file.
* gdb.base/unwindonsignal.exp: New file.
* gdb.base/unwindonsignal.c: New file.
* gdb.threads/interrupted-hand-call.exp: New file.
* gdb.threads/interrupted-hand-call.c: New file.
* gdb.threads/thread-unwindonsignal.exp: New file.
Diffstat (limited to 'gdb/dummy-frame.c')
-rw-r--r-- | gdb/dummy-frame.c | 112 |
1 files changed, 76 insertions, 36 deletions
diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c index 8e3708d..6e63686 100644 --- a/gdb/dummy-frame.c +++ b/gdb/dummy-frame.c @@ -42,8 +42,8 @@ struct dummy_frame /* This frame's ID. Must match the value returned by gdbarch_dummy_id. */ struct frame_id id; - /* The caller's regcache. */ - struct regcache *regcache; + /* The caller's state prior to the call. */ + struct inferior_thread_state *caller_state; }; static struct dummy_frame *dummy_frame_stack = NULL; @@ -81,61 +81,101 @@ deprecated_pc_in_call_dummy (CORE_ADDR pc) return 0; } -/* Push the caller's state, along with the dummy frame info, onto a +/* Push the caller's state, along with the dummy frame info, onto the dummy-frame stack. */ void -dummy_frame_push (struct regcache *caller_regcache, +dummy_frame_push (struct inferior_thread_state *caller_state, const struct frame_id *dummy_id) { struct dummy_frame *dummy_frame; dummy_frame = XZALLOC (struct dummy_frame); - dummy_frame->regcache = caller_regcache; + dummy_frame->caller_state = caller_state; dummy_frame->id = (*dummy_id); dummy_frame->next = dummy_frame_stack; dummy_frame_stack = dummy_frame; } -/* Pop the dummy frame with ID dummy_id from the dummy-frame stack. */ +/* Remove *DUMMY_PTR from the dummy frame stack. */ -void -dummy_frame_pop (struct frame_id dummy_id) +static void +remove_dummy_frame (struct dummy_frame **dummy_ptr) { - struct dummy_frame **dummy_ptr; + struct dummy_frame *dummy = *dummy_ptr; - for (dummy_ptr = &dummy_frame_stack; - (*dummy_ptr) != NULL; - dummy_ptr = &(*dummy_ptr)->next) - { - struct dummy_frame *dummy = *dummy_ptr; - if (frame_id_eq (dummy->id, dummy_id)) - { - *dummy_ptr = dummy->next; - regcache_xfree (dummy->regcache); - xfree (dummy); - break; - } - } + *dummy_ptr = dummy->next; + discard_inferior_thread_state (dummy->caller_state); + xfree (dummy); } -/* There may be stale dummy frames, perhaps left over from when a longjump took us - out of a function that was called by the debugger. Clean them up at least once - whenever we start a new inferior. */ +/* Pop *DUMMY_PTR, restoring program state to that before the + frame was created. */ static void -cleanup_dummy_frames (struct target_ops *target, int from_tty) +pop_dummy_frame (struct dummy_frame **dummy_ptr) { - struct dummy_frame *dummy, *next; + struct dummy_frame *dummy; - for (dummy = dummy_frame_stack; dummy; dummy = next) + restore_inferior_thread_state ((*dummy_ptr)->caller_state); + + /* restore_inferior_status frees inf_state, + all that remains is to pop *dummy_ptr */ + dummy = *dummy_ptr; + *dummy_ptr = dummy->next; + xfree (dummy); + + /* We've made right mess of GDB's local state, just discard + everything. */ + reinit_frame_cache (); +} + +/* Look up DUMMY_ID. + Return NULL if not found. */ + +static struct dummy_frame ** +lookup_dummy_frame (struct frame_id dummy_id) +{ + struct dummy_frame **dp; + + for (dp = &dummy_frame_stack; *dp != NULL; dp = &(*dp)->next) { - next = dummy->next; - regcache_xfree (dummy->regcache); - xfree (dummy); + if (frame_id_eq ((*dp)->id, dummy_id)) + return dp; } - dummy_frame_stack = NULL; + return NULL; +} + +/* Pop the dummy frame DUMMY_ID, 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. */ + +void +dummy_frame_pop (struct frame_id dummy_id) +{ + struct dummy_frame **dp; + + dp = lookup_dummy_frame (dummy_id); + gdb_assert (dp != NULL); + + pop_dummy_frame (dp); +} + +/* There may be stale dummy frames, perhaps left over from when a longjump took + us out of a function that was called by the debugger. Clean them up at + least once whenever we start a new inferior. */ + +static void +cleanup_dummy_frames (struct target_ops *target, int from_tty) +{ + while (dummy_frame_stack != NULL) + remove_dummy_frame (&dummy_frame_stack); } /* Return the dummy frame cache, it contains both the ID, and a @@ -146,7 +186,7 @@ struct dummy_frame_cache struct regcache *prev_regcache; }; -int +static int dummy_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_prologue_cache) @@ -162,7 +202,7 @@ dummy_frame_sniffer (const struct frame_unwind *self, that PC to apply standard frame ID unwind techniques is just asking for trouble. */ - /* Don't bother unles there is at least one dummy frame. */ + /* Don't bother unless there is at least one dummy frame. */ if (dummy_frame_stack != NULL) { /* Use an architecture specific method to extract this frame's @@ -178,7 +218,7 @@ dummy_frame_sniffer (const struct frame_unwind *self, { struct dummy_frame_cache *cache; cache = FRAME_OBSTACK_ZALLOC (struct dummy_frame_cache); - cache->prev_regcache = dummyframe->regcache; + cache->prev_regcache = get_inferior_thread_state_regcache (dummyframe->caller_state); cache->this_id = this_id; (*this_prologue_cache) = cache; return 1; @@ -215,7 +255,7 @@ dummy_frame_prev_register (struct frame_info *this_frame, return reg_val; } -/* Assuming that THIS frame is a dummy, return the ID of THIS frame. That ID is +/* Assuming that THIS_FRAME is a dummy, return its ID. That ID is determined by examining the NEXT frame's unwound registers using the method dummy_id(). As a side effect, THIS dummy frame's dummy cache is located and and saved in THIS_PROLOGUE_CACHE. */ |