This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

x86_64 unwinder in libgcc_s


Hello!

I got strange problem in LuaJIT [1] stack unwinding on Solaris x64.
If I build everything using GCC with unwinder from libgcc_s everything works fine.
But when I try to use GCC-built libluajit.a in executable built using Sun Studio 12.2 with standard solaris unwinder from libc I got a crash.


As it turned out this is due to invalid value that _Unwind_GetCFA() function returned (called from Lua personality routine)

E.g. in core I can see the following stack:

[1] err_unwind(0x71255e31, 0x6e0bd80, 0x0, 0x6e0bd80, 0x6e0b5d0, 0x7124bbb5), at 0x7124b875
[2] lj_err_unwind_dwarf(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x7124bc25
[3] _Unwind_RaiseException_Body(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffaae0bfc
[4] _SUNW_Unwind_RaiseException(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0xfffffd7ffaae0de9
[5] err_raise_ext(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x7124be2c
[6] lj_err_throw(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x7124be89
[7] lj_trace_err_info(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x7129b8d8
[8] lj_record_ins(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x7127f0ec
[9] trace_state(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x7129d7cd
[10] lj_vm_cpcall(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x712473ba
[11] lj_trace_ins(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x7129db8d
[12] lj_dispatch_ins(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x71255e31
[13] lj_vm_inshook(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x71248a41
[14] lua_pcall(0x0, 0x0, 0x0, 0x0, 0x0, 0x0), at 0x7125a584
...


lj_err_unwind_dwarf() is personality routine for lj_vm_cpcall() (frame 10) so it's called to process its stack frame.

x86_64 psABI says that _Unwind_GetCFA() "returns the 64-bit Canonical Frame Address which is defined as
the value of %rsp at the call site in the previous frame." (6.2.5 Context Management)


So if I understand this correctly *(CFA - 8) should contain address somewhere inside lj_vm_cpcall() caller, i.e. in lj_trace_ins() (frame 11).
And when using Solaris std unwinder it's in fact true, but it crashes.
When using GCC unwinder return address is somewhere inside lj_vm_cpcall() itself, i.e. AFAIU CFA for trace_state() (frame 9) is returned instead, but it works.


I can make std unwinder work by adjusting returned CFA to point to next frame by subtracting 80 bytes from it but it's interesting to understand why this happens.

Am I missing something and GCC unwinder is right?

TIA

[1] http://luajit.org/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]