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