Re: Unwinding CFI gcc practice of assumed `same value' regs
GCC's unwinder doesn't distinguish undefined from same_value, because it doesn't matter for EH unwinding purposes. Both mean "nothing to be done for this register". The distinction only matters to informative unwinding purposes like debugging. I'm not sure why libgcc's unwinder really ought to care. It's not that I'm against it knowing the difference; that certainly seems a cleaner way for it to be internally. But as to the idea that it needs to distinguish them for correctness, and thus other things need to rely on having a libgcc_s version that does, and so forth, I don't see the motivation. In the ideal world, things would use cfi_undefined on the pc regno to indicate the base frame, as the dwarf3 spec says to. I certainly think it would be cleanest for everything to do that. But again, in practice on i386 and x86_64, I'm not sure I see the need. Correct unwind info should always restore the caller's bp register value. When that unwinds to the outermost frame, that will be a zero value as the runtime code of base frames sets it. My reading is that the "ABI authoring body" for GNU systems or the "compilation system authoring body" for GNU compilers already specifies that the default rule is same_value for callee-saves registers (as chosen by each particular ABI), even if this has not been formally documented anywhere heretofore. (This is how I've written ABI support in another unwinder implementation I've worked on.) As you've said, this is the only reading by which current CFI is correct and complete for getting the values of callee-saves registers. I presume that GCC's omission of rules for those registers is in fact simply because EH unwinding doesn't care and people on the generation side just didn't think about it beyond that. Regardless of the true reasons for the history, the description above applies to the manifest practice that constitutes what we want the formal specification to mean. Thanks, Roland
Re: Unwinding CFI gcc practice of assumed `same value' regs
Jan Kratochvil writes: > currently (on x86_64) the gdb backtrace does not properly stop at > the outermost frame: > > #3 0x0036ddb0610a in start_thread () from /lib64/tls/libpthread.so.0 > #4 0x0036dd0c68c3 in clone () from /lib64/tls/libc.so.6 > #5 0x in ?? () > > Currently it relies only on clearing %rbp (0x above is > unrelated to it, it got read from uninitialized memory). That's how it's defined to work: %rbp is zero. > http://sourceware.org/ml/gdb/2004-08/msg00060.html suggests frame > pointer 0x0 should be enough for a debugger not finding CFI to stop > unwinding, still it is a heuristic. Not by my understanding it isn't. It's set up by the runtime system, and 0 (i.e. NULL on x86-64) marks the end of the stack. Officially. See page 28, AMD64 ABI Draft 0.98 \u2013 September 27, 2006 -- 9:24. Andrew.
Re: Unwinding CFI gcc practice of assumed `same value' regs
> Jan Kratochvil writes: > > > currently (on x86_64) the gdb backtrace does not properly stop at > > the outermost frame: > > > > #3 0x0036ddb0610a in start_thread () from > /lib64/tls/libpthread.so.0 > > #4 0x0036dd0c68c3 in clone () from /lib64/tls/libc.so.6 > > #5 0x in ?? () > > > > Currently it relies only on clearing %rbp (0x above is > > unrelated to it, it got read from uninitialized memory). > > That's how it's defined to work: %rbp is zero. > > > http://sourceware.org/ml/gdb/2004-08/msg00060.html suggests frame > > pointer 0x0 should be enough for a debugger not finding CFI to stop > > unwinding, still it is a heuristic. > > Not by my understanding it isn't. It's set up by the runtime system, > and 0 (i.e. NULL on x86-64) marks the end of the stack. Officially. > > See page 28, AMD64 ABI Draft 0.98 \u2013 September 27, 2006 -- 9:24. Unfortunately whoever wrote that down didn't think it through. In Figure 3.4 on page 20, %rbp is listed as "callee-saved register; optionally used as frame pointer". So %rbp can be used for anything, as long as you save its contents and restore it before you return. Since it may be used for anything, it may contain 0 at any point in the middle of the call stack. So it is unusable as a stack trace termination condition. The only viable option is explicitly marking it as such in the CFI. Initializing %rbp to 0 in the outermost frame is sort of pointless on amd64.
Re: Unwinding CFI gcc practice of assumed `same value' regs
Mark Kettenis writes: > > Jan Kratochvil writes: > > > > > currently (on x86_64) the gdb backtrace does not properly stop at > > > the outermost frame: > > > > > > #3 0x0036ddb0610a in start_thread () from > > /lib64/tls/libpthread.so.0 > > > #4 0x0036dd0c68c3 in clone () from /lib64/tls/libc.so.6 > > > #5 0x in ?? () > > > > > > Currently it relies only on clearing %rbp (0x above is > > > unrelated to it, it got read from uninitialized memory). > > > > That's how it's defined to work: %rbp is zero. > > > > > http://sourceware.org/ml/gdb/2004-08/msg00060.html suggests frame > > > pointer 0x0 should be enough for a debugger not finding CFI to stop > > > unwinding, still it is a heuristic. > > > > Not by my understanding it isn't. It's set up by the runtime system, > > and 0 (i.e. NULL on x86-64) marks the end of the stack. Officially. > > > > See page 28, AMD64 ABI Draft 0.98 \u2013 September 27, 2006 -- 9:24. > > Unfortunately whoever wrote that down didn't think it through. In > Figure 3.4 on page 20, %rbp is listed as "callee-saved register; > optionally used as frame pointer". So %rbp can be used for anything, as > long as you save its contents and restore it before you return. Null-terminating the call stack is too well-established practice to be changed now. In practice, %ebp either points to a call frame -- not necessarily the most recent one -- or is null. I don't think that having an optional frame pointer mees you can use %ebp for anything random at all, but we need to make a clarification request of the ABI. > Since it may be used for anything, it may contain 0 at any point in > the middle of the call stack. > So it is unusable as a stack trace termination condition. The only > viable option is explicitly marking it as such in the CFI. > > Initializing %rbp to 0 in the outermost frame is sort of pointless > on amd64. The right way to fix the ABI is to specify that %ebp mustn't be [mis]used in this way, not to add a bunch more unwinder data. Andrew.
Re: Unwinding CFI gcc practice of assumed `same value' regs
Andrew Haley wrote: Null-terminating the call stack is too well-established practice to be changed now. Which does not mean that the mistake should hold people back. This is just one of the mistakes in the x86-64 ABI. It was copied from x86 and it was wrong there already. In practice, %ebp either points to a call frame -- not necessarily the most recent one -- or is null. I don't think that having an optional frame pointer mees you can use %ebp for anything random at all, Of course it means that. The right way to fix the ABI is to specify that %ebp mustn't be [mis]used in this way, not to add a bunch more unwinder data. Nope. The right way is to specify things like backtraces with the adequate mechanism. I fully support adding the Dwarf3 unwinder requirements. -- ➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Re: Unwinding CFI gcc practice of assumed `same value' regs
Ulrich Drepper writes: > Andrew Haley wrote: > > Null-terminating the call stack is too well-established practice to be > > changed now. > > Which does not mean that the mistake should hold people back. Sure it does. Not breaking things is an excellent reason, probably one of the the best reasons you can have. > This is just one of the mistakes in the x86-64 ABI. It was copied > from x86 and it was wrong there already. > > > In practice, %ebp either points to a call frame -- not necessarily the > > most recent one -- or is null. I don't think that having an optional > > frame pointer mees you can use %ebp for anything random at all, > > Of course it means that. Really? Well, that's one interpretation. I don't believe that, though. It's certainly an inconsistency in the specification, which says that null-termination is supported, and this implies that you can't put a zero in there. > > The right way to fix the ABI is to specify that %ebp mustn't be > > [mis]used in this way, not to add a bunch more unwinder data. > > Nope. The right way is to specify things like backtraces with the > adequate mechanism. I fully support adding the Dwarf3 unwinder > requirements. "All of these" might be the right way to go. That is, keep null-terminating the stack, strengthen the rules about what you might do with %ebp, and extend debuginfo. Andrew.
Re: Unwinding CFI gcc practice of assumed `same value' regs
Andrew Haley wrote: Sure it does. Not breaking things is an excellent reason, probably one of the the best reasons you can have. Nothing breaks if the responsible tools are updated in unison. Really? Well, that's one interpretation. I don't believe that, though. It's certainly an inconsistency in the specification, which says that null-termination is supported, and this implies that you can't put a zero in there. Again, this is just because the "authors" of the ABI didn't think. x86 has the same problem. ebp is freely used and not just for non-NULL values. Register's a scarce and I doubt you'll find any support introducing a register class which says that the register can only hold non-zero value. "All of these" might be the right way to go. That is, keep null-terminating the stack, strengthen the rules about what you might do with %ebp, and extend debuginfo. The thread setup and the startup code certainly does initialize the register with zero. But this means nothing, the register can have zero values in all kinds of other places. -- ➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖
Re: Unwinding CFI gcc practice of assumed `same value' regs
On Tue, 12 Dec 2006 16:26:34 +0100, Andrew Haley wrote: ... > It's certainly an inconsistency in the specification, which says that > null-termination is supported, and this implies that you can't put a zero in > there. I tested now that you can put the zero there for both the libgcc unwinder and for gdb(1) [tested only Fedora Core gdb-6.5-13.fc6], attached, on x86_64 compile [gcc-4.1.1-30] and run by: gcc -o fp0-x86_64 -O9 -fomit-frame-pointer -Wall fp0-x86_64.c -ggdb3; ./fp0-x86_64 The output provided at the end of this mail. Therefore I believe this sentence is wrong and it should be removed: http://www.x86-64.org/documentation/abi.pdf (draft 0.98) Page 28 (29/124) %rbp ... but the user code should mark the deepest stack frame by %setting the frame pointer to zero. On the other hand the right stack terminator for libgcc unwinder is `PC == 0': unwind-dw2.c:uw_frame_state_for (): if (context->ra == 0) return _URC_END_OF_STACK; And gdb should just get updated to behave the same way. libunwind already assumed end of stack on `PC == 0' before and I do not expect any platform would consider `PC == 0' as a valid _return_address_ (which is usually several bytes after any starting function address due to the call instruction). ... > "All of these" might be the right way to go. That is, keep > null-terminating the stack, strengthen the rules about what you might > do with %ebp, and extend debuginfo. For best compatibility null terminate the stack but by CFI and its indicated return address. Do not use %rbp (frame pointer register) in any way (regarding the stack termination condition). Believe only CFI-specified CFA address, unrelated to %rbp content. Regards, Jan -- GNU gdb Red Hat Linux (6.5-13.fc6rh) This GDB was configured as "x86_64-redhat-linux-gnu"...Using host libthread_db library "/lib64/libthread_db.so.1". (gdb) b 12 Breakpoint 1 at 0x40060b: file fp0-x86_64.c, line 12. (gdb) r Starting program: /root/jkratoch/redhat/unwind/fp0-x86_64 Breakpoint 1, backtracer () at fp0-x86_64.c:12 12 int i = backtrace (buf, 512); (gdb) bt #0 backtracer () at fp0-x86_64.c:12 #1 0x00400739 in badone () at fp0-x86_64.c:31 #2 0x0040074e in main () at fp0-x86_64.c:47 (gdb) p/x $rbp $1 = 0x7fff6ed61ca0 (gdb) up #1 0x00400739 in badone () at fp0-x86_64.c:31 31 backtracer (); (gdb) p/x $rbp $2 = 0x0 (gdb) c Continuing. dummy 5 /root/jkratoch/redhat/unwind/fp0-x86_64[0x40062c] /root/jkratoch/redhat/unwind/fp0-x86_64[0x400739] /root/jkratoch/redhat/unwind/fp0-x86_64[0x40074e] /lib64/libc.so.6(__libc_start_main+0xf4)[0x301e81da44] /root/jkratoch/redhat/unwind/fp0-x86_64[0x400559] Program received signal SIGSEGV, Segmentation fault. 0x00400684 in backtracer () at fp0-x86_64.c:21 21 RAFA(1); (gdb) q #include #include #include #include static void backtracer (void) __attribute__((__noinline__)); static void backtracer (void) { void *buf[512]; puts("dummy"); int i = backtrace (buf, 512); printf ("%d\n", i); fflush (stdout); backtrace_symbols_fd (buf, i, STDOUT_FILENO); #define RAFA(level) \ printf("RA (%d) = %p, FA (%d) = %p\n", \ level, __builtin_return_address (level), \ level, __builtin_frame_address (level)) RAFA(0); RAFA(1); RAFA(2); RAFA(3); RAFA(4); RAFA(5); } static int badone (void) __attribute__((__noinline__)); static int badone (void) { backtracer (); return 0; } asm( " .text \n" "clearstack:\n" " pushq $0 \n" " popq%rax\n" " ret \n" ); extern void clearstack(void); int main (void) { clearstack (); badone (); return 0; }
Re: Unwinding CFI gcc practice of assumed `same value' regs
On Mon, Dec 11, 2006 at 02:40:22PM -0800, Roland McGrath wrote: > My reading is that the "ABI authoring body" for GNU systems or the > "compilation system authoring body" for GNU compilers already specifies > that the default rule is same_value for callee-saves registers (as chosen > by each particular ABI), even if this has not been formally documented > anywhere heretofore. (This is how I've written ABI support in another > unwinder implementation I've worked on.) As you've said, this is the only > reading by which current CFI is correct and complete for getting the values > of callee-saves registers. I presume that GCC's omission of rules for > those registers is in fact simply because EH unwinding doesn't care and > people on the generation side just didn't think about it beyond that. > Regardless of the true reasons for the history, the description above > applies to the manifest practice that constitutes what we want the formal > specification to mean. Well, for satisfying the requirement that undefined retaddr_column identifies outermost frame it matters whether retaddr_column's default rule is same_value or undefined. If it is by default same_value, then unwind-dw2.c should just handle explicit DW_CFA_undefined retaddr_column as outermost frame mark, otherwise it would need to handle any unspecified or explicit DW_CFA_undefined retaddr_column (but not DW_CFA_same_value). Here is something that would handle by default same_value retaddr_column: --- gcc/unwind-dw2.h2006-10-29 21:49:23.0 +0100 +++ gcc/unwind-dw2.h2006-12-12 16:30:29.0 +0100 @@ -1,5 +1,5 @@ /* DWARF2 frame unwind data structure. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. This file is part of GCC. @@ -55,7 +55,8 @@ typedef struct REG_SAVED_REG, REG_SAVED_EXP, REG_SAVED_VAL_OFFSET, - REG_SAVED_VAL_EXP + REG_SAVED_VAL_EXP, + REG_UNDEFINED } how; } reg[DWARF_FRAME_REGISTERS+1]; --- gcc/unwind-dw2.c2006-12-08 15:57:44.0 +0100 +++ gcc/unwind-dw2.c2006-12-12 16:38:26.0 +0100 @@ -887,12 +887,16 @@ execute_cfa_program (const unsigned char fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED; break; - case DW_CFA_undefined: case DW_CFA_same_value: insn_ptr = read_uleb128 (insn_ptr, ®); fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNSAVED; break; + case DW_CFA_undefined: + insn_ptr = read_uleb128 (insn_ptr, ®); + fs->regs.reg[DWARF_REG_TO_UNWIND_COLUMN(reg)].how = REG_UNDEFINED; + break; + case DW_CFA_nop: break; @@ -1255,6 +1259,7 @@ uw_update_context_1 (struct _Unwind_Cont switch (fs->regs.reg[i].how) { case REG_UNSAVED: + case REG_UNDEFINED: break; case REG_SAVED_OFFSET: @@ -1323,10 +1328,21 @@ uw_update_context (struct _Unwind_Contex { uw_update_context_1 (context, fs); - /* Compute the return address now, since the return address column - can change from frame to frame. */ - context->ra = __builtin_extract_return_addr -(_Unwind_GetPtr (context, fs->retaddr_column)); + /* In general this unwinder doesn't make any distinction between + undefined and same_value rule. Call-saved registers are assumed + to have same_value rule by default and explicit undefined + rule is handled like same_value. The only exception is + DW_CFA_undefined on retaddr_column which is supposed to + mark outermost frame in DWARF 3. */ + if (fs->regs[fs->retaddr_column].how == REG_UNDEFINED) +/* uw_frame_state_for uses context->ra == 0 check to find outermost + stack frame. */ +context->ra = 0; + else +/* Compute the return address now, since the return address column + can change from frame to frame. */ +context->ra = __builtin_extract_return_addr + (_Unwind_GetPtr (context, fs->retaddr_column)); } static void Jakub
Re: Unwinding CFI gcc practice of assumed `same value' regs
On Tue, Dec 12, 2006 at 03:26:34PM +, Andrew Haley wrote: > Ulrich Drepper writes: > > Andrew Haley wrote: > > > Null-terminating the call stack is too well-established practice to be > > > changed now. > > > > Which does not mean that the mistake should hold people back. > > Sure it does. Not breaking things is an excellent reason, probably > one of the the best reasons you can have. Well, libgcc unwinder handles neither %rbp 0 termination (even if that would be rephrased as outermost frame on x86-64 is determined by %rbp == 0 if CFA is %rbp + offset (that would handle the -fomit-frame-pointer routines where CFA is %rsp + offset)), nor DW_CFA_undefined %rip termination ATM. Things worked until now simply because the outermost routine (_start resp. thread_start hunk in clone in glibc) so far didn't have any unwind info. What would work with stock libgcc unwinder would probably be if _start or clone's child hunk had %rip point to memory containing 0 or DW_CFA_val_expression returning 0 (well, on SPARC that would need to be -8, as RETURN_ADDR_OFFSET is added to it). Jakub
Re: Unwinding CFI gcc practice of assumed `same value' regs
Andrew Haley <[EMAIL PROTECTED]> writes: > In practice, %ebp either points to a call frame -- not necessarily the > most recent one -- or is null. I don't think that having an optional > frame pointer mees you can use %ebp for anything random at all, but we > need to make a clarification request of the ABI. I don't see that as feasible. If %ebp/%rbp may be used as a general callee-saved register, then it can hold any value. And permitting %ebp/%rbp to hold any value is a very useful optimization in a function which does not require a frame pointer, since it gives the compiler an extra register to use. If you want to require %ebp/%rbp to hold a non-zero value, then you are effectively saying that this optimization is forbidden. There is no meaningful way to tell gcc "this is a general register, but you may not store zero in it." It would be a poor tradeoff to forbid that optimization in order to provide better support for exception handling: exception handling is supposed to be unusual. Ian
Re: Unwinding CFI gcc practice of assumed `same value' regs
Ian Lance Taylor writes: > Andrew Haley <[EMAIL PROTECTED]> writes: > > > In practice, %ebp either points to a call frame -- not necessarily the > > most recent one -- or is null. I don't think that having an optional > > frame pointer mees you can use %ebp for anything random at all, but we > > need to make a clarification request of the ABI. > > I don't see that as feasible. If %ebp/%rbp may be used as a general > callee-saved register, then it can hold any value. Sure, we already know that, as has been clear. The question is *if* %rbp may be used as a general callee-saved register that can hold any value. > And permitting %ebp/%rbp to hold any value is a very useful > optimization in a function which does not require a frame pointer, > since it gives the compiler an extra register to use. > > If you want to require %ebp/%rbp to hold a non-zero value, then you > are effectively saying that this optimization is forbidden. There is > no meaningful way to tell gcc "this is a general register, but you may > not store zero in it." It would be a poor tradeoff to forbid that > optimization in order to provide better support for exception > handling: exception handling is supposed to be unusual. Sure, that's reasonable: it's a good reason to suggest that the ABI spec (still in DRAFT state, I note!) might be changed. Andrew.
Re: Unwinding CFI gcc practice of assumed `same value' regs
> Ian Lance Taylor writes: > > Andrew Haley <[EMAIL PROTECTED]> writes: > > > > > In practice, %ebp either points to a call frame -- not necessarily > the > > > most recent one -- or is null. I don't think that having an optional > > > frame pointer mees you can use %ebp for anything random at all, but > we > > > need to make a clarification request of the ABI. > > > > I don't see that as feasible. If %ebp/%rbp may be used as a general > > callee-saved register, then it can hold any value. > > Sure, we already know that, as has been clear. The question is *if* > %rbp may be used as a general callee-saved register that can hold any > value. The amd64 ABI is specifically *designed* to allow this. Mark
Re: Unwinding CFI gcc practice of assumed `same value' regs
Hi, On Tue, 12 Dec 2006, Andrew Haley wrote: > > > In practice, %ebp either points to a call frame -- not necessarily > > > the most recent one -- or is null. I don't think that having an > > > optional frame pointer mees you can use %ebp for anything random at > > > all, but we need to make a clarification request of the ABI. > > > > I don't see that as feasible. If %ebp/%rbp may be used as a general > > callee-saved register, then it can hold any value. > > Sure, we already know that, as has been clear. The question is *if* > %rbp may be used as a general callee-saved register that can hold any > value. Yes of course it was meant to be used such. The ABI actually only gives a recommendation that %rbp should be zero in the outermost frame, it's not a must. The ABI _requires_ proper .eh_frame descriptors when unwinding is desired; so it's useless (and wrong) for any unwinder to look at %rbp and determine if it should stop. Alternatively (though not sanctioned by the ABI) all functions through which unwinding is desired but for which no unwind info is created _have_ to use %rbp as frame pointer and not as general register. In that case the zeroing of %rbp would be a usable stop condition for functions without unwind info. But that's already outside the ABI. Ciao, Michael.
Re: Unwinding CFI gcc practice of assumed `same value' regs
Hi, On Mon, 11 Dec 2006, Jan Kratochvil wrote: > currently (on x86_64) the gdb backtrace does not properly stop at the > outermost > frame: > > #3 0x0036ddb0610a in start_thread () from /lib64/tls/libpthread.so.0 > #4 0x0036dd0c68c3 in clone () from /lib64/tls/libc.so.6 > #5 0x in ?? () > > Currently it relies only on clearing %rbp (0x above is > unrelated to it, it got read from uninitialized memory). > > http://sourceware.org/ml/gdb/2004-08/msg00060.html suggests frame > pointer 0x0 should be enough for a debugger not finding CFI to stop > unwinding, still it is a heuristic. In the -fno-frame-pointer compiled > code there is no indication the frame pointer register became a regular > one and 0x0 is its valid value. Right. Unwinding through functions (without frame pointer) requires CFI. If there is CFI for a function the unwinder must not look at %rbp for stop condition. If there's no CFI for a function it can't be unwound (strictly per ABI). If one relaxes that and wants to unwind through CFI-less functions it has to have a frame pointer. In that case zero in that frame pointer could indicate the outermost frame (_if_ the suggestion in the ABI is adhered to, which noone is required to). Ciao, Michael.
Re: Unwinding CFI gcc practice of assumed `same value' regs
Hi, On Tue, 12 Dec 2006, Ulrich Drepper wrote: > > Really? Well, that's one interpretation. I don't believe that, > > though. It's certainly an inconsistency in the specification, which > > says that null-termination is supported, and this implies that you > > can't put a zero in there. > > Again, this is just because the "authors" of the ABI didn't think. [Blaeh, Ulrich talk] No, I think it's because the "readers" of the ABI can't read. Ciao, Michael.
[PATCH] Re: Unwinding CFI gcc practice of assumed `same value' regs
Hi, On Tue, 12 Dec 2006 16:52:33 +0100, Jakub Jelinek wrote: ... > Here is something that would handle by default same_value retaddr_column: [ http://sources.redhat.com/ml/gdb/2006-12/msg00100.html ] Thanks for this backward compatible glibc unwinder patch. I wish to have it accepted as a step in preparing the environment to use `.cfi_undefined PC' sometimes in the future. Attaching patch for current glibc CVS which removes the `.cfi_undefined PC' unwinder handling requirement but which provides explicit return address 0 from the `__clone' function. Currently the 0 is already present there but it is uninitialized value out of some TLS or 'struct pthread' area (did not check). Attaching patch for current gdb CVS to properly terminate on return address 0. The check was already present there but it got applied one backward step later. I hope these three patches are be 100% reliable and also backward compatible. Regards, Jan 2006-12-13 Jan Kratochvil <[EMAIL PROTECTED]> * sysdeps/unix/sysv/linux/i386/clone.S: CFI `clone' unwinding outermost frame indicator replaced by more unwinders compatible termination indication of `PC == 0'. * sysdeps/unix/sysv/linux/x86_64/clone.S: Likewise. --- libc/sysdeps/unix/sysv/linux/i386/clone.S 3 Dec 2006 23:12:36 - 1.27 +++ libc/sysdeps/unix/sysv/linux/i386/clone.S 13 Dec 2006 11:20:55 - @@ -68,6 +68,8 @@ ENTRY (BP_SYM (__clone)) thread is started with an alignment of (mod 16). */ andl$0xfff0, %ecx subl$28,%ecx + /* Terminate the stack frame by pretended return address 0. */ + movl$0,16(%ecx) movlARG(%esp),%eax /* no negative argument counts */ movl%eax,12(%ecx) @@ -121,10 +123,15 @@ L(pseudo_end): L(thread_start): cfi_startproc; - /* Clearing frame pointer is insufficient, use CFI. */ - cfi_undefined (eip); - /* Note: %esi is zero. */ - movl%esi,%ebp /* terminate the stack frame */ + /* This CFI recommended way of unwindable function is incompatible + across unwinders incl. the libgcc_s one. + cfi_undefined (eip); + */ + /* Frame pointer 0 was considered as the stack frame termination + before but it is no longer valid for -fomit-frame-pointer code. + Still keep the backward compatibility and clear the register. + Note: %esi is zero. */ + movl%esi,%ebp #ifdef RESET_PID testl $CLONE_THREAD, %edi je L(newpid) --- libc/sysdeps/unix/sysv/linux/x86_64/clone.S 3 Dec 2006 23:12:36 - 1.7 +++ libc/sysdeps/unix/sysv/linux/x86_64/clone.S 13 Dec 2006 11:20:55 - @@ -61,8 +61,12 @@ ENTRY (BP_SYM (__clone)) testq %rsi,%rsi /* no NULL stack pointers */ jz SYSCALL_ERROR_LABEL + /* Prepare the data located at %rsp after `syscall' below. + Used only 3*8 bytes but the stack is 16 bytes aligned. */ + subq$32,%rsi + /* Terminate the stack frame by pretended return address 0. */ + movq$0,16(%rsi) /* Insert the argument onto the new stack. */ - subq$16,%rsi movq%rcx,8(%rsi) /* Save the function pointer. It will be popped off in the @@ -90,10 +94,15 @@ L(pseudo_end): L(thread_start): cfi_startproc; - /* Clearing frame pointer is insufficient, use CFI. */ - cfi_undefined (rip); - /* Clear the frame pointer. The ABI suggests this be done, to mark - the outermost frame obviously. */ + /* This CFI recommended way of unwindable function is incompatible + across unwinders incl. the libgcc_s one. + cfi_undefined (rip); + */ + /* Frame pointer 0 was considered as the stack frame termination + before but it is no longer valid for -fomit-frame-pointer code. + Still keep the backward compatibility and clear the register, + the ABI suggests this be done, to mark the outermost frame + obviously. */ xorl%ebp, %ebp #ifdef RESET_PID 2006-12-13 Jan Kratochvil <[EMAIL PROTECTED]> * gdb/frame.c (get_prev_frame): Already the first `PC == 0' stack frame is declared invalid, not the second one as before. 2006-12-13 Jan Kratochvil <[EMAIL PROTECTED]> * gdb.threads/bt-clone-stop.exp, gdb.threads/bt-clone-stop.c: Backtraced `clone' must not have `PC == 0' as its previous frame. --- ./gdb/frame.c 10 Nov 2006 20:11:35 - 1.215 +++ ./gdb/frame.c 13 Dec 2006 19:06:19 - @@ -1390,19 +1390,28 @@ get_prev_frame (struct frame_info *this_ return NULL; } + prev_frame = get_prev_frame_1 (this_frame); + if (!prev_frame) +return NULL; + /* Assume that the only way to get a zero PC is through something like a SIGSEGV or a dummy frame, and hence that NORMAL frames - will never unwi