IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an
email to Administrator. User accounts are meant only to access repo
and report issues and/or generate pull requests.
This is a purpose-specific Git hosting for
BaseALT
projects. Thank you for your understanding!
Только зарегистрированные пользователи имеют доступ к сервису!
Для получения аккаунта, обратитесь к администратору.
The unwind subsystem uses the mmap_cache subsystem even it uses
unwind-libdw as backend. unwind-libdw doesn't need the full set of the
mmap_cache subsystem; libdw has a feature for caching a memory
mapping.
This commit does three things.
(1) Make the unwind subsystem not use the mmap_cache subsystem.
The unwind subsystem never concern the memory mapping of the target.
It becomes a thin layer.
(2) Make unwind-libunwind use the mmap_cache subsystem directly.
(3) Make unwind-libdw use the mmap_notify subsystem to know when it
should call dwfl_linux_proc_report/dwfl_report_end for updating the
cache.
Here is a subsystem structure that this patch
introduces:
+-------------------------------------+
| unwind subsys |
+------------------+------------------+
| unwind-libunwind | unwind-libdw |
+------------------+------------------+
| mmap_cache | |
+------------------+ |
| mmap_notify |
+-------------------------------------+
| syscall |
+-------------------------------------+
mmap/munmap/mprotect/brk...
* unwind.c: Don't include "mmap_cache.h".
(unwind_init): Don't call mmap_cache_enable.
(unwind_tcb_print, unwind_tcb_capture): Don't call mmap_cache related
functions, just invoke unwinder.tcb_walk.
* unwind.h (struct unwind_unwinder_t): Remove tcb_flush_cache field.
* unwind-libdw.c: Include "mmap_notify.h" instead of "mmap_cache.h".
(struct ctx): Add last_proc_updating field to record the generation
of memory mapping that is cached by dwfl_linux_proc_report
and dwfl_report_end.
(mapping_generation): A variable counting how many times the memory
mapping of targets has been changed.
(updating_mapping_generation): New utility function for updating
mapping_generation.
(init): New function for registering updating_mapping_generation
in the mmap_notify subsystem as a callback function.
(tcb_init): Initialize ctx::last_proc_updating.
(tcb_flush_cache): Rename to flush_cache_maybe. Rebuild the cache data
only if the data is stale.
(tcb_walk): Call flush_cache_maybe for avoiding referring staled cache data.
(unwinder): Set init function, remove tcb_flush_cache field.
* unwind-libunwind.c (init): Enable the mmap_cache subsystem.
(tcb_walk): Call mmap_cache_rebuild_if_invalid and unw_flush_cache for
updating the cache of the memory mapping before walking the stack.
(tcb_walk): Rename to walk.
(unwinder): Remove tcb_flush_cache field.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
There is no need to call unwind_tcb_init before the tracee is attached.
* strace.c (alloctcb) [ENABLE_STACKTRACE]: Move unwind_tcb_init
invocation ...
(after_successful_attach) [ENABLE_STACKTRACE]: ... here.
(init) [ENABLE_STACKTRACE]: Remove unwind_tcb_init invocation loop.
* unwind.c (unwind_tcb_fin): Skip if tcp->unwind_queue is NULL.
This opens the way for alternative unwinder back-ends.
* unwind.h: New file, defines the unwinder back-end interface.
* unwind.c: Move all libunwind related code ...
* unwind-libunwind.c: ... here.
* Makefile.am [USE_LIBUNWIND] (strace_SOURCES): Add unwind.h
and unwind-libunwind.c.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
This change renames functions exported to strace core part from unwind
subsystem.
The new names imply that unwind subsystem exports two types of
functions. One is for manipulating back-end itself, "unwind_" prefix
is used for this type. Another is for manipulating back-end private data
structure (unwind_ctx) attached to tcb, "unwind_tcb_" is used for this
type.
This naming should help people to understand unwind subsystem
and the relation between unwind subsystem and back-ends.
* defs.h (unwind_print_stacktrace): Rename to unwind_tcb_print.
(unwind_capture_stacktrace): Rename to unwind_tcb_capture.
* unwind.c: Ditto.
* syscall.c (syscall_entering_trace, syscall_exiting_trace): Use
new names.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
The names given to struct tcb.queue field and its type are too common,
this may cause conflicts in the future if new fields are added
to struct tcb.
* defs.h (struct tcb): Rename queue field to unwind_queue,
rename its type queue_t to unwind_queue_t.
* unwind.c (struct unwind_queue_t): Rename to unwind_queue_t.
All users updated.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
Narrowing the area where the code refers to names associated with
libunwind is needed to utilize libdw of elfutils as an alternative
unwinder.
* defs.h (struct tcb): Rename libunwind_ui field to unwind_ctx, change
its type to "void *".
* unwind.c (unwind_tcb_init, unwind_tcb_fin, stracetrace_walk): Reflect
* the above field renaming.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
mmap_cache was enabled indirectly via unwind feature. As now mmap_cache
can be used by other part of strace, a way to enable mmap_cache directly
is needed.
* defs.h (mmap_cache_enable, mmap_cache_is_enabled): New function
prototypes.
* mmap_cache.c (use_mmap_cache): New file local variable.
(mmap_cache_enable, mmap_cache_is_enabled): New functions.
* syscall.c (syscall_exiting_decode): Use mmap_cache_is_enabled()
instead of stack_trace_enabled.
* unwind.c (unwind_init): Invoke mmap_cache_enable.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
mmap_cache_delete function used to be called by destructor of unwind
related code. Now that other parts can use mmap cache,
mmap_cache_delete is called separately from unwind_tcb_fin.
* unwind.c (unwind_tcb_fin): Move mmap_cache_delete invocation ...
* strace.c (droptcb): ... here.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
To make mmap_cache reusable, records protection bits of mmap entries.
* defs.h (mmap_cache_protection): New enum.
* mmap_cache.c (build_mmpa_cache): Don't ignore entries that are not
executable, just record the protection bits here.
* unwind.c (print_stack_frame): Ignore entries that are not executable.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
print_stack_frame function in unwind.c searches a mmap entry in mmap
cache. The found entry is then used for unwinding. However, a function
searching for a mmap entry may be useful for other purposes than
unwinding.
This change re-factors the function; code for searching an entry is
now defined as a stand-alone function named mmap_cache_search.
* defs.h (mmap_cache_search): New function prototype.
print_stack_frame.
* mmap_cached.c (mmap_cache_search): New function derived from
print_stack_frame.
* unwind.c (print_stack_frame): Use it.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
For making mmap cache code reusable from other areas in strace than
unwind, mmap cache related code and unwind related code should be
separated.
This change moves the most of mmap cache code from unwind.c
to mmap_cache.c, a new file.
* unwind.c: Move mmap_cache implementation ...
* mmap_cache.c: ... to this new file.
* Makefile.am (strace_SOURCES): add mmap_cache.c.
* defs.h (struct tcb): Move mmap_cache, mmap_cache_size, and
mmap_cache_generation fields out of [USE_LIBUNWIND] condition.
(mmap_cache_invalidate, mmap_cache_delete,
mmap_cache_rebuild_if_invalid): New function prototypes.
(struct mmap_cache_t, enum mmap_cache_rebuild_result): Move from
unwind.c.
* syscall.c (syscall_exiting_decode): Replace unwind_cache_invalidate
with mmap_cache_invalidate.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
For making mmap cache code reusable from other areas in strace
than unwind, mmap cache related code and unwind related code
should be separated.
This change is one of the steps for the separation. It moves
unw_flush_cache function call from the core of mmap cache code
to upper level code.
* unwind.c (mmap_cache_rebuild_result): New enum.
(rebuild_cache_if_invalid): Return MMAP_CACHE_REBUILD_* instead of
a bool value.
(build_mmap_cache): Don't call unw_flush_cache here.
(unwind_print_stacktrace, unwind_capture_stacktrace): Call
unw_flush_cache here instead.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
This is the location where this header is installed on Debian-based
systems.
* configure.ac: Check for libiberty/demangle.h in addition to
demangle.h.
* unwind.c [USE_DEMANGLE]: Include either <demangle.h> or
<libiberty_demangle.h> based on the presence of HAVE_DEMANGLE_H and
HAVE_LIBIBERTY_DEMANGLE_H macros.
An error returned by asprintf is a poor excuse for dying.
* unwind.c (asprintf_error_str): New string constant.
(sprint_call_or_error): Replace error_msg_and_die() with
perror_func_msg() and usage of asprintf_error_str for a return value.
(queue_print): Free tmp->output line only if it is not
asprintf_error_str.
Since DPRINTF is simply a macro that provides debugging information
along with some information about printing routine call site, now standard
debug_func_* macros are deemed to be a suitable replacement.
* unwind.c (DPRINTF): Remove.
(build_mmap_cache, delete_mmap_cache, unwind_cache_invalidate,
unwind_print_stacktrace, unwind_captiure_stacktrace): Replace
DPRINTF(fmt, str, ...) with debug_func_msg(fmt, ...)/
Enclose macros with multiple statements and macros starting
with "if" statement in a do/while loop.
Do not enclose single statement macros in a do/while loop.
Reported by kernel's checkpatch.pl script.
Linux does not prevent a user from creating a lot of nested directories
with length of the absolute path of the deepest one exceeding PATH_MAX,
then chdir'ing into it, creating a file there and mmap'ing it. Since the
length of the prefix preceding the pathname in /proc/[pid]/maps is not
necessary 80 (it's 73 on my machine), an overflow is possible.
* unwind.c (build_mmap_cache): Fix a possible buffer overflow.
* strace.c (init) [USE_LIBUNWIND]: Call unwind_tcb_init after
unwind_init for all allocated tcb structures if stack trace is enabled.
* unwind.c (unwind_tcb_init): Skip if tcb is already initialized.
Co-authored-by: Dmitry V. Levin <ldv@altlinux.org>
Introduce wrappers to the following functions that do memory allocation:
malloc, calloc, realloc, strdup.
This commit is a follow-up to the related discussions in strace-devel ML:
http://sourceforge.net/p/strace/mailman/message/33618180/http://sourceforge.net/p/strace/mailman/message/33733470/
* defs.h (xmalloc, xcalloc, xreallocarray, xstrdup): New prototypes.
* xmalloc.c: New file.
* Makefile.am (strace_SOURCES): Add it.
* count.c (count_syscall, call_summary_pers): Use xcalloc.
* desc.c (decode_select): Use xmalloc.
* dirent.c (sys_getdents, sys_getdents64): Likewise.
* net.c (sys_recvmmsg): Use xstrdup.
* pathtrace.c (storepath): Use xreallocarray.
(pathtrace_match): Use xmalloc.
* strace.c (die_out_of_memory): Move to xmalloc.c.
(expand_tcbtab): Use xcalloc and xreallocarray.
(startup_child): Use xstrdup.
(init): Use xmalloc, xcalloc, and xstrdup.
* syscall.c (reallocate_qual): Use xreallocarray.
(qualify): Use xstrdup.
* unwind.c (unwind_tcb_init): Use xmalloc.
(build_mmap_cache): Use xcalloc, xreallocarray, and xstrdup.
(get_symbol_name): Use xreallocarray.
(stacktrace_walk, queue_put): Use xmalloc.
* util.c (printstr): Use xmalloc.
* vsprintf.c (strace_vfprintf): Likewise.
The output format of the stack trace is supposed to be different
depending on whether symbol names are available in the build.
However, the check only verified the validity of the pointer, not of the
string pointed to (which could be empty).
This commit fixes the check so that the original output:
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x5e000
> /lib/libc-2.10.1.so(_IO_file_doallocate+0x8c) [0x68a38]
> /lib/libc-2.10.1.so(_IO_doallocbuf+0x6c) [0x78574]
> /lib/libc-2.10.1.so(_IO_file_overflow+0x184) [0x7763c]
> /lib/libc-2.10.1.so(_IO_file_xsputn+0x88) [0x76aac]
> /lib/libc-2.10.1.so(_IO_puts+0xc8) [0x6b64c]
> /bin/busybox(+0x0) [0x62c60]
> /bin/busybox(+0x0) [0x4940]
> /bin/busybox(+0x0) [0x499c]
> /bin/busybox(+0x0) [0x4e08]
> /lib/libc-2.10.1.so(__libc_init_first+0x30c) [0x1f84c]
> /lib/libc-2.10.1.so(__libc_start_main+0xd8) [0x1f9f8]
becomes:
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x5e000
> /lib/libc-2.10.1.so(_IO_file_doallocate+0x8c) [0x68a38]
> /lib/libc-2.10.1.so(_IO_doallocbuf+0x6c) [0x78574]
> /lib/libc-2.10.1.so(_IO_file_overflow+0x184) [0x7763c]
> /lib/libc-2.10.1.so(_IO_file_xsputn+0x88) [0x76aac]
> /lib/libc-2.10.1.so(_IO_puts+0xc8) [0x6b64c]
> /bin/busybox() [0x62c60]
> /bin/busybox() [0x4940]
> /bin/busybox() [0x499c]
> /bin/busybox() [0x4e08]
> /lib/libc-2.10.1.so(__libc_init_first+0x30c) [0x1f84c]
> /lib/libc-2.10.1.so(__libc_start_main+0xd8) [0x1f9f8]
Signed-off-by: Thomas De Schampheleire <thomas.de.schampheleire@gmail.com>
Acked-by: Masatake YAMATO <yamato@redhat.com>
* unwind.c (build_mmap_cache): Move local variables to the code branch
where they are used. Check return code of sscanf and strdup. Do not
treat unusual memory mappings as fatal errors. Do not skip memory
mappings with path names starting with "[".
* unwind.c (fopen_for_input): Define to fopen64 iff
[_LARGEFILE64_SOURCE && HAVE_FOPEN64], otherwise define it to fopen.
(build_mmap_cache): Use fopen_for_input instead of fopen.
Fix compilation warnings in unwind.c on 32-bit architectures.
On some architectures getuid is actually getuid32, so change the test
to use getpid instead of getuid.
* unwind.c (STACK_ENTRY_SYMBOL_FMT): Explicitly cast function_off_set
to unsigned long.
(queue_put_error): Change the 3rd argument's type to unsigned long.
* tests/stack-fcall.c (f1): Use getpid instead of getuid.
* tests/strace-k.test: Likewise.
Here is the benchmark of the dwarf cache.
Target program:
#include <sched.h>
int main(void)
{
unsigned int max = 0x6fff, i;
for (i = 0; i < max; i++)
sched_yield();
return 0;
}
Command line:
./strace -o /dev/null -k a.out
With the dwarf cache:
real 0m12.081s
user 0m3.858s
sys 0m8.194s
Without the dwarf cache:
real 0m22.326s
user 0m5.218s
sys 0m16.952s
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
When a file mmap'ed to the target process is unlink'ed, backtracing the
stack would fail. Current implementation reports it as
"backtracing_error". To avoid confusion, the message is changed to
"expected_backtracing_error".
Here is the reproducer:
$ cat ./p-deleted.c
#include <unistd.h>
int main(int argc, char **argv) {
return unlink(argv[0]) < 0;
}
$ strace -e unlink -k ./p-deleted
unlink("./p-deleted") = 0
> /usr/lib64/libc-2.18.so(unlink+0x7) [0xe7f17]
> /home/yamato/var/strace/t_unwind/p-deleted (deleted)(+0x0) [0x575]
> /usr/lib64/libc-2.18.so(__libc_start_main+0xf5) [0x21d65]
> backtracing_error [0x7ffff1365590]
+++ exited with 0 +++
p-deleted is deleted therefore backtracing_error is reported. This
patch records the deleted marker when making mmap cache and refers the
recorded information in the case "backtracing_error" to switch the
message.
Here is the output of this patch:
$ strace -e unlink -k ./p-deleted
unlink("./p-deleted") = 0
> /usr/lib64/libc-2.18.so(unlink+0x7) [0xe7f17]
> /home/yamato/var/strace/t_unwind/p-deleted (deleted)(+0x0) [0x575]
> /usr/lib64/libc-2.18.so(__libc_start_main+0xf5) [0x21d65]
> expected_backtracing_error [0x7ffff1365590]
+++ exited with 0 +++
This solution is not perfect: if a file is unlink'ed after making the
mmap cache and before unwinding, strace cannot have a chance to record
the deleted marker.
In this version of patch, hardcoded magic number used in comparing "(delete)"
string is replaced with strlen as suggested by Dmitry Levin.
In old version of patch, the deleted entry was thrown away from mmap
cache to avoid to report "backtracing_error". In this patch I keep it,
and just switch the error message.
Inspired by the review comment from Dmitry Levin.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
A mmap cache belonging to a tcb was updated when a system call which
changed the memory mapping was called. This implementation was assumed
the mapping was changed only by the tcb. However, this assumption is
incorrect if the target application is multi-threaded; more than two
tcbs can shared the same memory mapping and a tcb can modify it without
being noticed by the others.
This change introduces a global integer variable mmap_cache_generation,
and mmap_cache_generation field to struct tcb. The variable
is incremented each time a process enters a syscall that can modify its
memory mapping. Each tcb records the value of this variable at the
moment if building its mmap cache. Every mmap cache associated with
the given tcb can be validated by comparing its mmap_cache_generation
field with the variable mmap_cache_generation.
This implementation is inefficient. If strace attaches two processes
which don't share the memory mapping, rebuilding mmap cache of a tcb
triggered by another tcb's mmap system call is not necessary.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>