| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
| |
1. hidden _step_n64 to avoid a strange bug which
will reproduce under `perf report`.
The value `tdep_init_done` of suddenly be changed to zero
when entering `_step_n64` from `unw_step`.
2. refactor code to improve the readability.
use `FP_REG`, `SP_REG` and `RA_REG` to abstract the guessing
logical.
|
|
|
|
| |
Use correct size variable.
|
|
|
| |
x86_64: tsan clean
|
|
|
|
|
| |
Clang doesn't respect the static alias, resulting in global instead
of local symbols, and name collisions. Work around for clang by always
going through the PLT (at a small perf hit)
|
| |
|
|
|
|
|
| |
- gp at 8(sp)
- fp at 16(sp)
- ra at 24(sp)
|
|
|
|
|
|
|
|
|
|
|
|
| |
Currently the README's formatting shows up rather poorly on GitHub, as
the file isn't written as a Markdown document but GitHub tries to render
it as one due to the symlink from README.md to README. This commit
reformats the file as a Markdown document, preserving the original
content with two exceptions:
1. The platform support list has been converted to a Markdown table.
2. The severely outdated information regarding libexecinfo on FreeBSD
has been amended and the note about FreeBSD 8.0 removed.
|
|
|
|
|
|
|
|
| |
dwarf: Push correct CFA onto stack for dwarf expression evaluation.
This change fixes a bug where stale CFAs were pushed onto the dwarf
expression stack before expression evaluation. Some optimising compilers
emit CFI which relies on this being correct.
|
|
|
| |
This patch adds two opcodes to the operands table in Gexpr.c, which is a mapping between opcodes and the number and types of the operands for those opcodes. Two opcodes, DW_OP_constu and DW_OP_consts are missing from this table, which caused failures later in the CFI expression parsing logic. This patch adds the missing information into the table, and thus allows correct parsing of CFA_def_cfa_expression, CFA_expression and CFA_val_expression expressions which contain the offending opcodes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Otherwise this fails to compile with -stc=c99 like:
$ cat <<EOF > bla.c
#include <libunwind.h>
int main()
{
unw_tdep_context_t *uc = NULL;
unw_tdep_getcontext(uc);
}
EOF
# This works
$ gcc bla.c
# This does not
$ gcc -std=c99 bla.c
In file included from /usr/include/aarch64-linux-gnu/libunwind.h:7,
from bla.c:1:
bla.c: In function ‘main’:
bla.c:6:5: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘asm’
unw_tdep_getcontext(uc);
^~~~~~~~~~~~~~~~~~~
bla.c:6:5: error: ‘mcontext_t’ {aka ‘struct <anonymous>’} has no member named ‘regs’; did you mean ‘__regs’?
unw_tdep_getcontext(uc);
^~~~~~~~~~~~~~~~~~~
bla.c:6:5: error: ‘unw_base’ undeclared (first use in this function); did you mean ‘unw_ctx’?
unw_tdep_getcontext(uc);
^~~~~~~~~~~~~~~~~~~
bla.c:6:5: note: each undeclared identifier is reported only once for each function it appears in
bla.c:6:5: error: invalid lvalue in asm output 0
unw_tdep_getcontext(uc);
^~~~~~~~~~~~~~~~~~~
See https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html:
The asm keyword is a GNU extension. When writing code that can be
compiled with -ansi and the various -std options, use __asm__ instead of
asm (see Alternate Keywords).
|
|
|
|
|
| |
than malloc and qsort, to process debug frames and reduce problems with
non signal-safe functions in supposedly signal-safe libunwind procedures.
|
|
|
|
|
| |
Fix missing Gparser.c changes from patchset
'aarch64 PLT entry recognition & fixes'
|
|
|
| |
implement _UPT_access_fpreg, _UCD_access_reg_freebsd for aarch64, and add a unw_fpsimd_context_t instead of using the one from the linux headers.
|
|
|
|
|
| |
Compose debug messages depending on selected unwind methods.
Fix indentation.
|
|
|
| |
readme: fix typo
|
|
|
|
| |
This patch also adds munmap() for unw_debug_frame_list elements.
|
|
|
|
|
|
|
|
| |
The floating point registers on s390x are 64-bits wide so type
them as double precision rather than long double.
Also, GCC on Ubuntu 18.04 complains about the sizeof calls so fix
those too.
|
|
|
|
|
|
|
|
|
| |
This uncovered the use of NLGA to guard the initializaition
of the valid mem cache. This code is removed, as it isn't
working properly for a per-thread cache anyways. What's more,
it shouldn't be required anyways since static data is guaranteed
to be initialized to zero anyways.
Fixes https://github.com/libunwind/libunwind/issues/79
|
|
|
|
|
| |
When libunwind is compiled with per-thread-caches, then also
make the cache of valid memory addresses thread-local.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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)
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
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)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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)
|
| |
|
|
|
|
| |
Without these, I was getting errors from this test set claiming that
wait, WIFCONTINUED, et al. were undefined on FreeBSD 11.1.
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
linux kernel's perf tool depends on this being public.
reported-by: Luke Diamand <luke@diamand.org>
blame: b56e4cb88989f82988a6a70acb32e187e88b5cac ("ALIAS dwarf symbols")
|
| |
|
| |
|
|
|
| |
Returns the location of RIP through unw_get_save_loc().
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
| |
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
|
|
|
| |
Ports e287b69 to s390x and fixes the namespace check.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
| |
|
| |
|
|
|
|
| |
This only works on bfd ld, not lld or gold.
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
This is required for perf to show call graphs.
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
3d9a694de85f2ba10368b4fbc2aff1c6b8b76f58 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>
```
e9e8ed73e34a2d65c7ec71c296156637763ffd5c 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.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
(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.
|
| |
|
|
|
|
|
|
|
|
|
| |
* 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.
|