diff options
author | Daniel Jacobowitz <drow@false.org> | 2009-06-28 00:20:24 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2009-06-28 00:20:24 +0000 |
commit | edb3359dff90ef8a3352408bfef8ce1438c2b2e1 (patch) | |
tree | 36b3ee7b866889c22ffb06aaa2ad0dfad826ab10 /gdb/breakpoint.c | |
parent | c7ce8faacb57cd10f919caff6c5018c4526e752e (diff) | |
download | fsf-binutils-gdb-edb3359dff90ef8a3352408bfef8ce1438c2b2e1.zip fsf-binutils-gdb-edb3359dff90ef8a3352408bfef8ce1438c2b2e1.tar.gz fsf-binutils-gdb-edb3359dff90ef8a3352408bfef8ce1438c2b2e1.tar.bz2 |
gdb/
* NEWS: Document inlined function support.
* Makefile.in (SFILES): Add inline-frame.c.
(COMMON_OBS): Add inline-frame.o.
* block.c (contained_in): Rewrite to use lexical nesting.
(block_linkage_function): Skip inlined function blocks.
(block_inlined_p): New.
* block.h (struct block): Update comment.
(block_inlined_p): New prototype.
* blockframe.c (get_frame_block): Handle inlined functions.
(get_frame_function): Do not use block_linkage_function.
(block_innermost_frame): Use get_frame_block and contained_in.
* breakpoint.c (watchpoint_check): Remove extra reinit_frame_cache.
Skip over inlined functions. Simplify epilogue check.
(bpstat_check_breakpoint_conditions): Use get_stack_frame_id.
Update comments.
(set_momentary_breakpoint): Only accept non-inlined frames.
(watch_command_1): Use frame_unwind_caller_pc and
frame_unwind_caller_id instead of get_prev_frame.
(until_break_command): Likewise. Use get_stack_frame_id.
* buildsym.c (end_symtab): Set SYMBOL_SYMTAB for block functions.
* dwarf2loc.c (dwarf_expr_frame_base): Use block_linkage_function.
* dwarf2read.c (process_die): Handle DW_TAG_inlined_subroutine.
(read_func_scope, new_symbol): Likewise. Handle arguments specially
for inlined functions without call site information.
(inherit_abstract_dies): Allow tag mismatch for inlined subroutines.
(die_specification): Treat DW_AT_abstract_origin as a specification.
(read_type_die): Handle DW_TAG_inlined_subroutine.
* frame-unwind.c (frame_unwind_init): Add inline_frame_unwind.
* frame.c (fprint_frame_id): Print inline depth.
(fprint_frame_type): Handle INLINE_FRAME and SENTINEL_FRAME.
(skip_inlined_frames, get_stack_frame_id): New.
(frame_unwind_caller_id): Use skip_inlined_frames.
(frame_id_inlined_p): New.
(frame_id_eq): Make the logic match the comments. Add inline_depth
check.
(frame_id_inner): Handle inlined functions.
(frame_unwind_pc): New function, copied from frame_unwind_caller_pc.
(frame_unwind_caller_pc): Use skip_inlined_frames and frame_unwind_pc.
(get_prev_frame_1): Check for inline frames. Split out frame
allocation to get_prev_frame_raw.
(get_prev_frame_raw): New function.
(get_prev_frame): Handle inline frames.
(get_frame_pc): Use frame_unwind_pc.
(get_frame_address_in_block): Skip inlined frames on both sides.
(pc_notcurrent): Delete.
(find_frame_sal): Rewrite to handle inline call sites. Use
get_frame_address_in_block.
(deprecated_update_frame_pc_hack): Make static.
* frame.h: Update comments.
(struct frame_id): Add inline_depth.
(enum frame_type): Add INLINE_FRAME.
(frame_id_inlined_p, get_stack_frame_id): New prototypes.
* gdbthread.h (struct thread_info): Add step_stack_frame_id field.
* infcmd.c (set_step_frame): New function.
(step_once): Use set_step_frame. Handle inlined functions.
(until_next_command): Use set_step_frame.
(finish_backward), finish_forward): Use get_stack_frame_id.
(finish_command): Support inlined functions.
* inferior.h (set_step_info): New prototype.
* infrun.c (RESUME_ALL): Use minus_one_ptid.
(clear_proceed_status): Clear step_stack_frame_id.
(init_wait_for_inferior): Call clear_inline_frame_state.
(init_execution_control_state): Make static.
(set_step_info): New function.
(init_thread_stepping_state): Do not set the symtab or line here.
(stepped_in_from): New function.
(handle_inferior_event): Handle inlined functions. Use set_step_info.
(insert_step_resume_breakpoint_at_frame): Use get_stack_frame_id.
(struct inferior_status): Add step_stack_frame_id.
(save_inferior_status, restore_inferior_status): Save and restore
step_stack_frame_id.
* inline-frame.c, inline-frame.h: New files.
* minsyms.c (prim_record_minimal_symbol_and_info): Use XCALLOC.
* regcache.c (regcache_write_pc): Call reinit_frame_cache.
* s390-tdep.c (s390_prologue_frame_unwind_cache): Handle INLINE_FRAME.
* stack.c (frame_show_address): New.
(print_frame_info, print_frame): Use it.
(find_frame_funname): Use get_frame_function. Handle inlined blocks.
(frame_info): Mark inlined functions.
(backtrace_command_1): Use get_current_user_frame.
(print_frame_local_vars, print_frame_label_vars): Update comments.
(return_command): Refuse inlined functions.
* symtab.c (lookup_symbol_aux_local): Stop at inlined function
boundaries.
(find_function_start_sal): Avoid inlined functions.
(completion_list_add_fields): New function.
(default_make_symbol_completion_list): Use it. Use block_static_block
and block_global_block. Check for inlined functions.
(skip_prologue_using_sal): Avoid line number comparison across
inlining.
* symtab.h (struct symbol): Add is_inlined.
(SYMBOL_INLINED): New.
* target.c (target_resume): Call clear_inline_frame_state.
* valops.c (value_of_variable): Check block_inlined_p.
gdb/doc/
* gdb.texinfo (Debugging Optimized Code): New chapter.
(Compiling for Debugging): Reference it. Move some
text to the new section.
gdb/testsuite/
* gdb.base/break.exp: Add an XFAIL for gcc/36748.
* gdb.cp/annota2.exp: Accept frames-invalid in more places.
* gdb.opt/Makefile.in (EXECUTABLES): Update.
* gdb.opt/clobbered-registers-O2.exp: Update to GPL v3.
* gdb.opt/inline-bt.c, gdb.opt/inline-bt.exp,
gdb.opt/inline-cmds.c, gdb.opt/inline-cmds.exp,
gdb.opt/inline-locals.c, gdb.opt/inline-locals.exp,
gdb.opt/inline-markers.c: New files.
* lib/gdb.exp (skip_inline_frame_tests): New function.
(skip_inline_var_tests): New function.
Diffstat (limited to 'gdb/breakpoint.c')
-rw-r--r-- | gdb/breakpoint.c | 111 |
1 files changed, 59 insertions, 52 deletions
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 1998acf..710a792 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -2772,40 +2772,38 @@ watchpoint_check (void *p) within_current_scope = 1; else { - /* There is no current frame at this moment. If we're going to have - any chance of handling watchpoints on local variables, we'll need - the frame chain (so we can determine if we're in scope). */ - reinit_frame_cache (); + struct frame_info *frame = get_current_frame (); + struct gdbarch *frame_arch = get_frame_arch (frame); + CORE_ADDR frame_pc = get_frame_pc (frame); + fr = frame_find_by_id (b->watchpoint_frame); within_current_scope = (fr != NULL); /* If we've gotten confused in the unwinder, we might have returned a frame that can't describe this variable. */ - if (within_current_scope - && (block_linkage_function (b->exp_valid_block) - != get_frame_function (fr))) - within_current_scope = 0; + if (within_current_scope) + { + struct symbol *function; + + function = get_frame_function (fr); + if (function == NULL + || !contained_in (b->exp_valid_block, + SYMBOL_BLOCK_VALUE (function))) + within_current_scope = 0; + } /* in_function_epilogue_p() returns a non-zero value if we're still in the function but the stack frame has already been invalidated. Since we can't rely on the values of local variables after the stack has been destroyed, we are treating the watchpoint in that - state as `not changed' without further checking. - - vinschen/2003-09-04: The former implementation left out the case - that the watchpoint frame couldn't be found by frame_find_by_id() - because the current PC is currently in an epilogue. Calling - gdbarch_in_function_epilogue_p() also when fr == NULL fixes that. */ - if (!within_current_scope || fr == get_current_frame ()) - { - struct frame_info *frame = get_current_frame (); - struct gdbarch *frame_arch = get_frame_arch (frame); - CORE_ADDR frame_pc = get_frame_pc (frame); + state as `not changed' without further checking. Don't mark + watchpoints as changed if the current frame is in an epilogue - + even if they are in some other frame, our view of the stack + is likely to be wrong. */ + if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc)) + return WP_VALUE_NOT_CHANGED; - if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc)) - return WP_VALUE_NOT_CHANGED; - } - if (fr && within_current_scope) + if (within_current_scope) /* If we end up stopping, the current frame will get selected in normal_stop. So this call to select_frame won't affect the user. */ @@ -3039,7 +3037,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) struct breakpoint *b = bl->owner; if (frame_id_p (b->frame_id) - && !frame_id_eq (b->frame_id, get_frame_id (get_current_frame ()))) + && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ()))) bs->stop = 0; else if (bs->stop) { @@ -3061,8 +3059,12 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) function call. */ struct value *mark = value_mark (); - /* Need to select the frame, with all that implies - so that the conditions will have the right context. */ + /* Need to select the frame, with all that implies so that + the conditions will have the right context. Because we + use the frame, we will not see an inlined function's + variables when we arrive at a breakpoint at the start + of the inlined function; the current frame will be the + call site. */ select_frame (get_current_frame ()); value_is_zero = catch_errors (breakpoint_cond_eval, (bl->cond), @@ -5032,6 +5034,11 @@ set_momentary_breakpoint (struct symtab_and_line sal, struct frame_id frame_id, enum bptype type) { struct breakpoint *b; + + /* If FRAME_ID is valid, it should be a real frame, not an inlined + one. */ + gdb_assert (!frame_id_inlined_p (frame_id)); + b = set_raw_breakpoint (sal, type); b->enable_state = bp_enabled; b->disposition = disp_donttouch; @@ -6143,7 +6150,6 @@ watch_command_1 (char *arg, int accessflag, int from_tty) struct block *exp_valid_block; struct value *val, *mark; struct frame_info *frame; - struct frame_info *prev_frame = NULL; char *exp_start = NULL; char *exp_end = NULL; char *tok, *id_tok_start, *end_tok; @@ -6283,34 +6289,34 @@ watch_command_1 (char *arg, int accessflag, int from_tty) bp_type = bp_watchpoint; frame = block_innermost_frame (exp_valid_block); - if (frame) - prev_frame = get_prev_frame (frame); - else - prev_frame = NULL; /* If the expression is "local", then set up a "watchpoint scope" breakpoint at the point where we've left the scope of the watchpoint expression. Create the scope breakpoint before the watchpoint, so that we will encounter it first in bpstat_stop_status. */ - if (innermost_block && prev_frame) + if (innermost_block && frame) { - scope_breakpoint = create_internal_breakpoint (get_frame_pc (prev_frame), - bp_watchpoint_scope); + if (frame_id_p (frame_unwind_caller_id (frame))) + { + scope_breakpoint + = create_internal_breakpoint (frame_unwind_caller_pc (frame), + bp_watchpoint_scope); - scope_breakpoint->enable_state = bp_enabled; + scope_breakpoint->enable_state = bp_enabled; - /* Automatically delete the breakpoint when it hits. */ - scope_breakpoint->disposition = disp_del; + /* Automatically delete the breakpoint when it hits. */ + scope_breakpoint->disposition = disp_del; - /* Only break in the proper frame (help with recursion). */ - scope_breakpoint->frame_id = get_frame_id (prev_frame); + /* Only break in the proper frame (help with recursion). */ + scope_breakpoint->frame_id = frame_unwind_caller_id (frame); - /* Set the address at which we will stop. */ - scope_breakpoint->loc->requested_address - = get_frame_pc (prev_frame); - scope_breakpoint->loc->address - = adjust_breakpoint_address (scope_breakpoint->loc->requested_address, - scope_breakpoint->type); + /* Set the address at which we will stop. */ + scope_breakpoint->loc->requested_address + = frame_unwind_caller_pc (frame); + scope_breakpoint->loc->address + = adjust_breakpoint_address (scope_breakpoint->loc->requested_address, + scope_breakpoint->type); + } } /* Now set up the breakpoint. */ @@ -6491,7 +6497,6 @@ until_break_command (char *arg, int from_tty, int anywhere) struct symtabs_and_lines sals; struct symtab_and_line sal; struct frame_info *frame = get_selected_frame (NULL); - struct frame_info *prev_frame = get_prev_frame (frame); struct breakpoint *breakpoint; struct breakpoint *breakpoint2 = NULL; struct cleanup *old_chain; @@ -6524,20 +6529,22 @@ until_break_command (char *arg, int from_tty, int anywhere) we don't specify a frame at which we need to stop. */ breakpoint = set_momentary_breakpoint (sal, null_frame_id, bp_until); else - /* Otherwise, specify the current frame, because we want to stop only + /* Otherwise, specify the selected frame, because we want to stop only at the very same frame. */ - breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), + breakpoint = set_momentary_breakpoint (sal, get_stack_frame_id (frame), bp_until); old_chain = make_cleanup_delete_breakpoint (breakpoint); /* Keep within the current frame, or in frames called by the current one. */ - if (prev_frame) + + if (frame_id_p (frame_unwind_caller_id (frame))) { - sal = find_pc_line (get_frame_pc (prev_frame), 0); - sal.pc = get_frame_pc (prev_frame); - breakpoint2 = set_momentary_breakpoint (sal, get_frame_id (prev_frame), + sal = find_pc_line (frame_unwind_caller_pc (frame), 0); + sal.pc = frame_unwind_caller_pc (frame); + breakpoint2 = set_momentary_breakpoint (sal, + frame_unwind_caller_id (frame), bp_until); make_cleanup_delete_breakpoint (breakpoint2); } |