From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3482 invoked by alias); 21 Nov 2005 05:50:54 -0000 Received: (qmail 3475 invoked by uid 22791); 21 Nov 2005 05:50:53 -0000 X-Spam-Check-By: sourceware.org Received: from ip127.bb146.pacific.net.hk (HELO stl.com.hk) (202.64.146.127) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 21 Nov 2005 05:50:53 +0000 Received: from rccomp.stl.com.hk ([192.168.100.200]) by stl.com.hk with esmtp (Exim 4.50) id 1Ee4VG-0001Iy-5F for gdb@sources.redhat.com; Mon, 21 Nov 2005 13:46:10 +0800 Message-ID: <4381603E.1060500@tausq.org> Date: Mon, 21 Nov 2005 05:50:00 -0000 From: Randolph Chung User-Agent: Mozilla Thunderbird 1.0.6 (Windows/20050805) MIME-Version: 1.0 To: gdb@sources.redhat.com Subject: Argument pointers, dwarf and prologue analysis Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2005-11/txt/msg00440.txt.bz2 Here's another interesting bit from HPPA's abi -- on 64-bit, the HPPA ABI uses an "argument pointer" (r29) that points inside the stack frame for storing various things. The argument pointer is set by the caller, and is *not* a call preserved register. Moreover, in gcc, in the callee frame, the compiler will compute an offset to r29, and use that to store the arguments. For example: foo .PROC .CALLINFO FRAME=80,NO_CALLS,SAVE_SP,ENTRY_GR=3 .ENTRY copy %r3,%r1 copy %r30,%r3 std,ma %r1,80(%r30) std %r3,-8(%r30) ldo -64(%r29),%r20 stw %r26,4(%r20) stw %r25,12(%r20) stw %r24,20(%r20) [...] Here, r20 is a scratch register (also not call preserved). r26, r25, r24 are the first three arguments to the function. Based on the above code, the dwarf debug info emitted describes the arguments using DW_OP_breg20 {4,12,20} This causes obvious problems when trying to retrieve arguments from outer frames, for example: int foo(int a, int b, int c, int d, int e, int f, int g, int h) { return a+b+c+d+e+f+g+h; } int bar(int a, int b, int c, int d, int e, int f, int g, int h) { return foo(a+1, b+1, c+1, d+1, e+1, f+1, g+1, h+1); } int main(int argc, char **argv) { return bar(1,2,3,4,5,6,7,8); } in foo, the arguments to bar are incorrectly read because r20 may have been clobbered and cannot be recovered (currently). Possibly, gcc should be changed to generate code that stores arguments based on a call preserved register, but in talking with Dave Anglin, it seems this is not so straightforward. He also suggested another idea: In fact, r20 above can be determined by looking at the caller frame (bar in the example). A few insn before the call to foo, you will find: ldo -48(%r30),%r29 copy %r27,%r4 b,l foo,%r2 r30 is the stack pointer. So, theoretically, one could find the return pointer of the current frame, look at a few insns before that point, determine the offset from the frame base of the current frame, then adjust that based on the ldo insn in the prologue in the current frame to get the value of r20, and store that value in the frame cache. Then, the dwarf evaluation will be able to read the argument values from the correct location. Whew! Before I go and try to implement this mess, I would like to get some feedback about whether this seems to be a good solution. Are there better ways to do this? Can we simply make gcc emit a few more dwarf ops to describe all the offsets and pointers that are involved? Comments much appreciated :) randolph -- Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/