Hi, On gcc/stabs, a function with a normal frame setup sequence has the parameter offsets output as offsets from the frame pointer: E.g., from funcargs.c: void call0a (char c, short s, int i, long l); .stabs "call0a:F(0,15)",36,0,32,call0a .stabs "c:p(0,1)",160,0,31,8 .stabs "s:p(0,1)",160,0,31,12 .stabs "i:p(0,1)",160,0,31,16 .stabs "l:p(0,3)",160,0,31,20 .globl call0a .type call0a, @function call0a: .stabd 46,0,0 Notice the 8 on the first parameter ("c:p(0,1)",160,0,31,8) -- that would be argument word 0 at 8($ebp). Since gcc 4.1 and later started putting code in the prologue to realign the stack pointer, the offset on the parameter stabs changed from being relative to the frame pointer to being relative to the argument's address. E.g.: int main (int argc, char **argv, char **envp); notice the 0, 4, 8: .zero 16 .text .stabs "main:F(0,1)",36,0,10,main .stabs "argc:p(0,1)",160,0,9,0 .stabs "argv:p(0,16)=*(3,54)",160,0,9,4 .stabs "envp:p(0,16)",160,0,9,8 .globl main .type main, @function I don't know if this is a gcc bug or if this is specified somewhere. Several gcc's have been out with this problem, so I guess the best option is to account for it in gdb. The attached patch adds that special casing. In order to fully fix the issue, there is another tweak that needs to be made. By the time we're analyzing the frame, to read the value of a parameter, the register that holds the %esp of the previous frame may have been clobbered. If we see it being saved in the stack before being clobbered, we can still get to it. Eg from args.exp: int main (int argc, char **argv) { 80483e4: 8d 4c 24 04 lea 0x4(%esp),%ecx 80483e8: 83 e4 f0 and $0xfffffff0,%esp 80483eb: ff 71 fc pushl 0xfffffffc(%ecx) 80483ee: 55 push %ebp 80483ef: 89 e5 mov %esp,%ebp 80483f1: 51 push %ecx << register save, 80483f2: 83 ec 24 sub $0x24,%esp << before stack adjustment 80483f5: 89 4d e8 mov %ecx,0xffffffe8(%ebp) int i = 0; While fixing this, I noticed that i386_analyze_stack_align recognizes %ecx, %edx or %eax as the register that is used to hold the %esp of the calling frame, but i386_frame_cache always expected it in %ecx. I've added a new variable in struct i386_frame_cache to represent which register it was, and use it in the i386_frame_cache function. Another change, which is purely cosmetic, is the s/saved_sp/prev_frame_sp/ renaming. For normal, non-main frames, this field doesn't hold anything "saved", but computed in i386_frame_cache: cache->saved_sp = cache->base + 8; The patch has been tested on i686-pc-linux-gnu/dwarf, i686-pc-linux-gnu/"--target_board=unix/gdb:debug_flags=-gstabs+" and on i686-pc-cygwin. On stabs, I get these fixes: --- 0/gdb.sum 2007-11-30 01:30:02.000000000 +0000 +++ 1/gdb.sum 2007-11-30 01:45:33.000000000 +0000 @@ -1,4 +1,4 @@ -Test Run By pedro on Fri Nov 30 01:16:23 2007 +Test Run By pedro on Fri Nov 30 01:31:55 2007 Native configuration is i686-pc-linux-gnu === gdb tests === @@ -283,31 +283,31 @@ PASS: gdb.base/annota3.exp: signal sent PASS: gdb.base/annota3.exp: cleanup core file (removed) Running /home/pedro/gdb/autotester/frame_args_stabs/src/gdb/testsuite/gdb.base/args.exp ... PASS: gdb.base/args.exp: continue to breakpoint: breakpoint for basic -FAIL: gdb.base/args.exp: argc for basic -FAIL: gdb.base/args.exp: argv[1] for basic -FAIL: gdb.base/args.exp: argv[2] for basic +PASS: gdb.base/args.exp: argc for basic +PASS: gdb.base/args.exp: argv[1] for basic +PASS: gdb.base/args.exp: argv[2] for basic PASS: gdb.base/args.exp: continue to breakpoint: breakpoint for one empty -FAIL: gdb.base/args.exp: argc for one empty -FAIL: gdb.base/args.exp: argv[1] for one empty -FAIL: gdb.base/args.exp: argv[2] for one empty -FAIL: gdb.base/args.exp: argv[3] for one empty +PASS: gdb.base/args.exp: argc for one empty +PASS: gdb.base/args.exp: argv[1] for one empty +PASS: gdb.base/args.exp: argv[2] for one empty +PASS: gdb.base/args.exp: argv[3] for one empty PASS: gdb.base/args.exp: continue to breakpoint: breakpoint for two empty -FAIL: gdb.base/args.exp: argc for two empty -FAIL: gdb.base/args.exp: argv[1] for two empty -FAIL: gdb.base/args.exp: argv[2] for two empty -FAIL: gdb.base/args.exp: argv[3] for two empty -FAIL: gdb.base/args.exp: argv[4] for two empty +PASS: gdb.base/args.exp: argc for two empty +PASS: gdb.base/args.exp: argv[1] for two empty +PASS: gdb.base/args.exp: argv[2] for two empty +PASS: gdb.base/args.exp: argv[3] for two empty +PASS: gdb.base/args.exp: argv[4] for two empty PASS: gdb.base/args.exp: continue to breakpoint: breakpoint for one empty -FAIL: gdb.base/args.exp: argc for one empty -FAIL: gdb.base/args.exp: argv[1] for one empty -FAIL: gdb.base/args.exp: argv[2] for one empty -FAIL: gdb.base/args.exp: argv[3] for one empty +PASS: gdb.base/args.exp: argc for one empty +PASS: gdb.base/args.exp: argv[1] for one empty +PASS: gdb.base/args.exp: argv[2] for one empty +PASS: gdb.base/args.exp: argv[3] for one empty PASS: gdb.base/args.exp: continue to breakpoint: breakpoint for two empty -FAIL: gdb.base/args.exp: argc for two empty -FAIL: gdb.base/args.exp: argv[1] for two empty -FAIL: gdb.base/args.exp: argv[2] for two empty -FAIL: gdb.base/args.exp: argv[3] for two empty -FAIL: gdb.base/args.exp: argv[4] for two empty +PASS: gdb.base/args.exp: argc for two empty +PASS: gdb.base/args.exp: argv[1] for two empty +PASS: gdb.base/args.exp: argv[2] for two empty +PASS: gdb.base/args.exp: argv[3] for two empty +PASS: gdb.base/args.exp: argv[4] for two empty Running /home/pedro/gdb/autotester/frame_args_stabs/src/gdb/testsuite/gdb.base/arithmet.exp ... PASS: gdb.base/arithmet.exp: set variable x=14 PASS: gdb.base/arithmet.exp: set variable y=2 @@ -12259,8 +12259,8 @@ PASS: gdb.xml/tdesc-xinclude.exp: set td === gdb Summary === -# of expected passes 11491 -# of unexpected failures 207 +# of expected passes 11512 +# of unexpected failures 186 # of unexpected successes 4 # of expected failures 52 # of unknown successes 6 On dwarf, there are no changes to the testsuite, as in that case, get_frame_args_address is only used for 'info frame'. -- Pedro Alves