dwarf: If the dwarf_readu8 call to set op fails, and if there are register
states pushed onto the stack, the stack is not emptied before the function
returns. This change addresses that.
Most of the rest is eliminating ‘goto fail’ from the code.
0-valued hints are used when they are just initial values with no use as
hints. And I think there were some other problems as well.
This patch cleans up and stores hint values with 1 added, so that 0-valued
hints can be ignored.
In src/ppc64/Gstep.c, we use fetch32 to fetch instruction from the
inferior process. In UNW_REMOTE case, fetch32 asserts that the
address we are fetching from is aligned.
But if the inferior is corrupt, we can get unaligned IP, and hit the assert.
Attached patch removes the assert, and makes fetch32 (and fetch16)
return -UNW_EINVAL instead.
unw_get_proc_info must always load the unwind info so that unw_resume
works with GNU_args_size expressions, but must not update
use_prev_expr unless we are unw_step()ing.
blame rev: 4b63a536ee
reported-by: Doug Moore <dougm@rice.edu>
The attached patch fixes a problem with Xorg on MIPS64 n32 which is explained here:
https://bugs.freedesktop.org/show_bug.cgi?id=79939
Basically, libunwind is using a word size of 64-bit for all MIPS variants.
Then, Xorg does a casting to (void *) of a 64-bit variable provided by
libunwind. Given that the size of the pointers in MIPS64 n32 is 32-bit wide,
that casting causes an error like this one:
backtrace.c:90:20: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
libunwind already had support for local unwind on a MIPS. This patch makes
support for remote unwinding on a MIPS.
I should add a few words to the changes to _UPT_access_mem.c: On MIPS, an
unw_word_t is defined as a 64-bit integer whether it's compiled for a 32- or a
64-bit MIPS.
When doing remote unwinding using the default _UPT_accessors, dwarf_readu8()
therefore expects _UPT_access_mem() to return a 64-bit integer. However, if
compiled on a 32-bit MIPS, only 32 bits are valid upon return from
_UPT_access_mem(). The patch detects this and will in this case perform two
calls to ptrace(PTRACE_POKE/PEEK_DATA) and organize the return value according
to endianness.
Centralize gnu_debuglink logic in elfxx. Remove previous duplicated logic
from Gfind_proc_info and os-linux.
Logic is roughly the same as previous load_debug_frame, but uses VLAs
instead of malloc.
This fixes GCC 4.9.3 warnings (Linux/mipsel):
In file included from dwarf/Lfind_unwind_table.c:4:0:
dwarf/Gfind_unwind_table.c: In function '_ULmips_dwarf_find_unwind_table':
dwarf/Gfind_unwind_table.c:140:14: warning: cast from pointer to integer of
different size [-Wpointer-to-int-cast]
addr = (unw_word_t) (hdr + 1);
^
dwarf/Gfind_unwind_table.c:196:50: warning: cast from pointer to integer of
different size [-Wpointer-to-int-cast]
+ (addr - (unw_word_t) edi->ei.image
^
dwarf/Gfind_unwind_table.c:202:40: warning: cast from pointer to integer of
different size [-Wpointer-to-int-cast]
+ ((unw_word_t) hdr - (unw_word_t)
edi->ei.image
^
dwarf/Gfind_unwind_table.c:202:59: warning: cast from pointer to integer of
different size [-Wpointer-to-int-cast]
+ ((unw_word_t) hdr - (unw_word_t)
edi->ei.image
^
```
src/dwarf/Gfind_proc_info-lsb.c:536:16: warning: 'eh_frame' may be used uninitialized in this function [-Wmaybe-uninitialized]
Elf_W (Addr) eh_frame;
^
```
Introduced-in: 25413c729a
It is possible to have multiple CFA_args_size adjustments for a single
frame. If the CFA_args_size adjustment is immediately following the
return from a function which can raise an exception, it is possible to
incorrectly adjust the stack pointer. Consider the following:
...
.cfi_escape 0x2e, 0x00
call f
.Ltmp:
.cfi_escape 0x2e, 0x10
lea label@GOTOFF(%ebx), %eax
...
Because we process the CFI program up to and *INCLUDING* IP, where the
IP is the RA, we would process the associated DW_CFA_GNU_args_size for
the post-call instruction. The result would be a DW_CFA_GNU_args_size
of 0x10 rather than 0x00, resulting in an incorrect stack adjustment.
Handle this by processing the CFI operation but not adjusting the state
record unless we are below the current IP.
Commit 92327a3 "ARM: prefer to unwind using DWARF info"
changes order of unwind info searching to prefer DWARF (.debug_frame)
section in prior to ARM specific (.ARM.exidx). This patch only affects
local process unwinding. Now the same is done for remote unwinding.
Sometimes probing .ARM.exidx first causes backtrace truncation
after __aeabi_ldiv0 (division by 0 handler that generates SIGFPE),
because it hits [cantunwind] generated by cross-gcc for __divsi3
function copied with __aeabi_ldiv0 from libgcc.a. Perhaps, lack of
debug info for __divsi3 causes [cantunwind], or there is a problem
converting DWARF to ARM unwind tables, but when unwinding using
DWARF, it hits proper entry, and backtrace is shown correctly.
Reported-by: Frederic Berat <fberat@de.adit-jv.com>
Signed-off-by: Vitaly Kuzmichev <Vitaly_Kuzmichev@mentor.com>
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.
Debian likes to hive off symbol information to separate -dbg packages,
installing the debug information in a parallel tree rooted at /usr/lib/debug.
libunwind doesn't know how to find these files but it's easy, per the tested,
attached patch, to make it so. I don't see /usr/lib/debug at
http://www.pathname.com/fhs/pub/fhs-2.3.html#USRLIBLIBRARIESFORPROGRAMMINGANDPA
but
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Debugging_with_gdb/separate-debug-files.html
says it's not just Debian and hints it might be driven by gdb. I do see mention
of /usr/lib/debug in libunwind already, but only in a DWARF-specific part of
the code. A minor concern might be checking errno to see if the problem is
ENOENT before trying the alternate path. That might be better than flogging a
mmap problem or being out of file handles or whatever.
Add interface for configurable dwarf cache size
* Use item size and round up to nearest power of 2.
* Initial cache still exists in BSS. Without this, it means we would fail
backtrace when out of memory. The test-mem test fails without this
Currently setcontext for x86_64 restores the signal mask, even
though it is never saved anywhere. This means the signal mask
is often garbage after an unw_resume.
(changed in commit f8a15e9679)
It looks like this was a fix for the Gtest-resume-sig function -
testing if signal masks are restored across signal frames. The
root issue looks like that x86_64 only uses sigreturn for the exact
signal frame, and not for any decedant frames as well (as i64 does).
Instead, modify Gresume to use sigreturn if *any* frame on the stack
is a signal frame, so that we correct fixup the signal mask and any
sigaltstacks. The sigreturn os-specific functions are changed slightly
to copy in the saved ucontext structure if we are jumping farther
up the stack.
This should fix sigprocmask reported issues such as
https://github.com/dropbox/pyston/blob/master/libunwind_patches/0002-pyston-stop-x86_64-setcontext-restoring-uninitialize.patch
Tests pass on freebsd, linux
Read the address using strtoul(). If strtol() is used and the number is
bigger than LONG_MAX, LONG_MAX is returned instead, which leads to a failure
if the mapping address is 0x80000000 or larger on 32-bit platforms (and
similarly for 64-bit platforms).
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)
GCC versions 4.9~current will often generate stack alignment prologues like:
lea 0x8(%rsp),%r10
and $0xfffffffffffffff0,%rsp
...
push %rbp
mov %rsp, %rbp
push %r10
resulting in dwarf expressions:
DW_CFA_def_cfa_expression (DW_OP_breg6: -8; DW_OP_deref)
DW_CFA_expression: r6 (rbp) (DW_OP_breg6: 0)
These prologues seem to be generated for SSE/AVX code, but sometimes
other times as well.
tdep_trace fastpath currently falls back to the slow dwarf parsing path
if it encounters any cfa_expressions. Unfortunately this is happening
often enough in our codebase to cause perf issues. We could also fix the
fallback path (make the rs cache bigger, lock-free instead of locking, etc),
but that seems like a separate issue, and it will ever be as fast as the tracing
code. Our binaries each have at least ~100 functions in them like this.
This patch teaches the tdep_trace about the two specific cfa_expressions,
which really just result in a single extra memory dereference of the stack
at a fixed offset from rbp.
next = inote.descdata + align_power (inote.descsz, 2);
this align is missing, leading to parsing errors. In one case
libunwind only found 1 thread out of 4.
Improves support for binaries missing the GNU_EH_FRAME segment
(.eh_frame_hdr section) by adding a function
'dwarf_find_eh_frame_section' that can create a synthetic one.
If we don't link to libexecinfo, as detected by the
AC_SEARCH_LIBS(backtrace, execinfo) configure probe, we get
```
test-coredump-unwind.o: In function `handle_sigsegv':
/home/libunwind/tests/test-coredump-unwind.c:246: undefined reference to
`backtrace_symbols_fd'
collect2: error: ld returned 1 exit status
Makefile:1187: recipe for target 'test-coredump-unwind' failed
```
and
```
Gtest-init.o: In function `do_backtrace()':
Gtest-init.cxx:(.text+0x2f): undefined reference to `_Ux86_64_getcontext'
Gtest-init.cxx:(.text+0x48): undefined reference to `_Ux86_64_init_local'
Gtest-init.cxx:(.text+0x63): undefined reference to `_Ux86_64_get_reg'
Gtest-init.cxx:(.text+0x96): undefined reference to `_Ux86_64_get_proc_name'
Gtest-init.cxx:(.text+0x171): undefined reference to `_Ux86_64_step'
collect2: error: ld returned 1 exit status
Makefile:1063: recipe for target 'Gtest-init' failed
```
There are 2 XFAIL and 6 FAIL tests, but it's a start