On Tue, Aug 14, 2012 at 6:14 AM, Dmitri Shubin <s...@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

Reply via email to