From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 427 invoked by alias); 16 Mar 2009 18:22:40 -0000 Received: (qmail 417 invoked by uid 22791); 16 Mar 2009 18:22:39 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL,BAYES_00,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 16 Mar 2009 18:22:33 +0000 Received: (qmail 5791 invoked from network); 16 Mar 2009 18:22:30 -0000 Received: from unknown (HELO orlando) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 16 Mar 2009 18:22:30 -0000 From: Pedro Alves To: gdb@sourceware.org Subject: Re: [RFC] stepping over permanent breakpoint Date: Mon, 16 Mar 2009 18:22:00 -0000 User-Agent: KMail/1.9.10 Cc: Aleksandar Ristovski References: In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200903161822.29862.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2009-03/txt/msg00088.txt.bz2 On Monday 16 March 2009 17:40:49, Aleksandar Ristovski wrote: > Hello, > > When there is a hard-coded breakpoint in code, like in this > example (for x86): > > #include > > int main() > { > __asm(" int $0x03\n"); > printf("Hello World\n"); > return 0; > } > > gdb on linux will appear to work correctly. > > However, on systems that do not need pc adjustment after > break (like QNX) gdb will not be able to step over that > breakpoint (...) > (...) unless user explicitly sets a breakpoint on top > of it. Which I think your patch breaks? :-) > > I think that in case of linux it is actually working by > accident - because kernel does not back-up instruction > pointer after hard-coded breakpoint instruction was > executed. Gdb will receive SIGTRAP but will not really know why. > > Attached patch fixes this for systems where > gdbarch_decr_pc_after_break (gdbarch) == 0 > > I am still not sure this is the final fix. Wouldn't it be > better if we recognized a hard-coded breakpoint as a > breakpoint? There would be an issue since it is not in the > breakpoint list, but maybe we should either automatically > add it when we encounter it, or perhaps print with some > "special" number (to make it clear to the user it is not one > of the user-generated breakpoints). How about if you do the detection on resume instead? (please forgive my manual-patch-writing-in-email skills) infrun.c:resume: /* Normally, by the time we reach `resume', the breakpoints are either removed or inserted, as appropriate. The exception is if we're sitting at a permanent breakpoint; we need to step over it, but permanent breakpoints can't be removed. So we have to test for it here. */ - if (breakpoint_here_p (pc) == permanent_breakpoint_here) + if (pc == stop_pc + && gdbarch_decr_pc_after_break (gdbarch) == 0 + && (breakpoint_here_p (pc) == permanent_breakpoint_here + || hardcoded_breakpoint_inserted_here_p (pc))) { if (gdbarch_skip_permanent_breakpoint_p (gdbarch)) gdbarch_skip_permanent_breakpoint (gdbarch, regcache); else error (_("\ The program is stopped at a permanent breakpoint, but GDB does not know\n\ how to step past a permanent breakpoint on this architecture. Try using\n\ a command like `return' or `jump' to continue execution.")); } Then, have to make sure all decr_pc_after_break == 0 archs implement gdbarch_skip_permanent_breakpoint. Maybe change the default to just skip the breakpoint op, like i386_skip_permanent_breakpoint. I wonder why that isn't the case today? Hmmm, actually, why isn't this done on `proceed' instead of on `resume': infrun.c:proceed (): (...) if (addr == (CORE_ADDR) -1) { + if (pc == stop_pc + && gdbarch_decr_pc_after_break (gdbarch) == 0 + && execution_direction != EXEC_REVERSE + && (breakpoint_here_p (pc) == permanent_breakpoint_here + || hardcoded_breakpoint_inserted_here_p (pc))) + gdbarch_skip_permanent_breakpoint (gdbarch, regcache); - if (pc == stop_pc && breakpoint_here_p (pc) + else if (pc == stop_pc && breakpoint_here_p (pc) && execution_direction != EXEC_REVERSE) ? What do you think? What do others think? One thing this changes if that on decr_pc_after_break == 0 targets, if you single-step into a hardcoded breakpoint trap, and then issue a "continue", you'll not get a SIGTRAP reported, instead it is silently skipped. Not sure if that's a problem, and if it is, if it is worth tackling. I can't see how easily to fix it without having a "had been stepping before" thread flag, that isn't cleared by clear_proceed_status. -- Pedro Alves