From 87f73f3220469d7dca9beb3804daf195395c5911 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 16 Apr 2018 09:10:19 +0200 Subject: [PATCH] fixes --- CMakeLists.txt | 2 +- client/process.c | 44 ++++++++++++++++++++++----------------- debug.h | 12 +++++------ dwarf.c | 8 +++---- library.h | 1 + mtelf.c | 17 ++++++++------- report.c | 13 ++++++++---- sysdeps/linux-gnu/trace.c | 34 +++++++++++++++--------------- task.c | 1 + task.h | 1 + 10 files changed, 73 insertions(+), 60 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e11023d..2a2e493 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ include_directories( "${PROJECT_SOURCE_DIR}/sysdeps" ) -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -D__FORITFY_SOURCE=2 -rdynamic") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -D__FORITFY_SOURCE=2 -rdynamic -DDEBUG") set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined") set(CMAKE_C_FLAGS_LTO "${CMAKE_C_FLAGS_RELEASE} -flto") diff --git a/client/process.c b/client/process.c index 1730be8..6b82895 100644 --- a/client/process.c +++ b/client/process.c @@ -92,8 +92,7 @@ struct realloc_entry { unsigned long addr; unsigned long size; unsigned long flags; - struct rb_stack *stack; - enum mt_operation operation; + struct rb_stack *stack_node; }; struct regex_list { @@ -815,8 +814,8 @@ static void process_init(struct process *process, unsigned int swap_endian, unsi static void realloc_del(struct realloc_entry *re) { - if (re->stack) - stack_put(re->stack); + if (re->stack_node) + stack_put(re->stack_node); list_del(&re->list); free(re); } @@ -1390,6 +1389,22 @@ static int is_sane(struct rb_block *block, enum mt_operation op) return 1; } +static void realloc_add(struct process *process, unsigned long pid, unsigned long addr, unsigned long size, unsigned long flags, struct rb_stack *stack_node) +{ + struct realloc_entry *re = malloc(sizeof(*re)); + + re->addr = addr; + re->size = size; + re->flags = flags; + re->pid = pid; + re->stack_node = stack_node; + + if (re->stack_node) + stack_get(re->stack_node); + + list_add_tail(&re->list, &process->realloc_list); +} + void process_free(struct process *process, struct mt_msg *mt_msg, void *payload) { struct rb_block *block = NULL; @@ -1444,20 +1459,8 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload) } } - if (mt_msg->operation == MT_REALLOC_ENTER) { - struct realloc_entry *re = malloc(sizeof(*re)); - - re->addr = block->addr; - re->size = block->size; - re->flags = block->flags; - re->operation = block->stack_node->stack->operation; - re->pid = pid; - re->stack = block->stack_node; - - stack_get(re->stack); - - list_add_tail(&re->list, &process->realloc_list); - } + if (mt_msg->operation == MT_REALLOC_ENTER) + realloc_add(process, pid, block->addr, block->size, block->flags, block->stack_node); process_rb_delete_block(process, block); } @@ -1475,6 +1478,9 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload) stack->tsc = process->tsc++; } } + + if (mt_msg->operation == MT_REALLOC_ENTER) + realloc_add(process, pid, 0, 0, 0, NULL); } } @@ -1509,7 +1515,7 @@ void process_realloc_done(struct process *process, struct mt_msg *mt_msg, void * if (re->pid == pid) { if (!ptr && re->addr) - process_rb_insert_block(process, re->addr, re->size, re->stack, re->flags, re->operation); + process_rb_insert_block(process, re->addr, re->size, re->stack_node, re->flags, re->stack_node->stack->operation); realloc_del(re); return; diff --git a/debug.h b/debug.h index 8cce8ce..84f5b48 100644 --- a/debug.h +++ b/debug.h @@ -25,16 +25,14 @@ #include "config.h" -#define DEBUG - /* debug levels: */ enum { - DEBUG_EVENT_HANDLER = 01, - DEBUG_DWARF = 02, - DEBUG_EVENT = 010, - DEBUG_PROCESS = 020, - DEBUG_FUNCTION = 040 + DEBUG_TRACE = 1, + DEBUG_DWARF = 2, + DEBUG_EVENT = 4, + DEBUG_PROCESS = 8, + DEBUG_FUNCTION = 16, }; #ifdef DEBUG diff --git a/dwarf.c b/dwarf.c index 52504a6..cd80675 100644 --- a/dwarf.c +++ b/dwarf.c @@ -483,8 +483,8 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local, if (*addr < ARCH_ADDR_T(libref->mmap_addr)) fatal("invalid access mem: addr %#lx < %p", *addr, libref->mmap_addr); - if (*addr >= ARCH_ADDR_T(libref->mmap_addr + libref->txt_size)) - fatal("invalid access mem: addr %#lx >= %p", *addr, libref->mmap_addr + libref->txt_size); + if (*addr >= ARCH_ADDR_T(libref->mmap_addr + libref->mmap_size)) + fatal("invalid access mem: addr %#lx >= %p", *addr, libref->mmap_addr + libref->mmap_size); #endif memset(&tmp, 0, sizeof(tmp)); @@ -687,7 +687,7 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf return ret; if (version != DWARF_CIE_VERSION && version != DWARF_CIE_VERSION_GCC) { - debug(DEBUG_DWARF, "Got CIE version %u, expected version " STR(DWARF_CIE_VERSION) "or" STR(DWARF_CIE_VERSION_GCC), version); + debug(DEBUG_DWARF, "Got CIE version %u, expected version " STR(DWARF_CIE_VERSION) " or " STR(DWARF_CIE_VERSION_GCC), version); return -DWARF_EBADVERSION; } @@ -937,7 +937,7 @@ static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip return -DWARF_ENOINFO; } - fde_addr = libref->mmap_addr - libref->mmap_offset + e->fde_offset + libref->eh_frame_hdr; + fde_addr = libref->mmap_addr - (libref->txt_offset - libref->mmap_offset) + e->fde_offset + libref->eh_frame_hdr; if (unlikely((ret = dwarf_extract_cfi_from_fde(as, fde_addr)) < 0)) return ret; diff --git a/library.h b/library.h index f38173b..682db3b 100644 --- a/library.h +++ b/library.h @@ -61,6 +61,7 @@ struct libref { /* executable segment */ unsigned long txt_vaddr; unsigned long txt_size; + unsigned long txt_offset; /* loadable segments */ unsigned int loadsegs; diff --git a/mtelf.c b/mtelf.c index 434f46c..c5e8b6a 100644 --- a/mtelf.c +++ b/mtelf.c @@ -223,7 +223,7 @@ static inline int elf_map_image(struct mt_elf *mte, void **mmap_addr) { void *addr; - addr = mmap(NULL, mte->txt_hdr.p_filesz, PROT_READ, MAP_PRIVATE, mte->fd, mte->txt_hdr.p_offset); + addr = mmap(NULL, mte->loadsize, PROT_READ, MAP_PRIVATE, mte->fd, mte->loadbase); if (addr == MAP_FAILED) { fprintf(stderr, "mmap failed\n"); return -1; @@ -240,10 +240,11 @@ static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *li return -1; libref->entry = ARCH_ADDR_T(mte->entry_addr); - libref->mmap_offset = mte->txt_hdr.p_offset; + libref->mmap_offset = mte->loadbase; libref->mmap_size = mte->loadsize; libref->txt_vaddr = mte->txt_hdr.p_vaddr + mte->bias; libref->txt_size = mte->txt_hdr.p_filesz; + libref->txt_offset = mte->txt_hdr.p_offset; libref->bias = mte->bias; libref->eh_frame_hdr = mte->eh_hdr.p_offset; libref->pltgot = mte->pltgot; @@ -262,7 +263,7 @@ static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *li #endif if (mte->eh_hdr.p_filesz && mte->dyn) { - if (dwarf_get_unwind_table(task, libref, (struct dwarf_eh_frame_hdr *)(libref->mmap_addr - libref->mmap_offset + mte->eh_hdr.p_offset)) < 0) + if (dwarf_get_unwind_table(task, libref, (struct dwarf_eh_frame_hdr *)(libref->mmap_addr - libref->txt_offset + mte->eh_hdr.p_offset)) < 0) return -1; } @@ -310,8 +311,8 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename, mte->loadseg[mte->loadsegs++] = phdr; - if (loadbase > phdr.p_vaddr) - loadbase = phdr.p_vaddr; + if (loadbase > phdr.p_offset) + loadbase = phdr.p_offset; if (loadsize < phdr.p_offset + phdr.p_filesz) loadsize = phdr.p_offset + phdr.p_filesz; @@ -344,12 +345,12 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename, return -1; } -fprintf(stderr, "%s:%d %s loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, filename, loadbase, loadsize); +//fprintf(stderr, "%s:%d %s loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, filename, loadbase, loadsize); mte->loadbase = loadbase & ~PAGEALIGN; mte->loadsize = (loadsize + (loadbase - mte->loadbase) + PAGEALIGN) & ~PAGEALIGN; -fprintf(stderr, "%s:%d loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, mte->loadbase, mte->loadsize); +//fprintf(stderr, "%s:%d loadbase:%#lx loadsize:%#lx\n", __func__, __LINE__, mte->loadbase, mte->loadsize); - debug(DEBUG_FUNCTION, "filename=`%s' mmap_offset=%#llx addr=%#llx size=%#llx", + debug(DEBUG_FUNCTION, "filename=`%s' text offset=%#llx addr=%#llx size=%#llx", filename, (unsigned long long)mte->txt_hdr.p_offset, (unsigned long long)mte->txt_hdr.p_vaddr + bias, diff --git a/report.c b/report.c index baad854..cf3be27 100644 --- a/report.c +++ b/report.c @@ -189,16 +189,17 @@ static void report_delete_array(struct task *task, struct library_symbol *libsym static void _report_realloc(struct task *task, struct library_symbol *libsym) { - unsigned long addr = fetch_param(task, 0); unsigned long size = fetch_param(task, 1); unsigned long ret = fetch_retval(task); - if (!addr) { + if (!task->in_realloc) { if (ret) report_alloc(task, MT_REALLOC, ret, size, options.bt_depth, libsym); return; } + task->in_realloc = 0; + if (ret) report_alloc(task, MT_REALLOC, ret, size, options.bt_depth, libsym); @@ -224,8 +225,12 @@ static void report_realloc(struct task *task, struct library_symbol *libsym) { unsigned long addr = fetch_param(task, 0); - if (addr) + assert(!task->in_realloc); + + if (addr) { + task->in_realloc = 1; report_alloc(task, MT_REALLOC_ENTER, addr, task->pid, options.sanity ? options.bt_depth : 0, libsym); + } } static void _report_calloc(struct task *task, struct library_symbol *libsym) @@ -440,7 +445,7 @@ int _report_map(struct task *task, struct library *lib, enum mt_operation op) struct mt_map_payload *payload = alloca(sizeof(struct mt_map_payload) + len); payload->addr = libref->txt_vaddr; - payload->offset = libref->mmap_offset; + payload->offset = libref->txt_offset; payload->size = libref->txt_size; payload->bias = libref->bias; diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c index 68490f4..92de0c9 100644 --- a/sysdeps/linux-gnu/trace.c +++ b/sysdeps/linux-gnu/trace.c @@ -127,10 +127,10 @@ static int child_event(struct task *task, enum event_type ev) { unsigned long data = 0; - debug(DEBUG_EVENT, "child event %d pid=%d, newpid=%d", ev, task->pid, task->event.e_un.newpid); + debug(DEBUG_TRACE, "child event %d pid=%d, newpid=%d", ev, task->pid, task->event.e_un.newpid); if (unlikely(ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1)) - debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno)); + debug(DEBUG_TRACE, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno)); int pid = data; @@ -161,7 +161,7 @@ static int _process_event(struct task *task, int status) assert(task->event.type == EVENT_NONE); if (WIFSIGNALED(status)) { - debug(DEBUG_EVENT, "EXIT_SIGNAL: pid=%d, signum=%d", task->pid, task->event.e_un.signum); + debug(DEBUG_TRACE, "EXIT_SIGNAL: pid=%d, signum=%d", task->pid, task->event.e_un.signum); task->event.type = EVENT_EXIT_SIGNAL; task->event.e_un.signum = WTERMSIG(status); @@ -169,7 +169,7 @@ static int _process_event(struct task *task, int status) } if (WIFEXITED(status)) { - debug(DEBUG_EVENT, "EXIT: pid=%d, status=%d", task->pid, task->event.e_un.ret_val); + debug(DEBUG_TRACE, "EXIT: pid=%d, status=%d", task->pid, task->event.e_un.ret_val); task->event.type = EVENT_EXIT; task->event.e_un.ret_val = WEXITSTATUS(status); @@ -201,26 +201,26 @@ static int _process_event(struct task *task, int status) case 0: break; case PTRACE_EVENT_VFORK: - debug(DEBUG_EVENT, "VFORK: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid); + debug(DEBUG_TRACE, "VFORK: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid); return child_event(task, EVENT_VFORK); case PTRACE_EVENT_FORK: - debug(DEBUG_EVENT, "FORK: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid); + debug(DEBUG_TRACE, "FORK: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid); return child_event(task, EVENT_FORK); case PTRACE_EVENT_CLONE: - debug(DEBUG_EVENT, "CLONE: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid); + debug(DEBUG_TRACE, "CLONE: pid=%d, newpid=%d", task->pid, task->event.e_un.newpid); return child_event(task, EVENT_CLONE); case PTRACE_EVENT_EXEC: task->event.type = EVENT_EXEC; - debug(DEBUG_EVENT, "EXEC: pid=%d", task->pid); + debug(DEBUG_TRACE, "EXEC: pid=%d", task->pid); return 0; case PTRACE_EVENT_EXIT: { unsigned long data = 0; - debug(DEBUG_EVENT, "ABOUT_EXIT: pid=%d", task->pid); + debug(DEBUG_TRACE, "ABOUT_EXIT: pid=%d", task->pid); if (unlikely(ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1)) - debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno)); + debug(DEBUG_TRACE, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno)); task->event.e_un.ret_val = WEXITSTATUS(data); task->event.type = EVENT_ABOUT_EXIT; @@ -253,7 +253,7 @@ static int _process_event(struct task *task, int status) task->event.type = EVENT_SIGNAL; task->event.e_un.signum = sig; - debug(DEBUG_EVENT, "SIGNAL: pid=%d, signum=%d", task->pid, sig); + debug(DEBUG_TRACE, "SIGNAL: pid=%d, signum=%d", task->pid, sig); return sig; } @@ -334,7 +334,7 @@ static struct task * process_event(struct task *task, int status) task->event.type = EVENT_BREAKPOINT; task->event.e_un.breakpoint = breakpoint_get(bp); - debug(DEBUG_EVENT, "BREAKPOINT: pid=%d, addr=%#lx", task->pid, task->event.e_un.breakpoint->addr); + debug(DEBUG_TRACE, "BREAKPOINT: pid=%d, addr=%#lx", task->pid, task->event.e_un.breakpoint->addr); return task; } @@ -467,7 +467,7 @@ static void do_stop_cb(struct task *task, void *data) if (task->stopped) return; - debug(DEBUG_EVENT, "task stop pid=%d", task->pid); + debug(DEBUG_TRACE, "task stop pid=%d", task->pid); task_kill(task, SIGSTOP); } @@ -478,7 +478,7 @@ void stop_threads(struct task *task) assert(task->leader != NULL); - debug(DEBUG_EVENT, "stop threads pid=%d", task->pid); + debug(DEBUG_TRACE, "stop threads pid=%d", task->pid); if (leader->threads != leader->threads_stopped) { struct timespec start; @@ -581,7 +581,7 @@ struct task *wait_event(void) pid = wait_task(NULL, &status); if (unlikely(pid == -1)) { if (errno == ECHILD) - debug(DEBUG_EVENT, "No more traced programs"); + debug(DEBUG_TRACE, "No more traced programs"); return NULL; } @@ -631,10 +631,10 @@ struct task *wait_event(void) if (unlikely(options.verbose)) fprintf(stderr, "!!!%s: exit event for stopped pid=%d\n", __func__, task->pid); - debug(DEBUG_EVENT, "ABOUT_EXIT: pid=%d", task->pid); + debug(DEBUG_TRACE, "ABOUT_EXIT: pid=%d", task->pid); if (unlikely(ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1)) - debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno)); + debug(DEBUG_TRACE, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno)); task->event.e_un.ret_val = WEXITSTATUS(data); task->event.type = EVENT_ABOUT_EXIT; diff --git a/task.c b/task.c index bbd33bc..e35ecc7 100644 --- a/task.c +++ b/task.c @@ -283,6 +283,7 @@ struct task *task_new(pid_t pid) task->attached = 0; task->stopped = 0; task->bp_skipped = 0; + task->in_realloc = 0; task->is_new = 1; task->defer_func = NULL; task->defer_data = NULL; diff --git a/task.h b/task.h index 24857d1..2367cb5 100644 --- a/task.h +++ b/task.h @@ -50,6 +50,7 @@ struct task { unsigned int is_new:1; unsigned int bad:1; unsigned int bp_skipped:1; + unsigned int in_realloc:1; struct breakpoint *breakpoint; struct library_symbol *libsym;