How are call trampolines supposed to be handled?
Randolph Chung
randolph@tausq.org
Mon Apr 19 03:11:00 GMT 2004
Hi, while trying to get unwinding and "next" to work on hppa, i noticed
a problem:
On hppa, many function calls go through stubs (or trampolines as gdb
calls them). There are import stubs for calling shared library
functions, long call stubs when the target function is too far away,
stubs for indirect function calls, and your typical plt fixup stubs.
With the current code, what I see is that when gdb tries to step over
a function that goes through a stub, it gets into an infinite loop.
The problem seems to be that gdb puts a breakpoint at the target of
the original function call (which is a stub), and then tries to do an
unwind from there. The hppa unwinder fails to unwind from the stub [*]
and results in an infinite loop.
([*] On hpux with the hp compiler/linker, the linker generates some
unwinding information for the stub entries, but GCC/binutils do not)
The unwinder probably should not go into an infinite loop, but in any
case it seems that we should be trying to break at the target function,
instead of the stub, and unwind from there. How is this done for other
architectures that uses call stubs? I implemented the
solib_in_call_trampoline/skip_trampoline_code methods for hppa-linux,
but they don't seem to get called in time for things to work. I was able
to get this to work only with the following patch to
step_over_function() (probably wrong):
=======
--- infrun.c 15 Apr 2004 14:29:20 -0000 1.146
+++ infrun.c 19 Apr 2004 02:32:27 -0000
@@ -2864,13 +2999,22 @@ step_over_function (struct execution_con
The d10v handles all this by bailing out of the prologue analsis
when it reaches the current instruction. */
+ if (IN_SOLIB_CALL_TRAMPOLINE (stop_pc, ecs->stop_func_name))
+ {
+ CORE_ADDR real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+ if (real_stop_pc)
+ {
+ sr_sal.pc = real_stop_pc;
+ sr_id = null_frame_id;
+ }
+ }
+
+ if (sr_sal.pc == 0)
+ {
if (DEPRECATED_SAVED_PC_AFTER_CALL_P ())
sr_sal.pc = ADDR_BITS_REMOVE (DEPRECATED_SAVED_PC_AFTER_CALL (get_current_frame ()));
else
sr_sal.pc = ADDR_BITS_REMOVE (frame_pc_unwind (get_current_frame ()));
- sr_sal.section = find_pc_overlay (sr_sal.pc);
-
- check_for_old_step_resume_breakpoint ();
/* NOTE: cagney/2004-03-31: Code using the current value of
"step_frame_id", instead of unwinding that frame ID, removed. On
@@ -2882,9 +3026,13 @@ step_over_function (struct execution_con
doing a frame ID unwind, it's possible to assert that the code is
always using the correct ID. */
sr_id = frame_unwind_id (get_current_frame ());
+ }
+ sr_sal.section = find_pc_overlay (sr_sal.pc);
+
+ check_for_old_step_resume_breakpoint ();
step_resume_breakpoint = set_momentary_breakpoint (sr_sal, sr_id, bp_step_resume);
=======
Can someone please explain what is the right way to deal with this?
thanks
randolph
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/
More information about the Gdb
mailing list