From 3b7a0d055204dba3f8f5536d30c34e2a78bb32d6 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Tue, 24 May 2016 10:01:41 +0200 Subject: [PATCH] clean up, option for invalid free releases --- breakpoint.c | 2 +- client/client.c | 8 +-- client/dump.c | 4 +- client/process.c | 115 +++++++++++++++++++++--------- client/process.h | 1 + client/readline.c | 9 +-- dwarf.c | 2 +- event.c | 2 +- library.c | 3 - list.h | 2 +- main.c | 2 +- mtelf.c | 4 +- mtrace-ng.1 | 14 +++- options.c | 9 ++- options.h | 1 + rbtree.c | 2 +- report.c | 4 +- server.c | 3 +- sysdeps/linux-gnu/arm/arch.c | 2 +- sysdeps/linux-gnu/arm/dwarf-arm.c | 2 +- sysdeps/linux-gnu/os.c | 42 +++++------ sysdeps/linux-gnu/proc.c | 3 +- sysdeps/linux-gnu/socket.c | 2 +- sysdeps/linux-gnu/trace.c | 4 +- sysdeps/linux-gnu/x86/arch.c | 2 +- sysdeps/linux-gnu/x86/regs.c | 4 +- 26 files changed, 153 insertions(+), 95 deletions(-) diff --git a/breakpoint.c b/breakpoint.c index a9513dc..910f49d 100644 --- a/breakpoint.c +++ b/breakpoint.c @@ -383,7 +383,7 @@ struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struc case BP_AUTO: case BP_HW: #if HW_BREAKPOINTS > 1 - list_add_tail(&bp->link_list, &leader->hw_bp_list); + list_add_tail(&bp->link_list, &leader->hw_bp_list); leader->hw_bp_num++; #endif case BP_SW: diff --git a/client/client.c b/client/client.c index 23f867d..308e526 100644 --- a/client/client.c +++ b/client/client.c @@ -202,7 +202,7 @@ static int parse_config(const char *filename) char *p; struct stat statbuf; int fd; - + fd = open(filename, O_RDONLY); if (fd == -1) fatal("could not open config file: `%s' (%s)", filename, strerror(errno)); @@ -248,10 +248,10 @@ static struct process *pid_rb_delete(struct rb_root *root, unsigned int pid) if (data) { process = data->process; - + rb_erase(&data->node, root); free(data); - + return process; } return NULL; @@ -807,7 +807,7 @@ int client_send_msg(struct process *process, enum mt_operation op, void *payload ret = sock_send_msg(client_fd, process->val16(op), process->pid, payload, payload_len); - if (ret < 0) + if (ret < 0) client_broken(); return ret; } diff --git a/client/dump.c b/client/dump.c index d648491..9076cf4 100644 --- a/client/dump.c +++ b/client/dump.c @@ -112,7 +112,7 @@ static int dump_pager(void) struct termios termios_old; int len; ioevent_func oldfunc; - + len = printf("Press for next line, q for quit and any other for next page\r") - 1; fflush(stdout); @@ -194,7 +194,7 @@ static int dump_line(char *s, int n) } return 0; } - + int dump_printf(const char *fmt, ...) { char *str; diff --git a/client/process.c b/client/process.c index 25dcb8d..7cf985b 100644 --- a/client/process.c +++ b/client/process.c @@ -72,6 +72,7 @@ struct rb_stack { unsigned long long bytes_leaked; unsigned long long tsc; unsigned long long n_mismatched; + unsigned long long n_badfree; }; struct map { @@ -460,6 +461,7 @@ static struct rb_stack *stack_clone(struct process *process, struct rb_stack *st this->leaks = stack_node->leaks; this->n_allocations = stack_node->n_allocations; this->n_mismatched = stack_node->n_mismatched; + this->n_badfree = stack_node->n_badfree; this->total_allocations = stack_node->total_allocations; this->bytes_used = stack_node->bytes_used; this->bytes_leaked = stack_node->bytes_leaked; @@ -527,6 +529,7 @@ static struct rb_stack *stack_add(struct process *process, unsigned int pid, voi this->refcnt = 0; this->n_allocations = 0; this->n_mismatched = 0; + this->n_badfree = 0; this->total_allocations = 0; this->bytes_used = 0; this->leaks = 0; @@ -924,7 +927,16 @@ static int sort_tsc(const struct rb_stack **p, const struct rb_stack **q) return 0; } -static int sort_mismatched(const struct rb_stack **p, const struct rb_stack **q) +static int _sort_badfree(const struct rb_stack **p, const struct rb_stack **q) +{ + if ((*p)->n_badfree > (*q)->n_badfree) + return -1; + if ((*p)->n_badfree < (*q)->n_badfree) + return 1; + return 0; +} + +static int _sort_mismatched(const struct rb_stack **p, const struct rb_stack **q) { if ((*p)->n_mismatched > (*q)->n_mismatched) return -1; @@ -933,6 +945,26 @@ static int sort_mismatched(const struct rb_stack **p, const struct rb_stack **q) return 0; } +static int sort_badfree(const struct rb_stack **p, const struct rb_stack **q) +{ + int ret; + + ret = _sort_badfree(p, q); + if (ret) + return ret; + return _sort_mismatched(p, q); +} + +static int sort_mismatched(const struct rb_stack **p, const struct rb_stack **q) +{ + int ret; + + ret = _sort_mismatched(p, q); + if (ret) + return ret; + return _sort_badfree(p, q); +} + static int sort_usage(const struct rb_stack **p, const struct rb_stack **q) { if ((*p)->bytes_used > (*q)->bytes_used) @@ -1047,7 +1079,18 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb struct rb_stack *stack = arr[i]; if (!skipfunc(stack)) { - if (!stack->n_mismatched) { + if (stack->n_mismatched || stack->n_badfree) { + if (dump_printf( + "Stack (%s):\n" + " total number of mismatches: %llu\n" + " total number of bad free: %llu\n", + str_operation(stack->stack->operation), + stack->n_mismatched, + stack->n_badfree + ) == -1) + break; + } + else { if (dump_printf( "Stack (%s):\n" " bytes used: %llu\n" @@ -1065,15 +1108,6 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb break; } } - else { - if (dump_printf( - "Stack (%s):\n" - " total number of mismatches: %llu\n", - str_operation(stack->stack->operation), - stack->n_mismatched - ) == -1) - break; - } if (dump_printf(" tsc: %llu\n", stack->tsc) == -1) break; @@ -1118,11 +1152,6 @@ static int skip_zero_allocations(struct rb_stack *stack) return !stack->n_allocations; } -static int skip_non_mismatched(struct rb_stack *stack) -{ - return !stack->n_mismatched; -} - static int skip_zero_leaks(struct rb_stack *stack) { return !stack->leaks; @@ -1165,7 +1194,12 @@ void process_dump_sort_tsc(struct process *process, const char *outfile, int lfl void process_dump_sort_mismatched(struct process *process, const char *outfile, int lflag) { - process_dump(process, sort_mismatched, skip_non_mismatched, outfile, lflag); + process_dump(process, sort_mismatched, skip_none, outfile, lflag); +} + +void process_dump_sort_badfree(struct process *process, const char *outfile, int lflag) +{ + process_dump(process, sort_badfree, skip_none, outfile, lflag); } void process_dump_stacks(struct process *process, const char *outfile, int lflag) @@ -1260,10 +1294,10 @@ void process_munmap(struct process *process, struct mt_msg *mt_msg, void *payloa break; if (!is_mmap(block->stack_node->stack->operation)) { - fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr); - - if (unlikely(options.kill)) + if (unlikely(options.kill)) { + fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr); abort(); + } break; } @@ -1388,17 +1422,19 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload) block = process_rb_search(&process->block_table, ptr); if (block) { if (is_mmap(block->stack_node->stack->operation)) { - fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr); - - if (unlikely(options.kill)) + if (unlikely(options.kill)) { + fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr); abort(); + } } - if (!is_sane(block, mt_msg->operation)) { - struct rb_stack *stack = stack_add(process, process->pid, stack_data, stack_size, mt_msg->operation); + if (stack_size) { + if (!is_sane(block, mt_msg->operation)) { + struct rb_stack *stack = stack_add(process, process->pid, stack_data, stack_size, mt_msg->operation); - stack->n_mismatched++; - stack->tsc = process->tsc++; + stack->n_mismatched++; + stack->tsc = process->tsc++; + } } if (mt_msg->operation == MT_REALLOC_ENTER) { @@ -1420,10 +1456,17 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload) } else { if (!process->attached) { - fprintf(stderr, ">>> block %#lx not found pid:%d\n", ptr, process->pid); - - if (unlikely(options.kill)) + if (unlikely(options.kill)) { + fprintf(stderr, ">>> block %#lx not found pid:%d\n", ptr, process->pid); abort(); + } + + if (stack_size) { + struct rb_stack *stack = stack_add(process, process->pid, stack_data, stack_size, mt_msg->operation); + + stack->n_badfree++; + stack->tsc = process->tsc++; + } } } } @@ -1464,7 +1507,10 @@ void process_realloc_done(struct process *process, struct mt_msg *mt_msg, void * } } -// fprintf(stderr, ">>> unexpected realloc done pid: %u\n", pid); + if (unlikely(options.kill)) { + fprintf(stderr, ">>> unexpected realloc done pid: %u\n", pid); + abort(); + } return; } @@ -1579,7 +1625,10 @@ void process_dump_sortby(struct process *process) _process_dump(process, sort_usage, skip_zero_allocations, options.output, options.lflag); break; case OPT_SORT_MISMATCHED: - _process_dump(process, sort_mismatched, skip_non_mismatched, options.output, options.lflag); + _process_dump(process, sort_mismatched, skip_none, options.output, options.lflag); + break; + case OPT_SORT_BADFREE: + _process_dump(process, sort_badfree, skip_none, options.output, options.lflag); break; default: _process_dump(process, sort_allocations, skip_zero_allocations, options.output, options.lflag); @@ -1688,7 +1737,7 @@ struct block_helper { unsigned long mask; unsigned long fmask; unsigned long fmode; - void * data; + void * data; }; static void set_block(struct rb_block *block, void *data) diff --git a/client/process.h b/client/process.h index 8a38122..16c1206 100644 --- a/client/process.h +++ b/client/process.h @@ -112,6 +112,7 @@ void process_dump_sort_allocations(struct process *process, const char *outfile, void process_dump_sort_total(struct process *process, const char *outfile, int lflag); void process_dump_sort_tsc(struct process *process, const char *outfile, int lflag); void process_dump_sort_mismatched(struct process *process, const char *outfile, int lflag); +void process_dump_sort_badfree(struct process *process, const char *outfile, int lflag); void process_dump_stacks(struct process *process, const char *outfile, int lflag); void add_ignore_regex(regex_t *re); diff --git a/client/readline.c b/client/readline.c index 12188f6..c8f79d3 100644 --- a/client/readline.c +++ b/client/readline.c @@ -92,6 +92,7 @@ static int quit; static struct cmd_opt dump_opts[] = { { "allocations", 2, process_dump_sort_allocations, "sort by number of open allocations" }, { "average", 2, process_dump_sort_average, "sort by average allocation of bytes (usage / allocations)" }, + { "badfree", 1, process_dump_sort_badfree, "sort by number of badfree releases" }, { "bytes-leaked", 1, process_dump_sort_bytes_leaked, "sort by number of leaked bytes" }, { "leaks", 1, process_dump_sort_leaks, "sort by number of detected leaks" }, { "mismatched", 1, process_dump_sort_mismatched, "sort by number of mismatched releases" }, @@ -170,7 +171,7 @@ static struct cmd_opt cmds[] = { { set_str, 2, - do_set, + do_set, "change settings", "