From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27553 invoked by alias); 15 Feb 2012 23:59:58 -0000 Received: (qmail 27404 invoked by uid 22791); 15 Feb 2012 23:59:43 -0000 X-SWARE-Spam-Status: No, hits=-6.8 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 15 Feb 2012 23:59:11 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q1FNx8r2019891 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 15 Feb 2012 18:59:08 -0500 Received: from mesquite.lan (ovpn-113-100.phx2.redhat.com [10.3.113.100]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q1FNx71M004871 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO) for ; Wed, 15 Feb 2012 18:59:08 -0500 Date: Thu, 16 Feb 2012 00:13:00 -0000 From: Kevin Buettner To: gdb-patches@sourceware.org Subject: Re: [PATCH] [SH] Prologue skipping if there is none Message-ID: <20120215165907.33f2e9a6@mesquite.lan> In-Reply-To: <20120215075413.1313f7fa@mesquite.lan> References: <87pqdgciho.fsf@schwinge.name> <20120215075413.1313f7fa@mesquite.lan> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-02/txt/msg00315.txt.bz2 On Wed, 15 Feb 2012 07:54:13 -0700 Kevin Buettner wrote: > On Wed, 15 Feb 2012 14:51:31 +0100 > Thomas Schwinge wrote: > > > The prologue skipping issue is that GDB fails to place breakpoints > > correctly at the beginning of a function -- such as for ``break main'' -- > > for the case that there is no prologue in that function. > > Hi Thomas, > > I've been sitting on a patch which is similar to what you just posted, > though I think it might provide more accurate results in some instances. > Would you mind checking to see if it solves your problem? Below is an updated patch which builds cleanly against current sources. I've verified that it produces better test results than not having the patch. I have not compared the test results to Thomas' patch. I ran my tests against the simulator. I found that a sim patch is necessary to do so. I'll post that in a moment. Kevin * sh-tdep.c (sh_analyze_prologue): Change loop to run to the limit PC. Keep track of the PC value after frame related instructions; return this value. (after_prologue): Delete. (sh_skip_prologue): Find the function limit and pass that as the limit address to sh_analyze_prologue(). Also use skip_prologue_using_sal() and return the lower result. Index: sh-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sh-tdep.c,v retrieving revision 1.236 diff -u -p -r1.236 sh-tdep.c --- sh-tdep.c 28 Jan 2012 18:08:20 -0000 1.236 +++ sh-tdep.c 15 Feb 2012 23:55:14 -0000 @@ -518,39 +518,43 @@ sh_breakpoint_from_pc (struct gdbarch *g static CORE_ADDR sh_analyze_prologue (struct gdbarch *gdbarch, - CORE_ADDR pc, CORE_ADDR current_pc, + CORE_ADDR pc, CORE_ADDR limit_pc, struct sh_frame_cache *cache, ULONGEST fpscr) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); ULONGEST inst; - CORE_ADDR opc; + CORE_ADDR after_last_frame_setup_insn = pc; + CORE_ADDR next_pc; int offset; int sav_offset = 0; int r3_val = 0; int reg, sav_reg = -1; - if (pc >= current_pc) - return current_pc; - cache->uses_fp = 0; - for (opc = pc + (2 * 28); pc < opc; pc += 2) + + for (;pc < limit_pc; pc = next_pc) { inst = read_memory_unsigned_integer (pc, 2, byte_order); + next_pc = pc + 2; + /* See where the registers will be saved to. */ if (IS_PUSH (inst)) { cache->saved_regs[GET_SOURCE_REG (inst)] = cache->sp_offset; cache->sp_offset += 4; + after_last_frame_setup_insn = next_pc; } else if (IS_STS (inst)) { cache->saved_regs[PR_REGNUM] = cache->sp_offset; cache->sp_offset += 4; + after_last_frame_setup_insn = next_pc; } else if (IS_MACL_STS (inst)) { cache->saved_regs[MACL_REGNUM] = cache->sp_offset; cache->sp_offset += 4; + after_last_frame_setup_insn = next_pc; } else if (IS_MOV_R3 (inst)) { @@ -563,11 +567,14 @@ sh_analyze_prologue (struct gdbarch *gdb else if (IS_ADD_R3SP (inst)) { cache->sp_offset += -r3_val; + after_last_frame_setup_insn = next_pc; } else if (IS_ADD_IMM_SP (inst)) { offset = ((inst & 0xff) ^ 0x80) - 0x80; cache->sp_offset -= offset; + if (offset < 0) + after_last_frame_setup_insn = next_pc; } else if (IS_MOVW_PCREL_TO_REG (inst)) { @@ -626,6 +633,7 @@ sh_analyze_prologue (struct gdbarch *gdb sav_reg = -1; } cache->sp_offset += sav_offset; + after_last_frame_setup_insn = next_pc; } else if (IS_FPUSH (inst)) { @@ -637,17 +645,20 @@ sh_analyze_prologue (struct gdbarch *gdb { cache->sp_offset += 4; } + after_last_frame_setup_insn = next_pc; } else if (IS_MOV_SP_FP (inst)) { + CORE_ADDR opc; cache->uses_fp = 1; + after_last_frame_setup_insn = next_pc; /* At this point, only allow argument register moves to other registers or argument register moves to @(X,fp) which are moving the register arguments onto the stack area allocated by a former add somenumber to SP call. Don't allow moving to an fp indirect address above fp + cache->sp_offset. */ pc += 2; - for (opc = pc + 12; pc < opc; pc += 2) + for (opc = pc + 12; pc < opc && pc < limit_pc; pc += 2) { inst = read_memory_integer (pc, 2, byte_order); if (IS_MOV_ARG_TO_IND_R14 (inst)) @@ -681,7 +692,10 @@ sh_analyze_prologue (struct gdbarch *gdb so, note that before returning the current pc. */ inst = read_memory_integer (pc + 2, 2, byte_order); if (IS_MOV_SP_FP (inst)) - cache->uses_fp = 1; + { + cache->uses_fp = 1; + after_last_frame_setup_insn = pc; + } break; } #if 0 /* This used to just stop when it found an instruction @@ -693,61 +707,30 @@ sh_analyze_prologue (struct gdbarch *gdb #endif } - return pc; + return after_last_frame_setup_insn; } /* Skip any prologue before the guts of a function. */ -/* Skip the prologue using the debug information. If this fails we'll - fall back on the 'guess' method below. */ -static CORE_ADDR -after_prologue (CORE_ADDR pc) -{ - struct symtab_and_line sal; - CORE_ADDR func_addr, func_end; - - /* If we can not find the symbol in the partial symbol table, then - there is no hope we can determine the function's start address - with this code. */ - if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end)) - return 0; - - /* Get the line associated with FUNC_ADDR. */ - sal = find_pc_line (func_addr, 0); - - /* There are only two cases to consider. First, the end of the source line - is within the function bounds. In that case we return the end of the - source line. Second is the end of the source line extends beyond the - bounds of the current function. We need to use the slow code to - examine instructions in that case. */ - if (sal.end < func_end) - return sal.end; - else - return 0; -} - static CORE_ADDR sh_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) { - CORE_ADDR pc; + CORE_ADDR pc, sal_end, func_addr, func_end; struct sh_frame_cache cache; + const char *name; - /* See if we can determine the end of the prologue via the symbol table. - If so, then return either PC, or the PC after the prologue, whichever - is greater. */ - pc = after_prologue (start_pc); - - /* If after_prologue returned a useful address, then use it. Else - fall back on the instruction skipping code. */ - if (pc) - return max (pc, start_pc); + /* Try to find the extent of the function that contains PC. */ + if (!find_pc_partial_function (start_pc, &name, &func_addr, &func_end)) + return start_pc; cache.sp_offset = -4; - pc = sh_analyze_prologue (gdbarch, start_pc, (CORE_ADDR) -1, &cache, 0); - if (!cache.uses_fp) - return start_pc; + pc = sh_analyze_prologue (gdbarch, func_addr, func_end, &cache, 0); - return pc; + sal_end = skip_prologue_using_sal (gdbarch, start_pc); + if (sal_end != 0 && sal_end != start_pc && sal_end < pc) + return sal_end; + else + return pc; } /* The ABI says: