mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 08:46:41 +08:00
clean up, option for invalid free releases
This commit is contained in:
parent
3e2980613c
commit
3b7a0d0552
@ -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:
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
115
client/process.c
115
client/process.c
@ -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)
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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" },
|
||||||
|
|||||||
@ -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
2
list.h
@ -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
|
||||||
|
|||||||
14
mtrace-ng.1
14
mtrace-ng.1
@ -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.
|
||||||
|
|||||||
@ -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"
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
2
report.c
2
report.c
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
server.c
3
server.c
@ -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)
|
||||||
|
|||||||
@ -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> */
|
||||||
|
|||||||
@ -70,34 +70,34 @@ 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();
|
bfd_init();
|
||||||
|
|
||||||
abfd = bfd_openr(linkname, 0);
|
abfd = bfd_openr(linkname, 0);
|
||||||
if (!abfd) {
|
if (!abfd) {
|
||||||
perror("bfd_openr failed: ");
|
perror("bfd_openr failed: ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* oddly, this is required for it to work... */
|
/* oddly, this is required for it to work... */
|
||||||
bfd_check_format(abfd,bfd_object);
|
bfd_check_format(abfd,bfd_object);
|
||||||
|
|
||||||
unsigned storage_needed = bfd_get_symtab_upper_bound(abfd);
|
unsigned storage_needed = bfd_get_symtab_upper_bound(abfd);
|
||||||
syms = (asymbol **) malloc(storage_needed);
|
syms = (asymbol **) malloc(storage_needed);
|
||||||
|
|
||||||
bfd_canonicalize_symtab(abfd, syms);
|
bfd_canonicalize_symtab(abfd, syms);
|
||||||
|
|
||||||
text = bfd_get_section_by_name(abfd, ".text");
|
text = bfd_get_section_by_name(abfd, ".text");
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user