From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14370 invoked by alias); 26 Nov 2004 22:34:19 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 14343 invoked from network); 26 Nov 2004 22:34:11 -0000 Received: from unknown (HELO takamaka.act-europe.fr) (142.179.108.108) by sourceware.org with SMTP; 26 Nov 2004 22:34:11 -0000 Received: by takamaka.act-europe.fr (Postfix, from userid 507) id 7E48347DA0; Fri, 26 Nov 2004 14:34:10 -0800 (PST) Date: Fri, 26 Nov 2004 22:34:00 -0000 From: Joel Brobecker To: gdb-patches@sources.redhat.com Subject: [RFC/RFA/sparc] problem with prologue analyzer Message-ID: <20041126223410.GZ908@adacore.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="1yeeQ81UyVL57Vl7" Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2004-11/txt/msg00478.txt.bz2 --1yeeQ81UyVL57Vl7 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 3107 Hello, Using break.exp, we have a function marker2 defined in break1.c as follow (sic): int marker2 (a) int a; { return (1); } /* set breakpoint 9 here */ Because the entire declaration is on one single line, the function that skips prologue can not use the line number information from debugging data (sparc32_skip_prologue()): /* This is the preferred method, find the end of the prologue by using the debugging information. */ if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end)) { sal = find_pc_line (func_start, 0); if (sal.end < func_end && start_pc <= sal.end) return sal.end; } So sparc32_skip_prologue() fallsback to sparc_analyze_prologue(). Unfortunately, this function recognizes the prologue instructions only up to the "save" instruction. But the prologue of a function can contain store instructions that home the input registers into their stack location. This is the case of our function marker2 above: (gdb) disass &marker2 Dump of assembler code for function marker2: 0x00010aa8 : save %sp, -112, %sp 0x00010aac : st %i0, [ %fp + 0x44 ] 0x00010ab0 : mov 1, %g1 0x00010ab4 : mov %g1, %i0 0x00010ab8 : nop 0x00010abc : ret 0x00010ac0 : restore End of assembler dump. A visible consequence of this problem is that GDB will insert a breakpoint inside marker2 one instruction too earlier, and hence just before parameter a has been homed. And that causes the following FAIL in the GDB testsuite: (gdb) PASS: gdb.base/break.exp: run until file:function(1) breakpoint continue Continuing. 720 Breakpoint 2, 0x00010aac in marker2 (a=720) at break1.c:41 41 int marker2 (a) int a; { return (1); } /* set breakpoint 9 here */ (gdb) FAIL: gdb.base/break.exp: run until quoted breakpoint The value for parameter a is incorrect, it should be 43. This test used to pass with 5.3. Doing a bit of archeology, I discovered that the code analyzing problogues has been heavily rewritten at the end of 2003, and that the piece of code that handles these store insns got lost during one large code rewrite. Assuming this was an accident, I put the code back more or less blindly. I did exclude the part of the code that recognizes an instruction adding and offset to sp, as I haven't seen evidences that this is needed, and removed one if block that could only be executed in that case. But I'd be happy to put the entire code back, if it is felt more appropriate. 2004-11-26 Joel Brobecker * sparc-tdep.c (sparc_analyze_prologue): Recognize certain store instructions following the save instructions as part of the prologue. Tested on sparc-solaris 2.8, with GCC (based on a 3.4.x backend). Fixes: . break.exp: run until quoted breakpoint (the case I used to study the problem) . funcargs.exp: print *stp Ok to apply? Thanks, -- Joel --1yeeQ81UyVL57Vl7 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="prologue.diff" Content-length: 3473 Index: sparc-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc-tdep.c,v retrieving revision 1.157 diff -u -p -r1.157 sparc-tdep.c --- sparc-tdep.c 23 Nov 2004 18:59:13 -0000 1.157 +++ sparc-tdep.c 26 Nov 2004 22:12:15 -0000 @@ -80,6 +80,7 @@ struct regset; #define X_OP2(i) (((i) >> 22) & 0x7) #define X_IMM22(i) ((i) & 0x3fffff) #define X_OP3(i) (((i) >> 19) & 0x3f) +#define X_RS1(i) (((i) >> 14) & 0x1f) #define X_I(i) (((i) >> 13) & 1) /* Sign extension macros. */ #define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000) @@ -575,7 +576,59 @@ sparc_analyze_prologue (CORE_ADDR pc, CO if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c) { cache->frameless_p = 0; - return pc + offset + 4; + offset += 4; + + insn = sparc_fetch_instruction (pc + offset); + + while (1) + { + /* Recognize stores into the frame from the input registers. + This recognizes all non alternate stores of an input register, + into a location offset from the frame pointer between + +68 and +92. */ + + /* The above will fail for arguments that are promoted + (eg. shorts to ints or floats to doubles), because the compiler + will pass them in positive-offset frame space, but the prologue + will save them (after conversion) in negative frame space at an + unpredictable offset. Therefore I am going to remove the + restriction on the target-address of the save, on the theory + that any unbroken sequence of saves from input registers must + be part of the prologue. In un-optimized code (at least), I'm + fairly sure that the compiler would emit SOME other instruction + (eg. a move or add) before emitting another save that is actually + a part of the function body. + + Besides, the reserved stack space is different for SPARC64 anyway. + + MVS 4/23/2000 */ + + if (X_OP (insn) == 3 + && (X_OP3 (insn) & 0x3c) == 4 /* Store, non-alternate. */ + && (X_RD (insn) & 0x18) == 0x18 /* Input register. */ + && X_I (insn) /* Immediate mode. */ + && X_RS1 (insn) == 30) /* Off of frame pointer. */ + ; /* empty statement -- fall thru to end of loop */ + else if ((gdbarch_ptr_bit (current_gdbarch) == 64) + && X_OP (insn) == 3 + && (X_OP3 (insn) & 0x3c) == 12 /* store, extended (64-bit) */ + && (X_RD (insn) & 0x18) == 0x18 /* input register */ + && X_I (insn) /* immediate mode */ + && X_RS1 (insn) == 30) /* off of frame pointer */ + ; /* empty statement -- fall thru to end of loop */ + else if (X_OP (insn) == 3 + && (X_OP3 (insn) & 0x3c) == 36 /* store, floating-point */ + && X_I (insn) /* immediate mode */ + && X_RS1 (insn) == 30) /* off of frame pointer */ + ; /* empty statement -- fall thru to end of loop */ + else + break; + + offset += 4; + insn = sparc_fetch_instruction (pc + offset); + } + + return pc + offset; } return pc; --1yeeQ81UyVL57Vl7--