diff options
author | Juan Cespedes <cespedes@coco.thehackers.org> | 2009-07-03 11:55:44 +0200 |
---|---|---|
committer | Juan Cespedes <cespedes@coco.thehackers.org> | 2009-07-03 11:55:44 +0200 |
commit | 61da33723c5fb09762e38bd39a26ee15d62ffebc (patch) | |
tree | ebfece2b8b14d918468073e55b628165702ad753 | |
parent | 8d1b92ba755f6d6229f5e230fc43d958b13836f8 (diff) | |
download | ltrace-61da33723c5fb09762e38bd39a26ee15d62ffebc.tar.gz |
Added different callback handlers for each event
-rw-r--r-- | handle_event.c | 148 | ||||
-rw-r--r-- | libltrace.c | 38 | ||||
-rw-r--r-- | ltrace.h | 34 | ||||
-rw-r--r-- | main.c | 22 | ||||
-rw-r--r-- | output.h | 1 | ||||
-rw-r--r-- | sysdeps/linux-gnu/breakpoint.c | 1 | ||||
-rw-r--r-- | sysdeps/linux-gnu/events.c | 2 | ||||
-rw-r--r-- | sysdeps/linux-gnu/ppc/regs.c | 8 |
8 files changed, 142 insertions, 112 deletions
diff --git a/handle_event.c b/handle_event.c index 18f64c6..48b9945 100644 --- a/handle_event.c +++ b/handle_event.c @@ -34,13 +34,88 @@ static void callstack_push_symfunc(Process *proc, struct library_symbol *sym); static void callstack_pop(Process *proc); +static char * shortsignal(Process *proc, int signum); +static char * sysname(Process *proc, int sysnum); +static char * arch_sysname(Process *proc, int sysnum); + +void +handle_event(Event *event) { + debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)", event->proc ? event->proc->pid : -1, event->type); + switch (event->type) { + case EVENT_NONE: + debug(1, "event: none"); + return; + case EVENT_SIGNAL: + debug(1, "event: signal (%s [%d])", + shortsignal(event->proc, event->e_un.signum), + event->e_un.signum); + handle_signal(event); + return; + case EVENT_EXIT: + debug(1, "event: exit (%d)", event->e_un.ret_val); + handle_exit(event); + return; + case EVENT_EXIT_SIGNAL: + debug(1, "event: exit signal (%s [%d])", + shortsignal(event->proc, event->e_un.signum), + event->e_un.signum); + handle_exit_signal(event); + return; + case EVENT_SYSCALL: + debug(1, "event: syscall (%s [%d])", + sysname(event->proc, event->e_un.sysnum), + event->e_un.sysnum); + handle_syscall(event); + return; + case EVENT_SYSRET: + debug(1, "event: sysret (%s [%d])", + sysname(event->proc, event->e_un.sysnum), + event->e_un.sysnum); + handle_sysret(event); + return; + case EVENT_ARCH_SYSCALL: + debug(1, "event: arch_syscall (%s [%d])", + arch_sysname(event->proc, event->e_un.sysnum), + event->e_un.sysnum); + handle_arch_syscall(event); + return; + case EVENT_ARCH_SYSRET: + debug(1, "event: arch_sysret (%s [%d])", + arch_sysname(event->proc, event->e_un.sysnum), + event->e_un.sysnum); + handle_arch_sysret(event); + return; + case EVENT_CLONE: + debug(1, "event: clone (%u)", event->e_un.newpid); + handle_clone(event); + return; + case EVENT_EXEC: + debug(1, "event: exec()"); + handle_exec(event); + return; + case EVENT_BREAKPOINT: + debug(1, "event: breakpoint"); + handle_breakpoint(event); + return; + case EVENT_NEW: + debug(1, "event: new process"); + handle_new(event); + return; + default: + fprintf(stderr, "Error! unknown event?\n"); + exit(1); + } +} + /* TODO */ -void * address_clone(void * addr) { +static void * +address_clone(void * addr) { debug(DEBUG_FUNCTION, "address_clone(%p)", addr); return addr; } -void * breakpoint_clone(void * bp) { +static void * +breakpoint_clone(void * bp) { Breakpoint * b; debug(DEBUG_FUNCTION, "breakpoint_clone(%p)", bp); b = malloc(sizeof(Breakpoint)); @@ -247,75 +322,6 @@ arch_sysname(Process *proc, int sysnum) { } } -void -handle_event(Event *event) { - debug(DEBUG_FUNCTION, "handle_event(pid=%d, type=%d)", event->proc ? event->proc->pid : -1, event->type); - switch (event->type) { - case EVENT_NONE: - debug(1, "event: none"); - return; - case EVENT_SIGNAL: - debug(1, "event: signal (%s [%d])", - shortsignal(event->proc, event->e_un.signum), - event->e_un.signum); - handle_signal(event); - return; - case EVENT_EXIT: - debug(1, "event: exit (%d)", event->e_un.ret_val); - handle_exit(event); - return; - case EVENT_EXIT_SIGNAL: - debug(1, "event: exit signal (%s [%d])", - shortsignal(event->proc, event->e_un.signum), - event->e_un.signum); - handle_exit_signal(event); - return; - case EVENT_SYSCALL: - debug(1, "event: syscall (%s [%d])", - sysname(event->proc, event->e_un.sysnum), - event->e_un.sysnum); - handle_syscall(event); - return; - case EVENT_SYSRET: - debug(1, "event: sysret (%s [%d])", - sysname(event->proc, event->e_un.sysnum), - event->e_un.sysnum); - handle_sysret(event); - return; - case EVENT_ARCH_SYSCALL: - debug(1, "event: arch_syscall (%s [%d])", - arch_sysname(event->proc, event->e_un.sysnum), - event->e_un.sysnum); - handle_arch_syscall(event); - return; - case EVENT_ARCH_SYSRET: - debug(1, "event: arch_sysret (%s [%d])", - arch_sysname(event->proc, event->e_un.sysnum), - event->e_un.sysnum); - handle_arch_sysret(event); - return; - case EVENT_CLONE: - debug(1, "event: clone (%u)", event->e_un.newpid); - handle_clone(event); - return; - case EVENT_EXEC: - debug(1, "event: exec()"); - handle_exec(event); - return; - case EVENT_BREAKPOINT: - debug(1, "event: breakpoint"); - handle_breakpoint(event); - return; - case EVENT_NEW: - debug(1, "event: new process"); - handle_new(event); - return; - default: - fprintf(stderr, "Error! unknown event?\n"); - exit(1); - } -} - static void handle_signal(Event *event) { debug(DEBUG_FUNCTION, "handle_signal(pid=%d, signum=%d)", event->proc->pid, event->e_un.signum); diff --git a/libltrace.c b/libltrace.c index 731ead2..6827257 100644 --- a/libltrace.c +++ b/libltrace.c @@ -119,34 +119,38 @@ ltrace_init(int argc, char **argv) { } } -static int num_ltrace_callbacks = 0; -static void (**ltrace_callbacks)(Event *) = NULL; +static int num_ltrace_callbacks[EVENT_MAX]; +static callback_func * ltrace_callbacks[EVENT_MAX]; void -ltrace_add_callback(void (*func)(Event *)) { - ltrace_callbacks = realloc(ltrace_callbacks, (num_ltrace_callbacks+1)*sizeof(*ltrace_callbacks)); - ltrace_callbacks[num_ltrace_callbacks++] = func; - - { - int i; +ltrace_add_callback(callback_func func, Event_type type) { + ltrace_callbacks[type] = realloc(ltrace_callbacks[type], (num_ltrace_callbacks[type]+1)*sizeof(callback_func)); + ltrace_callbacks[type][num_ltrace_callbacks[type]++] = func; +} - printf("*** Added callback\n"); - printf("\tThere are %d callbacks:\n", num_ltrace_callbacks); - for (i=0; i<num_ltrace_callbacks; i++) { - printf("\t\t%10p\n", ltrace_callbacks[i]); - } +static void +dispatch_callbacks(Event * ev) { + int i; + /* Ignoring case 1: signal into a dying tracer */ + if (ev->type==EVENT_SIGNAL && + exiting && ev->e_un.signum == SIGSTOP) { + return; + } + /* Ignoring case 2: process being born before a clone event */ + if (ev->proc && ev->proc->state == STATE_IGNORED) { + return; + } + for (i=0; i<num_ltrace_callbacks[ev->type]; i++) { + ltrace_callbacks[ev->type][i](ev); } } void ltrace_main(void) { - int i; Event * ev; while (1) { ev = next_event(); - for (i=0; i<num_ltrace_callbacks; i++) { - ltrace_callbacks[i](ev); - } + dispatch_callbacks(ev); handle_event(ev); } } @@ -1,9 +1,6 @@ -typedef struct Process Process; -typedef struct Event Event; -struct Event { - Process *proc; - enum { - EVENT_NONE, +typedef enum Event_type Event_type; +enum Event_type { + EVENT_NONE=0, EVENT_SIGNAL, EVENT_EXIT, EVENT_EXIT_SIGNAL, @@ -14,17 +11,26 @@ struct Event { EVENT_CLONE, EVENT_EXEC, EVENT_BREAKPOINT, - EVENT_NEW /* in this case, proc is NULL */ - } type; + EVENT_NEW, /* in this case, proc is NULL */ + EVENT_MAX +}; + +typedef struct Process Process; +typedef struct Event Event; +struct Event { + Process * proc; + Event_type type; union { - int ret_val; /* EVENT_EXIT */ - int signum; /* EVENT_SIGNAL, EVENT_EXIT_SIGNAL */ - int sysnum; /* EVENT_SYSCALL, EVENT_SYSRET */ - void *brk_addr; /* EVENT_BREAKPOINT */ - int newpid; /* EVENT_CLONE, EVENT_NEW */ + int ret_val; /* EVENT_EXIT */ + int signum; /* EVENT_SIGNAL, EVENT_EXIT_SIGNAL */ + int sysnum; /* EVENT_SYSCALL, EVENT_SYSRET */ + void * brk_addr; /* EVENT_BREAKPOINT */ + int newpid; /* EVENT_CLONE, EVENT_NEW */ } e_un; }; +typedef void (*callback_func) (Event *); + extern void ltrace_init(int argc, char **argv); -extern void ltrace_add_callback(void (*func)(Event *)); +extern void ltrace_add_callback(callback_func f, Event_type type); extern void ltrace_main(void); @@ -4,18 +4,34 @@ #include "ltrace.h" /* +static int count_call =0; +static int count_ret =0; + +static void +callback_call(Event * ev) { + count_call ++; +} +static void +callback_ret(Event * ev) { + count_ret ++; +} + static void -callback(Event * ev) { - printf("\n\tcallback(ev->type=%d)\n", ev->type); +endcallback(Event *ev) { + printf("%d calls\n%d rets\n",count_call, count_ret); } */ int main(int argc, char *argv[]) { ltrace_init(argc, argv); + /* - ltrace_add_callback(callback); + ltrace_add_callback(callback_call, EVENT_SYSCALL); + ltrace_add_callback(callback_ret, EVENT_SYSRET); + ltrace_add_callback(endcallback, EVENT_EXIT); */ + ltrace_main(); return 0; } @@ -1,4 +1,3 @@ void output_line(Process *proc, char *fmt, ...); - void output_left(enum tof type, Process *proc, char *function_name); void output_right(enum tof type, Process *proc, char *function_name); diff --git a/sysdeps/linux-gnu/breakpoint.c b/sysdeps/linux-gnu/breakpoint.c index df6e52c..ebd8d8a 100644 --- a/sysdeps/linux-gnu/breakpoint.c +++ b/sysdeps/linux-gnu/breakpoint.c @@ -4,6 +4,7 @@ #include <sys/ptrace.h> #include <string.h> + #include "common.h" static unsigned char break_insn[] = BREAKPOINT_VALUE; diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c index 4ad6f88..3e681a8 100644 --- a/sysdeps/linux-gnu/events.c +++ b/sysdeps/linux-gnu/events.c @@ -60,7 +60,7 @@ next_event(void) { } if (opt_i) { event.proc->instruction_pointer = - get_instruction_pointer(event.proc); + get_instruction_pointer(event.proc); } switch (syscall_p(event.proc, status, &tmp)) { case 1: diff --git a/sysdeps/linux-gnu/ppc/regs.c b/sysdeps/linux-gnu/ppc/regs.c index 714d57f..67df5c9 100644 --- a/sysdeps/linux-gnu/ppc/regs.c +++ b/sysdeps/linux-gnu/ppc/regs.c @@ -18,19 +18,17 @@ void * get_instruction_pointer(Process *proc) { - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long) * PT_NIP, - 0); + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_NIP, 0); } void set_instruction_pointer(Process *proc, void *addr) { - ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long) * PT_NIP, addr); + ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long)*PT_NIP, addr); } void * get_stack_pointer(Process *proc) { - return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long) * PT_R1, - 0); + return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, sizeof(long)*PT_R1, 0); } void * |