2011-07-01 Gary Benson * infrun.c (solib_event_breakpoint_helper_arg): New structure. (at_solib_event_breakpoint_helper): New function. (at_solib_event_breakpoint): Likewise. (handle_inferior_event): Avoid calling find_pc_partial_function and skip_inline_frames when stopping at the solib event breakpoint. diff --git a/gdb/infrun.c b/gdb/infrun.c index a656cbf..6e7a062 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -3080,6 +3080,56 @@ handle_syscall_event (struct execution_control_state *ecs) return 1; } +/* Argument for at_solib_event_breakpoint_helper. */ + +struct solib_event_breakpoint_helper_arg +{ + CORE_ADDR prev_pc; + int shlib_bp_count; + int other_bp_count; +}; + +/* Helper for at_solib_event_breakpoint. */ + +static int +at_solib_event_breakpoint_helper (struct breakpoint *b, void *argp) +{ + struct solib_event_breakpoint_helper_arg *arg + = (struct solib_event_breakpoint_helper_arg *) argp; + struct bp_location *loc; + + for (loc = b->loc; loc; loc = loc->next) + { + if (loc->pspace == current_program_space + && (loc->address == stop_pc || loc->address == arg->prev_pc)) + { + if (b->type == bp_shlib_event) + arg->shlib_bp_count++; + else + { + arg->other_bp_count++; + return 1; /* quick exit */ + } + } + } + + return 0; /* carry on looking */ +} + +/* Nonzero if the location stopoed at is the shlib event breakpoint. */ + +static int +at_solib_event_breakpoint (struct execution_control_state *ecs) +{ + struct solib_event_breakpoint_helper_arg arg; + arg.prev_pc = ecs->event_thread->prev_pc; + arg.shlib_bp_count = arg.other_bp_count = 0; + + iterate_over_breakpoints (at_solib_event_breakpoint_helper, &arg); + + return arg.shlib_bp_count && !arg.other_bp_count; +} + /* Given an execution control state that has been freshly filled in by an event from the inferior, figure out what it means and take appropriate action. */ @@ -3928,12 +3978,6 @@ handle_inferior_event (struct execution_control_state *ecs) ecs->stop_func_start = 0; ecs->stop_func_end = 0; ecs->stop_func_name = 0; - /* Don't care about return value; stop_func_start and stop_func_name - will both be 0 if it doesn't work. */ - find_pc_partial_function (stop_pc, &ecs->stop_func_name, - &ecs->stop_func_start, &ecs->stop_func_end); - ecs->stop_func_start - += gdbarch_deprecated_function_start_offset (gdbarch); ecs->event_thread->stepping_over_breakpoint = 0; bpstat_clear (&ecs->event_thread->control.stop_bpstat); ecs->event_thread->control.stop_step = 0; @@ -3941,11 +3985,30 @@ handle_inferior_event (struct execution_control_state *ecs) ecs->random_signal = 0; stopped_by_random_signal = 0; - /* Hide inlined functions starting here, unless we just performed stepi or - nexti. After stepi and nexti, always show the innermost frame (not any - inline function call sites). */ - if (ecs->event_thread->control.step_range_end != 1) - skip_inline_frames (ecs->ptid); + /* If we have stopped at the solib event breakpoint and + stop_on_solib_events is not set then we can avoid calling + anything that calls find_pc_section. This saves a lot + of time when the inferior loads a lot of shared libraries, + because otherwise the section map gets regenerated every + time we stop. */ + if (stop_on_solib_events + || ecs->event_thread->suspend.stop_signal != TARGET_SIGNAL_TRAP + || stop_after_trap + || !at_solib_event_breakpoint (ecs)) + { + /* Don't care about return value; stop_func_start and stop_func_name + will both be 0 if it doesn't work. */ + find_pc_partial_function (stop_pc, &ecs->stop_func_name, + &ecs->stop_func_start, &ecs->stop_func_end); + ecs->stop_func_start + += gdbarch_deprecated_function_start_offset (gdbarch); + + /* Hide inlined functions starting here, unless we just + performed stepi or nexti. After stepi and nexti, always show + the innermost frame (not any inline function call sites). */ + if (ecs->event_thread->control.step_range_end != 1) + skip_inline_frames (ecs->ptid); + } if (ecs->event_thread->suspend.stop_signal == TARGET_SIGNAL_TRAP && ecs->event_thread->control.trap_expected