glibc no longer defines sigreturn, but we want to use it
when unwinding through signal stacks to resture the signal mask,
without forcing all uses of getcontext/setcontext to save and
restore the signal mask
When adjusting the stack for a DW_CFA_arg_size adjustment, ensure that
we use the target dependent register name as the generic name does not
necessarily map to the same register. For example, on x86, ESP maps to
the eip register, which results in the wrong stack adjustment being
applied.
When resuming execution, DW_CFA_GNU_args_size from the current frame
must be added back to the stack pointer. Clang now generates these frequently
at -O3. A simple repro for x86_64, that will crash with clang ~3.9 or newer:
void f(int, int,int,int,int,int,int,int,int);
int main() {
try {
f(0,1,2,3,4,5,6,7,8);
} catch (int) {
return 0;
}
return 1;
}
Where f is something that throws an int, but in a different translation unit to
prevent optimization.
This results in cfi instructions before the call:
.cfi_escape 0x2e, 0x20
Grabbing the args_size means fully parsing the cfi in the current frame, which
is unfortunate because it means nearly twice the work at each step. The logic
to grab args_size can be in unw_step or get_proc_info (since this is always
called before resuming in stack unwinding). Putting it in get_proc_info allows
the more common unw_step code to remain fast.
It would potentially fit in nicely with a proc info cache (as mentioned in the
if0 comment block)
unw_is_signal_frame() returns <= 0 if not a signal frame. Several places in
code were only checking for a "if (unw_is_signal_frame())", or
"if (!unw_is_signal_frame())".
Mark frames which are unwound with the frame-chain walker or
syscall frame code, as non-interrupted. The return PC in the frame
points to the instruction after the call.
Check the endianness earlier in unw_create_addr_space() on all
architectures to avoid leaking the dynamically allocated address space
struct.
This was already fixed for ARM in commit cf6a998796 ("Fix memory leak
in ARM unw_create_addr_space()"). Move the endianness check also on ARM
to avoid malloc() & free() in the error case.
Adds new function to perform a pure stack walk without unwinding,
functionally similar to backtrace() but accelerated by an address
attribute cache the caller maintains across calls.
the instruction after the call for a normal frame. libunwind uses
IP-1 to lookup unwind information. However, this is not necessary for
interrupted frames such as signal frames (or interrupt frames) in
the kernel context.
This patch handles both cases correctly.
Based on work by Mark Wielaard <mwielaard@redhat.com>