mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 16:56:41 +08:00
introduce new features
- disable hardware breakpoints useful for running mtrace inside a virtual machine - sanity check check new/new[] against mismatch operation and all c allocation functions against c++ allocation functions and visa versa.
This commit is contained in:
parent
96cd4a6ce8
commit
802a1a3b22
@ -329,6 +329,9 @@ struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struc
|
||||
if (bp == NULL)
|
||||
goto fail1;
|
||||
|
||||
if (options.nohwbp)
|
||||
bp_type = BP_SW;
|
||||
|
||||
bp->on_hit = NULL;
|
||||
bp->libsym = libsym;
|
||||
bp->addr = addr;
|
||||
|
||||
@ -427,10 +427,14 @@ static int client_func(void)
|
||||
case MT_PVALLOC:
|
||||
case MT_MMAP:
|
||||
case MT_MMAP64:
|
||||
case MT_NEW:
|
||||
case MT_NEW_ARRAY:
|
||||
process_alloc(process, &mt_msg, payload);
|
||||
break;
|
||||
case MT_REALLOC_ENTER:
|
||||
case MT_FREE:
|
||||
case MT_DELETE:
|
||||
case MT_DELETE_ARRAY:
|
||||
process_free(process, &mt_msg, payload);
|
||||
break;
|
||||
case MT_MUNMAP:
|
||||
|
||||
@ -70,6 +70,7 @@ struct rb_stack {
|
||||
unsigned long long bytes_used;
|
||||
unsigned long long bytes_leaked;
|
||||
unsigned long long tsc;
|
||||
unsigned long long n_mismatched;
|
||||
};
|
||||
|
||||
struct map {
|
||||
@ -139,6 +140,14 @@ static const char *str_operation(enum mt_operation operation)
|
||||
return "free";
|
||||
case MT_MUNMAP:
|
||||
return "munmap";
|
||||
case MT_NEW:
|
||||
return "new";
|
||||
case MT_NEW_ARRAY:
|
||||
return "new[]";
|
||||
case MT_DELETE:
|
||||
return "delete";
|
||||
case MT_DELETE_ARRAY:
|
||||
return "delete[]";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -422,6 +431,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->total_allocations = stack_node->total_allocations;
|
||||
this->bytes_used = stack_node->bytes_used;
|
||||
this->bytes_leaked = stack_node->bytes_leaked;
|
||||
@ -486,6 +496,7 @@ static struct rb_stack *stack_add(struct process *process, pid_t pid, void *addr
|
||||
memcpy(stack->addrs, addrs, stack_size);
|
||||
|
||||
this->n_allocations = 0;
|
||||
this->n_mismatched = 0;
|
||||
this->total_allocations = 0;
|
||||
this->bytes_used = 0;
|
||||
this->leaks = 0;
|
||||
@ -832,6 +843,15 @@ 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)
|
||||
{
|
||||
if ((*p)->n_mismatched > (*q)->n_mismatched)
|
||||
return -1;
|
||||
if ((*p)->n_mismatched < (*q)->n_mismatched)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sort_usage(const struct rb_stack **p, const struct rb_stack **q)
|
||||
{
|
||||
if ((*p)->bytes_used > (*q)->bytes_used)
|
||||
@ -939,6 +959,7 @@ 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 (dump_printf(
|
||||
"Stack (%s):\n"
|
||||
" bytes used: %llu\n"
|
||||
@ -955,6 +976,16 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb
|
||||
if (dump_printf( " leaked allocations: %lu (%llu bytes)\n", stack->leaks, stack->bytes_leaked) == -1)
|
||||
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;
|
||||
@ -995,6 +1026,11 @@ 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;
|
||||
@ -1035,6 +1071,11 @@ void process_dump_sort_tsc(struct process *process, const char *outfile)
|
||||
process_dump(process, sort_tsc, skip_zero_allocations, outfile);
|
||||
}
|
||||
|
||||
void process_dump_sort_mismatched(struct process *process, const char *outfile)
|
||||
{
|
||||
process_dump(process, sort_mismatched, skip_non_mismatched, outfile);
|
||||
}
|
||||
|
||||
void process_dump_stacks(struct process *process, const char *outfile)
|
||||
{
|
||||
process_dump(process, sort_allocations, skip_none, outfile);
|
||||
@ -1188,10 +1229,43 @@ void process_munmap(struct process *process, struct mt_msg *mt_msg, void *payloa
|
||||
} while(size);
|
||||
}
|
||||
|
||||
static int is_sane(struct rb_block *block, enum mt_operation op)
|
||||
{
|
||||
switch(block->stack_node->stack->operation) {
|
||||
case MT_MALLOC:
|
||||
case MT_REALLOC:
|
||||
case MT_REALLOC_FAILED:
|
||||
case MT_MEMALIGN:
|
||||
case MT_POSIX_MEMALIGN:
|
||||
case MT_ALIGNED_ALLOC:
|
||||
case MT_VALLOC:
|
||||
case MT_PVALLOC:
|
||||
if (op != MT_FREE && op != MT_REALLOC_ENTER)
|
||||
return 0;
|
||||
break;
|
||||
case MT_NEW:
|
||||
if (op != MT_DELETE)
|
||||
return 0;
|
||||
break;
|
||||
case MT_NEW_ARRAY:
|
||||
if (op != MT_DELETE_ARRAY)
|
||||
return 0;
|
||||
break;
|
||||
case MT_MMAP:
|
||||
case MT_MMAP64:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||
{
|
||||
struct rb_block *block = NULL;
|
||||
uint32_t payload_len = mt_msg->payload_len;
|
||||
unsigned long ptr;
|
||||
void *stack_data;
|
||||
unsigned long stack_size;
|
||||
|
||||
if (!process->tracing)
|
||||
return;
|
||||
@ -1200,11 +1274,17 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||
struct mt_alloc_payload_64 *mt_alloc = payload;
|
||||
|
||||
ptr = process->get_ulong(&mt_alloc->ptr);
|
||||
|
||||
stack_data = payload + sizeof(*mt_alloc);
|
||||
stack_size = (payload_len - sizeof(*mt_alloc));
|
||||
}
|
||||
else {
|
||||
struct mt_alloc_payload_32 *mt_alloc = payload;
|
||||
|
||||
ptr = process->get_ulong(&mt_alloc->ptr);
|
||||
|
||||
stack_data = payload + sizeof(*mt_alloc);
|
||||
stack_size = (payload_len - sizeof(*mt_alloc));
|
||||
}
|
||||
|
||||
debug(DEBUG_FUNCTION, "ptr=%#lx", ptr);
|
||||
@ -1219,6 +1299,14 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
process_rb_delete_block(process, block);
|
||||
}
|
||||
else {
|
||||
@ -1338,6 +1426,9 @@ void process_dump_sortby(struct process *process)
|
||||
case OPT_SORT_USAGE:
|
||||
_process_dump(process, sort_usage, skip_zero_allocations, options.output);
|
||||
break;
|
||||
case OPT_SORT_MISMATCHED:
|
||||
_process_dump(process, sort_mismatched, skip_non_mismatched, options.output);
|
||||
break;
|
||||
default:
|
||||
_process_dump(process, sort_allocations, skip_zero_allocations, options.output);
|
||||
break;
|
||||
|
||||
@ -109,6 +109,7 @@ void process_dump_sort_bytes_leaked(struct process *process, const char *outfile
|
||||
void process_dump_sort_allocations(struct process *process, const char *outfile);
|
||||
void process_dump_sort_total(struct process *process, const char *outfile);
|
||||
void process_dump_sort_tsc(struct process *process, const char *outfile);
|
||||
void process_dump_sort_mismatched(struct process *process, const char *outfile);
|
||||
void process_dump_stacks(struct process *process, const char *outfile);
|
||||
|
||||
void add_ignore_regex(regex_t *re);
|
||||
|
||||
@ -93,6 +93,7 @@ static struct cmd_opt dump_opts[] = {
|
||||
{ "average", 2, process_dump_sort_average, "sort by average allocation of bytes (usage / allocations)" },
|
||||
{ "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" },
|
||||
{ "stacks", 1, process_dump_stacks, "dump all stack sort by number of total allocations" },
|
||||
{ "total", 2, process_dump_sort_total, "sort by number of total allocations" },
|
||||
{ "tsc", 2, process_dump_sort_tsc, "sort by time stamp counter" },
|
||||
|
||||
@ -65,6 +65,10 @@ enum mt_operation {
|
||||
MT_STOP,
|
||||
MT_START,
|
||||
MT_DETACH,
|
||||
MT_NEW,
|
||||
MT_NEW_ARRAY,
|
||||
MT_DELETE,
|
||||
MT_DELETE_ARRAY,
|
||||
};
|
||||
|
||||
struct mt_msg {
|
||||
|
||||
22
mtrace.1
22
mtrace.1
@ -42,6 +42,8 @@ mtrace \- A dynamic memory allocation tracer
|
||||
[\-i|\-\-interactive]
|
||||
[\-l|\-\-logfile \fIfilename\fR]
|
||||
[\-n|\-\-nocpp]
|
||||
[\-N|\-\-nohwbp]
|
||||
[\-S|\-\-sanity]
|
||||
[\-O|\-\-omit \fIfilename\fR]
|
||||
[\-u|\-\-user \fIusername\fR]
|
||||
[\-v|\-\-verbose]
|
||||
@ -70,6 +72,8 @@ mtrace \- A dynamic memory allocation tracer
|
||||
[\-D|\-\-debug \fImask\fR]
|
||||
[\-l|\-\-logfile \fIfilename\fR]
|
||||
[\-n|\-\-nocpp]
|
||||
[\-N|\-\-nohwbp]
|
||||
[\-S|\-\-sanity]
|
||||
[\-O|\-\-omit \fIfilename\fR]
|
||||
[\-u|\-\-user \fIusername\fR]
|
||||
[\-v|\-\-verbose]
|
||||
@ -266,6 +270,9 @@ since the trace will be split into to different actions.
|
||||
.IP "\-n, \-\-nocpp"
|
||||
Disable the trace of C++ allocation operators. This is safe and faster for libstdc++,
|
||||
since this library does call malloc() and free() inside the allocation operators.
|
||||
.IP "\-N, \-\-nohwbp"
|
||||
Disable the usage of hardware breakpoints. This options is intended for some
|
||||
virtual machines, where hardware breakpoints not working.
|
||||
.IP "\-p, \-\-pid \fIpid"
|
||||
Attach to the process with the process ID \fIpid\fR and begin tracing.
|
||||
This option can be used together with passing a command to execute.
|
||||
@ -301,6 +308,12 @@ Sort by number of bytes leaked (only useful with \-a option).
|
||||
.RE
|
||||
.RE
|
||||
.RS
|
||||
\fImismatched\fR
|
||||
.RS
|
||||
Sort by number of mismatched releases (only useful with \-S option).
|
||||
.RE
|
||||
.RE
|
||||
.RS
|
||||
\fIleaks\fR
|
||||
.RS
|
||||
Sort by number of leaked allocations (only useful with \-a option).
|
||||
@ -330,6 +343,9 @@ Sort by the pseudo time stamp counter. Each stack backtrace will get an increme
|
||||
Sort by number of bytes in use of all open allocations.
|
||||
.RE
|
||||
.RE
|
||||
.IP "\-S, \-\-sanity"
|
||||
Check mismatching operations against new/new[] allocations. This options also
|
||||
sets the sort-by options to mismatched.
|
||||
.IP "\-t, \-\-trace"
|
||||
Run \fBmtrace\fR in trace mode. In this mode all attached processes will run under
|
||||
the control of \fBmtrace\fR and all dynamic memory function calls will be traced.
|
||||
@ -380,9 +396,9 @@ at any time. It accepts a maximum of three parameters:
|
||||
.RS
|
||||
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,
|
||||
\fIstacks\fR, \fItotal\fR, \fItsc\fR and \fIusage\fR). See \-S option for
|
||||
more details about the sortby keywords. The default sort order is
|
||||
\fIallocations\fR when no sortby parameter is used.
|
||||
\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
|
||||
is \fIallocations\fR when no sortby parameter is used.
|
||||
.RE
|
||||
.RE
|
||||
.RS
|
||||
|
||||
37
options.c
37
options.c
@ -48,7 +48,7 @@
|
||||
#define MIN_STACK 4
|
||||
#define MAX_STACK 64
|
||||
|
||||
#define DEFAULT_STACK 15
|
||||
#define DEFAULT_STACK 16
|
||||
#define DEFAULT_PORT 4576
|
||||
|
||||
static char *sockdef;
|
||||
@ -89,15 +89,17 @@ static void usage(void)
|
||||
" -h, --help display this help and exit\n"
|
||||
" -i, --interactive interactive client mode\n"
|
||||
" -O, --omit=FILE do not place breakpoint in this file\n"
|
||||
" -k, --kill abort mtrace on unexpected error conditon\n"
|
||||
" -k, --kill abort mtrace due unexpected error conditon\n"
|
||||
" -l, --logfile use log file instead of socket connection\n"
|
||||
" -n, --nocpp disable trace of c++ allocation operators (faster for libstdc++)\n"
|
||||
" -N, --nohwbp disable hardware breakpoint support\n"
|
||||
" -o, --output=FILE write the trace output to file with given name\n"
|
||||
" -p, --pid=PID attach to the process with the process ID pid (may be repeated)\n"
|
||||
" -P, --port=PORT socket port (default: " STR(DEFAULT_PORT) ")\n"
|
||||
" -r, --remote=addr remote use address (path, address or host)\n"
|
||||
" -s, --sort-by=type sort dump by type:\n"
|
||||
" allocations, average, bytes-leaked, leaks, stacks, total, tsc, usage\n"
|
||||
" -S, --sanity check mismatching operations against new/new[] allocations\n"
|
||||
" -t, --trace trace mode\n"
|
||||
" -u, --user=USERNAME run command with the userid, groupid of username\n"
|
||||
" -V, --version output version information and exit\n"
|
||||
@ -276,9 +278,11 @@ char **process_options(int argc, char **argv)
|
||||
options.opt_b = NULL;
|
||||
options.opt_O = NULL;
|
||||
options.sort_by = -1;
|
||||
options.sanity = 0;
|
||||
options.debug = 0;
|
||||
options.kill = 0;
|
||||
options.nocpp = 0;
|
||||
options.nohwbp = 0;
|
||||
|
||||
for(;;) {
|
||||
int c;
|
||||
@ -296,13 +300,15 @@ char **process_options(int argc, char **argv)
|
||||
{ "interactive", 0, 0, 'i' },
|
||||
{ "kill", 0, 0, 'k' },
|
||||
{ "logfile", 1, 0, 'l' },
|
||||
{ "nocpp", 1, 0, 'n' },
|
||||
{ "nocpp", 0, 0, 'n' },
|
||||
{ "nohwbp", 0, 0, 'N' },
|
||||
{ "output", 1, 0, 'o' },
|
||||
{ "omit", 1, 0, 'O' },
|
||||
{ "pid", 1, 0, 'p' },
|
||||
{ "port", 1, 0, 'P' },
|
||||
{ "remote", 1, 0, 'r' },
|
||||
{ "sort-by", 1, 0, 's' },
|
||||
{ "sanity", 0, 0, 'S' },
|
||||
{ "trace", 0, 0, 't' },
|
||||
{ "user", 1, 0, 'u' },
|
||||
{ "version", 0, 0, 'V' },
|
||||
@ -312,7 +318,7 @@ char **process_options(int argc, char **argv)
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv,
|
||||
"+aefhikLntVvw"
|
||||
"+aefhikLnNStVvw"
|
||||
"b:c:d:D:F:l:o:O:p:P:r:s:u:",
|
||||
long_options,
|
||||
&option_index);
|
||||
@ -414,6 +420,9 @@ char **process_options(int argc, char **argv)
|
||||
case 'n':
|
||||
options.nocpp = 1;
|
||||
break;
|
||||
case 'N':
|
||||
options.nohwbp = 1;
|
||||
break;
|
||||
case 'p':
|
||||
{
|
||||
struct opt_p_t *tmp = malloc(sizeof(*tmp));
|
||||
@ -452,6 +461,9 @@ char **process_options(int argc, char **argv)
|
||||
if (!strncmp(optarg, "leaks", 1))
|
||||
options.sort_by = OPT_SORT_LEAKS;
|
||||
else
|
||||
if (!strncmp(optarg, "mismatched", 1))
|
||||
options.sort_by = OPT_SORT_MISMATCHED;
|
||||
else
|
||||
if (!strncmp(optarg, "stacks", 1))
|
||||
options.sort_by = OPT_SORT_STACKS;
|
||||
else
|
||||
@ -468,6 +480,9 @@ char **process_options(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
options.sanity = 1;
|
||||
break;
|
||||
case 't':
|
||||
options.trace = 1;
|
||||
break;
|
||||
@ -545,6 +560,16 @@ char **process_options(int argc, char **argv)
|
||||
err_usage();
|
||||
}
|
||||
|
||||
if (options.nohwbp) {
|
||||
fprintf(stderr, "%s: client mode does not require -N\n", progname);
|
||||
err_usage();
|
||||
}
|
||||
|
||||
if (options.sanity) {
|
||||
fprintf(stderr, "%s: client mode does not require -S\n", progname);
|
||||
err_usage();
|
||||
}
|
||||
|
||||
if (options.user) {
|
||||
fprintf(stderr, "%s: user can only passed in trace mode\n", progname);
|
||||
err_usage();
|
||||
@ -583,6 +608,10 @@ char **process_options(int argc, char **argv)
|
||||
options.sort_by = -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (options.sanity)
|
||||
options.sort_by = OPT_SORT_MISMATCHED;
|
||||
}
|
||||
|
||||
if (output) {
|
||||
if (options.interactive) {
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#define OPT_SORT_TOTAL 5
|
||||
#define OPT_SORT_TSC 6
|
||||
#define OPT_SORT_USAGE 7
|
||||
#define OPT_SORT_MISMATCHED 8
|
||||
|
||||
struct options_t options;
|
||||
|
||||
@ -83,8 +84,10 @@ struct options_t {
|
||||
struct opt_b_t *opt_b; /* binary search path(s) */
|
||||
struct opt_O_t *opt_O; /* omits path list */
|
||||
int sort_by; /* sort dump in non interative and non server mode */
|
||||
int sanity; /* check mismatching operations against new/new[] allocations */
|
||||
int debug; /* debug */
|
||||
int nocpp; /* disable trace of c++ allocation operators */
|
||||
int nohwbp; /* disable hardware breakpoint support */
|
||||
};
|
||||
|
||||
char **process_options(int argc, char **argv);
|
||||
|
||||
64
report.c
64
report.c
@ -50,6 +50,7 @@ static int report_alloc64(struct task *task, enum mt_operation op, unsigned long
|
||||
alloc->size = (uint64_t)size;
|
||||
|
||||
if (depth) {
|
||||
if (libsym)
|
||||
alloc->data[i++] = libsym->addr;
|
||||
|
||||
if (backtrace_init_unwind(task) >= 0) {
|
||||
@ -83,6 +84,7 @@ static int report_alloc32(struct task *task, enum mt_operation op, unsigned long
|
||||
alloc->size = (uint32_t)size;
|
||||
|
||||
if (depth) {
|
||||
if (libsym)
|
||||
alloc->data[i++] = libsym->addr;
|
||||
|
||||
if (backtrace_init_unwind(task) >= 0) {
|
||||
@ -128,7 +130,7 @@ static int _null(struct task *task, struct library_symbol *libsym)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _report_malloc(struct task *task, struct library_symbol *libsym)
|
||||
static int _report_alloc_op(struct task *task, struct library_symbol *libsym, enum mt_operation op)
|
||||
{
|
||||
if (!server_connected())
|
||||
return -1;
|
||||
@ -136,17 +138,47 @@ static int _report_malloc(struct task *task, struct library_symbol *libsym)
|
||||
unsigned long size = fetch_param(task, 0);
|
||||
unsigned long ret = fetch_retval(task);
|
||||
|
||||
return report_alloc(task, MT_MALLOC, ret, size, options.bt_depth, libsym);
|
||||
return report_alloc(task, op, ret, size, options.bt_depth, libsym);
|
||||
}
|
||||
|
||||
static int report_free(struct task *task, struct library_symbol *libsym)
|
||||
static int _report_malloc(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
return _report_alloc_op(task, libsym, MT_MALLOC);
|
||||
}
|
||||
|
||||
static int _report_new(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
return _report_alloc_op(task, libsym, options.sanity ? MT_NEW : MT_MALLOC);
|
||||
}
|
||||
|
||||
static int _report_new_array(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
return _report_alloc_op(task, libsym, options.sanity ? MT_NEW_ARRAY : MT_MALLOC);
|
||||
}
|
||||
|
||||
static int _report_free_op(struct task *task, struct library_symbol *libsym, enum mt_operation op)
|
||||
{
|
||||
if (!server_connected())
|
||||
return -1;
|
||||
|
||||
unsigned long addr = fetch_param(task, 0);
|
||||
|
||||
return report_alloc(task, MT_FREE, addr, 0, 0, libsym);
|
||||
return report_alloc(task, op, addr, 0, options.sanity ? options.bt_depth : 0, NULL);
|
||||
}
|
||||
|
||||
static int report_free(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
return _report_free_op(task, libsym, MT_FREE);
|
||||
}
|
||||
|
||||
static int report_delete(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
return _report_free_op(task, libsym, options.sanity ? MT_DELETE : MT_FREE);
|
||||
}
|
||||
|
||||
static int report_delete_array(struct task *task, struct library_symbol *libsym)
|
||||
{
|
||||
return _report_free_op(task, libsym, options.sanity ? MT_DELETE_ARRAY : MT_FREE);
|
||||
}
|
||||
|
||||
static int _report_realloc(struct task *task, struct library_symbol *libsym)
|
||||
@ -345,20 +377,20 @@ static const struct function flist[] = {
|
||||
{ "mremap", "mremap", 0, report_mremap, _report_mremap },
|
||||
{ "cfree", "cfree", 1, report_free, NULL },
|
||||
|
||||
{ "new(unsigned int)", "_Znwj", 1, NULL, _report_malloc },
|
||||
{ "new[](unsigned int)", "_Znaj", 1, NULL, _report_malloc },
|
||||
{ "new(unsigned int, std::nothrow_t const&)", "_ZnwjRKSt9nothrow_t", 1, NULL, _report_malloc },
|
||||
{ "new[](unsigned int, std::nothrow_t const&)", "_ZnajRKSt9nothrow_t", 1, NULL, _report_malloc },
|
||||
{ "new(unsigned int)", "_Znwj", 1, NULL, _report_new },
|
||||
{ "new[](unsigned int)", "_Znaj", 1, NULL, _report_new_array },
|
||||
{ "new(unsigned int, std::nothrow_t const&)", "_ZnwjRKSt9nothrow_t", 1, NULL, _report_new },
|
||||
{ "new[](unsigned int, std::nothrow_t const&)", "_ZnajRKSt9nothrow_t", 1, NULL, _report_new_array },
|
||||
|
||||
{ "new(unsigned long)", "_Znwm", 1, NULL, _report_malloc },
|
||||
{ "new[](unsigned long)", "_Znam", 1, NULL, _report_malloc },
|
||||
{ "new(unsigned long, std::nothrow_t const&)", "_ZnwmRKSt9nothrow_t", 1, NULL, _report_malloc },
|
||||
{ "new[](unsigned long, std::nothrow_t const&)", "_ZnamRKSt9nothrow_t", 1, NULL, _report_malloc },
|
||||
{ "new(unsigned long)", "_Znwm", 1, NULL, _report_new },
|
||||
{ "new[](unsigned long)", "_Znam", 1, NULL, _report_new_array },
|
||||
{ "new(unsigned long, std::nothrow_t const&)", "_ZnwmRKSt9nothrow_t", 1, NULL, _report_new },
|
||||
{ "new[](unsigned long, std::nothrow_t const&)", "_ZnamRKSt9nothrow_t", 1, NULL, _report_new_array },
|
||||
|
||||
{ "delete(void*)", "_ZdlPv", 1, report_free, NULL },
|
||||
{ "delete[](void*)", "_ZdaPv", 1, report_free, NULL },
|
||||
{ "delete(void*, std::nothrow_t const&)", "_ZdlPvRKSt9nothrow_t", 1, report_free, NULL },
|
||||
{ "delete[](void*, std::nothrow_t const&)", "_ZdaPvRKSt9nothrow_t", 1, report_free, NULL },
|
||||
{ "delete(void*)", "_ZdlPv", 1, report_delete, NULL },
|
||||
{ "delete[](void*)", "_ZdaPv", 1, report_delete_array, NULL },
|
||||
{ "delete(void*, std::nothrow_t const&)", "_ZdlPvRKSt9nothrow_t", 1, report_delete, NULL },
|
||||
{ "delete[](void*, std::nothrow_t const&)", "_ZdaPvRKSt9nothrow_t", 1, report_delete_array, NULL },
|
||||
};
|
||||
|
||||
const struct function *flist_matches_symbol(const char *sym_name)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user