Re: Unwinding CFI gcc practice of assumed `same value' regs

2006-12-11 Thread Roland McGrath
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

2006-12-12 Thread Andrew Haley
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

2006-12-12 Thread Mark Kettenis
>  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

2006-12-12 Thread Andrew Haley
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

2006-12-12 Thread Ulrich Drepper

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

2006-12-12 Thread Andrew Haley
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

2006-12-12 Thread Ulrich Drepper

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

2006-12-12 Thread Jan Kratochvil
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

2006-12-12 Thread Jakub Jelinek
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

2006-12-12 Thread Jakub Jelinek
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

2006-12-12 Thread Ian Lance Taylor
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

2006-12-12 Thread Andrew Haley
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

2006-12-12 Thread Mark Kettenis
>  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

2006-12-13 Thread Michael Matz
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

2006-12-13 Thread Michael Matz
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

2006-12-13 Thread Michael Matz
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

2006-12-13 Thread Jan Kratochvil
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