From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11584 invoked by alias); 26 Nov 2012 21:27:00 -0000 Received: (qmail 11568 invoked by uid 22791); 26 Nov 2012 21:26:59 -0000 X-SWARE-Spam-Status: No, hits=-4.4 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,TW_SR X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 26 Nov 2012 21:26:49 +0000 Received: from svr-orw-exc-10.mgc.mentorg.com ([147.34.98.58]) by relay1.mentorg.com with esmtp id 1Td6CV-0004Wd-Oj from Maciej_Rozycki@mentor.com ; Mon, 26 Nov 2012 13:26:47 -0800 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by SVR-ORW-EXC-10.mgc.mentorg.com with Microsoft SMTPSVC(6.0.3790.4675); Mon, 26 Nov 2012 13:26:47 -0800 Received: from [172.30.3.48] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.1.289.1; Mon, 26 Nov 2012 21:26:45 +0000 Date: Mon, 26 Nov 2012 21:27:00 -0000 From: "Maciej W. Rozycki" To: Pierre Muller CC: 'GDB Patches' Subject: Re: PING [RFC] Fix MIPS frame prologue scan problem In-Reply-To: <005901cdcbef$c4a28560$4de79020$@muller@ics-cnrs.unistra.fr> Message-ID: References: <00a501cd495e$db6adea0$92409be0$@muller@ics-cnrs.unistra.fr> <002a01cd5043$a0e9f310$e2bdd930$@muller@ics-cnrs.unistra.fr> <005901cdcbef$c4a28560$4de79020$@muller@ics-cnrs.unistra.fr> User-Agent: Alpine 1.10 (DEB 962 2008-03-14) MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" 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-11/txt/msg00693.txt.bz2 Pierre, > I didn't get any answer on the question I raised > on the bottom of my answer to your comments. > > I just summarize here: > 1) It's true that my pot might not be ABI complaint, but I saw > several other assembly code that use the same approach (it might > be really old assembler) > 2) The current code in mips-tdep.c should either > handle the > add $s8, $sp, LOCALSIZE > in a way similar to what I propose or > otherwise at least complain about non-ABI code, no? Thanks for the reminder and apologies to have lost your case. See further comments below. > > > > I am trying to extend the Free Pascal compiler to support > > > > MIPS architecture. > > > > > > > > From what I read so far, register $s8 (register number 30) can be > used > > > as > > > > a frame register, > > > > but when I set $s8 to the value of the stack pointer ($sp, register > > number > > > > 29) > > > > I get all my locals and parameter of functions wrong. > > > > > > > > I traced it down to the fact that GDB seems to use a > > > > 'virtual' frame pointer register called $fp, > > > > but which is miscalculated in my case. > > > > > > > > In GCC generated code, $s8 register gets the same value as > > > > $sp register, so that this problem does not show up in that case, > > > > but for me, if I have a prologue that reserves 80 bytes, > > > > I will typically get > > > > > > > > # Reserve 80 bytes for locals and area for called function > parameters > > > > addi $sp,$sp,-80 > > > > # Save $ra and $s8 registers, there could be others... > > > > sw $ra,44($sp) > > > > sw $s8,40($sp) > > > > # Set $s8 to function entry value of $sp > > > > addi $s8,$sp,80 > > > > > > > > Analysis of first instruction leads to setting of > > > > frame_offset to 80. > > > > > > > > The problem is that when the last instruction > > > > is analyzed by mips32_scan_prologue, > > > > it switches the frame_reg from $sp to $s8, > > > > but does not modify frame_offset value. > > > > This leads to a frame pointer $fp > > > > being computed as $s8 + frame_offset > > > > which is equal to $sp + 2*frame_offset. > > > > Thus all my locals are wrong :( > > > > > > > > Substraction of the constant in the last addi instruction (low_word) > > > > to frame_offset seems to cure my problem. > > > > > > Well, to put it short, you're not supposed to do that if you want to > > > follow the MIPS ABI. The MIPS processor has no hardware stack and the > > > software implementation of the stack has been made such that there is > > > generally no need to arrange for a hard frame pointer (in a register > > > separate from the stack pointer), except where dynamic stack allocation > > > is used (alloca in C terms). > > > > I tried to read several MIPS documents, > > and the message was not that clear to me... I agree documentation appears ambiguous, for example SGI's "MIPSpro Assembly Language Programmer's Guide" (doc #007-2418-004) refers to the "virtual frame pointer ($fp)" as the incoming value of $sp. However I still think the MIPS psABI document referred below is the normative standard. > > > Therefore the right place to look for how the hard frame pointer has > been > > > specified is the "Dynamic Allocation of Stack Space" section in Chapter > 3 > > > "Machine Interface" of the MIPS psABI document: > > > > > > "When a function requires dynamically allocated stack space it manifests > a > > > frame pointer on entry to the function. The frame pointer is kept in a > > > callee-saved register so that it is not changed across subsequent > function > > > calls. Dynamic stack allocation requires the following steps. > > > > > > 1. On function entry, the function adjusts the stack pointer by the > size > > > of the static stack frame. The frame pointer is then set to this > > > initial sp value and is used for referencing the static elements > > > within the stack frame, performing the normal function of the stack > > > pointer." > > > > > > So in fact both GCC and GDB are correct, you're not supposed to add a > > > constant to the stack pointer when calculating the value of the frame > > > pointer -- it is supposed to hold the value of the stack pointer *after* > > > the frame has been allocated (in other words any frame offsets are > > > non-negative). > > > > Our current problem is that we don't yet knoow the > > stacksize that we need for the function while we generate > > its code, so that using a frame pointer at previous value of stack pointer > > makes this > > really easier for now. NB the use of the frame pointer at the incoming value of $sp does not seem to help you as the local stack variables are meant to be allocated first (toward the bottom of the stack), followed by the incoming register save area and finally the argument build area. See Figure 3-21 in the MIPS psABI document. And you need to know the offset from the frame pointer register to save the incoming registers that happens first in the function prologue. However this simple program: $ cat alloca.c #include extern int bar(void *, int *); int foo(unsigned int i) { int v; return bar(alloca(i), &v); } $ is compiled to this by GCC (I've stripped some less relevant bits for brevity): .text .align 2 .globl foo .ent foo .type foo, @function foo: .frame $fp,40,$31 # vars= 8, regs= 2/0, args= 16, gp= 8 .mask 0xc0000000,-4 .fmask 0x00000000,0 .set noreorder .set nomacro addiu $4,$4,14 srl $2,$4,3 addiu $sp,$sp,-40 sll $2,$2,3 sw $31,36($sp) sw $fp,32($sp) move $fp,$sp subu $sp,$sp,$2 addiu $4,$sp,16 jal bar addiu $5,$fp,24 move $sp,$fp lw $31,36($sp) lw $fp,32($sp) j $31 addiu $sp,$sp,40 .set macro .set reorder .end foo .size foo, .-foo so this does not really follow the standard referred above, as v (at $fp + 24) is clearly allocated farther from the bottom of the stack than the incoming register save area (from $fp + 32 on). And then the stack layout used in code above is hardwired in the implementation of the MIPS16 SAVE instruction, so I think this means you're essentially free to pick your choice. > > > You need to adjust your code generated (BTW, note that the > > > convention assumed by the ABI is to use non-trapping arithmetic; I'm > > Is this the difference between > > ADDI and ADDIU? > > I thought it was only a signed/unsigned difference, > > Do that mean that you never generate any exception if you use the U > version? Correct, the use of signed/unsigned reference in the context of additive operations (ADDI/ADD/SUB and likewise the doubleword variants) is a bit of a misnomer. The only difference between each pair of signed/unsigned operations is that the former takes an overflow exception on a signed overflow and the latter does not. The result computed is otherwise the same for both operations in each pair. > > I am really new to MIPS assembly... Well, I suggest a MIPS assembly book first then, getting a grasp on the dialect purely from technical specs may be quite a challenge. Especially for such a long-lived architecure with its all twists and quirks accumulated over the years. Dominic Sweetman's "See MIPS Run" (ISBN: 0-12-088421-6) is one I can recommend, and it covers much more than lone MIPS assembly programming. Although for some reason the hard frame pointer usage consideration in Section 11.2.9 there also builds on the approach outlined in the SGI document referred above. I don't know why, I have never seen a piece of code doing anything like this and there is no hard example of such code in either text either, although there are many assembly pieces using $sp only quoted. > > > assuming that you deliberately want to trap on overflows to detect the > > > stack pointer crossing the user/kernel segment boundary, right?). > > Not really as explained above ... Ack. > > > NB I suggest that you get real debug information generated as well; it > > > can be stabs if DWARF-2 is too difficult to start with. The heuristic > > > unwinder is really the last-chance attempt made by GDB to find its way > > > around, can only be relied on when applied to conservative code and is > > > best avoided if possible. > > > > But my problem is really that > > GDB found my I do generate stabs debugging information, > > and give parameters and locals > > offsets relative to frame pointer. I'm not sure what you mean -- do you want to say that with stabs debug information GDB still uses the heuristic unwinders to examine function prologues? Hmm, I have been to short into MIPS debug internals to have ever had a need to use stabs, for me DWARF-2 support has been there since forever. But I realise it may be easier for you to start with this simpler debugging format and it's a bit unfortunate that it's not capable enough to get away without the heuristic unwinders, as they are overall quite fragile. > > But in mips32_scan_prologue, > > the first > > ADDI $s8,$sp,LocalSize > > instruction, > > interpreted it in mips32_scan_prologue function > > but ended up with a wrong position of my > > non-ABI standard frame pointer > > because it changed frame pointer register from sp to s8 register, > > but kept frame_offset value as set by the > > SUBI $sp, $sp, LocalSize > > instruction > > analyzed before. > > > > Thus GDB wrongly ends up with a > > frame pointer located a > > value of $s8 register (as from ADDI instruction analysis) > > + LocalSize (from SUBI instruction) > > > > This means that of > > $sp is say at address addr > > $s8 is at addr +LocalSize > > and the virtual frame pointer > > $fp at $s8 + LocalSize = addr + 2 * LocalSize > > > > > > This means that it would be better to remove > > analysis of the ADDI $s8, $sp, LocalSize > > than to leave the current behavior. > > > > I think that we should either use my proposed patch, > > or completely remove the analysis of this ADDI $s8, $sp, LocalSize... Given the ambiguities noted above and following the principle of being liberal as to what to accept I agree your proposal makes sense. I am fairly sure though that in the presence of a hard frame pointer ($fp) it is that value we should rely on as it's there for a reason. I'll get back to you shortly, sorry for the delay and thanks for persistence. Maciej