diff options
author | Pedro Alves <palves@redhat.com> | 2011-03-18 18:44:34 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2011-03-18 18:44:34 +0000 |
commit | e3eebbd742b7c1820bead11710b71bfee694d7fa (patch) | |
tree | 5d5ad80e0aa482d4985427484fe1555132a757e8 /gdb/frame.c | |
parent | 79e1a869ac109293fb60c1909c085ea8c6c7cd12 (diff) | |
download | gdb-e3eebbd742b7c1820bead11710b71bfee694d7fa.zip gdb-e3eebbd742b7c1820bead11710b71bfee694d7fa.tar.gz gdb-e3eebbd742b7c1820bead11710b71bfee694d7fa.tar.bz2 |
gdb/
* frame.c (frame_unwind_pc): Rename to ...
(frame_unwind_pc_if_available): ... this. New `pc' output
parameter. Change return type to int. Gracefully handle
gdbarch_unwind_pc throwing NOT_AVAILABLE_ERROR. Return 0 if that
happened, or 1 otherwise.
(frame_unwind_pc): Reimplement on top of
frame_unwind_pc_if_available.
(get_frame_func): Rename to ...
(get_frame_func_if_available): New `pc' output parameter. Change
return type to int. Gracefully handle the PC not being available.
(get_frame_func): Reimplement on top of
get_frame_func_if_available.
(select_frame): Handle the PC being unavailable.
(get_prev_frame): Handle the PC being unavailable.
(get_frame_pc_if_available): New.
(get_frame_address_in_block_if_available): New.
(find_frame_sal): Handle the frame PC not being available.
* frame.h (get_frame_pc_if_available): Declare.
(get_frame_address_in_block_if_available): Declare.
(get_frame_func_if_available): Declare.
* stack.c (print_frame_info): Handle the PC being unavailable.
(find_frame_funname): Ditto.
(print_frame): Handle the PC being unavailable.
(get_frame_language): Ditto.
* blockframe.c (get_frame_block): Ditto.
* macroscope.c (default_macro_scope): Ditto.
* tui/tui-stack.c (tui_show_frame_info): Ditto.
Diffstat (limited to 'gdb/frame.c')
-rw-r--r-- | gdb/frame.c | 220 |
1 files changed, 177 insertions, 43 deletions
diff --git a/gdb/frame.c b/gdb/frame.c index 5bd1b03..20d8404 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -619,15 +619,17 @@ frame_find_by_id (struct frame_id id) return NULL; } -static CORE_ADDR -frame_unwind_pc (struct frame_info *this_frame) +static int +frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc) { if (!this_frame->prev_pc.p) { - CORE_ADDR pc; - if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame))) { + volatile struct gdb_exception ex; + struct gdbarch *prev_gdbarch; + CORE_ADDR pc = 0; + /* The right way. The `pure' way. The one true way. This method depends solely on the register-unwind code to determine the value of registers in THIS frame, and hence @@ -644,20 +646,62 @@ frame_unwind_pc (struct frame_info *this_frame) frame. This is all in stark contrast to the old FRAME_SAVED_PC which would try to directly handle all the different ways that a PC could be unwound. */ - pc = gdbarch_unwind_pc (frame_unwind_arch (this_frame), this_frame); + prev_gdbarch = frame_unwind_arch (this_frame); + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); + } + if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR) + { + this_frame->prev_pc.p = -1; + + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_unwind_pc (this_frame=%d)" + " -> <unavailable> }\n", + this_frame->level); + } + else if (ex.reason < 0) + { + throw_exception (ex); + } + else + { + this_frame->prev_pc.value = pc; + this_frame->prev_pc.p = 1; + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_unwind_pc (this_frame=%d) " + "-> %s }\n", + this_frame->level, + hex_string (this_frame->prev_pc.value)); + } } else internal_error (__FILE__, __LINE__, _("No unwind_pc method")); - this_frame->prev_pc.value = pc; - this_frame->prev_pc.p = 1; - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_caller_pc " - "(this_frame=%d) -> %s }\n", - this_frame->level, - hex_string (this_frame->prev_pc.value)); } - return this_frame->prev_pc.value; + if (this_frame->prev_pc.p < 0) + { + *pc = -1; + return 0; + } + else + { + *pc = this_frame->prev_pc.value; + return 1; + } +} + +static CORE_ADDR +frame_unwind_pc (struct frame_info *this_frame) +{ + CORE_ADDR pc; + + if (!frame_unwind_pc_if_available (this_frame, &pc)) + throw_error (NOT_AVAILABLE_ERROR, _("PC not available")); + else + return pc; } CORE_ADDR @@ -666,25 +710,59 @@ frame_unwind_caller_pc (struct frame_info *this_frame) return frame_unwind_pc (skip_inlined_frames (this_frame)); } -CORE_ADDR -get_frame_func (struct frame_info *this_frame) +int +get_frame_func_if_available (struct frame_info *this_frame, CORE_ADDR *pc) { struct frame_info *next_frame = this_frame->next; if (!next_frame->prev_func.p) { + CORE_ADDR addr_in_block; + /* Make certain that this, and not the adjacent, function is found. */ - CORE_ADDR addr_in_block = get_frame_address_in_block (this_frame); - next_frame->prev_func.p = 1; - next_frame->prev_func.addr = get_pc_function_start (addr_in_block); - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ get_frame_func (this_frame=%d) -> %s }\n", - this_frame->level, - hex_string (next_frame->prev_func.addr)); + if (!get_frame_address_in_block_if_available (this_frame, &addr_in_block)) + { + next_frame->prev_func.p = -1; + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ get_frame_func (this_frame=%d)" + " -> unavailable }\n", + this_frame->level); + } + else + { + next_frame->prev_func.p = 1; + next_frame->prev_func.addr = get_pc_function_start (addr_in_block); + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ get_frame_func (this_frame=%d) -> %s }\n", + this_frame->level, + hex_string (next_frame->prev_func.addr)); + } + } + + if (next_frame->prev_func.p < 0) + { + *pc = -1; + return 0; } - return next_frame->prev_func.addr; + else + { + *pc = next_frame->prev_func.addr; + return 1; + } +} + +CORE_ADDR +get_frame_func (struct frame_info *this_frame) +{ + CORE_ADDR pc; + + if (!get_frame_func_if_available (this_frame, &pc)) + throw_error (NOT_AVAILABLE_ERROR, _("PC not available")); + + return pc; } static enum register_status @@ -1298,8 +1376,6 @@ deprecated_safe_get_selected_frame (void) void select_frame (struct frame_info *fi) { - struct symtab *s; - selected_frame = fi; /* NOTE: cagney/2002-05-04: FI can be NULL. This occurs when the frame is being invalidated. */ @@ -1319,23 +1395,28 @@ select_frame (struct frame_info *fi) source language of this frame, and switch to it if desired. */ if (fi) { - /* We retrieve the frame's symtab by using the frame PC. However - we cannot use the frame PC as-is, because it usually points to - the instruction following the "call", which is sometimes the - first instruction of another function. So we rely on - get_frame_address_in_block() which provides us with a PC which - is guaranteed to be inside the frame's code block. */ - s = find_pc_symtab (get_frame_address_in_block (fi)); - if (s - && s->language != current_language->la_language - && s->language != language_unknown - && language_mode == language_mode_auto) + CORE_ADDR pc; + + /* We retrieve the frame's symtab by using the frame PC. + However we cannot use the frame PC as-is, because it usually + points to the instruction following the "call", which is + sometimes the first instruction of another function. So we + rely on get_frame_address_in_block() which provides us with a + PC which is guaranteed to be inside the frame's code + block. */ + if (get_frame_address_in_block_if_available (fi, &pc)) { - set_language (s->language); + struct symtab *s = find_pc_symtab (pc); + + if (s + && s->language != current_language->la_language + && s->language != language_unknown + && language_mode == language_mode_auto) + set_language (s->language); } } } - + /* Create an arbitrary (i.e. address specified by user) or innermost frame. Always returns a non-NULL value. */ @@ -1755,10 +1836,14 @@ inside_entry_func (struct frame_info *this_frame) struct frame_info * get_prev_frame (struct frame_info *this_frame) { + CORE_ADDR frame_pc; + int frame_pc_p; + /* There is always a frame. If this assertion fails, suspect that something should be calling get_selected_frame() or get_current_frame(). */ gdb_assert (this_frame != NULL); + frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc); /* tausq/2004-12-07: Dummy frames are skipped because it doesn't make much sense to stop unwinding at a dummy frame. One place where a dummy @@ -1773,6 +1858,7 @@ get_prev_frame (struct frame_info *this_frame) if (this_frame->level >= 0 && get_frame_type (this_frame) == NORMAL_FRAME && !backtrace_past_main + && frame_pc_p && inside_main_func (this_frame)) /* Don't unwind past main(). Note, this is done _before_ the frame has been marked as previously unwound. That way if the @@ -1819,6 +1905,7 @@ get_prev_frame (struct frame_info *this_frame) if (this_frame->level >= 0 && get_frame_type (this_frame) == NORMAL_FRAME && !backtrace_past_entry + && frame_pc_p && inside_entry_func (this_frame)) { frame_debug_got_null_frame (this_frame, "inside entry func"); @@ -1832,7 +1919,7 @@ get_prev_frame (struct frame_info *this_frame) && (get_frame_type (this_frame) == NORMAL_FRAME || get_frame_type (this_frame) == INLINE_FRAME) && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME - && get_frame_pc (this_frame) == 0) + && frame_pc_p && frame_pc == 0) { frame_debug_got_null_frame (this_frame, "zero PC"); return NULL; @@ -1848,6 +1935,28 @@ get_frame_pc (struct frame_info *frame) return frame_unwind_pc (frame->next); } +int +get_frame_pc_if_available (struct frame_info *frame, CORE_ADDR *pc) +{ + volatile struct gdb_exception ex; + + gdb_assert (frame->next != NULL); + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + *pc = frame_unwind_pc (frame->next); + } + if (ex.reason < 0) + { + if (ex.error == NOT_AVAILABLE_ERROR) + return 0; + else + throw_exception (ex); + } + + return 1; +} + /* Return an address that falls within THIS_FRAME's code block. */ CORE_ADDR @@ -1908,11 +2017,30 @@ get_frame_address_in_block (struct frame_info *this_frame) return pc; } +int +get_frame_address_in_block_if_available (struct frame_info *this_frame, + CORE_ADDR *pc) +{ + volatile struct gdb_exception ex; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + *pc = get_frame_address_in_block (this_frame); + } + if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR) + return 0; + else if (ex.reason < 0) + throw_exception (ex); + else + return 1; +} + void find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal) { struct frame_info *next_frame; int notcurrent; + CORE_ADDR pc; /* If the next frame represents an inlined function call, this frame's sal is the "call site" of that inlined function, which can not @@ -1953,8 +2081,14 @@ find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal) PC and such a PC indicates the current (rather than next) instruction/line, consequently, for such cases, want to get the line containing fi->pc. */ - notcurrent = (get_frame_pc (frame) != get_frame_address_in_block (frame)); - (*sal) = find_pc_line (get_frame_pc (frame), notcurrent); + if (!get_frame_pc_if_available (frame, &pc)) + { + init_sal (sal); + return; + } + + notcurrent = (pc != get_frame_address_in_block (frame)); + (*sal) = find_pc_line (pc, notcurrent); } /* Per "frame.h", return the ``address'' of the frame. Code should |