1
0
Fork 0
mirror of https://github.com/tobast/libunwind-eh_elf.git synced 2024-12-22 19:43:42 +01:00
Commit graph

3178 commits

Author SHA1 Message Date
Milian Wolff
cd8c5d70d4 Optionally use a thread-local cache for valid memory
When libunwind is compiled with per-thread-caches, then also
make the cache of valid memory addresses thread-local.
2018-05-07 21:38:19 +02:00
Milian Wolff
3d473e183d Fix race conditions in validate_mem via atomics
When atomics are not available, the address cache is disabled.

Fixes data race found by TSAN:

WARNING: ThreadSanitizer: data race (pid=17824)
  Read of size 8 at 0x7f4dac484140 by thread T3:
    #0 validate_mem ../../src/x86_64/Ginit.c:201 (libunwind.so.
8+0x00000001f836)
    #1 access_mem ../../src/x86_64/Ginit.c:242 (libunwind.so.8+0x00000001fe06)
    #2 dwarf_get ../../include/tdep-x86_64/libunwind_i.h:168 (libunwind.so.
8+0x0000000221cf)
    #3 _ULx86_64_access_reg ../../src/x86_64/Gregs.c:130 (libunwind.so.
8+0x000000022e99)
    #4 _ULx86_64_get_reg ../../src/mi/Gget_reg.c:40 (libunwind.so.
8+0x00000001e5bc)
    #5 apply_reg_state ../../src/dwarf/Gparser.c:796 (libunwind.so.
8+0x000000038209)
    #6 _ULx86_64_dwarf_step ../../src/dwarf/Gparser.c:961 (libunwind.so.
8+0x000000039dbc)
    #7 _ULx86_64_step ../../src/x86_64/Gstep.c:71 (libunwind.so.
8+0x00000002481f)
    #8 trace_init_addr ../../src/x86_64/Gtrace.c:248 (libunwind.so.
8+0x000000026f0e)
    #9 trace_lookup ../../src/x86_64/Gtrace.c:330 (libunwind.so.
8+0x000000027429)
    #10 _ULx86_64_tdep_trace ../../src/x86_64/Gtrace.c:447 (libunwind.so.
8+0x00000002789a)
    #11 unw_backtrace ../../src/mi/backtrace.c:69 (libunwind.so.
8+0x00000001cb07)

  Previous write of size 8 at 0x7f4dac484140 by thread T2:
    #0 validate_mem ../../src/x86_64/Ginit.c:220 (libunwind.so.
8+0x00000001fc54)
    #1 access_mem ../../src/x86_64/Ginit.c:242 (libunwind.so.8+0x00000001fe06)
    #2 dwarf_get ../../include/tdep-x86_64/libunwind_i.h:168 (libunwind.so.
8+0x0000000221cf)
    #3 _ULx86_64_access_reg ../../src/x86_64/Gregs.c:130 (libunwind.so.
8+0x000000022e99)
    #4 _ULx86_64_get_reg ../../src/mi/Gget_reg.c:40 (libunwind.so.
8+0x00000001e5bc)
    #5 apply_reg_state ../../src/dwarf/Gparser.c:796 (libunwind.so.
8+0x000000038209)
    #6 _ULx86_64_dwarf_step ../../src/dwarf/Gparser.c:961 (libunwind.so.
8+0x000000039dbc)
    #7 _ULx86_64_step ../../src/x86_64/Gstep.c:71 (libunwind.so.
8+0x00000002481f)
    #8 trace_init_addr ../../src/x86_64/Gtrace.c:248 (libunwind.so.
8+0x000000026f0e)
    #9 trace_lookup ../../src/x86_64/Gtrace.c:330 (libunwind.so.
8+0x000000027429)
    #10 _ULx86_64_tdep_trace ../../src/x86_64/Gtrace.c:447 (libunwind.so.
8+0x00000002789a)
    #11 unw_backtrace ../../src/mi/backtrace.c:69 (libunwind.so.
8+0x00000001cb07)

  Location is global 'last_good_addr' of size 32 at 0x7f4dac484140
(libunwind.so.8+0x000000273140)
2018-05-07 21:38:19 +02:00
Milian Wolff
3f689c9ee1 Cleanup: remove unused variable 2018-05-04 23:13:26 +02:00
Milian Wolff
b256722d49 Do not try to close invalid fds
This was found by Valgrind:

==8330== Warning: invalid file descriptor -1 in syscall close()
==8330==    at 0x504B9F4: close (in /usr/lib/libpthread-2.26.so)
==8330==    by 0x40914DA: open_pipe (Ginit.c:82)
==8330==    by 0x40914DA: _ULx86_64_init_mem_validate (Ginit.c:154)
==8330==    by 0x4090CFE: _ULx86_64_init (Gglobal.c:93)
==8330==    by 0x4090A8C: _ULx86_64_set_caching_policy (Gset_caching_policy.c:32)
2018-05-04 23:13:26 +02:00
Milian Wolff
2bb51aa4fd Fix data race on cache hints in find_reg_state
This can be reproduced by using libunwind from multiple threads with
UNW_CACHE_GLOBAL cache policy, as e.g. happens by default or when
libunwind wasn't build with --enable-per-thread-cache.

The call to put_rs_cache unlocks the cache, but we used to access
data that needs to be guarded still. So move the call to put_rs_cache
down to protect the data properly. Fixes the following data race
reported by TSAN:

WARNING: ThreadSanitizer: data race (pid=16551)
  Read of size 2 at 0x7f7dda69ed7a by thread T2:
    #0 find_reg_state ../../src/dwarf/Gparser.c:939 (libunwind.so.
8+0x000000037254)
    #1 _ULx86_64_dwarf_step ../../src/dwarf/Gparser.c:958 (libunwind.so.
8+0x000000037543)
    #2 _ULx86_64_step ../../src/x86_64/Gstep.c:71 (libunwind.so.
8+0x000000021fdd)
    #3 trace_init_addr ../../src/x86_64/Gtrace.c:248 (libunwind.so.
8+0x0000000246cc)
    #4 trace_lookup ../../src/x86_64/Gtrace.c:330 (libunwind.so.
8+0x000000024be7)
    #5 _ULx86_64_tdep_trace ../../src/x86_64/Gtrace.c:447 (libunwind.so.
8+0x000000025058)
    #6 unw_backtrace ../../src/mi/backtrace.c:69 (libunwind.so.
8+0x00000001a6e7)

  Previous write of size 2 at 0x7f7dda69ed7a by thread T3:
    #0 find_reg_state ../../src/dwarf/Gparser.c:940 (libunwind.so.
8+0x000000037383)
    #1 _ULx86_64_dwarf_step ../../src/dwarf/Gparser.c:958 (libunwind.so.
8+0x000000037543)
    #2 _ULx86_64_step ../../src/x86_64/Gstep.c:71 (libunwind.so.
8+0x000000021fdd)
    #3 trace_init_addr ../../src/x86_64/Gtrace.c:248 (libunwind.so.
8+0x0000000246cc)
    #4 trace_lookup ../../src/x86_64/Gtrace.c:330 (libunwind.so.
8+0x000000024be7)
    #5 _ULx86_64_tdep_trace ../../src/x86_64/Gtrace.c:447 (libunwind.so.
8+0x000000025058)
    #6 unw_backtrace ../../src/mi/backtrace.c:69 (libunwind.so.
8+0x00000001a6e7)

  Location is global 'local_addr_space' of size 26296 at 0x7f7dda698c60
(libunwind.so.8+0x000000268d7a)
2018-05-04 23:13:26 +02:00
Deng, Yimin (NSB - CN/Shanghai)
fba2ae7b2c mipsN32: A modification suggestion to support mips N32 2018-04-24 10:34:47 -07:00
Alex Arslan
2be1c2754a tests: Include wait-related headers for Ltest-mem-validate (#74)
Without these, I was getting errors from this test set claiming that
wait, WIFCONTINUED, et al. were undefined on FreeBSD 11.1.
2018-04-12 09:46:15 -07:00
Dave Watson
729772149f
aarch64: tune down size of unw_context_t and unw_cursor_t (#71)
aarch64 defines a huge __reserved field in sigcontext.  Cut it down
to only the used FP fields.

unw_cursor_t can also be cut down a bit, while still maintaining some reserved space.
2018-04-10 10:55:45 -07:00
Dave Watson
b5cbcaee13
dwarf: do not allocate in load_debug_frame (#72)
load_debug_frame calls malloc() in a couple spots, use mmap via
GET_MEMORY instead.  These call paths are infrequent, and are never
freed.

Found by running tcmalloc unit tests on aarch64, when DEBUG_FRAME support is on.
2018-04-10 10:55:34 -07:00
Dave Watson
c91974f30f dwarf: make dwarf_find_debug_frame public
linux kernel's perf tool depends on this being public.

reported-by: Luke Diamand <luke@diamand.org>
blame: b56e4cb889 ("ALIAS dwarf symbols")
2018-04-03 11:14:08 -07:00
Bert Wesarg
bcd8c4a888 Remove unw_handle_signal_frame from header. (#70) 2018-04-02 15:37:31 -07:00
Romain Geissler @ Amadeus
54c1afdd51 Fix crasher test for gcc >= 8 when using -O2 or -O3. (#67) 2018-03-06 08:06:44 -08:00
laiwei-rice
7f04c2032f x86_64: support for RIP in unw_get_save_loc (#66)
Returns the location of RIP through unw_get_save_loc().
2018-03-06 08:04:45 -08:00
ShutterQuick
05d814b640 Don't check if the memory is in core (#64)
libunwind uses mincore() to validate that memory is mapped and available to the process.
For this purpose, checking the return value of mincore() is sufficient.
The result array tells us if the kernel has swapped out the page or not.
We don't care about this, and the check leads to failure in those
cases where the kernel has swapped out the page.
2018-02-09 07:41:54 -08:00
Dave Watson
7d6cc6696a Use syscall directly in write_validate to avoid ASAN errors
ASAN will complain about this write call with the following error:

ERROR: AddressSanitizer: stack-buffer-underflow on address
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext

This is similar to what google's abseil does to work around the issue.

Reported-by: qiwang@fb.com
2018-01-17 08:16:16 -08:00
Michael Munday
e1ca874882 s390x: remove unw_handle_signal_frame from public API. (#62)
Ports e287b69 to s390x and fixes the namespace check.
2018-01-11 10:53:09 -08:00
Dave Watson
647ca77f52 s390x: remove PROTECTED visibility 2018-01-09 07:41:19 -08:00
Michael Munday
441adc46ff Add port to Linux on IBM Z (s390x)
This adds a port to Linux on the IBM Z platform (a.k.a s390x). It only
supports the 64-bit ABI. Most functionality is working and all the tests
pass with the exception of the coredump tests*.

Unwinding is only supported if DWARF unwind information is present.
libunwind can't currently make use of the backchain (if present).

The getcontext/setcontext functions only preserve/restore a subset of
registers. Currently this only consists of callee-saved registers and
some parameter registers.

Vector registers and access registers are not saved (and aren't callee-
saved) by getcontext and cannot currently be modified. They will however
be restored unmodified after resuming a context from a signal handler.

There is no special libunwind support for setjmp, the functionality is
emulated using glibc (I think all the ports do this for modern Linux
kernels).

* Unwinding on s390x requires floating point register access which the
coredump library doesn't currently support.
2018-01-09 07:37:55 -08:00
Dave Watson
4c07b17037 ALIAS unwind_get_accessors 2017-12-28 09:42:16 -08:00
Dave Watson
b56e4cb889 ALIAS dwarf symbols 2017-12-28 09:31:11 -08:00
Dave Watson
e287b69068 Remove unw_handle_signal_frame from public API. 2017-12-28 09:07:08 -08:00
Dave Watson
a1437a3d27 Remove PROTECTED visibility
This only works on bfd ld, not lld or gold.
2017-12-28 08:26:42 -08:00
Michael Munday
29137c6fa9 dwarf: Fix size of state to avoid corrupting rs_stack
DW_CFA_remember_state used memcpy to overwrite state with the value
of rs_current. Unfortunately rs_current was slightly larger than state,
possibly resulting in rs_stack->next being overwritten.

Fix this by making the type of state match the type of rs_current and
using an assigment to perform the copy rather than memcpy. This should
ensure that the types match in future.
2017-11-28 07:55:25 -08:00
Dave Watson
02a3cc2cf3 Bump version to 1.3-rc1 2017-11-22 16:24:02 -08:00
Adrian Bunk
c1a65821a2 Default to --enable-debug-frame also on aarch64
This is required for perf to show call graphs.
2017-11-21 14:21:12 -08:00
Hans-Christian Noren Egtvedt
46c336d18f elfxx: store elf image pointer and size after mapping image
If loading debug link is not successful, the initial NULL pointer for
ei->image will eventually be restored, causing segfault during a later
call to valid_object.

Move populating the prev_image and prev_size to after elf_map_image() to
fix this.

Signed-off-by: Hans-Christian Noren Egtvedt <hegtvedt@cisco.com>
2017-11-09 10:23:18 -08:00
Yichao Yu
f248ac0c6e dwarf: Fix incorrect cfi execution (#54)
During unwinding/resuming execution of a normal call frame,
it is not only necessary to use the previous instruction to lookup the unwind info
but also when executing the cfi program. Although the call usually don't modify
any unwinding state, it can happen for noreturn call or when the callee cleanup the stack.
In these cases, the next instruction after the call may have a cfi adjusting the state
(e.g. stack pointer) and such instruction should be executed.

3d9a694de8 worked around this issue by treating `cfi_restore_state`
specially. It works when the compiler use that instruction to restore the state, i.e.

```
    .cfi_remember_state
    je .L0
    push ...
    .cfi_def_cfi_offset <new_value>
    call noreturn
.L0
    .cfi_restore_state
```

which is what GCC ususally does. However, it is not necessarily the case and clang/LLVM doesn't
do that. Instead LLVM emits the following unwind info which is also perfectly valid but is not
handled by the special case.

```
    je .L0
    push ...
    .cfi_def_cfi_offset <new_value>
    call noreturn
.L0
    .cfi_def_cfi_offset <old_value>
```

e9e8ed73e3 also worked around this issue for another special case.

This patch fix this issue for all cfi types by adjusting the `end_ip` based on the type of the
current frame instead, similar to what's done in `fetch_proc_info`.
Since this requires using the same `use_prev_instr` value after `fetch_proc_info` returns,
the patch also remove the `need_unwind_info` parameter to the function and move the code updating
`use_prev_instr` after all use of the old value are done.
2017-11-01 09:14:37 -07:00
Yichao Yu
1870b26a00 dwarf: Allow DWARF version both 3 and 4 (#56) 2017-10-31 08:55:07 -07:00
Yichao Yu
9e81e9efee arm: Handle non-signal frame unwind info lookup in ARM exidx unwinder (#55) 2017-10-31 08:52:22 -07:00
Yichao Yu
4238fa55c8 Fix intermittent test failure in test-resume-sig (#51)
(At least on x86(_32),) `unw_resume` will call `setcontext` which will modify the signal masks
based on the value in the context. Since the signal mask is not being initialized by
`unw_getcontext`, this cause the signal mask to be set to a random (uninitialized) value after
`unw_resume` which cause the test to fail since it relies on the signal mask for SIGUSR2 being
cleared.

The proper fix is likely to either make `unw_resume` not touch the signal mask if the context
wasn't initialized with a signal ucontext, or to make `unw_getcontext` record the signal mask too.
It's unclear to me which approach should be taken...

In the mean time, the intermittent failure can be fixed simply by zero initialing the context first
which would clear all the signal masks.
When siginfo is available, a more reliable way is to use the `ucontext` passed in
to the signal handler directly and rely on `sigreturn` to reset it.
Unfortunately, this is currently not implemented on all archs either.
2017-10-31 08:47:34 -07:00
Yichao Yu
3f9a629394 Ignore tests/Ltest-mem-validate (#52) 2017-10-31 08:42:15 -07:00
Yichao Yu
26c99a3a3e Fix init-local-signal test (#50)
* Add `SA_SIGINFO` flag

  This is needed to guarantee the availability of the `ucontext` argument

* Mark the `NULL` pointer load as `volatile`

  Further prevent any compiler optimization on the load.
2017-10-31 08:41:51 -07:00
Yichao Yu
b9fe811de9 Use ucontext_t instead of struct ucontext (#49)
Ref https://github.com/libunwind/libunwind/pull/40.
I didn't caught it last time since I don't have a 32bits buildbot.
2017-10-31 08:41:31 -07:00
Yichao Yu
ab39ae9e16 Fix local unwind compilation on ARM (#48)
This was broken by fd02fd59e7.
2017-10-23 08:37:59 -07:00
Konstantin Baladurin
36b46f1921 dwarf/Gparser: fix crash during unwinding (#46)
We should update locations of the registers after all of them will
be restored. Otherwise some locations will be incorrect.

For example if function stores ebp, edi, esi and ebx registers on
stack in its prologue, compiler can generate following unwind info:
DW_CFA_expression: r5 (ebp) (DW_OP_breg5 (ebp): 0)
DW_CFA_expression: r7 (edi) (DW_OP_breg5 (ebp): -4)
DW_CFA_expression: r6 (esi) (DW_OP_breg5 (ebp): -8)
DW_CFA_expression: r3 (ebx) (DW_OP_breg5 (ebp): -12)

In this case locations of the ebx and ebp will be calculated using
current ebp but locations of the esi and edi will be calculated using
previous (restored) one. Due to it their locations will be incorrect
and it could lead to crash if we will try to get esi or edi value.

This patch fixes this problem.
2017-10-17 11:27:43 -07:00
Konstantin Baladurin
38fe3bbb97 x86: Fix build (#45)
We should include <sys/syscall.h> for SYS_rt_sigreturn in x86/Gos-linux.c
2017-10-17 11:27:14 -07:00
Bert Wesarg
60ddc67196 check: Fix run-coredump-unwind-mdi when in a out-of-tree build. 2017-09-21 08:37:08 -07:00
Konstantin Belousov
fd02fd59e7 arm: FreeBSD/ARMv6 port
Sponsored by:	The FreeBSD Foundation
2017-08-24 09:08:58 -07:00
Dave Watson
60663c8f69 multilib: XFAIL some tests
Ptrace interface doesn't understand multilib registers, so tests all fail.
2017-08-24 08:51:39 -07:00
Dave Watson
7f1aebadbf x86: Add sigreturn asm stub
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
2017-08-24 08:51:27 -07:00
Dave Watson
3d9a694de8 dwarf: Fix incorrect application of restore_state
Repro for a multilib binary on host x86_64:

CFLAGS="-m32" LDFLAGS="-m32" ./configure --enable-debug -- host=i686-pc-linux-gnu --target=i686-pc-linux-gnu --libdur=/usr/lib32 --prefix=/usr --disable-documentation

make check

Gtest-init function fails trying to step through libc_start_main.  The CFA function is:

DW_CFA_def_cfa_offset: 112
DW_CFA_advance_loc: 5 to ...643
DW_CFA_restore state

Where the return address is 643.

Generally, it appears we apply all ip <= end_ip, which is incorrect in some circumstances.

libgcc only applies ip < end_ip + is_signal_frame, but that seems to break async signal handling
tests in libunwind for unknown reasons.

This is somewhat simlar to the fix in e9e8ed73e for GNU_args_size,
where the same ip check was added.
2017-08-24 08:51:18 -07:00
Johannes Ziegenbalg
836c91c43d x86_64: fix mincore_validate and msync_validate
The calls to mincore() or msync() are not checking for actual accessibility
this could lead to SIGSEGV if the address from a mapped page with the
PROT_NONE property occurs on the stack.
Hence an attempt to write one byte from the checked address to a pipe will
fail if the address is not readable.
2017-08-24 08:50:07 -07:00
Yichao Yu
e9e50d07b0 x86_64: Use ucontext_t instead of struct ucontext
Ref https://sourceware.org/git/?p=glibc.git;a=commit;h=251287734e89a52da3db682a8241eb6bccc050c9
And this is what other part of the code uses.
2017-08-22 11:51:20 -07:00
Guillaume Blanc
c26b603cd0 arm: argument type for unw_init_local2
I tried to build libunwind for arm target and got a build error. Type
for "uc" argument is inconsistent between unw_init_local2 and
unw_init_local_common.

From 54fb6483e47916836c314a38715e8e0ce8c3da44 Mon Sep 17 00:00:00 2001
From: Guillaume Blanc <guillaume.blanc@parrot.com>
Date: Tue, 22 Aug 2017 16:46:20 +0200
Subject: [PATCH] arm: Fix unw_init_local2 argument type
2017-08-22 11:50:02 -07:00
Leonid Chistov
5a491cb2d8 arm64: Support for restore of ARM64 Neon callee-saved registers during unwind 2017-08-18 09:56:06 -07:00
Jonathan Byrd
1c190a8f9e aarch64: PLT entry recognition & fixes
Attached is a corrected version of my previous patch for aarch64 PLT
entry recognition. The comparison in the is_plt_entry function should
have been:

     ret = (((w0 & 0xff0000009f000000) == 0xf900000090000000)
            && ((w1 & 0xffffffffff000000) == 0xd61f022091000000));
2017-08-18 09:55:49 -07:00
Felipe Cerqueira
819bf51bbd dwarf: Fix uninitialized variable c->dwarf.eh_valid_mask.
We were testing libunwind-coredump and got some warnings about
uninitialized eh_valid_mask.
The code was working fine because the default value of the mask was 0, but
it could potentially take a wrong branch if there's garbage in memory.
2017-08-17 14:18:07 -07:00
Dave Watson
971985133b doc: Add generated doc files apply_reg_state and reg_states_iterate 2017-08-16 13:11:27 -07:00
Dave Watson
bd3fb89e11 Change unw_init_local_signal to unw_init_local2(..., UNW_INIT_SIGNAL_FRAME)
Add unw_init_local2 with a flag for better extensibility in the future
2017-08-16 13:11:24 -07:00
Dave Watson
644cce3d72 half finished unw_local_init2 2017-08-16 11:27:43 -07:00