From 3e2980613c38f8e9babbb86bf35969ad3b0999ef Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 23 May 2016 10:27:47 +0200 Subject: [PATCH] more accurate single step, prelink fixes, cleanup --- backend.h | 2 +- breakpoint.c | 12 ++++++++++-- breakpoint.h | 2 ++ library.c | 2 +- library.h | 3 --- main.c | 8 ++++---- sysdeps/linux-gnu/os.c | 9 ++++----- sysdeps/linux-gnu/proc.c | 2 +- sysdeps/linux-gnu/trace.c | 22 +++++++++++----------- task.c | 4 ++-- task.h | 2 +- 11 files changed, 37 insertions(+), 31 deletions(-) diff --git a/backend.h b/backend.h index 71e4b7c..905d122 100644 --- a/backend.h +++ b/backend.h @@ -177,7 +177,7 @@ void wait_event_wakeup(void); int is_64bit(struct mt_elf *mte); /* change user id of a running process */ -void change_uid(const char *command); +void change_uid(void); #endif diff --git a/breakpoint.c b/breakpoint.c index 43588e9..a9513dc 100644 --- a/breakpoint.c +++ b/breakpoint.c @@ -73,6 +73,9 @@ static void enable_sw_breakpoint(struct task *task, struct breakpoint *bp) debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr); copy_from_to_proc(task, bp->addr, break_insn, bp->orig_value, BREAKPOINT_LENGTH); + + bp->break_insn = !memcmp(break_insn, bp->orig_value, BREAKPOINT_LENGTH); + bp->was_hw = 0; } static void disable_sw_breakpoint(struct task *task, const struct breakpoint *bp) @@ -230,6 +233,7 @@ void reorder_hw_bp(struct task *task) bp->hw_bp_slot = i; bp->hw = 1; + bp->was_hw = 1; each_task(leader, enable_hw_bp_cb, bp); @@ -260,6 +264,7 @@ static int insert_hw_bp_slot(struct task *task, struct breakpoint *bp) bp->enabled = 1; bp->hw_bp_slot = i; bp->hw = 1; + bp->was_hw = 1; each_task(leader, enable_hw_bp_cb, bp); @@ -357,6 +362,7 @@ struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struc bp->enabled = 0; bp->locked = 0; bp->deleted = 0; + bp->break_insn = 0; bp->ext = ext; bp->refcnt = 1; bp->count = 0; @@ -383,6 +389,7 @@ struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struc case BP_SW: memset(bp->orig_value, 0, sizeof(bp->orig_value)); bp->hw = 0; + bp->was_hw = 0; } if (dict_add(leader->breakpoints, (unsigned long)addr, bp) < 0) { @@ -505,12 +512,13 @@ void breakpoint_delete(struct task *task, struct breakpoint *bp) if (unlikely(options.verbose > 1 && bp->libsym)) { fprintf(stderr, - "delete %s breakpoint %s:%s [%#lx] count=%u\n", + "delete %s breakpoint %s:%s [%#lx] count=%u was_hw=%u\n", bp->type == BP_SW ? "sw" : "hw", bp->libsym->libref->filename, bp->libsym->func->demangled_name, bp->addr, - bp->count); + bp->count, + bp->was_hw); } bp->deleted = 1; diff --git a/breakpoint.h b/breakpoint.h index 6a2bd0a..b391c4a 100644 --- a/breakpoint.h +++ b/breakpoint.h @@ -51,6 +51,8 @@ struct breakpoint { unsigned int locked:1; unsigned int deleted:1; unsigned int hw:1; + unsigned int was_hw:1; + unsigned int break_insn:1; union { unsigned char orig_value[BREAKPOINT_LENGTH]; #if HW_BREAKPOINTS > 0 diff --git a/library.c b/library.c index 0c34d34..2e20aef 100644 --- a/library.c +++ b/library.c @@ -113,7 +113,7 @@ struct library_symbol *library_symbol_new(struct libref *libref, arch_addr_t add return libsym; } -void library_delete(struct task *task, struct library *lib) +static void library_delete(struct task *task, struct library *lib) { if (lib == NULL) return; diff --git a/library.h b/library.h index 3d2e667..d3b8e50 100644 --- a/library.h +++ b/library.h @@ -101,9 +101,6 @@ struct library { /* create a new symbol */ struct library_symbol *library_symbol_new(struct libref *libref, arch_addr_t addr, const struct function *func); -/* Delete library. Symbols are destroyed and freed. */ -void library_delete(struct task *leader, struct library *lib); - /* Add a library to the list of the thread leader libraries. */ struct library *library_add(struct task *leader, struct libref *libref); diff --git a/main.c b/main.c index 96c8bd3..c940c13 100644 --- a/main.c +++ b/main.c @@ -104,12 +104,12 @@ static void mtrace_exit(void) each_pid(remove_task); } -static void mtrace_init(char **cmd) +static void mtrace_init(char **cmd_args) { struct opt_p_t *opt_p_tmp; if (options.command) { - struct task *task = task_create(options.command, cmd); + struct task *task = task_create(cmd_args); if (!task) exit(EXIT_FAILURE); @@ -138,7 +138,7 @@ static void mtrace_main(void) int main(int argc, char *argv[]) { - char **cmd = process_options(argc, argv); + char **cmd_args = process_options(argc, argv); init_pid_hash(); @@ -186,7 +186,7 @@ int main(int argc, char *argv[]) if (os_init()) exit(EXIT_FAILURE); - mtrace_init(cmd); + mtrace_init(cmd_args); mtrace_main(); mtrace_exit(); diff --git a/sysdeps/linux-gnu/os.c b/sysdeps/linux-gnu/os.c index 5d68bb7..3deaed5 100644 --- a/sysdeps/linux-gnu/os.c +++ b/sysdeps/linux-gnu/os.c @@ -315,7 +315,7 @@ finish: return blocks; } -void change_uid(const char *command) +void change_uid(void) { uid_t run_uid, run_euid; gid_t run_gid, run_egid; @@ -348,12 +348,11 @@ void change_uid(const char *command) run_egid = run_gid; if (!stat(options.command, &statbuf)) { - if (statbuf.st_mode & S_ISUID) { + if (statbuf.st_mode & S_ISUID) run_euid = statbuf.st_uid; - } - if (statbuf.st_mode & S_ISGID) { + + if (statbuf.st_mode & S_ISGID) run_egid = statbuf.st_gid; - } } if (setregid(run_gid, run_egid) < 0) { perror("mtrace-ng: setregid"); diff --git a/sysdeps/linux-gnu/proc.c b/sysdeps/linux-gnu/proc.c index 8c09312..6578a67 100644 --- a/sysdeps/linux-gnu/proc.c +++ b/sysdeps/linux-gnu/proc.c @@ -462,7 +462,7 @@ static void linkmap_del(struct task *task, struct lt_r_debug_64 *dbg) addr = ARCH_ADDR_T(rlm.l_next); - lib = library_find_with_key(&tmp_list, ARCH_ADDR_T(rlm.l_addr)); + lib = library_find_with_key(&tmp_list, ARCH_ADDR_T(rlm.l_ld)); if (lib) list_move_tail(&lib->list, &task->libraries_list); } diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c index 97eb2e2..4947dcb 100644 --- a/sysdeps/linux-gnu/trace.c +++ b/sysdeps/linux-gnu/trace.c @@ -466,7 +466,6 @@ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task), s int status; int stop_signal; unsigned long ip; - int ret; for(;;) { if (unlikely(singlestep(task) == -1)) @@ -489,26 +488,27 @@ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task), s } if (ip != bp->addr) { - ret = 0; - - if (likely(stop_signal == SIGTRAP)) - return ret; + if (likely(stop_signal == SIGTRAP)) { + if (bp->break_insn) { + queue_event(task); + return 1; + } + return 0; + } } - else - ret = 1; if (likely(!stop_signal)) { queue_event(task); - return ret; + return 1; } if (fix_signal(task, stop_signal) > 0) { queue_event(task); - return ret; + return 1; } - if (!ret) - return ret; + if (ip != bp->addr) + return 0; } } diff --git a/task.c b/task.c index 3a9377a..642bda6 100644 --- a/task.c +++ b/task.c @@ -305,7 +305,7 @@ fail: return -1; } -struct task *task_create(const char *command, char **argv) +struct task *task_create(char **argv) { struct task *task; pid_t pid; @@ -319,7 +319,7 @@ struct task *task_create(const char *command, char **argv) } if (!pid) { /* child */ - change_uid(options.command); + change_uid(); trace_me(); execvp(options.command, argv); fprintf(stderr, "Can't execute `%s': %s\n", options.command, strerror(errno)); diff --git a/task.h b/task.h index 3b86ce4..cf8ece4 100644 --- a/task.h +++ b/task.h @@ -119,7 +119,7 @@ int process_exec(struct task *task); struct task *task_new(pid_t pid); -struct task *task_create(const char *command, char **argv); +struct task *task_create(char **argv); void open_pid(pid_t pid);