aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--breakpoints.c21
-rw-r--r--debug.c7
-rw-r--r--debug.h28
-rw-r--r--demangle.c3
-rw-r--r--dict.c25
-rw-r--r--elf.c7
-rw-r--r--ltrace.121
-rw-r--r--options.c14
-rw-r--r--process_event.c46
-rw-r--r--sysdeps/linux-gnu/breakpoint.c22
-rw-r--r--sysdeps/linux-gnu/events.c22
-rw-r--r--sysdeps/linux-gnu/trace.c10
12 files changed, 177 insertions, 49 deletions
diff --git a/breakpoints.c b/breakpoints.c
index 968d1f1..7112d49 100644
--- a/breakpoints.c
+++ b/breakpoints.c
@@ -20,6 +20,7 @@
Breakpoint *
address2bpstruct(Process *proc, void *addr) {
+ debug(DEBUG_FUNCTION, "address2bpstruct(pid=%d, addr=%p)", proc->pid, addr);
return dict_find_entry(proc->breakpoints, addr);
}
@@ -27,6 +28,8 @@ void
insert_breakpoint(Process *proc, void *addr,
struct library_symbol *libsym) {
Breakpoint *sbp;
+
+ debug(DEBUG_FUNCTION, "insert_breakpoint(pid=%d, addr=%p, symbol=%s)", proc->pid, addr, libsym ? libsym->name : "NULL");
debug(1, "symbol=%s, addr=%p", libsym?libsym->name:"(nil)", addr);
if (!addr)
@@ -56,7 +59,11 @@ insert_breakpoint(Process *proc, void *addr,
void
delete_breakpoint(Process *proc, void *addr) {
- Breakpoint *sbp = dict_find_entry(proc->breakpoints, addr);
+ Breakpoint *sbp;
+
+ debug(DEBUG_FUNCTION, "delete_breakpoint(pid=%d, addr=%p)", proc->pid, addr);
+
+ sbp = dict_find_entry(proc->breakpoints, addr);
assert(sbp); /* FIXME: remove after debugging has been done. */
/* This should only happen on out-of-memory conditions. */
if (sbp == NULL)
@@ -70,6 +77,7 @@ delete_breakpoint(Process *proc, void *addr) {
static void
enable_bp_cb(void *addr, void *sbp, void *proc) {
+ debug(DEBUG_FUNCTION, "enable_bp_cb(pid=%d)", ((Process *)proc)->pid);
if (((Breakpoint *)sbp)->enabled) {
enable_breakpoint(((Process *)proc)->pid, sbp);
}
@@ -77,6 +85,7 @@ enable_bp_cb(void *addr, void *sbp, void *proc) {
void
enable_all_breakpoints(Process *proc) {
+ debug(DEBUG_FUNCTION, "enable_all_breakpoints(pid=%d)", proc->pid);
if (proc->breakpoints_enabled <= 0) {
#ifdef __powerpc__
unsigned long a;
@@ -133,6 +142,7 @@ enable_all_breakpoints(Process *proc) {
static void
disable_bp_cb(void *addr, void *sbp, void *proc) {
+ debug(DEBUG_FUNCTION, "disable_bp_cb(pid=%d)", ((Process *)proc)->pid);
if (((Breakpoint *)sbp)->enabled) {
disable_breakpoint(((Process *)proc)->pid, sbp);
}
@@ -140,6 +150,7 @@ disable_bp_cb(void *addr, void *sbp, void *proc) {
void
disable_all_breakpoints(Process *proc) {
+ debug(DEBUG_FUNCTION, "disable_all_breakpoints(pid=%d)", proc->pid);
if (proc->breakpoints_enabled) {
debug(1, "Disabling breakpoints for pid %u...", proc->pid);
dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
@@ -149,6 +160,7 @@ disable_all_breakpoints(Process *proc) {
static void
free_bp_cb(void *addr, void *sbp, void *data) {
+ debug(DEBUG_FUNCTION, "free_bp_cb(sbp=%p)", sbp);
assert(sbp);
free(sbp);
}
@@ -157,6 +169,7 @@ void
breakpoints_init(Process *proc) {
struct library_symbol *sym;
+ debug(DEBUG_FUNCTION, "breakpoints_init(pid=%d)", proc->pid);
if (proc->breakpoints) { /* let's remove that struct */
dict_apply_to_all(proc->breakpoints, free_bp_cb, NULL);
dict_clear(proc->breakpoints);
@@ -198,7 +211,11 @@ breakpoints_init(Process *proc) {
void
reinitialize_breakpoints(Process *proc) {
- struct library_symbol *sym = proc->list_of_symbols;
+ struct library_symbol *sym;
+
+ debug(DEBUG_FUNCTION, "reinitialize_breakpoints(pid=%d)", proc->pid);
+
+ sym = proc->list_of_symbols;
while (sym) {
if (sym->needs_init) {
diff --git a/debug.c b/debug.c
index c31a9a9..e6b9748 100644
--- a/debug.c
+++ b/debug.c
@@ -6,19 +6,18 @@
#include "output.h"
void
-debug_(int level, const char *file, int line, const char *func,
- const char *fmt, ...) {
+debug_(int level, const char *file, int line, const char *fmt, ...) {
char buf[1024];
va_list args;
- if (options.debug < level) {
+ if (!(options.debug & level)) {
return;
}
va_start(args, fmt);
vsnprintf(buf, 1024, fmt, args);
va_end(args);
- output_line(NULL, "DEBUG: %s:%d: %s(): %s", file, line, func, buf);
+ output_line(NULL, "DEBUG: %s:%d: %s", file, line, buf);
}
// The following section provides a way to print things, like hex dumps,
diff --git a/debug.h b/debug.h
index 7a9761b..6b30e6a 100644
--- a/debug.h
+++ b/debug.h
@@ -1,23 +1,17 @@
#include <features.h>
-void debug_(int level, const char *file, int line, const char *func,
- const char *fmt, ...) __attribute__((format(printf,5,6)));
+/* debug levels:
+ */
+enum {
+ DEBUG_EVENT = 0x10,
+ DEBUG_PROCESS = 0x20,
+ DEBUG_FUNCTION = 0x40
+};
+
+void debug_(int level, const char *file, int line,
+ const char *fmt, ...) __attribute__((format(printf,4,5)));
int xinfdump(long, void *, int);
-# define debug(level, expr...) debug_(level, __FILE__, __LINE__, DEBUG_FUNCTION, expr)
+# define debug(level, expr...) debug_(level, __FILE__, __LINE__, expr)
-/* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__'
- which contains the name of the function currently being defined.
- This is broken in G++ before version 2.6.
- C9x has a similar variable called __func__, but prefer the GCC one since
- it demangles C++ function names. */
-# if __GNUC_PREREQ (2, 4)
-# define DEBUG_FUNCTION __PRETTY_FUNCTION__
-# else
-# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
-# define DEBUG_FUNCTION __func__
-# else
-# define DEBUG_FUNCTION "???"
-# endif
-# endif
diff --git a/demangle.c b/demangle.c
index 8626fe3..35fd63b 100644
--- a/demangle.c
+++ b/demangle.c
@@ -9,6 +9,7 @@
#include "options.h"
#include "output.h"
#include "demangle.h"
+#include "debug.h"
#include "dict.h"
@@ -26,6 +27,8 @@ my_demangle(const char *function_name) {
int status = 0;
#endif
+ debug(DEBUG_FUNCTION, "my_demangle(name=%s)", function_name);
+
if (!d)
d = dict_init(dict_key2hash_string, dict_key_cmp_string);
diff --git a/dict.c b/dict.c
index 0f44f5d..e55d367 100644
--- a/dict.c
+++ b/dict.c
@@ -36,6 +36,8 @@ dict_init(unsigned int (*key2hash) (void *),
struct dict *d;
int i;
+ debug(DEBUG_FUNCTION, "dict_init()");
+
d = malloc(sizeof(struct dict));
if (!d) {
perror("malloc()");
@@ -54,6 +56,7 @@ dict_clear(struct dict *d) {
int i;
struct dict_entry *entry, *nextentry;
+ debug(DEBUG_FUNCTION, "dict_clear()");
assert(d);
for (i = 0; i < DICTTABLESIZE; i++) {
for (entry = d->buckets[i]; entry != NULL; entry = nextentry) {
@@ -68,8 +71,13 @@ dict_clear(struct dict *d) {
int
dict_enter(struct dict *d, void *key, void *value) {
struct dict_entry *entry, *newentry;
- unsigned int hash = d->key2hash(key);
- unsigned int bucketpos = hash % DICTTABLESIZE;
+ unsigned int hash;
+ unsigned int bucketpos;
+
+ debug(DEBUG_FUNCTION, "dict_enter()");
+
+ hash = d->key2hash(key);
+ bucketpos = hash % DICTTABLESIZE;
assert(d);
newentry = malloc(sizeof(struct dict_entry));
@@ -98,10 +106,15 @@ dict_enter(struct dict *d, void *key, void *value) {
void *
dict_find_entry(struct dict *d, void *key) {
- unsigned int hash = d->key2hash(key);
- unsigned int bucketpos = hash % DICTTABLESIZE;
+ unsigned int hash;
+ unsigned int bucketpos;
struct dict_entry *entry;
+ debug(DEBUG_FUNCTION, "dict_find_entry()");
+
+ hash = d->key2hash(key);
+ bucketpos = hash % DICTTABLESIZE;
+
assert(d);
for (entry = d->buckets[bucketpos]; entry; entry = entry->next) {
if (hash != entry->hash) {
@@ -119,6 +132,8 @@ dict_apply_to_all(struct dict *d,
void (*func) (void *key, void *value, void *data), void *data) {
int i;
+ debug(DEBUG_FUNCTION, "dict_apply_to_all()");
+
if (!d) {
return;
}
@@ -171,6 +186,8 @@ dict_clone(struct dict *old, void * (*key_clone)(void*), void * (*value_clone)(v
struct dict *d;
int i;
+ debug(DEBUG_FUNCTION, "dict_clone()");
+
d = malloc(sizeof(struct dict));
if (!d) {
perror("malloc()");
diff --git a/elf.c b/elf.c
index 27ce1b0..ff9e26f 100644
--- a/elf.c
+++ b/elf.c
@@ -35,6 +35,7 @@ do_init_elf(struct ltelf *lte, const char *filename) {
GElf_Addr relplt_addr = 0;
size_t relplt_size = 0;
+ debug(DEBUG_FUNCTION, "do_init_elf(filename=%s)", filename);
debug(1, "Reading ELF from %s...", filename);
memset(lte, 0, sizeof(*lte));
@@ -320,6 +321,7 @@ do_init_elf(struct ltelf *lte, const char *filename) {
static void
do_close_elf(struct ltelf *lte) {
+ debug(DEBUG_FUNCTION, "do_close_elf()");
if (lte->lte_flags & LTE_HASH_MALLOCED)
free((char *)lte->hash);
elf_end(lte->elf);
@@ -331,6 +333,9 @@ add_library_symbol(GElf_Addr addr, const char *name,
struct library_symbol **library_symbolspp,
enum toplt type_of_plt, int is_weak) {
struct library_symbol *s;
+
+ debug(DEBUG_FUNCTION, "add_library_symbol()");
+
s = malloc(sizeof(struct library_symbol) + strlen(name) + 1);
if (s == NULL)
error(EXIT_FAILURE, errno, "add_library_symbol failed");
@@ -460,6 +465,8 @@ read_elf(Process *proc) {
struct library_symbol **lib_tail = NULL;
int exit_out = 0;
+ debug(DEBUG_FUNCTION, "read_elf(file=%s)", proc->filename);
+
elf_version(EV_CURRENT);
do_init_elf(lte, proc->filename);
diff --git a/ltrace.1 b/ltrace.1
index 04a1503..e24b16c 100644
--- a/ltrace.1
+++ b/ltrace.1
@@ -6,7 +6,7 @@ ltrace \- A library call tracer
.SH SYNOPSIS
.B ltrace
-.I "[-CdfhiLrStttV] [-a column] [-A maxelts] [-e expr] [-l filename] [-n nr] [-o filename] [-p pid] ... [-s strsize] [-u username] [-X extern] [-x extern] ... [--align=column] [--debug] [--demangle] [--help] [--indent=nr] [--library=filename] [--output=filename] [--version] [command [arg ...]]"
+.I "[-CfhiLrStttV] [-a column] [-A maxelts] [-d level] [-e expr] [-l filename] [-n nr] [-o filename] [-p pid] ... [-s strsize] [-u username] [-X extern] [-x extern] ... [--align=column] [--debug=level] [--demangle] [--help] [--indent=nr] [--library=filename] [--output=filename] [--version] [command [arg ...]]"
.SH DESCRIPTION
.B ltrace
@@ -36,11 +36,20 @@ Decode (demangle) low-level symbol names into user-level names.
Besides removing any initial underscore prefix used by the system,
this makes C++ function names readable.
.TP
-.I \-d, \-\-debug
-Increase the debugging level.
-Use more (ie.
-.I \-dd
-) for greater debugging information.
+.I \-d, \-\-debug level
+Show debugging output of
+.B ltrace
+itself.
+.I level
+must be a sum of some of the following numbers:
+.RS
+.TP
+.B 0x10
+DEBUG_EVENT. Shows every event received by a traced program
+.TP
+.B 0x20
+DEBUG_PROCESS. Shows every action carried out in a traced program
+.RE
.TP
.I \-e expr
A qualifying expression which modifies which events to trace.
diff --git a/options.c b/options.c
index e954eeb..042eb7a 100644
--- a/options.c
+++ b/options.c
@@ -93,9 +93,9 @@ usage(void) {
# endif
# endif
# if HAVE_GETOPT_LONG
- " -d, --debug print debugging info.\n"
+ " -d, --debug=LEVEL print debugging info.\n"
# else
- " -d print debugging info.\n"
+ " -d LEVEL print debugging info.\n"
# endif
" -e expr modify which events to trace.\n"
" -f trace children (fork() and clone()).\n"
@@ -226,18 +226,18 @@ process_options(int argc, char **argv) {
{"version", 0, 0, 'V'},
{0, 0, 0, 0}
};
- c = getopt_long(argc, argv, "+cdfhiLrStTV"
+ c = getopt_long(argc, argv, "+cfhiLrStTV"
# ifdef USE_DEMANGLE
"C"
# endif
- "a:A:e:F:l:n:o:p:s:u:x:X:", long_options,
+ "a:A:d:e:F:l:n:o:p:s:u:x:X:", long_options,
&option_index);
#else
- c = getopt(argc, argv, "+cdfhiLrStTV"
+ c = getopt(argc, argv, "+cfhiLrStTV"
# ifdef USE_DEMANGLE
"C"
# endif
- "a:A:e:F:l:n:o:p:s:u:x:X:");
+ "a:A:d:e:F:l:n:o:p:s:u:x:X:");
#endif
if (c == -1) {
break;
@@ -258,7 +258,7 @@ process_options(int argc, char **argv) {
break;
#endif
case 'd':
- options.debug++;
+ options.debug = strtoul(optarg,NULL,0);
break;
case 'e':
{
diff --git a/process_event.c b/process_event.c
index d15d8f7..94ecaac 100644
--- a/process_event.c
+++ b/process_event.c
@@ -40,11 +40,13 @@ static void callstack_pop(Process *proc);
/* TODO */
void * address_clone(void * addr) {
+ debug(DEBUG_FUNCTION, "address_clone(%p)", addr);
return addr;
}
void * breakpoint_clone(void * bp) {
Breakpoint * b;
+ debug(DEBUG_FUNCTION, "breakpoint_clone(%p)", bp);
b = malloc(sizeof(Breakpoint));
if (!b) {
perror("malloc()");
@@ -63,7 +65,11 @@ static Pending_New * pending_news = NULL;
static int
pending_new(pid_t pid) {
- Pending_New * p = pending_news;
+ Pending_New * p;
+
+ debug(DEBUG_FUNCTION, "pending_new(%d)", pid);
+
+ p = pending_news;
while (p) {
if (p->pid == pid) {
return 1;
@@ -75,7 +81,11 @@ pending_new(pid_t pid) {
static void
pending_new_insert(pid_t pid) {
- Pending_New * p = malloc(sizeof(Pending_New));
+ Pending_New * p;
+
+ debug(DEBUG_FUNCTION, "pending_new_insert(%d)", pid);
+
+ p = malloc(sizeof(Pending_New));
if (!p) {
perror("malloc()");
exit(1);
@@ -89,6 +99,8 @@ static void
pending_new_remove(pid_t pid) {
Pending_New *p, *pred;
+ debug(DEBUG_FUNCTION, "pending_new_remove(%d)", pid);
+
p = pending_news;
if (p->pid == pid) {
pending_news = p->next;
@@ -109,6 +121,8 @@ static void
process_clone(Event * event) {
Process *p;
+ debug(DEBUG_FUNCTION, "process_clone(pid=%d)", event->proc->pid);
+
p = malloc(sizeof(Process));
if (!p) {
perror("malloc()");
@@ -136,7 +150,11 @@ process_clone(Event * event) {
static void
process_new(Event * event) {
- Process * proc = pid2proc(event->e_un.newpid);
+ Process * proc;
+
+ debug(DEBUG_FUNCTION, "process_new(pid=%d)", event->e_un.newpid);
+
+ proc = pid2proc(event->e_un.newpid);
if (!proc) {
pending_new_insert(event->e_un.newpid);
} else {
@@ -163,6 +181,8 @@ shortsignal(Process *proc, int signum) {
sizeof signalent1 / sizeof signalent1[0]
};
+ debug(DEBUG_FUNCTION, "shortsignal(pid=%d, signum=%d)", proc->pid, signum);
+
if (proc->personality > sizeof signalents / sizeof signalents[0])
abort();
if (signum < 0 || signum >= nsignals[proc->personality]) {
@@ -186,6 +206,8 @@ sysname(Process *proc, int sysnum) {
sizeof syscalent1 / sizeof syscalent1[0]
};
+ debug(DEBUG_FUNCTION, "sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
+
if (proc->personality > sizeof syscalents / sizeof syscalents[0])
abort();
if (sysnum < 0 || sysnum >= nsyscals[proc->personality]) {
@@ -206,6 +228,8 @@ arch_sysname(Process *proc, int sysnum) {
};
int nsyscals = sizeof arch_syscalent / sizeof arch_syscalent[0];
+ debug(DEBUG_FUNCTION, "arch_sysname(pid=%d, sysnum=%d)", proc->pid, sysnum);
+
if (sysnum < 0 || sysnum >= nsyscals) {
sprintf(result, "ARCH_%d", sysnum);
return result;
@@ -218,6 +242,7 @@ arch_sysname(Process *proc, int sysnum) {
void
process_event(Event *event) {
+ debug(DEBUG_FUNCTION, "process_event(pid=%d, type=%d)", event->proc ? event->proc->pid : -1, event->type);
switch (event->type) {
case EVENT_NONE:
debug(1, "event: none");
@@ -286,6 +311,7 @@ process_event(Event *event) {
static void
process_signal(Event *event) {
+ debug(DEBUG_FUNCTION, "process_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
if (exiting && event->e_un.signum == SIGSTOP) {
pid_t pid = event->proc->pid;
disable_all_breakpoints(event->proc);
@@ -301,6 +327,7 @@ process_signal(Event *event) {
static void
process_exit(Event *event) {
+ debug(DEBUG_FUNCTION, "process_exit(pid=%d, status=%d)", event->proc->pid, event->e_un.ret_val);
output_line(event->proc, "+++ exited (status %d) +++",
event->e_un.ret_val);
remove_proc(event->proc);
@@ -308,6 +335,7 @@ process_exit(Event *event) {
static void
process_exit_signal(Event *event) {
+ debug(DEBUG_FUNCTION, "process_exit_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum);
output_line(event->proc, "+++ killed by %s +++",
shortsignal(event->proc, event->e_un.signum));
remove_proc(event->proc);
@@ -317,7 +345,7 @@ static void
remove_proc(Process *proc) {
Process *tmp, *tmp2;
- debug(1, "Removing pid %u\n", proc->pid);
+ debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid);
if (list_of_processes == proc) {
tmp = list_of_processes;
@@ -339,6 +367,7 @@ remove_proc(Process *proc) {
static void
process_syscall(Event *event) {
+ debug(DEBUG_FUNCTION, "process_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
if (options.syscalls) {
output_left(LT_TOF_SYSCALL, event->proc,
sysname(event->proc, event->e_un.sysnum));
@@ -352,12 +381,14 @@ process_syscall(Event *event) {
static void
process_exec(Event * event) {
+ debug(DEBUG_FUNCTION, "process_exec(pid=%d)", event->proc->pid);
output_line(event->proc, "--- exec() ---");
abort();
}
static void
process_arch_syscall(Event *event) {
+ debug(DEBUG_FUNCTION, "process_arch_syscall(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
if (options.syscalls) {
output_left(LT_TOF_SYSCALL, event->proc,
arch_sysname(event->proc, event->e_un.sysnum));
@@ -378,6 +409,7 @@ calc_time_spent(Process *proc) {
struct timeval diff;
struct callstack_element *elem;
+ debug(DEBUG_FUNCTION, "calc_time_spent(pid=%d)", proc->pid);
elem = &proc->callstack[proc->callstack_depth - 1];
gettimeofday(&tv, &tz);
@@ -394,6 +426,7 @@ calc_time_spent(Process *proc) {
static void
process_sysret(Event *event) {
+ debug(DEBUG_FUNCTION, "process_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
if (opt_T || options.summary) {
calc_time_spent(event->proc);
}
@@ -407,6 +440,7 @@ process_sysret(Event *event) {
static void
process_arch_sysret(Event *event) {
+ debug(DEBUG_FUNCTION, "process_arch_sysret(pid=%d, sysnum=%d)", event->proc->pid, event->e_un.sysnum);
if (opt_T || options.summary) {
calc_time_spent(event->proc);
}
@@ -423,6 +457,7 @@ process_breakpoint(Event *event) {
int i, j;
Breakpoint *sbp;
+ debug(DEBUG_FUNCTION, "process_breakpoint(pid=%d, addr=%p)", event->proc->pid, event->e_un.brk_addr);
debug(2, "event: breakpoint (%p)", event->e_un.brk_addr);
#ifdef __powerpc__
@@ -552,6 +587,7 @@ static void
callstack_push_syscall(Process *proc, int sysnum) {
struct callstack_element *elem;
+ debug(DEBUG_FUNCTION, "callstack_push_syscall(pid=%d, sysnum=%d)", proc->pid, sysnum);
/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
fprintf(stderr, "Error: call nesting too deep!\n");
@@ -574,6 +610,7 @@ static void
callstack_push_symfunc(Process *proc, struct library_symbol *sym) {
struct callstack_element *elem;
+ debug(DEBUG_FUNCTION, "callstack_push_symfunc(pid=%d, symbol=%s)", proc->pid, sym->name);
/* FIXME: not good -- should use dynamic allocation. 19990703 mortene. */
if (proc->callstack_depth == MAX_CALLDEPTH - 1) {
fprintf(stderr, "Error: call nesting too deep!\n");
@@ -601,6 +638,7 @@ callstack_pop(Process *proc) {
struct callstack_element *elem;
assert(proc->callstack_depth > 0);
+ debug(DEBUG_FUNCTION, "callstack_pop(pid=%d)", proc->pid);
elem = &proc->callstack[proc->callstack_depth - 1];
if (!elem->is_syscall && elem->return_addr) {
delete_breakpoint(proc, elem->return_addr);
diff --git a/sysdeps/linux-gnu/breakpoint.c b/sysdeps/linux-gnu/breakpoint.c
index 5a56bd3..64b70e4 100644
--- a/sysdeps/linux-gnu/breakpoint.c
+++ b/sysdeps/linux-gnu/breakpoint.c
@@ -15,6 +15,11 @@ static unsigned char break_insn[] = BREAKPOINT_VALUE;
extern void arch_enable_breakpoint(pid_t, Breakpoint *);
void
enable_breakpoint(pid_t pid, Breakpoint *sbp) {
+ if (sbp->libsym) {
+ debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
+ } else {
+ debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
+ }
arch_enable_breakpoint(pid, sbp);
}
#else
@@ -22,7 +27,11 @@ void
enable_breakpoint(pid_t pid, Breakpoint *sbp) {
unsigned int i, j;
- debug(1, "enable_breakpoint(%d,%p)", pid, sbp->addr);
+ if (sbp->libsym) {
+ debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
+ } else {
+ debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
+ }
for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
long a =
@@ -45,6 +54,11 @@ enable_breakpoint(pid_t pid, Breakpoint *sbp) {
extern void arch_disable_breakpoint(pid_t, const Breakpoint *sbp);
void
disable_breakpoint(pid_t pid, const Breakpoint *sbp) {
+ if (sbp->libsym) {
+ debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
+ } else {
+ debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
+ }
arch_disable_breakpoint(pid, sbp);
}
#else
@@ -52,7 +66,11 @@ void
disable_breakpoint(pid_t pid, const Breakpoint *sbp) {
unsigned int i, j;
- debug(2, "disable_breakpoint(%d,%p)", pid, sbp->addr);
+ if (sbp->libsym) {
+ debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
+ } else {
+ debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
+ }
for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
long a =
diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c
index dfb8284..6dedcc9 100644
--- a/sysdeps/linux-gnu/events.c
+++ b/sysdeps/linux-gnu/events.c
@@ -25,17 +25,18 @@ next_event(void) {
int tmp;
int stop_signal;
+ debug(DEBUG_FUNCTION, "next_event()");
if (!list_of_processes) {
- debug(1, "No more children");
+ debug(DEBUG_EVENT, "event: No more traced programs: exiting");
exit(0);
}
pid = wait(&status);
if (pid == -1) {
if (errno == ECHILD) {
- debug(1, "No more children");
+ debug(DEBUG_EVENT, "event: No more traced programs: exiting");
exit(0);
} else if (errno == EINTR) {
- debug(1, "wait received EINTR ?");
+ debug(DEBUG_EVENT, "event: none (wait received EINTR?)");
event.type = EVENT_NONE;
return &event;
}
@@ -45,6 +46,7 @@ next_event(void) {
event.proc = pid2proc(pid);
if (!event.proc) {
event.type = EVENT_NEW;
+ debug(DEBUG_EVENT, "event: NEW: pid=%d", pid);
return &event;
}
get_arch_dep(event.proc);
@@ -55,6 +57,7 @@ next_event(void) {
event.type = EVENT_NONE;
trace_set_options(event.proc, event.proc->pid);
continue_process(event.proc->pid);
+ debug(DEBUG_EVENT, "event: NONE: pid=%d (enabling breakpoints)", pid);
return &event;
}
if (opt_i) {
@@ -65,22 +68,27 @@ next_event(void) {
case 1:
event.type = EVENT_SYSCALL;
event.e_un.sysnum = tmp;
+ debug(DEBUG_EVENT, "event: SYSCALL: pid=%d, sysnum=%d", pid, tmp);
return &event;
case 2:
event.type = EVENT_SYSRET;
event.e_un.sysnum = tmp;
+ debug(DEBUG_EVENT, "event: SYSRET: pid=%d, sysnum=%d", pid, tmp);
return &event;
case 3:
event.type = EVENT_ARCH_SYSCALL;
event.e_un.sysnum = tmp;
+ debug(DEBUG_EVENT, "event: ARCH_SYSCALL: pid=%d, sysnum=%d", pid, tmp);
return &event;
case 4:
event.type = EVENT_ARCH_SYSRET;
event.e_un.sysnum = tmp;
+ debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp);
return &event;
case -1:
event.type = EVENT_NONE;
continue_process(event.proc->pid);
+ debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid);
return &event;
}
if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) {
@@ -88,24 +96,29 @@ next_event(void) {
ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data);
event.type = EVENT_CLONE;
event.e_un.newpid = data;
+ debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data);
return &event;
}
if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) {
event.type = EVENT_EXEC;
+ debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid);
return &event;
}
if (WIFEXITED(status)) {
event.type = EVENT_EXIT;
event.e_un.ret_val = WEXITSTATUS(status);
+ debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
return &event;
}
if (WIFSIGNALED(status)) {
event.type = EVENT_EXIT_SIGNAL;
event.e_un.signum = WTERMSIG(status);
+ debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
return &event;
}
if (!WIFSTOPPED(status)) {
event.type = EVENT_NONE;
+ debug(DEBUG_EVENT, "event: NONE: pid=%d (wait error?)", pid);
return &event;
}
@@ -133,6 +146,7 @@ next_event(void) {
&& stop_signal != SIGTRAP) {
event.type = EVENT_SIGNAL;
event.e_un.signum = stop_signal;
+ debug(DEBUG_EVENT, "event: SIGNAL: pid=%d, signum=%d", pid, stop_signal);
return &event;
}
@@ -151,6 +165,7 @@ next_event(void) {
breakpoints_init(event.proc);
event.proc->pid = saved_pid;
continue_process(event.proc->pid);
+ debug(DEBUG_EVENT, "event: NONE: pid=%d (was_exec; placed breakpoints)", pid);
return &event;
}
@@ -161,5 +176,6 @@ next_event(void) {
}
event.e_un.brk_addr =
event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
+ debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr);
return &event;
}
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
index cbda70b..65d561f 100644
--- a/sysdeps/linux-gnu/trace.c
+++ b/sysdeps/linux-gnu/trace.c
@@ -161,6 +161,7 @@ was_exec(Process *proc, int status) {
void
trace_me(void) {
+ debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid());
if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
perror("PTRACE_TRACEME");
exit(1);
@@ -169,6 +170,7 @@ trace_me(void) {
int
trace_pid(pid_t pid) {
+ debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid);
if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
return -1;
}
@@ -190,6 +192,8 @@ trace_set_options(Process *proc, pid_t pid) {
if (proc->tracesysgood & 0x80)
return;
+ debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid);
+
long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK |
PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE |
PTRACE_O_TRACEEXEC;
@@ -203,6 +207,7 @@ trace_set_options(Process *proc, pid_t pid) {
void
untrace_pid(pid_t pid) {
+ debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid);
ptrace(PTRACE_DETACH, pid, 1, 0);
}
@@ -210,6 +215,8 @@ void
continue_after_signal(pid_t pid, int signum) {
Process *proc;
+ debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum);
+
proc = pid2proc(pid);
if (proc && proc->breakpoint_being_enabled) {
#if defined __sparc__ || defined __ia64___
@@ -226,6 +233,8 @@ void
continue_process(pid_t pid) {
/* We always trace syscalls to control fork(), clone(), execve()... */
+ debug(DEBUG_PROCESS, "continue_process: pid=%d", pid);
+
ptrace(PTRACE_SYSCALL, pid, 0, 0);
}
@@ -237,6 +246,7 @@ continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) {
void
continue_after_breakpoint(Process *proc, Breakpoint *sbp) {
+ debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
if (sbp->enabled)
disable_breakpoint(proc->pid, sbp);
set_instruction_pointer(proc, sbp->addr);