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!
Только зарегистрированные пользователи имеют доступ к сервису!
Для получения аккаунта, обратитесь к администратору.
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>
This is the second step for splitting capturing from printing.
New `queue' field is added to tcb. Captured stacktrace is stored here.
The field is initialized/finalized at unwind_tcb_init/unwind_tcb_fin.
New API function unwind_capture_stacktrace is added. This function
captures the currest stack using stracktrace_walker and records it in
tcb. It's printing is delayed to the next call of
unwind_print_stacktrace.
unwind_print_stacktrace is extended. Now it checks queue field of
the given tcb at the start of function. If the function finds a
captured stack trace, the latter is printed using stracktrace_walker.
Currently unwind_capture_stacktrace invocations are added directly to
handlers of mmap, munmap, mprotect, and execve.
Here is the difference of output with/without patch:
(without patch)
execve("./test-fork", ["./test-fork"], [/* 56 vars */]) = 0
> /usr/lib64/ld-2.18.so(check_one_fd.part.0+0x82) [0x11f0]
(with patch)
execve("./test-fork", ["./test-fork"], [/* 54 vars */]) = 0
> /usr/lib64/libc-2.18.so(execve+0x7) [0xbcd27]
> /home/yamato/var/strace/strace(exec_or_die+0x10c) [0x26ac]
> /home/yamato/var/strace/strace(startup_child+0x346) [0x134f6]
> /home/yamato/var/strace/strace(init+0x89f) [0x13dff]
> /home/yamato/var/strace/strace(main+0xa) [0x26ca]
> /usr/lib64/libc-2.18.so(__libc_start_main+0xf5) [0x21d65]
> /home/yamato/var/strace/strace(_start+0x29) [0x2799]
In older version output lines of captured elements were built when
printing. In this version they are built when capturing the stack.
As result, unneeded dynamic memory allocations are avoided.
Suggested by Luca Clementi.
In older version the combination of snprintf and realloc were used.
In this version they are replaced with asprintf.
Suggested by Dmitry Levin.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
In current implementation, the stack trace is captured and printed at
the same time, in trace_syscall_exiting. This approach cannot
provide user expected information when a system call changes the
memory mapping. In such cases, the stack trace should be captured on
entering syscall and printed on exiting.
As the initial step for splitting capturing from printing, this change
introduces stacktrace_walker utility function. It can be used both for
capturing in trace_syscall_entering and printing in
trace_syscall_exiting.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
free_libunwind_ui is expected to release all unwind related resources
attached to tcp.
* strace.c (droptcb): Move delete_mmap_cache call ...
* unwind.c (free_libunwind_ui): ... to here.
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Print the stack trace of the traced process after each system call when
-k option is specified. It is implemented using libunwind to unwind the
stack and to obtain the function name pointed by the IP.
Based on the code that was originally taken from strace-plus
of Philip J. Guo.
* configure.ac: Add --with-libunwind option. Check libunwind support.
* Makefile.am: Add libunwind support.
* defs.h (struct tcb) [USE_LIBUNWIND]: Append libunwind specific fields.
[USE_LIBUNWIND] (stack_trace_enabled, alloc_mmap_cache,
delete_mmap_cache, print_stacktrace): New prototypes.
* mem.c (print_mmap, sys_munmap, sys_mprotect): Add libunwind support.
* process.c (sys_execve): Likewise.
* strace.c (usage, alloctcb, droptcb, init): Likewise.
* syscall.c (trace_syscall_exiting): Likewise.
* unwind.c: New file.
* strace.1: Document -k option.