Skip to content

Commit

Permalink
Add -w/--where to show backtraces of traced functions.
Browse files Browse the repository at this point in the history
- add libunwind as a dep to configure
- add a command line option to show backtraces from traced library functions
- best guess at autoconf stuff, seems to work x86_64 and i686
- NOT TESTED ON ANY OTHER PLATFORMS!
  • Loading branch information
ice799 committed Oct 31, 2010
1 parent 36b560a commit 14fb133
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 0 deletions.
11 changes: 11 additions & 0 deletions ChangeLog
@@ -1,3 +1,14 @@
2010-10-31 Joe Damato <ice799@gmail.com>

* Makefile.am: Add autotool support for libunwind.
* configure.ac: Ditto.
* common.h: New structure fields for libunwind.
* execute_program.c: Initialize libunwind.
* proc.c: Ditto.
* options.c: New command line option (-w).
* options.h: New options parameter for libunwind.
* output.c: Use libunwind to do backtraces.

2010-10-18 Petr Machata <pmachata@redhat.com>

* sysdeps/linux-gnu/s390/trace.c: Support 5th argument fetching on s390.
Expand Down
3 changes: 3 additions & 0 deletions Makefile.am
Expand Up @@ -28,6 +28,9 @@ libltrace_la_LIBADD = \
$(libelf_LIBS) \
$(liberty_LIBS) \
$(libsupcxx_LIBS) \
$(libunwind_LIBS) \
$(libunwind_ptrace_LIBS) \
$(libunwind_arch_LIBS) \
sysdeps/libos.la


Expand Down
10 changes: 10 additions & 0 deletions common.h
@@ -1,3 +1,7 @@
#if defined(HAVE_LIBUNWIND)
#include <libunwind.h>
#endif /* defined(HAVE_LIBUNWIND) */

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
Expand Down Expand Up @@ -186,6 +190,12 @@ struct Process {
/* output: */
enum tof type_being_displayed;

#if defined(HAVE_LIBUNWIND)
/* libunwind address space */
unw_addr_space_t unwind_as;
void *unwind_priv;
#endif /* defined(HAVE_LIBUNWIND) */

Process * next;
};

Expand Down
26 changes: 26 additions & 0 deletions configure.ac
Expand Up @@ -62,6 +62,32 @@ AC_CHECK_LIB([supc++], [__cxa_demangle], [
AC_SUBST(libsupcxx_LIBS)


# HAVE_LIBUNWIND
AC_ARG_WITH(libunwind,
[ --with-libunwind Use libunwind frame unwinding support],
[case "${withval}" in
yes) enable_libunwind=yes ;;
no) enable_libunwind=no ;;
*) AC_MSG_ERROR(bad value ${withval} for GDB with-libunwind option) ;;
esac],[
AC_CHECK_HEADERS(libunwind.h)
AC_CHECK_HEADERS(libunwind-ptrace.h)
if test x"$ac_cv_header_libunwind_h" = xyes; then
enable_libunwind=yes;
fi
])

if test x"$enable_libunwind" = xyes; then
AC_CHECK_LIB(unwind, backtrace, libunwind_LIBS=-lunwind, libunwind_LIBS=)
AC_SUBST(libunwind_LIBS)
AC_CHECK_LIB(unwind-ptrace, _UPT_create, libunwind_ptrace_LIBS=-lunwind-ptrace, libunwind_ptrace_LIBS=)
AC_SUBST(libunwind_ptrace_LIBS)
AC_CHECK_LIB(unwind-${HOST_CPU}, _U${HOST_CPU}_init_remote, libunwind_arch_LIBS=-lunwind-${HOST_CPU}, libunwind_arch_LIBS=)
AC_SUBST(libunwind_arch_LIBS)
AC_DEFINE([HAVE_LIBUNWIND], [1], [we have libunwind])
fi


# HAVE_ELF_C_READ_MMAP
AC_MSG_CHECKING([whether elf_begin accepts ELF_C_READ_MMAP])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <gelf.h>]], [[
Expand Down
8 changes: 8 additions & 0 deletions execute_program.c
@@ -1,5 +1,9 @@
#include "config.h"

#if defined(HAVE_LIBUNWIND)
#include <libunwind-ptrace.h>
#endif /* defined(HAVE_LIBUNWIND) */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
Expand Down Expand Up @@ -87,5 +91,9 @@ execute_program(Process *sp, char **argv) {

sp->pid = pid;

#if defined(HAVE_LIBUNWIND)
sp->unwind_priv = _UPT_create(pid);
#endif /* defined(HAVE_LIBUNWIND) */

return;
}
18 changes: 18 additions & 0 deletions options.c
Expand Up @@ -100,6 +100,9 @@ usage(void) {
" -T show the time spent inside each call.\n"
" -u USERNAME run command with the userid, groupid of username.\n"
" -V, --version output version information and exit.\n"
#if defined(HAVE_LIBUNWIND)
" -w=NR, --where=NR print backtrace showing NR stack frames at most.\n"
#endif /* defined(HAVE_LIBUNWIND) */
" -x NAME treat the global NAME like a library subroutine.\n"
#ifdef PLT_REINITALISATION_BP
" -X NAME same as -x; and PLT's will be initialized by here.\n"
Expand Down Expand Up @@ -183,6 +186,9 @@ process_options(int argc, char **argv) {
options.output = stderr;
options.no_plt = 0;
options.no_signals = 0;
#if defined(HAVE_LIBUNWIND)
options.bt_depth = -1;
#endif /* defined(HAVE_LIBUNWIND) */

guess_cols();

Expand All @@ -204,13 +210,20 @@ process_options(int argc, char **argv) {
{"version", 0, 0, 'V'},
{"no-plt", 0, 0, 'g'},
{"no-signals", 0, 0, 'b'},
#if defined(HAVE_LIBUNWIND)
{"where", 1, 0, 'w'},
#endif /* defined(HAVE_LIBUNWIND) */
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "+cfhiLrStTVgb"
# ifdef USE_DEMANGLE
"C"
# endif
#if defined(HAVE_LIBUNWIND)
"a:A:D:e:F:l:n:o:p:s:u:x:X:w:", long_options,
#else /* !defined(HAVE_LIBUNWIND) */
"a:A:D:e:F:l:n:o:p:s:u:x:X:", long_options,
#endif
&option_index);
if (c == -1) {
break;
Expand Down Expand Up @@ -313,6 +326,11 @@ process_options(int argc, char **argv) {
case 'n':
options.indent = atoi(optarg);
break;
#if defined(HAVE_LIBUNWIND)
case 'w':
options.bt_depth = atoi(optarg);
break;
#endif /* defined(HAVE_LIBUNWIND) */
case 'o':
options.output = fopen(optarg, "w");
if (!options.output) {
Expand Down
3 changes: 3 additions & 0 deletions options.h
Expand Up @@ -16,6 +16,9 @@ struct options_t {
int follow; /* trace child processes */
int no_plt; /* set bps on PLT entries */
int no_signals; /* don't print signals */
#if defined(HAVE_LIBUNWIND)
int bt_depth; /* how may levels of stack frames to show */
#endif /* defined(HAVE_LIBUNWIND) */
};
extern struct options_t options;

Expand Down
22 changes: 22 additions & 0 deletions output.c
Expand Up @@ -297,6 +297,28 @@ output_right(enum tof type, Process *proc, char *function_name) {
(int)current_time_spent.tv_usec);
}
fprintf(options.output, "\n");

#if defined(HAVE_LIBUNWIND)
if (options.bt_depth > 0) {
unw_cursor_t cursor;
unw_word_t ip, sp;
int unwind_depth = options.bt_depth;
char fn_name[100];

unw_init_remote(&cursor, proc->unwind_as, proc->unwind_priv);
while (unwind_depth) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
unw_get_reg(&cursor, UNW_REG_SP, &sp);
unw_get_proc_name(&cursor, fn_name, 100, NULL);
fprintf(options.output, "\t\t\t%s (ip = 0x%lx)\n", fn_name, (long) ip);
if (unw_step(&cursor) <= 0)
break;
unwind_depth--;
}
fprintf(options.output, "\n");
}
#endif /* defined(HAVE_LIBUNWIND) */

current_proc = 0;
current_column = 0;
}
17 changes: 17 additions & 0 deletions proc.c
@@ -1,3 +1,10 @@
#include "config.h"

#if defined(HAVE_LIBUNWIND)
#include <libunwind.h>
#include <libunwind-ptrace.h>
#endif /* defined(HAVE_LIBUNWIND) */

#include <sys/types.h>
#include <string.h>
#include <stdio.h>
Expand All @@ -18,11 +25,21 @@ open_program(char *filename, pid_t pid) {
proc->breakpoints_enabled = -1;
if (pid) {
proc->pid = pid;
#if defined(HAVE_LIBUNWIND)
proc->unwind_priv = _UPT_create(pid);
} else {
proc->unwind_priv = NULL;
#endif /* defined(HAVE_LIBUNWIND) */
}

breakpoints_init(proc);

proc->next = list_of_processes;
list_of_processes = proc;

#if defined(HAVE_LIBUNWIND)
proc->unwind_as = unw_create_addr_space(&_UPT_accessors, 0);
#endif /* defined(HAVE_LIBUNWIND) */
return proc;
}

Expand Down

0 comments on commit 14fb133

Please sign in to comment.