[PATCH v4 11/37] unwind: report expected backtracing error
Masatake YAMATO
yamato at redhat.com
Wed Apr 16 06:33:09 UTC 2014
When a file mmap'ed to the target process is unlink'ed, backtracing
the stack is failed. Current implementation reports it as
"backtracing_error". To reduce bug reports, this patch
changes the message to "expected_backtracing_error".
Here is the reproducer.
$ cat ./p-deleted.c
#include <unistd.h>
int
main(int argc, char **argv)
{
if (! ((argv[0][0] == '.') && (argv[0][1] == '/')))
return 1;
if (unlink(argv[0]) < 0)
return 1;
return 0;
}
$ LD_LIBRARY_PATH=/usr/local/lib ../strace -e unlink -k ./p-deleted
LD_LIBRARY_PATH=/usr/local/lib ../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:
$ LD_LIBRARY_PATH=/usr/local/lib ../strace -e unlink -k ./p-deleted
LD_LIBRARY_PATH=/usr/local/lib ../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 +++
Restriction:
This is not the perfect solution. 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, hardcode magic number used in comparing "(delete)"
string is replaced with strlen. Suggested by Dmitry V. Levin <ldv at altlinux.org>.
In old version of patch, I throw away the deleted entry 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 V. Levin <ldv at altlinux.org>.
Signed-off-by: Masatake YAMATO <yamato at redhat.com>
---
unwind.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/unwind.c b/unwind.c
index 42c885e..0e90a92 100644
--- a/unwind.c
+++ b/unwind.c
@@ -48,6 +48,7 @@ struct mmap_cache_t {
unsigned long end_addr;
unsigned long mmap_offset;
char* binary_filename;
+ bool deleted;
};
/*
@@ -134,6 +135,10 @@ build_mmap_cache(struct tcb* tcp)
struct mmap_cache_t *cache_head;
FILE *fp;
+ const char *deleted = " (deleted)";
+ size_t blen;
+ size_t dlen;
+
sprintf(filename, "/proc/%d/maps", tcp->pid);
fp = fopen(filename, "r");
if (!fp) {
@@ -170,6 +175,13 @@ build_mmap_cache(struct tcb* tcp)
cur_entry->mmap_offset = mmap_offset;
cur_entry->binary_filename = strdup(binary_path);
+ dlen = strlen(deleted);
+ blen = strlen(binary_path);
+ if (blen >= dlen && strcmp(binary_path + blen - dlen, deleted) == 0)
+ cur_entry->deleted = true;
+ else
+ cur_entry->deleted = false;
+
/*
* sanity check to make sure that we're storing
* non-overlapping regions in ascending order
@@ -271,6 +283,7 @@ stacktrace_walk(struct tcb *tcp,
char * symbol_name;
struct mmap_cache_t* cur_mmap_cache;
unsigned long true_offset;
+ bool berror_expected = false;
if (!tcp->mmap_cache)
error_msg_and_die("bug: mmap_cache is NULL");
@@ -313,6 +326,9 @@ stacktrace_walk(struct tcb *tcp,
die_out_of_memory();
}
+ if (cur_mmap_cache->deleted)
+ berror_expected = true;
+
true_offset = ip - cur_mmap_cache->start_addr +
cur_mmap_cache->mmap_offset;
if (symbol_name[0]) {
@@ -349,7 +365,10 @@ stacktrace_walk(struct tcb *tcp,
}
if (lower > upper) {
error_action(data,
- "backtracing_error", ip);
+ berror_expected
+ ?"expected_backtracing_error"
+ :"unexpected_backtracing_error",
+ ip);
goto ret;
}
--
1.9.0
More information about the Strace-devel
mailing list