3 * by Wolfram Gloger 1995.
6 * Copyright (C) 2002-2007, Parrot Foundation.
17 # include <asm/signal.h>
20 #include "malloc-trace.h"
22 #define ACTION_BUF_SIZE 1024
23 #define TIMESTAMP_FREQ 50
24 #define LOG_NAME "/tmp/mtrace"
26 static void malloc_trace_destructor(void);
28 static ACTION buffer
[ACTION_BUF_SIZE
+1];
29 static int buffer_i
= 0;
31 static int tracing
= 1;
33 static char *initial_brk
= 0;
55 =item C<static void open_log_file()>
57 Open a logfile for storing debugging information.
67 const unsigned version
= MTRACE_VERSION
;
69 char cmdline
[128], *s
;
76 sprintf(name
, "/proc/%d/cmdline", pid
);
77 fd2
= open(name
, O_RDONLY
);
78 if (fd2
>=0 && (count
= read(fd2
, cmdline
, 127)) > 0) {
81 for (s
=cmdline
; *s
++;); s
--;
82 while (--s
>cmdline
&& *s
!='/');
84 sprintf(name
, LOG_NAME
".%.12s.%d", s
, pid
);
87 sprintf(name
, LOG_NAME
".%d", pid
);
90 sprintf(name
, LOG_NAME
".%d", pid
);
92 fd
= open(name
, O_WRONLY
|O_CREAT
, 0600);
94 write(fd
, &version
, sizeof (version
));
95 write(fd
, &initial_brk
, sizeof (initial_brk
));
102 =item C<static void malloc_trace_destructor(void)>
104 Print out a final timestamp and message to the log file.
111 malloc_trace_destructor(void)
115 /* produce final timestamp */
116 gettimeofday(&t
, NULL
);
117 buffer
[buffer_i
].code
= CODE_TIMESTAMP
;
118 buffer
[buffer_i
].size
= t
.tv_sec
;
119 buffer
[buffer_i
].ptr
= (void *)t
.tv_usec
;
120 buffer
[buffer_i
].ptr2
= NULL
;
122 if (fd
< 0) open_log_file();
123 if (getpid() != pid
) { /* Oops, must have forked... */
124 if (fd
>= 0) close(fd
);
127 if (fd
>= 0) write(fd
, buffer
, buffer_i
*sizeof (ACTION
));
128 write(2, "<end malloc trace>\n", 19);
129 if (fd
>= 0) close(fd
);
136 =item C<static void malloc_segv_handler(int i, struct sigcontext_struct sc)>
138 Catch a segfault signal, print an error message, and end the logfile.
145 malloc_segv_handler(int i
, struct sigcontext_struct sc
)
148 fprintf(stderr
, "malloc-trace: caught SEGV signal.\n");
149 fprintf(stderr
, "sc.cr2 = %8lx\n", (unsigned long)sc
.cr2
);
150 malloc_trace_destructor();
157 =item C<static void malloc_record(int code, size_t size, void *ptr, void *ptr2)>
159 Record information about the allocation into the logfile.
166 malloc_record(int code
, size_t size
, void *ptr
, void *ptr2
)
168 static long count
= 0;
171 if (!tracing
) return;
173 if (count
== 0) signal(SIGSEGV
, (void (*)(int))malloc_segv_handler
);
175 if ((count
++ % TIMESTAMP_FREQ
) == 0) {
176 gettimeofday(&t
, NULL
);
177 buffer
[buffer_i
].code
= CODE_TIMESTAMP
;
178 buffer
[buffer_i
].size
= t
.tv_sec
;
179 buffer
[buffer_i
].ptr
= (void *)t
.tv_usec
;
180 buffer
[buffer_i
].ptr2
= NULL
;
183 buffer
[buffer_i
].code
= code
;
184 buffer
[buffer_i
].size
= size
;
185 buffer
[buffer_i
].ptr
= ptr
;
186 buffer
[buffer_i
].ptr2
= ptr2
;
187 if (++buffer_i
>= ACTION_BUF_SIZE
) {
188 if (fd
< 0) open_log_file();
189 if (getpid() != pid
) { /* Oops, must have forked... */
193 if (fd
>= 0) write(fd
, buffer
, buffer_i
*sizeof (ACTION
));
198 void* _real_malloc(size_t bytes
);
202 =item C<void* malloc(size_t bytes)>
204 Allocate memory with the specified size in bytes. Record information about it
211 void* malloc(size_t bytes
)
215 if (initial_brk
== 0) { /* Must be the first time. */
216 initial_brk
= sbrk(0);
217 atexit(malloc_trace_destructor
);
219 ptr
= _real_malloc(bytes
);
220 malloc_record(CODE_MALLOC
, bytes
, ptr
, 0);
223 #define malloc _real_malloc
225 void _real_free(void* mem
);
229 =item C<void free(void* mem)>
231 Record information about the free in the logfile, and free the memory.
239 malloc_record(CODE_FREE
, 0, mem
, 0);
242 #define free _real_free
244 void* _real_realloc(void* mem
, size_t bytes
);
248 =item C<void* realloc(void* mem, size_t bytes)>
250 Resize the allocated memory buffer to the new size.
256 void* realloc(void* mem
, size_t bytes
)
260 ptr
= _real_realloc(mem
, bytes
);
261 malloc_record(CODE_REALLOC
, bytes
, mem
, ptr
);
264 #define realloc _real_realloc
266 void* _real_memalign(size_t alignment
, size_t bytes
);
270 =item C<void* memalign(size_t alignment, size_t bytes)>
272 Return an allocated memory buffer that's of at least the given size in bytes
273 and is aligned along the given boundary.
279 void* memalign(size_t alignment
, size_t bytes
)
283 if (initial_brk
== 0) { /* Must be the first time. */
284 initial_brk
= sbrk(0);
285 atexit(malloc_trace_destructor
);
287 ptr
= _real_memalign(alignment
, bytes
);
288 malloc_record(CODE_MEMALIGN
, bytes
, ptr
, (void*)alignment
);
291 #define memalign _real_memalign
293 void* _real_calloc(size_t n
, size_t elem_size
);
297 =item C<void* calloc(size_t n, size_t elem_size)>
299 Allocate memory of the given size, initializing the memory to the given value.
305 void* calloc(size_t n
, size_t elem_size
)
309 if (initial_brk
== 0) { /* Must be the first time. */
310 initial_brk
= sbrk(0);
311 atexit(malloc_trace_destructor
);
313 ptr
= _real_calloc(n
, elem_size
);
314 malloc_record(CODE_CALLOC
, n
*elem_size
, ptr
, 0);
317 #define calloc _real_calloc
319 void _real_cfree(void *mem
);
323 =item C<void cfree(void *mem)>
325 free the given buffer, recording information about it in the log.
331 void cfree(void *mem
)
333 malloc_record(CODE_CFREE
, 0, mem
, 0);
336 #define cfree _real_cfree
350 * c-file-style: "parrot"
352 * vim: expandtab shiftwidth=4: