x86_64 unwinder in libgcc_s
Ian Lance Taylor
iant@google.com
Tue Aug 14 13:58:00 GMT 2012
On Tue, Aug 14, 2012 at 6:14 AM, Dmitri Shubin <sbn@tbricks.com> wrote:
> On 14.08.2012 14:18, Andrew Haley wrote:
>
> My question was: why I get wrong (from my pov) CFA value from GCC unwinder.
>
> I rewritten my small test.
> As one can see here in foo() I placed constant 0x1020304050 right after
> return address to main(), e.g. *(CFA - 16) and in personality routine I try
> to get it from there.
> First I use standard Solaris unwinder from libc:
>
> $ /opt/csw/bin/gas -64 foo.s
>
> $ cc -m64 main.c foo.o
> $ ./a.out
> &main = 400bc0, &foo = 400c00
> cfa = fffffd7fffdffb10
> ra = 400bf1
> ip = 400c10
> v = 1020304050
> *cfa = 1
>
> And got expected value (v = 1020304050).
>
> Then I use unwinder from libgcc_s:
>
>
> $ /opt/csw/bin/gcc -m64 main.c foo.s
> $ ./a.out
> &main = 40186a, &foo = 401894
> cfa = fffffd7fffdffb10
> ra = 4018a4
> ip = 4018a4
> v = fffffd7fffdffb20
> *cfa = 1020304050
>
> And got something totally wrong.
When I run your program on GNU/Linux, I get this:
&main = 0x4007ce, &foo = 0x4007f8
cfa = 0x7fff9cdbaf40
ra = 0x400808
ip = 0x400808
v = 7fff9cdbaf50
*cfa = 1020304050
> In foo_personality() I expect to have the following stack layout for foo()
> frame (width is 8 bytes):
>
> : : ^
> | main() frame | |
> +----------------+ <--- CFA for foo() |
> increasing addresses
> | return address | <--- points to somewhere in main() |
> +----------------+ |
> | 0x1020304050 | <--- some context value stored by foo() |
> +----------------+
> : :
>
> And this is what I have when using Solaris unwinder. But libgcc returned me
> another CFA:
>
> : : ^
> | main() frame | |
> +----------------+ | increasing addresses
> | return address | <--- points to somewhere in main() |
> +----------------+ |
> | 0x1020304050 | <--- some context value stored by foo() |
> +----------------+ <--- CFA for foo() returned by libgcc_s
> : :
>
> So the question is who is right here?
> From my understanding of definition of CFA given in x86_64 psABI Solaris
> unwinder is right and libgcc_s one is wrong.
I think the definition of _Unwind_GetCFA is ambiguous. It says "the
value of %rsp at the call site in the previous frame." GCC is
returning the value of %rsp at the point of the call to throw.
Solaris is returning the value of %rsp at the call to foo. I don't
know which is correct. _Unwind_GetCFA is not part of the C++
exception handling ABI; I'm not sure where it came from.
I agree that it would be nice if Solaris and GNU/Linux were
compatible, but I don't see how that is possible at this point.
Why do you want the CFA? Perhaps you can use _Unwind_GetGR or other
functions that are part of the C++ exception interface?
Ian
More information about the Gcc
mailing list