[patch/rfc] How to handle stepping into an unresolved plt entry?

Randolph Chung randolph@tausq.org
Fri May 21 06:44:00 GMT 2004


On hppa, I noticed that when I do a "step" over an indirect function
call, gdb does not stop inside the called function.  I've traced the
problem down to the following:

An indirect function call on hppa goes through a stub ($$dyncall).
$$dyncall loads a PLABEL from the PLT and jumps to it. In the case that
the PLT is not yet resolved, we need to do the normal PLT fixup () in 
the loader before calling the function.

What seems to be happening now is that when a "step" happens at the
indirect function call, we step into the $$dyncall stub, and in
infrun.c, we do a SKIP_TRAMPOLINE_CODE. This resolves into a pc that
points at the fixup routine. Next, in handle_inferior_event (), we try
to lookup the file/line information for this target pc; it's not found,
and so gdb just goes ahead and insert a breakpoint at the return address
of the stub (which is in the caller) and then calls keep_going ().
If we do a step on a second invocation of the indirect function call, it
works correctly; SKIP_TRAMPOLINE_CODE resolves to an address that points
to the target function, so the file/line lookup works and we insert a
breakpoint in the right place.

What is actually supposed to happen in this case? The documentation says:
@findex SKIP_TRAMPOLINE_CODE
If the target machine has trampoline code that sits between callers and
the functions being called, then define this macro to return a new PC
that is at the start of the real function.

But how do you do this if your target address is not yet resolved? The
attached patch gives a workaround for this problem (also needs a small
fix to the target code), but it seems a bit clumsy to me.... it's not
like handle_inferior_event () needs any more special cases... :-(

Comments? Suggestions?

thanks
randolph
-- 
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/


2004-05-20  Randolph Chung  <tausq@debian.org>

	* infrun.c (handle_inferior_event): If skipping a trampoline results
	in an address in the resolver, stop there before continuing.
	* hppa-linux-tdep.c (hppa_linux_skip_trampoline_code): Handle the
	case when the plabel points to a PLT stub.

Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.163
diff -u -p -r1.163 infrun.c
--- infrun.c	14 May 2004 18:45:42 -0000	1.163
+++ infrun.c	21 May 2004 06:36:36 -0000
@@ -2435,6 +2443,24 @@ process_event_stop_test:
 	  }
       }
 

+    /* If skipping a trampoline results in an address in the resolver,
+       stop there before continuing.  */
+      if (IN_SOLIB_DYNSYM_RESOLVE_CODE (ecs->stop_func_start))
+	{
+	  struct symtab_and_line sr_sal;
+	  init_sal (&sr_sal);
+	  sr_sal.pc = ecs->stop_func_start;
+
+	  check_for_old_step_resume_breakpoint ();
+	  step_resume_breakpoint =
+	    set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
+	  if (breakpoints_inserted)
+	    insert_breakpoints ();
+
+          keep_going (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.  */
Index: hppa-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-linux-tdep.c,v
retrieving revision 1.5
diff -u -p -r1.5 hppa-linux-tdep.c
--- hppa-linux-tdep.c	8 May 2004 03:59:34 -0000	1.5
+++ hppa-linux-tdep.c	21 May 2004 06:36:36 -0000
@@ -219,6 +211,24 @@ hppa_linux_skip_trampoline_code (CORE_AD
       if (pc & 0x2)
 	pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
 
+      /* if the plt slot has not yet been resolved, the target will
+         be the plt stub */
+      if (in_plt_section (pc, NULL))
+	{
+	  /* Sanity check: are we pointing to the plt stub? */
+  	  if (insns_match_pattern (pc, hppa_plt_stub, insn))
+	    {
+	      /* this should point to the fixup routine */
+      	      pc = (CORE_ADDR) read_memory_integer (pc + 8, TARGET_PTR_BIT / 8);
+	    }
+	  else
+	    {
+	      error ("Cannot resolve plt stub at 0x%s\n",
+		     paddr_nz (pc));
+	      pc = 0;
+	    }
+	}
+
       return pc;
     }
 



More information about the Gdb mailing list