This patch prints the stack trace of the traced process after
each system call when using -k flag. It uses libunwind to
unwind the stack and to obtain the function name pointed by
the IP.

Tested on Ubuntu 12.04 64 with the distribution version of
libunwind (0.99-0.3ubuntu1) and on CentOS 6.3 with libunwind
form the source code.

This code was originally taken from strace-plus of Philip J. Guo.

 v4:
   updated man page

 v3:
   adjusted several datatype to use unsigned (Denys)
   fix sybol_name leak (Denys)
   workaround for libunwind bug with libpthread (unw_step does
        not return 1 when at the end of the stack)
   fix several problem in in autoconf script (Dmitry)
   use PATH_MAX for DSO file path buffer

 v2:
   fixed several identation issues
   removed a strlen in alloc_mmap_cache (Denys)
   reload mmap_cache after execv
   fixed a bug in libunwind_backtrace binary search (Masatake)
   check return value of _UPT_create
   use die_out_of_memory after Xalloc
   use exiting instead of !entering
   created a new separate unwind.c file
   removed include from defs.h
   added --with-libunwind to autoconf script
   cleaned up defs.h from several inclusions
---
 Makefile.am  |   10 ++-
 configure.ac |   79 ++++++++++++++++++++
 defs.h       |   42 +++++++++++
 mem.c        |   15 ++++
 process.c    |   14 ++++
 strace.1     |    5 +-
 strace.c     |   43 +++++++++++
 syscall.c    |    9 +++
 unwind.c     |  230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 445 insertions(+), 2 deletions(-)
 create mode 100644 unwind.c

diff --git a/Makefile.am b/Makefile.am
index 9d611f3..c8ad026 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,7 +12,7 @@ ARCH          = @arch@
 
 ACLOCAL_AMFLAGS = -I m4
 AM_CFLAGS = $(WARN_CFLAGS)
-AM_CPPFLAGS = -I$(srcdir)/$(OS)/$(ARCH) -I$(srcdir)/$(OS) -I$(builddir)/$(OS)
+AM_CPPFLAGS = -I$(srcdir)/$(OS)/$(ARCH) -I$(srcdir)/$(OS) -I$(builddir)/$(OS) 
$(libunwind_CPPFLAGS)
 
 strace_SOURCES =       \
        bjm.c           \
@@ -43,6 +43,14 @@ strace_SOURCES =     \
        util.c          \
        vsprintf.c
 
+
+if LIB_UNWIND
+strace_SOURCES += unwind.c
+strace_LDADD = $(libunwind_LIBS)
+AM_LDFLAGS = $(libunwind_LDFLAGS)
+endif
+
+
 noinst_HEADERS = defs.h
 # Enable this to get link map generated
 #strace_CFLAGS = $(AM_CFLAGS) -Wl,-Map=strace.mapfile
diff --git a/configure.ac b/configure.ac
index b3b62e8..0f64a12 100644
--- a/configure.ac
+++ b/configure.ac
@@ -265,6 +265,85 @@ AC_CHECK_MEMBERS([struct sigcontext.sc_hi2],,, [#include 
<signal.h>
 # include <asm/sigcontext.h>
 #endif])
 
+
+dnl stack trace with libunwind
+AC_ARG_WITH([libunwind],
+           [AS_HELP_STRING([--with-libunwind],
+                           [libunwind is used to display system call 
stacktrace])],
+           [case "${withval}" in
+            (yes|no) with_libunwind=$withval;;
+            (*)      with_libunwind=yes
+                     libunwind_CPPFLAGS="-I${withval}/include"
+                     libunwind_LDFLAGS="-L${withval}/lib" ;;
+            esac],
+           [with_libunwind=check])
+
+AS_IF([test "x$with_libunwind" != "xno"],
+       [saved_CPPFLAGS="${CPPFLAGS}"
+       CPPFLAGS="${CPPFLAGS} ${libunwind_CPPFLAGS}"
+       AC_CHECK_HEADERS([libunwind-ptrace.h],[],
+                        [if test "x$with_libunwind" != "xcheck" ; then
+                            AC_MSG_FAILURE([Unable to find libunwind-ptrace.h 
header])
+                         fi])
+       AC_CHECK_HEADERS([libunwind.h],[],
+                        [if test "x$with_libunwind" != "xcheck" ; then
+                            AC_MSG_FAILURE([Unable to find libunwind.h header])
+                         fi])
+       CPPFLAGS="${saved_CPPFLAGS}" ])
+
+
+
+if test "x$ac_cv_header_libunwind_ptrace_h" = "xyes" &&
+       test "x$ac_cv_header_libunwind_h" = "xyes"; then
+
+       dnl code is taken from ltrace
+       case "${host_cpu}" in
+               arm*|sa110)         UNWIND_ARCH="arm" ;;
+               i?86)               UNWIND_ARCH="x86" ;;
+               powerpc)            UNWIND_ARCH="ppc32" ;;
+               powerpc64)          UNWIND_ARCH="ppc64" ;;
+               mips*)              UNWIND_ARCH="mips" ;;
+               *)                  UNWIND_ARCH="${host_cpu}" ;;
+       esac
+
+       saved_LDFLAGS="${LDFLAGS}"
+       LDFLAGS="${LDFLAGS} ${libunwind_LDFLAGS}"
+       AC_CHECK_LIB([unwind], [backtrace],
+                    [libunwind_LIBS="-lunwind"],
+                    [if test "x$with_libunwind" != "xcheck" ; then
+                       AC_MSG_FAILURE([Unable to find libunwind])
+                     fi])
+        AC_CHECK_LIB([unwind-generic], [_U${UNWIND_ARCH}_create_addr_space],
+                    [libunwind_LIBS="-lunwind-generic $libunwind_LIBS"],
+                    [if test "x$with_libunwind" != "xcheck" ; then
+                       AC_MSG_FAILURE([Unable to find libunwind-generic])
+                     fi],
+                    [$libunwind_LIBS])
+       AC_CHECK_LIB([unwind-ptrace], [_UPT_create],
+                    [libunwind_LIBS="-lunwind-ptrace $libunwind_LIBS"],
+                    [if test "x$with_libunwind" != "xcheck" ; then
+                       AC_MSG_FAILURE([Unable to find libunwind-ptrace])
+                     fi],
+                    [$libunwind_LIBS])
+       LDFLAGS="${saved_LDFLAGS}"
+
+       dnl we have all the dependencies we need we can activate stack tracing
+       AC_SUBST(libunwind_LIBS)
+       AC_SUBST(libunwind_LDFLAGS)
+       AC_SUBST(libunwind_CPPFLAGS)
+fi
+
+dnl enable libunwind
+if test "x$ac_cv_lib_unwind_ptrace__UPT_create" == "xyes" &&
+       eval test 
\"x\$ac_cv_lib_unwind_generic__U"${UNWIND_ARCH}"_create_addr_space\" == "xyes" 
&&
+       test "x$ac_cv_lib_unwind_backtrace" == "xyes"; then
+       AC_DEFINE([LIB_UNWIND], 1, [Compile stack tracing functionality])
+       AC_MSG_NOTICE([Enabled stack tracing])
+       with_libunwind="yes"
+fi
+AM_CONDITIONAL([LIB_UNWIND], [test "x$with_libunwind" == "xyes"])
+
+
 AC_CHECK_MEMBERS([struct utsname.domainname],,, [#include <sys/utsname.h>])
 
 AC_CHECK_DECLS([sys_errlist])
diff --git a/defs.h b/defs.h
index 964636b..1b1fa8d 100644
--- a/defs.h
+++ b/defs.h
@@ -414,6 +414,33 @@ typedef struct ioctlent {
        unsigned long code;
 } struct_ioctlent;
 
+
+#ifdef LIB_UNWIND
+
+/* keep a sorted array of cache entries, so that we can binary search
+ * through it
+ */
+struct mmap_cache_t {
+       /**
+        * example entry:
+        * 7fabbb09b000-7fabbb09f000 r--p 00179000 fc:00 1180246 
/lib/libc-2.11.1.so
+        *
+        * start_addr  is 0x7fabbb09b000
+        * end_addr    is 0x7fabbb09f000
+        * mmap_offset is 0x179000
+        * binary_filename is "/lib/libc-2.11.1.so"
+        */
+       unsigned long start_addr;
+       unsigned long end_addr;
+       unsigned long mmap_offset;
+       char* binary_filename;
+};
+
+
+/* if this is true do the stack trace for every system call */
+extern bool use_libunwind;
+#endif
+
 /* Trace Control Block */
 struct tcb {
        int flags;              /* See below for TCB_ values */
@@ -439,6 +466,12 @@ struct tcb {
        struct timeval etime;   /* Syscall entry time */
                                /* Support for tracing forked processes: */
        long inst[2];           /* Saved clone args (badly named) */
+
+#ifdef LIB_UNWIND
+       struct mmap_cache_t* mmap_cache;
+       unsigned int mmap_cache_size;
+       struct UPT_info* libunwind_ui;
+#endif
 };
 
 /* TCB flags */
@@ -724,6 +757,15 @@ extern void tv_sub(struct timeval *, struct timeval *, 
struct timeval *);
 extern void tv_mul(struct timeval *, struct timeval *, int);
 extern void tv_div(struct timeval *, struct timeval *, int);
 
+#ifdef LIB_UNWIND
+/**
+ * print stack (-k flag) memory allocation and deallocation
+ */
+extern void alloc_mmap_cache(struct tcb* tcp);
+extern void delete_mmap_cache(struct tcb* tcp);
+extern void print_stacktrace(struct tcb* tcp);
+#endif
+
 /* Strace log generation machinery.
  *
  * printing_tcp: tcb which has incomplete line being printed right now.
diff --git a/mem.c b/mem.c
index ef273c7..b3c6abe 100644
--- a/mem.c
+++ b/mem.c
@@ -175,6 +175,11 @@ static int
 print_mmap(struct tcb *tcp, long *u_arg, unsigned long long offset)
 {
        if (entering(tcp)) {
+#ifdef LIB_UNWIND
+               if (use_libunwind)
+                       delete_mmap_cache(tcp);
+#endif
+
                /* addr */
                if (!u_arg[0])
                        tprints("NULL, ");
@@ -304,6 +309,11 @@ sys_munmap(struct tcb *tcp)
                tprintf("%#lx, %lu",
                        tcp->u_arg[0], tcp->u_arg[1]);
        }
+
+#ifdef LIB_UNWIND
+       if (exiting(tcp) && use_libunwind)
+               delete_mmap_cache(tcp);
+#endif
        return 0;
 }
 
@@ -315,6 +325,11 @@ sys_mprotect(struct tcb *tcp)
                        tcp->u_arg[0], tcp->u_arg[1]);
                printflags(mmap_prot, tcp->u_arg[2], "PROT_???");
        }
+
+#ifdef LIB_UNWIND
+       if (exiting(tcp) && use_libunwind)
+               delete_mmap_cache(tcp);
+#endif
        return 0;
 }
 
diff --git a/process.c b/process.c
index e2fa25b..e058bbb 100644
--- a/process.c
+++ b/process.c
@@ -992,6 +992,13 @@ sys_execve(struct tcb *tcp)
                        tprints("]");
                }
        }
+
+
+#ifdef LIB_UNWIND
+       if (exiting(tcp) && use_libunwind)
+               delete_mmap_cache(tcp);
+#endif
+
        return 0;
 }
 
@@ -1209,6 +1216,13 @@ sys_waitid(struct tcb *tcp)
                                printrusage(tcp, tcp->u_arg[4]);
                }
        }
+
+
+#ifdef LIB_UNWIND
+       if (exiting(tcp) && use_libunwind)
+               delete_mmap_cache(tcp);
+#endif
+
        return 0;
 }
 
diff --git a/strace.1 b/strace.1
index 6ca4bda..e6373c0 100644
--- a/strace.1
+++ b/strace.1
@@ -39,7 +39,7 @@
 strace \- trace system calls and signals
 .SH SYNOPSIS
 .B strace
-[\fB-CdffhiqrtttTvVxxy\fR]
+[\fB-CdffhikqrtttTvVxxy\fR]
 [\fB-I\fIn\fR]
 [\fB-b\fIexecve\fR]
 [\fB-e\fIexpr\fR]...
@@ -306,6 +306,9 @@ Print all non-ASCII strings in hexadecimal string format.
 .B \-xx
 Print all strings in hexadecimal string format.
 .TP
+.B \-k
+Print the execution stack trace of the traced processes after each system call.
+.TP
 .B \-y
 Print paths associated with file descriptor arguments.
 .TP
diff --git a/strace.c b/strace.c
index 32a3f5e..5c46d7f 100644
--- a/strace.c
+++ b/strace.c
@@ -50,6 +50,13 @@ extern char **environ;
 extern int optind;
 extern char *optarg;
 
+#ifdef LIB_UNWIND
+# include <libunwind-ptrace.h>
+
+/* if this is true do the stack trace for every system call */
+bool use_libunwind = false;
+unw_addr_space_t libunwind_as;
+#endif
 
 #if defined __NR_tkill
 # define my_tkill(tid, sig) syscall(__NR_tkill, (tid), (sig))
@@ -231,6 +238,10 @@ usage: strace [-CdffhiqrtttTvVxxy] [-I n] [-e expr]...\n\
 -E var -- remove var from the environment for command\n\
 -P path -- trace accesses to path\n\
 "
+#ifdef LIB_UNWIND
+"-k obtain stack trace between each syscall\n\
+"
+#endif
 /* ancient, no one should use it
 -F -- attempt to follow vforks (deprecated, use -f)\n\
  */
@@ -685,6 +696,15 @@ alloctcb(int pid)
 #if SUPPORTED_PERSONALITIES > 1
                        tcp->currpers = current_personality;
 #endif
+
+#ifdef LIB_UNWIND
+                       if (use_libunwind) {
+                               tcp->libunwind_ui = _UPT_create(tcp->pid);
+                               if (!tcp->libunwind_ui)
+                                   die_out_of_memory();
+                       }
+#endif
+
                        nprocs++;
                        if (debug_flag)
                                fprintf(stderr, "new tcb for pid %d, active 
tcbs:%d\n", tcp->pid, nprocs);
@@ -721,6 +741,12 @@ droptcb(struct tcb *tcp)
        if (printing_tcp == tcp)
                printing_tcp = NULL;
 
+#ifdef LIB_UNWIND
+       if (use_libunwind) {
+               delete_mmap_cache(tcp);
+               _UPT_destroy(tcp->libunwind_ui);
+       }
+#endif
        memset(tcp, 0, sizeof(*tcp));
 }
 
@@ -1642,6 +1668,9 @@ init(int argc, char *argv[])
        qualify("signal=all");
        while ((c = getopt(argc, argv,
                "+b:cCdfFhiqrtTvVxyz"
+#ifdef LIB_UNWIND
+               "k"
+#endif
                "D"
                "a:e:o:O:p:s:S:u:E:P:I:")) != EOF) {
                switch (c) {
@@ -1744,6 +1773,11 @@ init(int argc, char *argv[])
                case 'u':
                        username = strdup(optarg);
                        break;
+#ifdef LIB_UNWIND
+               case 'k':
+                       use_libunwind = true;
+                       break;
+#endif
                case 'E':
                        if (putenv(optarg) < 0)
                                die_out_of_memory();
@@ -1775,6 +1809,15 @@ init(int argc, char *argv[])
                error_msg_and_die("-D and -p are mutually exclusive");
        }
 
+#ifdef LIB_UNWIND
+       if (use_libunwind) {
+               libunwind_as = unw_create_addr_space(&_UPT_accessors, 0);
+               if (!libunwind_as) {
+                       error_msg_and_die("Fatal error: unable to create 
address space for stack tracing\n");
+               }
+       }
+#endif
+
        if (!followfork)
                followfork = optF;
 
diff --git a/syscall.c b/syscall.c
index 1b49bb3..0c23e40 100644
--- a/syscall.c
+++ b/syscall.c
@@ -2683,6 +2683,15 @@ trace_syscall_exiting(struct tcb *tcp)
        dumpio(tcp);
        line_ended();
 
+#ifdef LIB_UNWIND
+       if (use_libunwind) {
+               if (!tcp->mmap_cache) {
+                       alloc_mmap_cache(tcp);
+               }
+               print_stacktrace(tcp);
+       }
+#endif
+
  ret:
        tcp->flags &= ~TCB_INSYSCALL;
        return 0;
diff --git a/unwind.c b/unwind.c
new file mode 100644
index 0000000..5dc0175
--- /dev/null
+++ b/unwind.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2013 Luca Clementi <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "defs.h"
+
+
+#include <limits.h>
+
+#include <libunwind.h>
+
+
+extern unw_addr_space_t libunwind_as;
+/*
+ * caching of /proc/ID/maps for each process to speed up stack tracing
+ *
+ * The cache must be refreshed after some syscall: mmap, mprotect, munmap, 
execve
+ */
+void
+alloc_mmap_cache(struct tcb* tcp)
+{
+       unsigned long start_addr, end_addr, mmap_offset;
+       char filename[sizeof ("/proc/0123456789/maps")];
+       char buffer[PATH_MAX + 80];
+       char binary_path[PATH_MAX];
+       struct mmap_cache_t *cur_entry, *prev_entry;
+       /* start with a small dynamically-allocated array and then expand it */
+       size_t cur_array_size = 10;
+       struct mmap_cache_t *cache_head = malloc(cur_array_size * 
sizeof(*cache_head));
+       if (!cache_head)
+               die_out_of_memory();
+
+       sprintf(filename, "/proc/%d/maps", tcp->pid);
+
+       FILE* f = fopen(filename, "r");
+       if (!f)
+               perror_msg_and_die("Can't open %s", filename);
+       while (fgets(buffer, sizeof(buffer), f) != NULL) {
+               binary_path[0] = '\0'; // 'reset' it just to be paranoid
+
+               sscanf(buffer, "%lx-%lx %*c%*c%*c%*c %lx %*x:%*x %*d %[^\n]", 
&start_addr,
+                       &end_addr, &mmap_offset, binary_path);
+
+               /* ignore special 'fake files' like "[vdso]", "[heap]", 
"[stack]", */
+               if (binary_path[0] == '[') {
+                       continue;
+               }
+
+               if (binary_path[0] == '\0') {
+                       continue;
+               }
+
+               if (end_addr < start_addr)
+                       perror_msg_and_die("Unrecognized maps file format %s", 
filename);
+
+               cur_entry = &cache_head[tcp->mmap_cache_size];
+               cur_entry->start_addr = start_addr;
+               cur_entry->end_addr = end_addr;
+               cur_entry->mmap_offset = mmap_offset;
+               cur_entry->binary_filename = strdup(binary_path);
+
+               /* sanity check to make sure that we're storing non-overlapping 
regions in
+                * ascending order
+                */
+               if (tcp->mmap_cache_size > 0) {
+                       prev_entry = &cache_head[tcp->mmap_cache_size - 1];
+                       if (prev_entry->start_addr >= cur_entry->start_addr)
+                               perror_msg_and_die("Overlaying memory region in 
%s", filename);
+                       if (prev_entry->end_addr > cur_entry->start_addr)
+                               perror_msg_and_die("Overlaying memory region in 
%s", filename);
+               }
+               tcp->mmap_cache_size++;
+
+               /* resize doubling its size */
+               if (tcp->mmap_cache_size >= cur_array_size) {
+                       cur_array_size *= 2;
+                       cache_head = realloc(cache_head, cur_array_size * 
sizeof(*cache_head));
+                       if (!cache_head)
+                               die_out_of_memory();
+               }
+       }
+       fclose(f);
+       tcp->mmap_cache = cache_head;
+}
+
+/* deleting the cache */
+void
+delete_mmap_cache(struct tcb* tcp)
+{
+       unsigned int i;
+       for (i = 0; i < tcp->mmap_cache_size; i++) {
+               free(tcp->mmap_cache[i].binary_filename);
+       }
+       free(tcp->mmap_cache);
+       tcp->mmap_cache = NULL;
+       tcp->mmap_cache_size = 0;
+}
+
+
+
+/*
+ * use libunwind to unwind the stack and print a backtrace
+ *
+ * Pre-condition: tcp->mmap_cache is already initialized
+ */
+void
+print_stacktrace(struct tcb* tcp)
+{
+       unw_word_t ip;
+       unw_cursor_t cursor;
+       unw_word_t function_off_set;
+       int stack_depth = 0, ret_val;
+       /* these are used for the binary search through the mmap_chace */
+       unsigned int lower, upper, mid;
+       size_t symbol_name_size = 40;
+       char * symbol_name;
+       struct mmap_cache_t* cur_mmap_cache;
+       unsigned long true_offset;
+
+       symbol_name = malloc(symbol_name_size);
+       if (!symbol_name)
+               die_out_of_memory();
+
+       if (unw_init_remote(&cursor, libunwind_as, tcp->libunwind_ui) < 0)
+               perror_msg_and_die("Can't initiate libunwind");
+
+       do {
+               /* looping on the stack frame */
+               if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0)
+                       perror_msg("Can't walk the stack of process %d", 
tcp->pid);
+
+               lower = 0;
+               upper = tcp->mmap_cache_size - 1;
+
+               while (lower <= upper) {
+                       /* find the mmap_cache and print the stack frame */
+                       mid = (unsigned int)((upper + lower) / 2);
+                       cur_mmap_cache = &tcp->mmap_cache[mid];
+
+                       if (ip >= cur_mmap_cache->start_addr &&
+                               ip < cur_mmap_cache->end_addr) {
+
+                               for (;;) {
+                                       symbol_name[0] = '\0';
+                                       ret_val = unw_get_proc_name(&cursor, 
symbol_name,
+                                               symbol_name_size, 
&function_off_set);
+                                       if (ret_val != -UNW_ENOMEM)
+                                               break;
+                                       symbol_name_size *= 2;
+                                       symbol_name = realloc(symbol_name, 
symbol_name_size);
+                                       if (!symbol_name)
+                                               die_out_of_memory();
+                               }
+
+                               true_offset = ip - cur_mmap_cache->start_addr + 
cur_mmap_cache->mmap_offset;
+                               if (symbol_name[0]) {
+                                       /*
+                                        * we want to keep the format used by 
backtrace_symbols from the glibc
+                                        *
+                                        * ./a.out() [0x40063d]
+                                        * ./a.out() [0x4006bb]
+                                        * ./a.out() [0x4006c6]
+                                        * 
/lib64/libc.so.6(__libc_start_main+0xed) [0x7fa2f8a5976d]
+                                        * ./a.out() [0x400569]
+                                        */
+                                       tprintf(" > %s(%s+0x%lx) [0x%lx]\n", 
cur_mmap_cache->binary_filename,
+                                               symbol_name, function_off_set, 
true_offset);
+                                       line_ended();
+                               } else {
+                                       tprintf(" > %s() [0x%lx]\n", 
cur_mmap_cache->binary_filename, true_offset);
+                                       line_ended();
+                               }
+
+                               break; /* stack frame printed */
+                       }
+                       else if (mid == 0) {
+                               /**
+                                * there is a bug in libunwind >= 1.0
+                                * after a set_tid_address syscall unw_get_reg 
returns IP=0
+                                */
+                               tprintf(" > backtracing_error\n");
+                               line_ended();
+                               goto ret;
+                       }
+                       else if (ip < cur_mmap_cache->start_addr)
+                               upper = mid - 1;
+
+                       else
+                               lower = mid + 1;
+
+               }
+               if (lower > upper) {
+                       tprintf(" > backtracing_error [0x%lx]\n", ip);
+                       line_ended();
+                       goto ret;
+               }
+
+               ret_val = unw_step(&cursor);
+
+               if (++stack_depth > 255) {
+                       tprintf("libunwind warning: stack frame greater than 
255 aborting backtracing\n");
+                       line_ended();
+                       break;
+               }
+       } while (ret_val > 0);
+ret:
+       free(symbol_name);
+}
-- 
1.7.9.5


------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to