From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8993 invoked by alias); 21 May 2004 06:44:33 -0000 Mailing-List: contact gdb-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sources.redhat.com Received: (qmail 8944 invoked from network); 21 May 2004 06:44:31 -0000 Received: from unknown (HELO pippin.tausq.org) (64.81.244.94) by sourceware.org with SMTP; 21 May 2004 06:44:31 -0000 Received: by pippin.tausq.org (Postfix, from userid 1000) id 6768DCD299; Thu, 20 May 2004 23:44:35 -0700 (PDT) Date: Fri, 21 May 2004 06:44:00 -0000 From: Randolph Chung To: gdb@sources.redhat.com Subject: [patch/rfc] How to handle stepping into an unresolved plt entry? Message-ID: <20040521064435.GJ566@tausq.org> Reply-To: Randolph Chung Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-GPG: for GPG key, see http://www.tausq.org/gpg.txt User-Agent: Mutt/1.5.5.1+cvs20040105i X-SW-Source: 2004-05/txt/msg00144.txt.bz2 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 * 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; }