+/* Wrapper for PC_IN_SIGTRAMP that takes care of the need to find the
+ function's name.
+
+ In a classic example of "left hand VS right hand", "infrun.c" was
+ trying to improve GDB's performance by caching the result of calls
+ to calls to find_pc_partial_funtion, while at the same time
+ find_pc_partial_function was also trying to ramp up performance by
+ caching its most recent return value. The below makes the the
+ function find_pc_partial_function solely responsibile for
+ performance issues (the local cache that relied on a global
+ variable - arrrggg - deleted).
+
+ Using the testsuite and gcov, it was found that dropping the local
+ "infrun.c" cache and instead relying on find_pc_partial_function
+ increased the number of calls to 12000 (from 10000), but the number
+ of times find_pc_partial_function's cache missed (this is what
+ matters) was only increased by only 4 (to 3569). (A quick back of
+ envelope caculation suggests that the extra 2000 function calls
+ @1000 extra instructions per call make the 1 MIP VAX testsuite run
+ take two extra seconds, oops :-)
+
+ Long term, this function can be eliminated, replaced by the code:
+ get_frame_type(current_frame()) == SIGTRAMP_FRAME (for new
+ architectures this is very cheap). */
+
+static int
+pc_in_sigtramp (CORE_ADDR pc)
+{
+ char *name;
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ return PC_IN_SIGTRAMP (pc, name);
+}
+
+/* Handle the inferior event in the cases when we just stepped
+ into a function. */
+
+static void
+handle_step_into_function (struct execution_control_state *ecs)
+{
+ CORE_ADDR real_stop_pc;
+
+ if ((step_over_calls == STEP_OVER_NONE)
+ || ((step_range_end == 1)
+ && in_prologue (prev_pc, ecs->stop_func_start)))
+ {
+ /* I presume that step_over_calls is only 0 when we're
+ supposed to be stepping at the assembly language level
+ ("stepi"). Just stop. */
+ /* Also, maybe we just did a "nexti" inside a prolog,
+ so we thought it was a subroutine call but it was not.
+ Stop as well. FENN */
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
+ }
+
+ if (step_over_calls == STEP_OVER_ALL || IGNORE_HELPER_CALL (stop_pc))
+ {
+ /* We're doing a "next". */
+
+ if (pc_in_sigtramp (stop_pc)
+ && frame_id_inner (step_frame_id,
+ frame_id_build (read_sp (), 0)))
+ /* We stepped out of a signal handler, and into its
+ calling trampoline. This is misdetected as a
+ subroutine call, but stepping over the signal
+ trampoline isn't such a bad idea. In order to do that,
+ we have to ignore the value in step_frame_id, since
+ that doesn't represent the frame that'll reach when we
+ return from the signal trampoline. Otherwise we'll
+ probably continue to the end of the program. */
+ step_frame_id = null_frame_id;
+
+ step_over_function (ecs);
+ keep_going (ecs);
+ return;
+ }
+
+ /* If we are in a function call trampoline (a stub between
+ the calling routine and the real function), locate the real
+ function. That's what tells us (a) whether we want to step
+ into it at all, and (b) what prologue we want to run to
+ the end of, if we do step into it. */
+ real_stop_pc = skip_language_trampoline (stop_pc);
+ if (real_stop_pc == 0)
+ real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+ if (real_stop_pc != 0)
+ ecs->stop_func_start = real_stop_pc;
+
+ /* If we have line number information for the function we
+ are thinking of stepping into, step into it.
+
+ If there are several symtabs at that PC (e.g. with include
+ files), just want to know whether *any* of them have line
+ numbers. find_pc_line handles this. */
+ {
+ struct symtab_and_line tmp_sal;
+
+ tmp_sal = find_pc_line (ecs->stop_func_start, 0);
+ if (tmp_sal.line != 0)
+ {
+ step_into_function (ecs);
+ return;
+ }
+ }
+
+ /* If we have no line number and the step-stop-if-no-debug
+ is set, we stop the step so that the user has a chance to
+ switch in assembly mode. */
+ if (step_over_calls == STEP_OVER_UNDEBUGGABLE && step_stop_if_no_debug)
+ {
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
+ }
+
+ step_over_function (ecs);
+ keep_going (ecs);
+ return;
+}