1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/trace-malloc/leakstats.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,161 @@ 1.4 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 +#include <stdio.h> 1.10 +#include <stdlib.h> 1.11 +#include <string.h> 1.12 +#include <errno.h> 1.13 +#ifdef HAVE_GETOPT_H 1.14 +#include <getopt.h> 1.15 +#else 1.16 +extern int getopt(int argc, char *const *argv, const char *shortopts); 1.17 +extern char *optarg; 1.18 +extern int optind; 1.19 +#ifdef XP_WIN32 1.20 +int optind=1; 1.21 +#endif 1.22 +#endif 1.23 +#include <time.h> 1.24 +#include "nsTraceMalloc.h" 1.25 +#include "tmreader.h" 1.26 +#include "prlog.h" 1.27 + 1.28 +static char *program; 1.29 + 1.30 +typedef struct handler_data { 1.31 + uint32_t current_heapsize; 1.32 + uint32_t max_heapsize; 1.33 + uint32_t bytes_allocated; 1.34 + uint32_t current_allocations; 1.35 + uint32_t total_allocations; 1.36 + uint32_t unmatched_frees; 1.37 + int finished; 1.38 +} handler_data; 1.39 + 1.40 +static void handler_data_init(handler_data *data) 1.41 +{ 1.42 + data->current_heapsize = 0; 1.43 + data->max_heapsize = 0; 1.44 + data->bytes_allocated = 0; 1.45 + data->current_allocations = 0; 1.46 + data->total_allocations = 0; 1.47 + data->unmatched_frees = 0; 1.48 + data->finished = 0; 1.49 +} 1.50 + 1.51 +static void handler_data_finish(handler_data *data) 1.52 +{ 1.53 +} 1.54 + 1.55 +static void my_tmevent_handler(tmreader *tmr, tmevent *event) 1.56 +{ 1.57 + handler_data *data = (handler_data*) tmr->data; 1.58 + 1.59 + switch (event->type) { 1.60 + case TM_EVENT_REALLOC: 1.61 + /* On Windows, original allocation could be before we overrode malloc */ 1.62 + if (event->u.alloc.oldserial != 0) { 1.63 + data->current_heapsize -= event->u.alloc.oldsize; 1.64 + --data->current_allocations; 1.65 + } else { 1.66 + ++data->unmatched_frees; 1.67 + PR_ASSERT(event->u.alloc.oldsize == 0); 1.68 + } 1.69 + /* fall-through intentional */ 1.70 + case TM_EVENT_MALLOC: 1.71 + case TM_EVENT_CALLOC: 1.72 + ++data->current_allocations; 1.73 + ++data->total_allocations; 1.74 + data->bytes_allocated += event->u.alloc.size; 1.75 + data->current_heapsize += event->u.alloc.size; 1.76 + if (data->current_heapsize > data->max_heapsize) 1.77 + data->max_heapsize = data->current_heapsize; 1.78 + break; 1.79 + case TM_EVENT_FREE: 1.80 + /* On Windows, original allocation could be before we overrode malloc */ 1.81 + if (event->serial != 0) { 1.82 + --data->current_allocations; 1.83 + data->current_heapsize -= event->u.alloc.size; 1.84 + } else { 1.85 + ++data->unmatched_frees; 1.86 + PR_ASSERT(event->u.alloc.size == 0); 1.87 + } 1.88 + break; 1.89 + case TM_EVENT_STATS: 1.90 + data->finished = 1; 1.91 + break; 1.92 + } 1.93 +} 1.94 + 1.95 + 1.96 +int main(int argc, char **argv) 1.97 +{ 1.98 + int i, j, rv; 1.99 + tmreader *tmr; 1.100 + FILE *fp; 1.101 + time_t start; 1.102 + handler_data data; 1.103 + 1.104 + program = *argv; 1.105 + 1.106 + handler_data_init(&data); 1.107 + tmr = tmreader_new(program, &data); 1.108 + if (!tmr) { 1.109 + perror(program); 1.110 + exit(1); 1.111 + } 1.112 + 1.113 + start = time(NULL); 1.114 + fprintf(stdout, "%s starting at %s", program, ctime(&start)); 1.115 + fflush(stdout); 1.116 + 1.117 + argc -= optind; 1.118 + argv += optind; 1.119 + if (argc == 0) { 1.120 + if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0) 1.121 + exit(1); 1.122 + } else { 1.123 + for (i = j = 0; i < argc; i++) { 1.124 + fp = fopen(argv[i], "r"); 1.125 + if (!fp) { 1.126 + fprintf(stderr, 1.127 + "TEST-UNEXPECTED-FAIL | leakstats | can't open %s: %s\n", 1.128 + argv[i], strerror(errno)); 1.129 + exit(1); 1.130 + } 1.131 + rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler); 1.132 + if (rv < 0) 1.133 + exit(1); 1.134 + if (rv > 0) 1.135 + j++; 1.136 + fclose(fp); 1.137 + } 1.138 + if (j == 0) 1.139 + exit(1); 1.140 + } 1.141 + 1.142 + if (!data.finished) { 1.143 + fprintf(stderr, "TEST-UNEXPECTED-FAIL | leakstats | log file incomplete\n"); 1.144 + exit(1); 1.145 + } 1.146 + 1.147 + fprintf(stdout, 1.148 + "Leaks: %u bytes, %u allocations\n" 1.149 + "Maximum Heap Size: %u bytes\n" 1.150 + "%u bytes were allocated in %u allocations.\n", 1.151 + data.current_heapsize, data.current_allocations, 1.152 + data.max_heapsize, 1.153 + data.bytes_allocated, data.total_allocations); 1.154 + if (data.unmatched_frees != 0) 1.155 + fprintf(stdout, 1.156 + "Logged %u free (or realloc) calls for which we missed the " 1.157 + "original malloc.\n", 1.158 + data.unmatched_frees); 1.159 + 1.160 + handler_data_finish(&data); 1.161 + tmreader_destroy(tmr); 1.162 + 1.163 + exit(0); 1.164 +}