clean up, option for invalid free releases

This commit is contained in:
Stefani Seibold 2016-05-24 10:01:41 +02:00
parent 3e2980613c
commit 3b7a0d0552
26 changed files with 153 additions and 95 deletions

View File

@ -383,7 +383,7 @@ struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struc
case BP_AUTO: case BP_AUTO:
case BP_HW: case BP_HW:
#if HW_BREAKPOINTS > 1 #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++; leader->hw_bp_num++;
#endif #endif
case BP_SW: case BP_SW:

View File

@ -202,7 +202,7 @@ static int parse_config(const char *filename)
char *p; char *p;
struct stat statbuf; struct stat statbuf;
int fd; int fd;
fd = open(filename, O_RDONLY); fd = open(filename, O_RDONLY);
if (fd == -1) if (fd == -1)
fatal("could not open config file: `%s' (%s)", filename, strerror(errno)); 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) { if (data) {
process = data->process; process = data->process;
rb_erase(&data->node, root); rb_erase(&data->node, root);
free(data); free(data);
return process; return process;
} }
return NULL; 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); ret = sock_send_msg(client_fd, process->val16(op), process->pid, payload, payload_len);
if (ret < 0) if (ret < 0)
client_broken(); client_broken();
return ret; return ret;
} }

View File

@ -112,7 +112,7 @@ static int dump_pager(void)
struct termios termios_old; struct termios termios_old;
int len; int len;
ioevent_func oldfunc; ioevent_func oldfunc;
len = printf("Press <space> for next line, q for quit and any other for next page\r") - 1; len = printf("Press <space> for next line, q for quit and any other for next page\r") - 1;
fflush(stdout); fflush(stdout);
@ -194,7 +194,7 @@ static int dump_line(char *s, int n)
} }
return 0; return 0;
} }
int dump_printf(const char *fmt, ...) int dump_printf(const char *fmt, ...)
{ {
char *str; char *str;

View File

@ -72,6 +72,7 @@ struct rb_stack {
unsigned long long bytes_leaked; unsigned long long bytes_leaked;
unsigned long long tsc; unsigned long long tsc;
unsigned long long n_mismatched; unsigned long long n_mismatched;
unsigned long long n_badfree;
}; };
struct map { 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->leaks = stack_node->leaks;
this->n_allocations = stack_node->n_allocations; this->n_allocations = stack_node->n_allocations;
this->n_mismatched = stack_node->n_mismatched; this->n_mismatched = stack_node->n_mismatched;
this->n_badfree = stack_node->n_badfree;
this->total_allocations = stack_node->total_allocations; this->total_allocations = stack_node->total_allocations;
this->bytes_used = stack_node->bytes_used; this->bytes_used = stack_node->bytes_used;
this->bytes_leaked = stack_node->bytes_leaked; 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->refcnt = 0;
this->n_allocations = 0; this->n_allocations = 0;
this->n_mismatched = 0; this->n_mismatched = 0;
this->n_badfree = 0;
this->total_allocations = 0; this->total_allocations = 0;
this->bytes_used = 0; this->bytes_used = 0;
this->leaks = 0; this->leaks = 0;
@ -924,7 +927,16 @@ static int sort_tsc(const struct rb_stack **p, const struct rb_stack **q)
return 0; 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) if ((*p)->n_mismatched > (*q)->n_mismatched)
return -1; return -1;
@ -933,6 +945,26 @@ static int sort_mismatched(const struct rb_stack **p, const struct rb_stack **q)
return 0; 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) static int sort_usage(const struct rb_stack **p, const struct rb_stack **q)
{ {
if ((*p)->bytes_used > (*q)->bytes_used) 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]; struct rb_stack *stack = arr[i];
if (!skipfunc(stack)) { 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( if (dump_printf(
"Stack (%s):\n" "Stack (%s):\n"
" bytes used: %llu\n" " bytes used: %llu\n"
@ -1065,15 +1108,6 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb
break; 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) if (dump_printf(" tsc: %llu\n", stack->tsc) == -1)
break; break;
@ -1118,11 +1152,6 @@ static int skip_zero_allocations(struct rb_stack *stack)
return !stack->n_allocations; 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) static int skip_zero_leaks(struct rb_stack *stack)
{ {
return !stack->leaks; 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) 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) 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; break;
if (!is_mmap(block->stack_node->stack->operation)) { 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)) {
fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr);
if (unlikely(options.kill))
abort(); abort();
}
break; 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); block = process_rb_search(&process->block_table, ptr);
if (block) { if (block) {
if (is_mmap(block->stack_node->stack->operation)) { 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)) {
fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr);
if (unlikely(options.kill))
abort(); abort();
}
} }
if (!is_sane(block, mt_msg->operation)) { if (stack_size) {
struct rb_stack *stack = stack_add(process, process->pid, stack_data, stack_size, mt_msg->operation); 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->n_mismatched++;
stack->tsc = process->tsc++; stack->tsc = process->tsc++;
}
} }
if (mt_msg->operation == MT_REALLOC_ENTER) { 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 { else {
if (!process->attached) { if (!process->attached) {
fprintf(stderr, ">>> block %#lx not found pid:%d\n", ptr, process->pid); if (unlikely(options.kill)) {
fprintf(stderr, ">>> block %#lx not found pid:%d\n", ptr, process->pid);
if (unlikely(options.kill))
abort(); 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; return;
} }
@ -1579,7 +1625,10 @@ void process_dump_sortby(struct process *process)
_process_dump(process, sort_usage, skip_zero_allocations, options.output, options.lflag); _process_dump(process, sort_usage, skip_zero_allocations, options.output, options.lflag);
break; break;
case OPT_SORT_MISMATCHED: 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; break;
default: default:
_process_dump(process, sort_allocations, skip_zero_allocations, options.output, options.lflag); _process_dump(process, sort_allocations, skip_zero_allocations, options.output, options.lflag);
@ -1688,7 +1737,7 @@ struct block_helper {
unsigned long mask; unsigned long mask;
unsigned long fmask; unsigned long fmask;
unsigned long fmode; unsigned long fmode;
void * data; void * data;
}; };
static void set_block(struct rb_block *block, void *data) static void set_block(struct rb_block *block, void *data)

View File

@ -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_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_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_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 process_dump_stacks(struct process *process, const char *outfile, int lflag);
void add_ignore_regex(regex_t *re); void add_ignore_regex(regex_t *re);

View File

@ -92,6 +92,7 @@ static int quit;
static struct cmd_opt dump_opts[] = { static struct cmd_opt dump_opts[] = {
{ "allocations", 2, process_dump_sort_allocations, "sort by number of open allocations" }, { "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)" }, { "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" }, { "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" }, { "leaks", 1, process_dump_sort_leaks, "sort by number of detected leaks" },
{ "mismatched", 1, process_dump_sort_mismatched, "sort by number of mismatched releases" }, { "mismatched", 1, process_dump_sort_mismatched, "sort by number of mismatched releases" },
@ -170,7 +171,7 @@ static struct cmd_opt cmds[] = {
{ {
set_str, set_str,
2, 2,
do_set, do_set,
"change settings", "change settings",
"<option> [arg]", "<option> [arg]",
set_opts set_opts
@ -178,7 +179,7 @@ static struct cmd_opt cmds[] = {
{ {
show_str, show_str,
2, 2,
do_show, do_show,
"show settings", "show settings",
"<option> [arg]", "<option> [arg]",
show_opts show_opts
@ -356,7 +357,7 @@ static void readline_handler(char *line)
s = linedup; s = linedup;
i = 0; i = 0;
for(;;) { for(;;) {
s = skip_spaces(s); s = skip_spaces(s);
if (!*s) if (!*s)
@ -616,7 +617,7 @@ static int do_help(struct cmd_opt *cmd, int argc, const char *argv[])
{ {
int i; int i;
unsigned int len; unsigned int len;
if (argc <= 1) { if (argc <= 1) {
for(i = 0; i != ARRAY_SIZE(cmds) - 1; ++i) for(i = 0; i != ARRAY_SIZE(cmds) - 1; ++i)
printf(" %s - %s\n", cmds[i].name, cmds[i].info); printf(" %s - %s\n", cmds[i].name, cmds[i].info);

View File

@ -495,7 +495,7 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
valp = &val; valp = &val;
tmp_ptr = NULL; tmp_ptr = NULL;
} }
if (local) if (local)
as = NULL; as = NULL;

View File

@ -259,7 +259,7 @@ static void handle_breakpoint(struct task *task)
{ {
struct breakpoint *bp = task->event.e_un.breakpoint; struct breakpoint *bp = task->event.e_un.breakpoint;
unsigned int hw = bp->hw; unsigned int hw = bp->hw;
debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", task->pid, bp->addr); debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", task->pid, bp->addr);
if (unlikely(options.verbose > 1)) if (unlikely(options.verbose > 1))

View File

@ -265,9 +265,6 @@ static struct library *_library_add(struct task *leader, struct libref *libref)
struct library *lib = malloc(sizeof(*lib)); struct library *lib = malloc(sizeof(*lib));
if (lib == NULL)
return NULL;
memset(lib, 0, sizeof(*lib)); memset(lib, 0, sizeof(*lib));
lib->libref = libref_get(libref); lib->libref = libref_get(libref);

2
list.h
View File

@ -212,7 +212,7 @@ static inline void list_splice_init(struct list_head *list,
*/ */
#define list_for_each(pos, head) \ #define list_for_each(pos, head) \
for (pos = (head)->next; prefetch(pos->next), 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 * list_for_each_safe - iterate over a list safe against removal of list entry

2
main.c
View File

@ -110,7 +110,7 @@ static void mtrace_init(char **cmd_args)
if (options.command) { if (options.command) {
struct task *task = task_create(cmd_args); struct task *task = task_create(cmd_args);
if (!task) if (!task)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);

View File

@ -370,7 +370,7 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
break; break;
} }
} }
mte->dyn_addr = shdr.sh_addr + bias; mte->dyn_addr = shdr.sh_addr + bias;
} }
} }
@ -448,7 +448,7 @@ static arch_addr_t find_solib_break(struct mt_elf *mte)
{ {
if (mte->symtab && mte->strtab) { if (mte->symtab && mte->strtab) {
arch_addr_t addr = _find_solib_break(mte, mte->symtab, mte->strtab, mte->symtab_count); arch_addr_t addr = _find_solib_break(mte, mte->symtab, mte->strtab, mte->symtab_count);
if (addr) if (addr)
return addr; return addr;
} }

View File

@ -165,6 +165,8 @@ void operator delete(void* p) __THROW
void operator delete(void* p, const std::nothrow_t& nt) __THROW void operator delete(void* p, const std::nothrow_t& nt) __THROW
void operator delete[](void* p) __THROW void operator delete[](void* p) __THROW
void operator delete[](void* p, const std::nothrow_t& nt) __THROW void operator delete[](void* p, const std::nothrow_t& nt) __THROW
void operator delete(void*, unsigned long)
void operator delete[](void*, unsigned long)
.fi .fi
.in .in
.PP .PP
@ -306,6 +308,12 @@ Sort by the number of average allocations (number of bytes in used / number of o
.RE .RE
.RE .RE
.RS .RS
\fIbadfree\fR
.RS
Sort by number of bad free releases (only useful with \-S option).
.RE
.RE
.RS
\fIbytes-leaked\fR \fIbytes-leaked\fR
.RS .RS
Sort by number of bytes leaked (only useful with \-a option). Sort by number of bytes leaked (only useful with \-a option).
@ -348,8 +356,8 @@ Sort by number of bytes in use of all open allocations.
.RE .RE
.RE .RE
.IP "\-S, \-\-sanity" .IP "\-S, \-\-sanity"
Check mismatching operations against new/delete. This options also Check mismatching operations against new/delete or free releases. This options
sets the sort-by options to mismatched. also sets the sort-by options to mismatched if no other sort option was set.
.IP "\-t, \-\-trace" .IP "\-t, \-\-trace"
Run \fBmtrace-ng\fR in trace mode. In this mode all attached processes will run under Run \fBmtrace-ng\fR in trace mode. In this mode all attached processes will run under
the control of \fBmtrace-ng\fR and all dynamic memory function calls will be traced. the control of \fBmtrace-ng\fR and all dynamic memory function calls will be traced.
@ -399,7 +407,7 @@ at any time. It accepts a maximum of three parameters:
\fIsortby\fR \fIsortby\fR
.RS .RS
Sort the output of dump by the keyword. The keyword is the same as for the Sort the output of dump by the keyword. The keyword is the same as for the
\-S option (\fIallocations, \fIaverage\fR, \fIbytes-leaked\fR, \fIleaks\fR, \-S option (\fIallocations, \fIaverage\fR, \fIbadfree\fR \fIbytes-leaked\fR, \fIleaks\fR,
\fImismatched\fR, \fIstacks\fR, \fItotal\fR, \fItsc\fR and \fIusage\fR). See \fImismatched\fR, \fIstacks\fR, \fItotal\fR, \fItsc\fR and \fIusage\fR). See
\-S option for more details about the sortby keywords. The default sort order \-S option for more details about the sortby keywords. The default sort order
is \fIallocations\fR when no sortby parameter is used. is \fIallocations\fR when no sortby parameter is used.

View File

@ -106,7 +106,7 @@ static void usage(void)
" allocations, average, bytes-leaked, leaks,\n" " allocations, average, bytes-leaked, leaks,\n"
" mismatched, stacks, total, tsc, usage\n" " mismatched, stacks, total, tsc, usage\n"
#endif #endif
" -S, --sanity check mismatching operations against new/delete\n" " -S, --sanity check for mismatching operations\n"
" -t, --trace trace mode\n" " -t, --trace trace mode\n"
" -u, --user=USERNAME run command with the userid, groupid of username\n" " -u, --user=USERNAME run command with the userid, groupid of username\n"
" -V, --version output version information and exit\n" " -V, --version output version information and exit\n"
@ -198,7 +198,7 @@ static void def_config(void)
{ {
char *path; char *path;
char *filename; char *filename;
path = getenv("HOME"); path = getenv("HOME");
if (!path) { if (!path) {
struct passwd *pwd = getpwuid(getuid()); struct passwd *pwd = getpwuid(getuid());
@ -504,6 +504,9 @@ char **process_options(int argc, char **argv)
if (!strncmp(optarg, "average", 2)) if (!strncmp(optarg, "average", 2))
options.sort_by = OPT_SORT_AVERAGE; options.sort_by = OPT_SORT_AVERAGE;
else else
if (!strncmp(optarg, "badfree", 1))
options.sort_by = OPT_SORT_BADFREE;
else
if (!strncmp(optarg, "bytes-leaked", 1)) if (!strncmp(optarg, "bytes-leaked", 1))
options.sort_by = OPT_SORT_BYTES_LEAKED; options.sort_by = OPT_SORT_BYTES_LEAKED;
else else
@ -666,7 +669,7 @@ char **process_options(int argc, char **argv)
} }
} }
else { else {
if (options.sanity) if (options.sanity && options.sort_by == -1)
options.sort_by = OPT_SORT_MISMATCHED; options.sort_by = OPT_SORT_MISMATCHED;
} }

View File

@ -39,6 +39,7 @@
#define OPT_SORT_TSC 6 #define OPT_SORT_TSC 6
#define OPT_SORT_USAGE 7 #define OPT_SORT_USAGE 7
#define OPT_SORT_MISMATCHED 8 #define OPT_SORT_MISMATCHED 8
#define OPT_SORT_BADFREE 9
struct options_t options; struct options_t options;

View File

@ -400,7 +400,7 @@ int rb_iterate(const struct rb_root *root, int (*func)(struct rb_node *,void *us
do { do {
parent = rb_parent(node); parent = rb_parent(node);
ret = func(node, user); ret = func(node, user);
if (ret) if (ret)
break; break;

View File

@ -63,7 +63,7 @@ static void report_alloc64(struct task *task, enum mt_operation op, unsigned lon
if (unlikely(!alloc->data[i])) if (unlikely(!alloc->data[i]))
break; break;
++i; ++i;
} }
} }
@ -244,7 +244,7 @@ static void _report_mmap64(struct task *task, struct library_symbol *libsym)
} size; } size;
size.l = fetch_param(task, 1); size.l = fetch_param(task, 1);
if (!task_is_64bit(task)) { if (!task_is_64bit(task)) {
size.v.v1 = fetch_param(task, 1); size.v.v1 = fetch_param(task, 1);
size.v.v2 = fetch_param(task, 2); size.v.v2 = fetch_param(task, 2);

View File

@ -98,8 +98,7 @@ int server_poll(void)
{ {
int ret = 0; int ret = 0;
if (command_pending) {
if (command_pending) {
ret = server_handle_command(); ret = server_handle_command();
if (options.trace) if (options.trace)

View File

@ -207,7 +207,7 @@ static int arm_get_next_pcs(struct task *task, const uint32_t pc, uint32_t next_
if (BITS(this_instr, 12, 15) != ARM_REG_PC) if (BITS(this_instr, 12, 15) != ARM_REG_PC)
break; break;
if (BITS(this_instr, 22, 25) == 0 && BITS(this_instr, 4, 7) == 9) /* multiply */ if (BITS(this_instr, 22, 25) == 0 && BITS(this_instr, 4, 7) == 9) /* multiply */
goto invalid; goto invalid;
/* BX <reg>, BLX <reg> */ /* BX <reg>, BLX <reg> */

View File

@ -612,7 +612,7 @@ static int arm_frame_step(struct dwarf_addr_space *as)
ip_loc = DWARF_MEM_LOC(fp); ip_loc = DWARF_MEM_LOC(fp);
fp_loc = DWARF_MEM_LOC(fp - 4); fp_loc = DWARF_MEM_LOC(fp - 4);
} }
if (dwarf_get(as, ip_loc, &ip) < 0) if (dwarf_get(as, ip_loc, &ip) < 0)
return -DWARF_EBADFRAME; return -DWARF_EBADFRAME;

View File

@ -59,7 +59,7 @@ struct map {
unsigned long long start; unsigned long long start;
unsigned long long end; unsigned long long end;
}; };
static void report_fault(int signo, siginfo_t* siginf, void* arg) static void report_fault(int signo, siginfo_t* siginf, void* arg)
{ {
fprintf(stderr, "fault signal %d (%s)\n", signo, strsignal(signo)); fprintf(stderr, "fault signal %d (%s)\n", signo, strsignal(signo));
@ -70,37 +70,37 @@ static void report_fault(int signo, siginfo_t* siginf, void* arg)
void *trace[48]; void *trace[48];
char **strings; char **strings;
Dl_info info; Dl_info info;
char linkname[PATH_MAX]; char linkname[PATH_MAX];
bfd* abfd = 0; bfd* abfd = 0;
asymbol **syms = 0; asymbol **syms = 0;
asection *text = 0; asection *text = 0;
int l; int l;
l = readlink("/proc/self/exe", linkname, sizeof(linkname)); l = readlink("/proc/self/exe", linkname, sizeof(linkname));
if (l == -1) { if (l == -1) {
perror("failed to find executable\n"); perror("failed to find executable\n");
return; return;
} }
linkname[l] = 0; linkname[l] = 0;
bfd_init();
abfd = bfd_openr(linkname, 0);
if (!abfd) {
perror("bfd_openr failed: ");
return;
}
/* oddly, this is required for it to work... */
bfd_check_format(abfd,bfd_object);
unsigned storage_needed = bfd_get_symtab_upper_bound(abfd);
syms = (asymbol **) malloc(storage_needed);
bfd_canonicalize_symtab(abfd, syms); bfd_init();
abfd = bfd_openr(linkname, 0);
if (!abfd) {
perror("bfd_openr failed: ");
return;
}
/* oddly, this is required for it to work... */
bfd_check_format(abfd,bfd_object);
unsigned storage_needed = bfd_get_symtab_upper_bound(abfd);
syms = (asymbol **) malloc(storage_needed);
bfd_canonicalize_symtab(abfd, syms);
text = bfd_get_section_by_name(abfd, ".text"); text = bfd_get_section_by_name(abfd, ".text");
nptrs = backtrace(trace, ARRAY_SIZE(trace)); nptrs = backtrace(trace, ARRAY_SIZE(trace));
strings = backtrace_symbols(trace, nptrs); strings = backtrace_symbols(trace, nptrs);
@ -216,7 +216,7 @@ static struct map *get_writeable_mappings(struct task *task)
if (permw != 'w' || permr != 'r') if (permw != 'w' || permr != 'r')
continue; continue;
if (map >= maps_size - 1) { if (map >= maps_size - 1) {
maps_size += 16; maps_size += 16;
maps = realloc(maps, maps_size * sizeof(*maps)); maps = realloc(maps, maps_size * sizeof(*maps));

View File

@ -473,7 +473,6 @@ static void linkmap_del(struct task *task, struct lt_r_debug_64 *dbg)
} }
static int load_debug_struct(struct task *task, arch_addr_t debug_addr, struct lt_r_debug_64 *ret) static int load_debug_struct(struct task *task, arch_addr_t debug_addr, struct lt_r_debug_64 *ret)
{ {
debug(DEBUG_FUNCTION, "pid=%d", task->pid); debug(DEBUG_FUNCTION, "pid=%d", task->pid);
@ -559,7 +558,7 @@ int process_get_entry(struct task *task, unsigned long *entryp, unsigned long *i
{ {
PROC_PID_FILE(fn, "/proc/%d/auxv", task->pid); PROC_PID_FILE(fn, "/proc/%d/auxv", task->pid);
int fd, ret; int fd, ret;
fd = open(fn, O_RDONLY); fd = open(fn, O_RDONLY);
if (fd == -1) if (fd == -1)
goto fail; goto fail;

View File

@ -106,7 +106,7 @@ int sock_send_msg(int fd, enum mt_operation op, uint32_t pid, const void *payloa
} }
ret = TEMP_FAILURE_RETRY(sendmsg(fd, &msghdr, MSG_NOSIGNAL)); ret = TEMP_FAILURE_RETRY(sendmsg(fd, &msghdr, MSG_NOSIGNAL));
if ((size_t)ret != sizeof(mt_msg) + payload_len) if ((size_t)ret != sizeof(mt_msg) + payload_len)
return -1; return -1;

View File

@ -227,7 +227,7 @@ static void process_event(struct task *task, int status)
start_time(&task->halt_time); start_time(&task->halt_time);
task->stopped = 1; task->stopped = 1;
leader->threads_stopped++; leader->threads_stopped++;
stop_signal = _process_event(task, status); stop_signal = _process_event(task, status);
@ -534,7 +534,7 @@ struct task *wait_event(void)
struct task *task; struct task *task;
int status; int status;
int pid; int pid;
pid = waitpid(-1, &status, __WALL); pid = waitpid(-1, &status, __WALL);
if (unlikely(pid == -1)) { if (unlikely(pid == -1)) {
if (errno != EINTR) { if (errno != EINTR) {

View File

@ -141,7 +141,7 @@ static int set_breakpoint_mode(struct task *task, unsigned int n, int type, int
dr7 = task->arch.dr7 & ~mask; dr7 = task->arch.dr7 & ~mask;
dr7 |= mode << (16 + 4 * n); dr7 |= mode << (16 + 4 * n);
if (local) { if (local) {
dr7 |= 0b01 << (2 * n); dr7 |= 0b01 << (2 * n);
dr7 |= 1 << 8; dr7 |= 1 << 8;

View File

@ -103,9 +103,9 @@ unsigned int ip_reg_addr(void)
arch_addr_t get_return_addr(struct task *task) arch_addr_t get_return_addr(struct task *task)
{ {
long a; long a;
errno = 0; errno = 0;
a = ptrace(PTRACE_PEEKTEXT, task->pid, get_stack_pointer(task), 0); a = ptrace(PTRACE_PEEKTEXT, task->pid, get_stack_pointer(task), 0);
if (a == -1 && errno) { if (a == -1 && errno) {
if (errno != ESRCH) if (errno != ESRCH)