mirror of
https://github.com/tobast/libunwind-eh_elf.git
synced 2024-11-14 20:28:12 +01:00
1010880548
The crashes were tracked down to f->rpb_cfa_offset being incorrect. The problem is that {rsp,rbp}_cfa_offset only have 15 bits, but for SIGRETURN frame they are filled with: // src/x86_64/Gstash_frame.c f->cfa_reg_offset = d->cfa - c->sigcontext_addr; f->rbp_cfa_offset = DWARF_GET_LOC(d->loc[RBP]) - d->cfa; f->rsp_cfa_offset = DWARF_GET_LOC(d->loc[RSP]) - d->cfa; The problem is that the delta here can be arbitrarily large when sigaltstack is used, and can easily overflow the 15 and 30-bit fields. When signal handler starts running, the stack layout is: ... higher addresses ... ucontext CFA-> __restore_rt (== pretcode in rt_sigframe from linux-2.6/arch/x86/include/asm/sigframe.h) SP -> ... sighandler runs on this stack. ... lower addresses ... This makes it very convenient to find ucontext from the CFA. Attached patch re-tested on Linux/x86_64, no new failures. Signed-off-by: Paul Pluzhnikov <ppluzhnikov@google.com> Reviwed-by: Lassi Tuura <lat@cern.ch> |
||
---|---|---|
.. | ||
Gcreate_addr_space.c | ||
getcontext.S | ||
Gget_proc_info.c | ||
Gget_save_loc.c | ||
Gglobal.c | ||
Ginit.c | ||
Ginit_local.c | ||
Ginit_remote.c | ||
Gos-freebsd.c | ||
Gos-linux.c | ||
Gregs.c | ||
Gresume.c | ||
Gstash_frame.c | ||
Gstep.c | ||
Gtrace.c | ||
init.h | ||
is_fpreg.c | ||
Lcreate_addr_space.c | ||
Lget_proc_info.c | ||
Lget_save_loc.c | ||
Lglobal.c | ||
Linit.c | ||
Linit_local.c | ||
Linit_remote.c | ||
Lis_signal_frame.c | ||
longjmp.S | ||
Los-freebsd.c | ||
Los-linux.c | ||
Lregs.c | ||
Lresume.c | ||
Lstash_frame.c | ||
Lstep.c | ||
Ltrace.c | ||
offsets.h | ||
regname.c | ||
setcontext.S | ||
siglongjmp.S | ||
ucontext_i.h | ||
unwind_i.h |