Skip to content

Commit

Permalink
clean up, option for invalid free releases
Browse files Browse the repository at this point in the history
  • Loading branch information
sstefani committed May 24, 2016
1 parent 3e29806 commit 3b7a0d0
Show file tree
Hide file tree
Showing 26 changed files with 151 additions and 93 deletions.
2 changes: 1 addition & 1 deletion breakpoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions client/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions client/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ static int dump_pager(void)
struct termios termios_old;
int len;
ioevent_func oldfunc;

len = printf("Press <space> for next line, q for quit and any other for next page\r") - 1;
fflush(stdout);

Expand Down Expand Up @@ -194,7 +194,7 @@ static int dump_line(char *s, int n)
}
return 0;
}

int dump_printf(const char *fmt, ...)
{
char *str;
Expand Down
115 changes: 82 additions & 33 deletions client/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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"
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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++;
}
}
}
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions client/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 5 additions & 4 deletions client/readline.c
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand Down Expand Up @@ -170,15 +171,15 @@ static struct cmd_opt cmds[] = {
{
set_str,
2,
do_set,
do_set,
"change settings",
"<option> [arg]",
set_opts
},
{
show_str,
2,
do_show,
do_show,
"show settings",
"<option> [arg]",
show_opts
Expand Down Expand Up @@ -356,7 +357,7 @@ static void readline_handler(char *line)

s = linedup;
i = 0;

for(;;) {
s = skip_spaces(s);
if (!*s)
Expand Down Expand Up @@ -616,7 +617,7 @@ static int do_help(struct cmd_opt *cmd, int argc, const char *argv[])
{
int i;
unsigned int len;

if (argc <= 1) {
for(i = 0; i != ARRAY_SIZE(cmds) - 1; ++i)
printf(" %s - %s\n", cmds[i].name, cmds[i].info);
Expand Down
2 changes: 1 addition & 1 deletion dwarf.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
valp = &val;
tmp_ptr = NULL;
}

if (local)
as = NULL;

Expand Down
2 changes: 1 addition & 1 deletion event.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ static void handle_breakpoint(struct task *task)
{
struct breakpoint *bp = task->event.e_un.breakpoint;
unsigned int hw = bp->hw;

debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", task->pid, bp->addr);

if (unlikely(options.verbose > 1))
Expand Down
3 changes: 0 additions & 3 deletions library.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,6 @@ static struct library *_library_add(struct task *leader, struct libref *libref)

struct library *lib = malloc(sizeof(*lib));

if (lib == NULL)
return NULL;

memset(lib, 0, sizeof(*lib));

lib->libref = libref_get(libref);
Expand Down
2 changes: 1 addition & 1 deletion list.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ static inline void list_splice_init(struct list_head *list,
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), pos != (head); \
pos = pos->next)
pos = pos->next)

/**
* list_for_each_safe - iterate over a list safe against removal of list entry
Expand Down
2 changes: 1 addition & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ static void mtrace_init(char **cmd_args)

if (options.command) {
struct task *task = task_create(cmd_args);

if (!task)
exit(EXIT_FAILURE);

Expand Down
4 changes: 2 additions & 2 deletions mtelf.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
break;
}
}

mte->dyn_addr = shdr.sh_addr + bias;
}
}
Expand Down Expand Up @@ -448,7 +448,7 @@ static arch_addr_t find_solib_break(struct mt_elf *mte)
{
if (mte->symtab && mte->strtab) {
arch_addr_t addr = _find_solib_break(mte, mte->symtab, mte->strtab, mte->symtab_count);

if (addr)
return addr;
}
Expand Down
Loading

0 comments on commit 3b7a0d0

Please sign in to comment.