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
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.
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())".
This fixes GCC 4.9.3 warnings (Linux/mipsel):
dwarf/Gfind_proc_info-lsb.c: In function 'locate_debug_info':
dwarf/Gfind_proc_info-lsb.c:244:23: warning: 'mi.buf_end' may be used
uninitialized in this function [-Wmaybe-uninitialized]
struct map_iterator mi;
^
dwarf/Gfind_proc_info-lsb.c:244:23: warning: 'mi.buf' may be used
uninitialized in this function [-Wmaybe-uninitialized]
In file included from dwarf/Gfind_proc_info-lsb.c:46:0:
./os-linux.h:292:27: warning: 'mi.buf_size' may be used uninitialized in
this function [-Wmaybe-uninitialized]
munmap (mi->buf_end - mi->buf_size, mi->buf_size);
^
dwarf/Gfind_proc_info-lsb.c:244:23: note: 'mi.buf_size' was declared here
struct map_iterator mi;
^
The detection logic introduced in 28f33c8ce0 is
broken, because it tests mincore using an address that is almost certainly not
page-aligned. straces confirms that msync is used all the time.
This patch fixes the logic by page-aligning the test pointer. strace now shows
that mincore is actually used. Furthermore, the return value of mincore is not
sufficient to assess whether the address can be safely dereferenced: we should
also check that the pages are mapped, through the passed mvec array. This patch
also adds this verification.
Tested on a system where unwinding a stack across a JNI boundary would cause
sporadic segfaults; no more crashes were observed after the patch.
A recent commit added code to override the unwind location for the
TOC pointer register r2:
unsigned int *inst = (unw_word_t*)c->dwarf.ip;
if (*inst == (0xE8410000 + 24)) {
// @plt call, restoring R2 from CFA+24
c->dwarf.loc[UNW_PPC64_R2] = DWARF_LOC(c->dwarf.cfa + 24, 0);
}
It is correct that such code is needed, since DWARF CFI does not
describe the unwind location for r2 on PowerPC. However, this
particular bit of code has a number of issues, which are fixed
in this patch.
First of all, the location CFA+24 is correct only for the ELFv2
ABI. In the ELFv1 ABI, the TOC location is actually CFA+40.
More problematically, attempting to read the current instruction
by just dereferencing the address in c->dwarf.ip is wrong, and
may often lead to crashes. In particular:
- During remote unwinding, this is always wrong since we're in
the wrong address space. I've used the fetch32 helper from
remote.h to use the proper access_mem under the covers.
- c->dwarf.ip may be NULL if we've reached the end-of-stack.
I've fixed this by moving the c->dwarf.ip == 0 check down
to after unwinding (instead of before), just like all other
platforms do.
- Even so, c->dwarf.ip may point to some random location if
we've gotten confused during unwinding earlier. One likely
cause for such confusion is that we did not find DWARF CFI
for some earlier frame and attempted to use the stack
backchain. The problem is that this code currently claims
all registers remain unchanges in such a frame, which is
generally wrong. In particular if the function actually
saves and modifies r31, and this is used as frame pointer
by a later frame, things will likely go quite wrong. While
it is not really possibly to completely fix this, I've at
least marked all registers as unavailable after unwinding
a frame via stack backchain.
Tested on powerpc64-linux and powerpc64le-linux. The patch fixes
about a dozen test cases that were crashing before.
Signed-off-by: Ulrich Weigand <ulrich.weigand@de.ibm.com>
By default, the start_ip_offset in libunwind's table_entry struct is
relative to the unw_dyn_info_t's segbase. This presents a problem
for us in conjunction with using LLVM's MCJIT because it likes to
spread text sections and the corresponding eh_frame sections quite
far apart. This represents my attempt to support this use case in the
simplest manner that is backwards compatible, by adding a new format
kind (UNW_INFO_FORMAT_REMOTE_TABLE2) that indicates that the
`start_ip_offset` should be interpreted as relative to `start_ip`
rather than segbase.
Detect if current frame is a signal frame by checking for preceeding
syscall instruction. For signal frames, update the cursor correctly
from user context before calling dwarf_step.
Due to a bug in the gold linker[1], the .eh_frame and .eh_frame_hdr
sections contains garbage. When dwarf_extract_proc_info_from_fde tried
to look up the begin of the CIE subsection, it would underflow the
.eh_frame segment, resulting in a crash[2].
This patch avoids that crash by checking whether the CIE pointer is
located after the begin of the .eh_frame section. The variable "base"
was misused in various places as a boolean (decode as .debug_frame or
decode as .eh_frame). These instances have been renamed to
is_debug_frame where applicable.
Tested on Linux x86_64.
[1]: https://sourceware.org/bugzilla/show_bug.cgi?id=17639
[2]: http://lists.nongnu.org/archive/html/libunwind-devel/2014-11/msg00009.html
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Set local_addr_space.big_endian flag according to current target
endianness. Before it was set by memset to 0, which corresponds
to little endian and it worked perfectly fine for aarch64.
But it breaks aarch64_be because dwarf_readu16, dwarf_readu32,
etc functions do not read values correctly since they operate
with wrong idea about current target endianness.
Signed-off-by: Victor Kamensky <victor.kamensky@linaro.org>
We've just traced a large memory increase to that patch (Google ref:
b/18069427).
It appears that labs() was there for a good reason.
Sorry about that :-(
For the curious:
unsigned long u1 = ~0UL;
unsigned long u2 = labs(u1);
assert(u1 != u2); // labs on unsigned *may* have an effect, despite
what Clang says.
Attached patch suppresses the Clang warning, while still keeping the
original behavior (which I believe to be correct).
Thanks,
--
Paul Pluzhnikov
Greetings,
Roman reports that Clang warns on unnecessary calls to labs():
taking the absolute value of unsigned type 'unw_word_t' (aka
'unsigned long') has no effect [-Werror,-Wabsolute-value]
Since rs->reg[...].val is unw_word_t and unsigned on all platforms,
this patch removes the unnecessary calls to labs().
Tested on Linux x86_64, no regressions.
Thanks,
--
Paul Pluzhnikov
Fix returning the name of the function containing the frame PC,
for the non-interrupted frames. The symbol lookup code should
take use_prev_instr value into account, otherwise it could return
the name of the function adjacent to the caller.
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.
We already have the value computed based on the executable. Furthermore,
debuginfo need not have valid program header table, thus the result
might be bogus.
Signed-off-by: Martin Milata <mmilata@redhat.com>
When JITs generate code without unwind information, it may be possible
to continue unwinding via RBP chaining. However, we currently disallow
RBP==RSP condition even though we can make forward progress.
Relax the check a bit in the code where we switch from one type of
unwinding to another to handle this situation. JIT authors
are encouraged to use the dynamic unwind info registration API when
the underlying platform supports it.
Signed-off-by: Kevin Modzelewski <kmod@dropbox.com>
The attached patch simply modifies the Debug statements for aarch64 to use
%lx instead of %x. Tested by compiling for aarch64 using a cross-compiler.
Signed-off-by: Christopher Ferris <cferris@google.com>
The coredump/elf32/elf64/elfxx libs use lzma funcs but don't link against
it. This produces sub-shared libs that don't link against lzma and can
make the linker angry due to underlinking like so:
libtool: link: x86_64-pc-linux-gnu-gcc -O2 -march=amdfam10 -pipe -g \
-frecord-gcc-switches -Wimplicit-function-declaration -fexceptions \
-Wall -Wsign-compare -Wl,-O1 -Wl,--hash-style=gnu \
-o .libs/test-coredump-unwind test-coredump-unwind.o \
../src/.libs/libunwind-coredump.so ../src/.libs/libunwind-x86_64.so
../src/.libs/libunwind-coredump.so: error: undefined reference to 'lzma_stream_footer_decode'
../src/.libs/libunwind-coredump.so: error: undefined reference to 'lzma_index_buffer_decode'
../src/.libs/libunwind-coredump.so: error: undefined reference to 'lzma_index_size'
../src/.libs/libunwind-coredump.so: error: undefined reference to 'lzma_index_end'
../src/.libs/libunwind-coredump.so: error: undefined reference to 'lzma_index_uncompressed_size'
../src/.libs/libunwind-coredump.so: error: undefined reference to 'lzma_stream_buffer_decode'
collect2: error: ld returned 1 exit status
So add LIBLZMA to the right LIBADD for each of these libraries.
URL: https://bugs.gentoo.org/444050
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Ubuntu's libc-bin (2.15-0ubuntu20.2) on x86_64 uses DW_CFA_val_expression
in describing the pthread spinlock operations __lll_unlock_wake() and
__lll_lock_wait(). libunwind 1.1 doesn't understand that opcode and
so backtraces from those operations are truncated.
This changeset adds basic support for it, by adding a new type to
dwarf_loc_t that describes the register's actual contents rather than
its location. I've only implemented the new type for x86_64, and
stubbed it out for all other architectures -- it looks like a lot
of that code is duplicated so oughtn't to be that hard, but I don't
have test cases for them.
Tested that DW_CFA_val_expression works on x86_64 (by using
https://code.google.com/p/gperftools/ on a lock-heavy program).
Build-tested on x86, x86_64 and arm. The unit tests don't pass for me
on any of those archs, but this cset doesn't break anything that was
passing before.
Signed-off-by: Tim Deegan <tjd@phlegethon.org>
This patch adds support for the powerpc64le-linux platform. It consists
of two main features:
- Support little-endian byte order
This is done via a "big_endian" member of struct unw_addr_space,
which is evaluated by common code via the dwarf_is_big_endian
macro, and also in endian-aware code in unw_is_signal_frame.
- Support the ELFv2 ABI
This is done via an "abi" member of struct unw_addr_space. This
is currently only needed in tdep_get_func_addr, since the ELFv2
ABI does not use function descriptors.
Both new members are initialized in unw_create_addr_space and
ppc64_local_addr_space_init, following the mips precedent.
Since ppc32 and ppc64 now no longer share the unw_create_addr_space
implementation, the file is duplicated from the ppc directory into
ppc32/ppc64.
Tested on powerpc64-linux and powerpc64le-linux. Support on LE
seems to be as good as existing BE support; I have not attempted to
fix the existing shortcomings of PPC support that already cause a
number to tests to fail due to unimplemented features.
Signed-off-by: Ulrich Weigand <uweigand@de.ibm.com>
The ppc64 implementation of tdep_get_func_addr would crash when
attempting to retrieve the address of a function in a shared
library. The problem was that it needs to dereference the
function descriptor, but common code was passing the *unrelocated*
adddress of the descriptor to the tdep_get_func_addr routine.
Instead, common code would attempt to relocate the *result* of
tdep_get_func_addr, which is also wrong: the ppc64 implementation
reads the function address from the in-memory copy of the
descriptor, which is already relocation and contains the final
address.
This patch fixes the problem by relocating the descriptor address
before passing it to tdep_get_func_addr, instead of relocating
the result of tdep_get_func_addr. Since ppc64 is the only
non-trivial implementation of tdep_get_func_addr, this cannot
affect any other platform.
Signed-off-by: Ulrich Weigand <uweigand@de.ibm.com>
The dwarf_eval_expr routine uses macros push, pop, and pick to
manipulate the DWARF expression stack. When these macros are
nested, e.g. in the implementation of DW_OP_dup:
push (pick (0));
the combination can lead to unfortunate results.
In particular, when substituting into:
do {
if (tos >= MAX_EXPR_STACK_SIZE)
{
Debug (1, "Stack overflow\n");
return -UNW_EINVAL;
}
stack[tos++] = (x);
} while (0)
a value of "x" that makes use of "tos" (as instances of the
pick or pop macros do), the resulting expression will both
use and modify tos without an intervening sequence point,
which is undefined behavior according to the C standard.
And in fact with current GCC on PowerPC, this leads to a
miscompilation of the DW_OP_dup implementation.
This patch fixes the problem by assigning "x" to a
temporary variable before modifying tos.
Signed-off-by: Ulrich Weigand <uweigand@de.ibm.com>
liblzuma used in decoding MiniDebuginfo is not listed in
libunwind.pc.
Changes in version 2 of patch:
* Don't check HAVE_LZMA. It is redundant.
* Make liblzma as private libraries in use.
Both are suggested by Mike Frysinger <vapier@gentoo.org>.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
pkg-config metadata template files are missing Cflags keyword
which is required to properly compile against libunwind using
PKG_* autoconf macros
Acked-by: Mike Frysinger <vapier@gentoo.org>
The DWARF code allocates its unwind_info objects out of a
memory pool. The code which frees the object therefore calls
the mempool freeing code. However, there are cases where the
free code will be run with an unwind_info that was allocated
through a different mechanism (e.g. an ARM exidx table entry).
In these cases, the object should not be freed through the
mempool code.
To correct this, a check was added to ensure that the unwind_info
is of the appropriate type before passing the object along to the
mempool to be freed.
This change adds some special cases to allow libunwind to compile
for QNX.
* QNX's copy of <elf.h> and <link.h> reside in sys/ instead. To deal
with this, an AC_CHECK_HEADERS() was added to check for the files
in both locations.
* Similarly, QNX does not have <endian.h>. In cases where the file is
not found, logic was added to refer to QNX-specific macros to determine
endianness.
* The QCC compiler, which is a wrapper around GCC, cannot handle some
standard GCC options. Therefore, logic was added to check for QCC,
and when it is found, to suppress the use of -lgcc, and to express the
option -nostartfiles as -Wc,-nostartfiles instead, which is correctly
passed on to the underlying GCC.
* Finally, the support file os-qnx.c was added, patterned after the existing
os-*.c files. Only local image lookup is currently supported (see the
comments for more information), but this is sufficient for QNX, since
ptrace is not supported there anyway, and that is the only case where the
function is required to do remote image lookup.
Change-Id: Ie7934f94a7317bdde59335f2acd4c3a97c0384c1
During the install, symlinks are added from libunwind-<arch> to
libunwind-generic. However, on platforms that don't support
symlinking (such as Windows), the $(LN_S) macro is defined
as 'cp -p' instead. This works fine, except that since the
target of the symlink is a relative path, the copy will only
succeed if the current directory is the directory that contains
the file.
The solution to this problem suggested in the Autotools manual
(see http://www.gnu.org/software/automake/manual/automake.html#Extending)
is to simply cd into the correct directory first. This patch
makes that change for the symlinks that are being made during install.
[ edit: use relative path for the link name as well ]
Currently, libunwind-setjmp is built whenever local unwinding is
built. This patch adds an explicit flag to control it instead.
The default if not specified is to follow the old behavior.
This change adds a manual override to control building of the ptrace
library, similar to the existing --enable-coredump option. The
default is set based on the existence of sys/ptrace.h, allowing it
to be automatically disabled for platforms that do not have ptrace.
Make sure that we have included `config.h' before checking HAVE_LZMA.
This makes a difference at least on MIPS, where we include `elfxx.c'
directly. For other platforms this does not make much difference, as we
are already indirectly including `config.h' from other headers.
We do not modify `_UPT_reg_offset', so let's set it `const'. Given that
the array is exported, it's technically possible that some library user
is actually modifying the content, but does not seem really all that
likely.
Add support for the 32bit SuperH architecture running Linux.
Specifically, support is added for SH4, and support for earlier SH
versions and to the 64bit SH5 are left out. This was tested in qemu with
a little-endian SH4 debian image & GCC 4.7 cross compiler.
Add MIPS support to the coredump library. Explicit support for the MIPS
program counter register is added so that we can start backtracing from
the program counter value we read from a core dump. The PC register
support was not strictly required for local backtracing, and we will in
fact just plug the return address to the PC register in getcontext().
I have only tested the 32bit "OABI" paths.
In file included from src/ia64/Ginit_remote.c:26:0:
src/ia64/init.h: In function 'common_init':
src/ia64/init.h:32:12: warning: variable 'natp' set but not used [-Wunused-but-set-variable]
Instead of maintaining a pointer to the `sos_memory' array, maintain an
index that tells the next free position. When atomic operations are
available, the allocation boils down to a single fetch-and-add
operation.
To ensure that we return properly aligned pointers from sos_alloc(),
MAX_ALIGN must be a power-of-two. On i386 the power-of-two assumption
fails as sizeof(long double) = 12. Fix this by rounding up to 16.
Use the __BIGGEST_ALIGNMENT__ macro provided by GCC for sos_alloc()
allocation alignment. The macro gives ``the largest alignment ever used
for any data type on the target machine you are compiling for.''
__BIGGEST_ALIGNMENT__ also has some other nice properties, e.g. it is
power-of-two on all architectures (note that on i386, sizeof(long
double) = 12), and on some architectures (e.g. SuperH) the alignment
requirement can be lower than sizeof(long double).
tdep_get_func_addr in ppc64 passes NULL for the last argument of
as->access_mem. tdep_get_func_addr is called by elf_w(lookup_symbol),
which in turn is called by elf_w(get_proc_name_in_image).
elf_w(get_proc_name_in_image) is part of the API, and is only passed an
unw_addr_space_t, not a unw_cursor_t, meaning that we cannot recover the
UPT_info on the PPC64 platform.
This could be fixed by giving libunwind the knowledge to perform
relocations itself, thus not needing to look at the running image to
determine function addresses.
Disable the building of libunwind-coredump except on x86_64 and x86
(where implimentations exsist).
Allow overriding of this autodetection via --enable-coredump and
--disable-coredump.
Rename the `ALIGN' macro to `UNW_ALIGN', and move it from
`_UCD_internal.h' to `libunwind_i.h' so that we can share it with the
mempool code. `ALIGN' was clashing with system headers on FreeBSD:
In file included from src/coredump/_UCD_access_reg_freebsd.c:26:
src/coredump/_UCD_internal.h:102:1: warning: "ALIGN" redefined
In file included from /usr/include/sys/param.h:115,
from src/coredump/_UCD_lib.h:52,
from src/coredump/_UCD_access_reg_freebsd.c:24:
/usr/include/machine/param.h:79:1: warning: this is the location of the previous definition
Unwinding over ptrace and unwinding coredump fail to lookup the
.debug_frame dwarf data when the ELF file text segment virtual address
is non-zero. Looking at some binaries, the virtual address is non-zero
for non-pie binaries, and zero for PIC shared libraries and PIE
executables.
The core dump unwinder can be used for demonstrating the bug. Without
this patch, the unwinding fails badly (testing with a ARM qemu image):
$ UNW_ARM_UNWIND_METHOD=1 ./test-coredump-unwind core `cat backing_files`
test-coredump-unwind: unw_get_proc_info(ip=0x86d8) failed: ret=-10
After applying this patch, we can unwind all the way until running out
of dwarf data:
$ UNW_ARM_UNWIND_METHOD=1 ./test-coredump-unwind core `cat backing_files`
ip=0x000086d8 proc=000086d4-000086dc handler=0x00000000 lsda=0x00000000
test-coredump-unwind: step
test-coredump-unwind: step done:1
ip=0x000086ef proc=000086dc-000086f2 handler=0x00000000 lsda=0x00000000
test-coredump-unwind: step
test-coredump-unwind: step done:1
ip=0x000086e7 proc=000086dc-000086f2 handler=0x00000000 lsda=0x00000000
test-coredump-unwind: step
test-coredump-unwind: step done:1
ip=0x00008597 proc=00008584-0000859a handler=0x00000000 lsda=0x00000000
test-coredump-unwind: step
test-coredump-unwind: step done:1
ip=0x76eacc3b proc=76eacba0-76eaccec handler=0x00000000 lsda=0x00000000
test-coredump-unwind: step
test-coredump-unwind: step done:1
test-coredump-unwind: unw_get_proc_info(ip=0x85c3) failed: ret=-10
Note how the binary itself is mapped to address 0x8000, the virtual
address for the text segment is 0x8000, and the .debug_frame program
counter values are relative to 0:
$ tr ' ' '\n' < backing_files
0x8000:/home/user/tests/crasher
0x76e96000:/lib/arm-linux-gnueabi/libc-2.13.so
0x76f77000:/lib/arm-linux-gnueabi/libgcc_s.so.1
0x76f88000:/lib/arm-linux-gnueabi/ld-2.13.so
$ readelf -l crasher
Elf file type is EXEC (Executable file)
Entry point 0x859d
There are 9 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x0007b0 0x000087b0 0x000087b0 0x00030 0x00030 R 0x4
PHDR 0x000034 0x00008034 0x00008034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x00008154 0x00008154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.3]
LOAD 0x000000 0x00008000 0x00008000 0x007e4 0x007e4 R E 0x8000
LOAD 0x000efc 0x00010efc 0x00010efc 0x00148 0x00154 RW 0x8000
DYNAMIC 0x000f08 0x00010f08 0x00010f08 0x000f8 0x000f8 RW 0x4
NOTE 0x000168 0x00008168 0x00008168 0x00044 0x00044 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
GNU_RELRO 0x000efc 0x00010efc 0x00010efc 0x00104 0x00104 R 0x1
$ readelf --debug-dump=frames crasher | grep FDE
00000010 00000024 00000000 FDE cie=00000000 pc=00008614..000086d4
00000038 0000000c 00000000 FDE cie=00000000 pc=000086d4..000086dc
00000048 00000014 00000000 FDE cie=00000000 pc=000086dc..000086f2
00000060 00000014 00000000 FDE cie=00000000 pc=00008584..0000859a
After successfully stepping the cursor on ARM, the proc info is
invalidated only in dwarf_step(). Invalidate the proc info also when
stepping with the non-dwarf based methods. This fixes
unw_get_proc_info() returning stale data.
The core dump unwinder can be used for demonstrating the bug. When
unwinding based only on DWARF data, the proc info is correct:
$ UNW_ARM_UNWIND_METHOD=1 ./test-coredump-unwind core `cat backing_files` 2>/dev/null
ip=0x000086d8 proc=000086d4-000086dc handler=0x00000000 lsda=0x00000000
ip=0x000086ef proc=000086dc-000086f2 handler=0x00000000 lsda=0x00000000
ip=0x000086e7 proc=000086dc-000086f2 handler=0x00000000 lsda=0x00000000
ip=0x00008597 proc=00008584-0000859a handler=0x00000000 lsda=0x00000000
ip=0x76e3ac3b proc=76e3aba0-76e3acec handler=0x00000000 lsda=0x00000000
When unwinding based only on the exidx method, we see the proc info
lagging behind:
$ UNW_ARM_UNWIND_METHOD=4 ./test-coredump-unwind core `cat backing_files` 2>/dev/null
ip=0x000086d8 proc=000086d4-000086db handler=0x00000000 lsda=0x00000000
ip=0x000086ef proc=000086d4-000086db handler=0x00000000 lsda=0x00000000
ip=0x000086e7 proc=000086dc-000086f3 handler=0x00000000 lsda=0x00000000
ip=0x00008597 proc=000086dc-000086f3 handler=0x00000000 lsda=0x00000000
ip=0x76e3ac3b proc=00008584-0000859b handler=0x00000000 lsda=0x00000000
ip=0x000085c3 proc=76e3aba0-76e3ae4b handler=0x00000000 lsda=0x00000000
Finally, with this patch applied, we get the desired proc info also with
the exidx unwinder:
$ UNW_ARM_UNWIND_METHOD=4 ./test-coredump-unwind core `cat backing_files` 2>/dev/null
ip=0x000086d8 proc=000086d4-000086db handler=0x00000000 lsda=0x00000000
ip=0x000086ef proc=000086dc-000086f3 handler=0x00000000 lsda=0x00000000
ip=0x000086e7 proc=000086dc-000086f3 handler=0x00000000 lsda=0x00000000
ip=0x00008597 proc=00008584-0000859b handler=0x00000000 lsda=0x00000000
ip=0x76e3ac3b proc=76e3aba0-76e3ae4b handler=0x00000000 lsda=0x00000000
ip=0x000085c3 proc=0000859c-00008613 handler=0x00000000 lsda=0x00000000
Implement the Linux version of _UCD_access_reg() for ARM. We can
sidestep the register number remapping, as the libunwind register
numbers match one-to-one to the ELF core file register numbers.
Just pass potentially NULL pointers to free() in the error path in
load_debug_frame(). Saved 40 bytes of code in libunwind.so on ARM -O2
thumb build at the expense of slightly slower execution.
Stop pretending that unw_get_proc_info() works on PPC, and instead give
an error back to the caller. As far as I can tell, none of the libunwind
tests clear out the `unw_proc_info_t' before passing it to
unw_get_proc_info(), so they would end up working on garbage data.
ppc32/Gstep.c:116: warning: comparison between pointer and integer
ppc32/Gstep.c:116: warning: comparison with string literal results in unspecified behavior
ppc32/Gstep.c:116: warning: initialization makes integer from pointer without a cast
ppc32/Gstep.c:116: warning: passing argument 2 of 'fprintf' makes pointer from integer without a cast
/usr/powerpc-linux-gnu/include/stdio.h:333: note: expected 'const char *__restrict__' but argument is of type 'int'
Fix bitrot in HPPA common_init(). This has only been compile tested.
hppa/init.h: In function 'common_init':
hppa/init.h:33: error: 'struct cursor' has no member named 'ip_loc'
hppa/init.h:33: warning: implicit declaration of function 'HPPA_REG_LOC'
hppa/init.h:34: error: 'struct cursor' has no member named 'sp_loc'
hppa/init.h:36: warning: implicit declaration of function 'hppa_get'
hppa/init.h:36: error: 'struct cursor' has no member named 'ip_loc'
hppa/init.h:36: error: 'struct cursor' has no member named 'ip'
hppa/init.h:40: error: 'struct cursor' has no member named 'sp'
When cross-compiling libunwind with optimizations (-O1 or higher),
gcc-4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) optimizes away the memory
writes prior to the inline asm() statement in arm_local_resume() in the
non-signal-frame path, causing the `regs' array to be only allocated on
the stack, but not populated. This means that we are restoring garbage
to the registers.
As suggested in the GCC docs, add a fixed size input memory constraint
for the array content. This is enough to get the desired code to be
generated.
Adding __builtin_unreachable() to the point that we should never reach
was also in itself enough to inhibit the optimization. It also reduces
the function size by a few instructions.
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.
Properly export the symbol names also on MIPS. `make check' was
complaining:
src/.libs/libunwind.a(Linit.o): In function `mips_local_addr_space_init':
src/mips/Ginit.c:183: multiple definition of `mips_local_addr_space_init'
../src/.libs/libunwind-mips.a(Ginit.o):src/mips/Ginit.c:183: first defined here
src/.libs/libunwind.a(Lglobal.o): In function `_ULmips_init':
src/mips/Gglobal.c:42: multiple definition of `mips_lock'
../src/.libs/libunwind-mips.a(Gglobal.o):src/mips/Gglobal.c:42: first defined here
collect2: ld returned 1 exit status
After searching the normal symbol table, look if the binary contains
.gnu_debugdata section. If it does, run LZMA decompression on it, load
the resulting ELF image into memory and call lookup_symbol() on it
again.
lookup_symbol() is modified so that it takes min_dist as a parameter and
only returns a symbol when it finds one that is closer than indicated by
the parameter.
Signed-off-by: Martin Milata <mmilata@redhat.com>
The code for symbol lookup (elfxx.c:lookup_symbol) works by iterating
over symbol tables while maintaing the symbol closest to the supplied
instruction pointer. Whenever this search encountered symbol that was
longer than result buffer, the function returned -UNW_ENOMEM even though
the final symbol wasn't too long.
Signed-off-by: Martin Milata <mmilata@redhat.com>
dwarf/Gfind_unwind_table.c: In function '_Ux86_dwarf_find_unwind_table':
dwarf/Gfind_unwind_table.c:223:46: error: 'struct elf_dyn_info' has no member named 'edi'
Fixup commit d93d96ad83 ("Fix compilation
on IA64"), and replace the dwarf_find_unwind_table() call with
tdep_find_unwind_table().
Fixes linkage error on IA64:
../src/.libs/libunwind-coredump.so: undefined reference to `dwarf_find_unwind_table'
Change the way we generate the cursor header files, so that we do not
need to invoke IA64 binaries, which would fail when cross-compiling
libunwind.
Adopt the strategy used in the Linux kernel build system, and parse our
annotated offset information from the assembler file produced by the
compiler.
- Add tdep macro for {dwarf,ia64}_find_unwind_table so that ia64
doesn't try to use dwarf code.
- Fix extraneous #if.
- Fix mistyped filename in Makefile.am.
- Link ia64-specific tests with correct libraries.
Signed-off-by: Martin Milata <mmilata@redhat.com>
This reverts commit c9c5a40be1.
dwarf_get() returns 0 on success. We should continue unwinding
in that case.
TBD: investigate test-ptrace failure on some platforms.
If dwarf_get returns 0 (indicating the end of call chain), we should
not override the return value to 1. This may result in the caller
continuing to unwind and getting spurious errors.
In the commit d04dc94cc2, the check for
dwarf.ip == 0 was removed from non-dwarf walker in x86_64 version of
unw_step(). Apparently this broke the detection of the end of frame
chain when NULL %rbp is specified, because the case just marked
dwarf.ip as 0. Explicitly set ret to 0 to indicate the end of
iteration.
Older kernels interpret the pid argument of the process information
sysctls as pid only. If libunwind UPT consumer passed tid to _UPT_create,
tdep_get_elf_image() returns error due to sysctls failure. Provide a
slow workaround by searching for a process owning the supplied tid if
sysctl returned ESRCH.
Currently the expression evaluation always succeeds,
and possible error is not propagated to the caller.
The ',' operator makes the condition always return 0.
Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Tested-by: Paul Pluzhnikov <ppluzhnikov@google.com>
ALIGN lets you align pointers and STRUCT_MEMBER lets you get
structure members at a specific offset.
These are useful in general, and will be needed for the coredump notes
cleanup work.