From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7545 invoked by alias); 15 Feb 2012 14:54:54 -0000 Received: (qmail 7515 invoked by uid 22791); 15 Feb 2012 14:54:50 -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 14:54:15 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q1FEsE0D004101 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 15 Feb 2012 09:54:14 -0500 Received: from mesquite.lan (ovpn-113-100.phx2.redhat.com [10.3.113.100]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q1FEsD53014842 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO) for ; Wed, 15 Feb 2012 09:54:14 -0500 Date: Wed, 15 Feb 2012 16:09:00 -0000 From: Kevin Buettner To: gdb-patches@sourceware.org Subject: Re: [PATCH] [SH] Prologue skipping if there is none Message-ID: <20120215075413.1313f7fa@mesquite.lan> In-Reply-To: <87pqdgciho.fsf@schwinge.name> References: <87pqdgciho.fsf@schwinge.name> 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/msg00302.txt.bz2 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? * 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: gdb/sh-tdep.c =================================================================== RCS file: /cvs/cvsfiles/gnupro/gdb/sh-tdep.c,v retrieving revision 1.21 diff -u -p -r1.21 sh-tdep.c --- gdb/sh-tdep.c 2 Jul 2011 02:04:18 -0000 1.21 +++ gdb/sh-tdep.c 28 Oct 2011 00:27:21 -0000 @@ -520,39 +520,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)) { @@ -565,11 +569,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)) { @@ -628,6 +635,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)) { @@ -639,17 +647,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)) @@ -683,7 +694,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 @@ -695,61 +709,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; + 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: