This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

How are call trampolines supposed to be handled?


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/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]