OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / bionic / libc / bionic / malloc_debug_qemu.c
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * Contains implementation of memory allocation routines instrumented for
31  * usage in the emulator to detect memory allocation violations, such as
32  * memory leaks, buffer overruns, etc.
33  * Code, implemented here is intended to run in the emulated environment only,
34  * and serves simply as hooks into memory allocation routines. Main job of this
35  * code is to notify the emulator about memory being allocated/deallocated,
36  * providing information about each allocation. The idea is that emulator will
37  * keep list of currently allocated blocks, and, knowing boundaries of each
38  * block it will be able to verify that ld/st access to these blocks don't step
39  * over boundaries set for the user. To enforce that, each memory block
40  * allocated by this code is guarded with "prefix" and "suffix" areas, so
41  * every time emulator detects access to any of these guarding areas, it can be
42  * considered as access violation.
43  */
44
45 #include <stdlib.h>
46 #include <stddef.h>
47 #include <stdio.h>
48 #include <fcntl.h>
49 #include <sys/mman.h>
50 #include <pthread.h>
51 #include <unistd.h>
52 #include <errno.h>
53 #include "dlmalloc.h"
54 #include "logd.h"
55 #include "malloc_debug_common.h"
56
57 /* This file should be included into the build only when
58  * MALLOC_QEMU_INSTRUMENT macro is defined. */
59 #ifndef MALLOC_QEMU_INSTRUMENT
60 #error MALLOC_QEMU_INSTRUMENT is not defined.
61 #endif  // !MALLOC_QEMU_INSTRUMENT
62
63 /* Controls access violation test performed to make sure that we catch AVs
64  * all the time they occur. See test_access_violation for more info. This macro
65  * is used for internal testing purposes and should always be set to zero for
66  * the production builds. */
67 #define TEST_ACCESS_VIOLATIONS  0
68
69 // =============================================================================
70 // Communication structures
71 // =============================================================================
72
73 /* Describes memory block allocated from the heap. This structure is passed
74  * along with TRACE_DEV_REG_MALLOC event. This descriptor is used to inform
75  * the emulator about new memory block being allocated from the heap. The entire
76  * structure is initialized by the guest system before event is fired up. It is
77  * important to remember that same structure (an exact copy, except for
78  * replacing pointers with target_ulong) is also declared in the emulator's
79  * sources (file memcheck/memcheck_common.h). So, every time a change is made to
80  * any of these two declaration, another one must be also updated accordingly.
81  */
82 typedef struct MallocDesc {
83     /* Pointer to the memory block actually allocated from the heap. Note that
84      * this is not the pointer that is returned to the malloc's caller. Pointer
85      * returned to the caller is calculated by adding value stored in this field
86      * to the value stored in prefix_size field of this structure.
87      */
88     void*       ptr;
89
90     /* Number of bytes requested by the malloc's caller. */
91     uint32_t    requested_bytes;
92
93     /* Byte size of the prefix data. Actual pointer returned to the malloc's
94      * caller is calculated by adding value stored in this field to the value
95      * stored in in the ptr field of this structure.
96      */
97     uint32_t    prefix_size;
98
99     /* Byte size of the suffix data. */
100     uint32_t    suffix_size;
101
102     /* Id of the process that initialized libc instance, in which allocation
103      * has occurred. This field is used by the emulator to report errors in
104      * the course of TRACE_DEV_REG_MALLOC event handling. In case of an error,
105      * emulator sets this field to zero (invalid value for a process ID).
106      */
107     uint32_t    libc_pid;
108
109     /* Id of the process in context of which allocation has occurred.
110      * Value in this field may differ from libc_pid value, if process that
111      * is doing allocation has been forked from the process that initialized
112      * libc instance.
113      */
114     uint32_t    allocator_pid;
115
116     /* Number of access violations detected on this allocation. */
117     uint32_t    av_count;
118 } MallocDesc;
119
120 /* Describes memory block info queried from emulator. This structure is passed
121  * along with TRACE_DEV_REG_QUERY_MALLOC event. When handling free and realloc
122  * calls, it is required that we have information about memory blocks that were
123  * actually allocated in previous calls to malloc, calloc, memalign, or realloc.
124  * Since we don't keep this information directly in the allocated block, but
125  * rather we keep it in the emulator, we need to query emulator for that
126  * information with TRACE_DEV_REG_QUERY_MALLOC query. The entire structure is
127  * initialized by the guest system before event is fired up. It is important to
128  * remember that same structure (an exact copy, except for replacing pointers
129  * with target_ulong) is also declared in the emulator's sources (file
130  * memcheck/memecheck_common.h). So, every time a change is made to any of these
131  * two declaration, another one must be also updated accordingly.
132  */
133 typedef struct MallocDescQuery {
134     /* Pointer, for which information is queried. Note that this pointer doesn't
135      * have to be exact pointer returned to malloc's caller, but can point
136      * anywhere inside an allocated block, including guarding areas. Emulator
137      * will respond with information about allocated block that contains this
138      * pointer.
139      */
140     void*       ptr;
141
142     /* Id of the process that initialized libc instance, in which this query
143      * is called. This field is used by the emulator to report errors in
144      * the course of TRACE_DEV_REG_QUERY_MALLOC event handling. In case of an
145      * error, emulator sets this field to zero (invalid value for a process ID).
146      */
147     uint32_t    libc_pid;
148
149     /* Process ID in context of which query is made. */
150     uint32_t    query_pid;
151
152     /* Code of the allocation routine, in context of which query has been made:
153      *  1 - free
154      *  2 - realloc
155      */
156     uint32_t    routine;
157
158     /* Address of memory allocation descriptor for the queried pointer.
159      * Descriptor, addressed by this field is initialized by the emulator in
160      * response to the query.
161      */
162     MallocDesc*  desc;
163 } MallocDescQuery;
164
165 /* Describes memory block that is being freed back to the heap. This structure
166  * is passed along with TRACE_DEV_REG_FREE_PTR event. The entire structure is
167  * initialized by the guest system before event is fired up. It is important to
168  * remember that same structure (an exact copy, except for replacing pointers
169  * with target_ulong) is also declared in the emulator's sources (file
170  * memcheck/memecheck_common.h). So, every time a change is made to any of these
171  * two declaration, another one must be also updated accordingly.
172  */
173 typedef struct MallocFree {
174     /* Pointer to be freed. */
175     void*       ptr;
176
177     /* Id of the process that initialized libc instance, in which this free
178      * is called. This field is used by the emulator to report errors in
179      * the course of TRACE_DEV_REG_FREE_PTR event handling. In case of an
180      * error, emulator sets this field to zero (invalid value for a process ID).
181      */
182     uint32_t    libc_pid;
183
184     /* Process ID in context of which memory is being freed. */
185     uint32_t    free_pid;
186 } MallocFree;
187
188 // =============================================================================
189 // Communication events
190 // =============================================================================
191
192 /* Notifies the emulator that libc has been initialized for a process.
193  * Event's value parameter is PID for the process in context of which libc has
194  * been initialized.
195  */
196 #define TRACE_DEV_REG_LIBC_INIT             1536
197
198 /* Notifies the emulator about new memory block been allocated.
199  * Event's value parameter points to MallocDesc instance that contains
200  * allocated block information. Note that 'libc_pid' field of the descriptor
201  * is used by emulator to report failure in handling this event. In case
202  * of a failure emulator will zero that field before completing this event.
203  */
204 #define TRACE_DEV_REG_MALLOC                1537
205
206 /* Notifies the emulator about memory block being freed.
207  * Event's value parameter points to MallocFree descriptor that contains
208  * information about block that's being freed. Note that 'libc_pid' field
209  * of the descriptor is used by emulator to report failure in handling this
210  * event. In case of a failure emulator will zero that field before completing
211  * this event.
212  */
213 #define TRACE_DEV_REG_FREE_PTR              1538
214
215 /* Queries the emulator about allocated memory block information.
216  * Event's value parameter points to MallocDescQuery descriptor that contains
217  * query parameters. Note that 'libc_pid' field of the descriptor is used by
218  * emulator to report failure in handling this event. In case of a failure
219  * emulator will zero that field before completing this event.
220  */
221 #define TRACE_DEV_REG_QUERY_MALLOC          1539
222
223 /* Queries the emulator to print a string to its stdout.
224  * Event's value parameter points to a zero-terminated string to be printed.
225  */
226 #define TRACE_DEV_REG_PRINT_USER_STR        1540
227
228 static void notify_qemu_string(const char* str);
229 static void qemu_log(int prio, const char* fmt, ...);
230 static void dump_malloc_descriptor(char* str,
231                                    size_t str_buf_size,
232                                    const MallocDesc* desc);
233
234 // =============================================================================
235 // Macros
236 // =============================================================================
237
238 /* Defines default size of allocation prefix.
239  * Note that we make prefix area quite large in order to increase chances of
240  * catching buffer overflow. */
241 #define DEFAULT_PREFIX_SIZE     (malloc_alignment * 4)
242
243 /* Defines default size of allocation suffix.
244  * Note that we make suffix area quite large in order to increase chances of
245  * catching buffer overflow. */
246 #define DEFAULT_SUFFIX_SIZE     (malloc_alignment * 4)
247
248 /* Debug tracing has been enabled by the emulator. */
249 #define DEBUG_TRACING_ENABLED   0x00000001
250 /* Error tracing has been enabled by the emulator. */
251 #define ERROR_TRACING_ENABLED   0x00000002
252 /* Info tracing has been enabled by the emulator. */
253 #define INFO_TRACING_ENABLED    0x00000004
254 /* All tracing flags combined. */
255 #define ALL_TRACING_ENABLED (DEBUG_TRACING_ENABLED |    \
256                              ERROR_TRACING_ENABLED |    \
257                              INFO_TRACING_ENABLED)
258
259 /* Prints a string to the emulator's stdout.
260  * In early stages of system loading, logging mesages via
261  * __libc_android_log_print API is not available, because ADB API has not been
262  * hooked up yet. So, in order to see such messages we need to print them to
263  * the emulator's stdout.
264  * Parameters passed to this macro are the same as parameters for printf
265  * routine.
266  */
267 #define TR(...)                                         \
268     do {                                                \
269         char tr_str[4096];                              \
270         snprintf(tr_str, sizeof(tr_str), __VA_ARGS__ ); \
271         tr_str[sizeof(tr_str) - 1] = '\0';              \
272         notify_qemu_string(&tr_str[0]);                 \
273     } while (0)
274
275 // =============================================================================
276 // Logging macros. Note that we simultaneously log messages to ADB and emulator.
277 // =============================================================================
278
279 /*
280  * Helper macros for checking if particular trace level is enabled.
281  */
282 #define debug_LOG_ENABLED       ((tracing_flags & DEBUG_TRACING_ENABLED) != 0)
283 #define error_LOG_ENABLED       ((tracing_flags & ERROR_TRACING_ENABLED) != 0)
284 #define info_LOG_ENABLED        ((tracing_flags & INFO_TRACING_ENABLED)  != 0)
285 #define tracing_enabled(type)   (type##_LOG_ENABLED)
286
287 /*
288  * Logging helper macros.
289  */
290 #define debug_log(format, ...)                                              \
291     do {                                                                    \
292         __libc_android_log_print(ANDROID_LOG_DEBUG, "memcheck",             \
293                                  (format), ##__VA_ARGS__ );                 \
294         if (tracing_flags & DEBUG_TRACING_ENABLED) {                        \
295             qemu_log(ANDROID_LOG_DEBUG, (format), ##__VA_ARGS__ );          \
296         }                                                                   \
297     } while (0)
298
299 #define error_log(format, ...)                                              \
300     do {                                                                    \
301         __libc_android_log_print(ANDROID_LOG_ERROR, "memcheck",             \
302                                  (format), ##__VA_ARGS__ );                 \
303         if (tracing_flags & ERROR_TRACING_ENABLED) {                        \
304             qemu_log(ANDROID_LOG_ERROR, (format), ##__VA_ARGS__ );          \
305         }                                                                   \
306     } while (0)
307
308 #define info_log(format, ...)                                               \
309     do {                                                                    \
310         __libc_android_log_print(ANDROID_LOG_INFO, "memcheck",              \
311                                  (format), ##__VA_ARGS__ );                 \
312         if (tracing_flags & INFO_TRACING_ENABLED) {                         \
313             qemu_log(ANDROID_LOG_INFO, (format), ##__VA_ARGS__ );           \
314         }                                                                   \
315     } while (0)
316
317 /* Logs message dumping MallocDesc instance at the end of the message.
318  * Param:
319  *  type - Message type: debug, error, or info
320  *  desc - MallocDesc instance to dump.
321  *  frmt + rest - Formats message preceding dumped descriptor.
322 */
323 #define log_mdesc(type, desc, frmt, ...)                                    \
324     do {                                                                    \
325         if (tracing_enabled(type)) {                                        \
326             char log_str[4096];                                             \
327             size_t str_len;                                                 \
328             snprintf(log_str, sizeof(log_str), frmt, ##__VA_ARGS__);        \
329             log_str[sizeof(log_str) - 1] = '\0';                            \
330             str_len = strlen(log_str);                                      \
331             dump_malloc_descriptor(log_str + str_len,                       \
332                                    sizeof(log_str) - str_len,               \
333                                    (desc));                                 \
334             type##_log(log_str);                                            \
335         }                                                                   \
336     } while (0)
337
338 // =============================================================================
339 // Static data
340 // =============================================================================
341
342 /* Emulator's magic page address.
343  * This page (mapped on /dev/qemu_trace device) is used to fire up events
344  * in the emulator. */
345 static volatile void* qtrace = NULL;
346
347 /* Cached PID of the process in context of which this libc instance
348  * has been initialized. */
349 static uint32_t malloc_pid = 0;
350
351 /* Memory allocation alignment that is used in dlmalloc.
352  * This variable is updated by memcheck_initialize routine. */
353 static uint32_t malloc_alignment = 8;
354
355 /* Tracing flags. These flags control which types of logging messages are
356  * enabled by the emulator. See XXX_TRACING_ENABLED for the values of flags
357  * stored in this variable. This variable is updated by memcheck_initialize
358  * routine. */
359 static uint32_t tracing_flags = 0;
360
361 // =============================================================================
362 // Static routines
363 // =============================================================================
364
365 /* Gets pointer, returned to malloc caller for the given allocation decriptor.
366  * Param:
367  *  desc - Allocation descriptor.
368  * Return:
369  *  Pointer to the allocated memory returned to the malloc caller.
370  */
371 static inline void*
372 mallocdesc_user_ptr(const MallocDesc* desc)
373 {
374     return (char*)desc->ptr + desc->prefix_size;
375 }
376
377 /* Gets size of memory block actually allocated from the heap for the given
378  * allocation decriptor.
379  * Param:
380  *  desc - Allocation descriptor.
381  * Return:
382  *  Size of memory block actually allocated from the heap.
383  */
384 static inline uint32_t
385 mallocdesc_alloc_size(const MallocDesc* desc)
386 {
387     return desc->prefix_size + desc->requested_bytes + desc->suffix_size;
388 }
389
390 /* Gets pointer to the end of the allocated block for the given descriptor.
391  * Param:
392  *  desc - Descriptor for the memory block, allocated in malloc handler.
393  * Return:
394  *  Pointer to the end of (one byte past) the allocated block.
395  */
396 static inline void*
397 mallocdesc_alloc_end(const MallocDesc* desc)
398 {
399     return (char*)desc->ptr + mallocdesc_alloc_size(desc);
400 }
401
402 /* Fires up an event in the emulator.
403  * Param:
404  *  code - Event code (one of the TRACE_DEV_XXX).
405  *  val  - Event's value parameter.
406  */
407 static inline void
408 notify_qemu(uint32_t code, uint32_t val)
409 {
410     if (NULL != qtrace) {
411         *(volatile uint32_t*)((uint32_t)qtrace + ((code - 1024) << 2)) = val;
412     }
413 }
414
415 /* Prints a zero-terminated string to the emulator's stdout (fires up
416  * TRACE_DEV_REG_PRINT_USER_STR event in the emulator).
417  * Param:
418  *  str - Zero-terminated string to print.
419  */
420 static void
421 notify_qemu_string(const char* str)
422 {
423     if (str != NULL) {
424         notify_qemu(TRACE_DEV_REG_PRINT_USER_STR, (uint32_t)str);
425     }
426 }
427
428 /* Fires up TRACE_DEV_REG_LIBC_INIT event in the emulator.
429  * Param:
430  *  pid - ID of the process that initialized libc.
431  */
432 static void
433 notify_qemu_libc_initialized(uint32_t pid)
434 {
435     notify_qemu(TRACE_DEV_REG_LIBC_INIT, pid);
436 }
437
438 /* Fires up TRACE_DEV_REG_MALLOC event in the emulator.
439  * Param:
440  *  desc - Pointer to MallocDesc instance containing allocated block
441  *      information.
442  * Return:
443  *  Zero on success, or -1 on failure. Note that on failure libc_pid field of
444  *  the desc parameter passed to this routine has been zeroed out by the
445  *  emulator.
446  */
447 static inline int
448 notify_qemu_malloc(volatile MallocDesc* desc)
449 {
450     desc->libc_pid = malloc_pid;
451     desc->allocator_pid = getpid();
452     desc->av_count = 0;
453     notify_qemu(TRACE_DEV_REG_MALLOC, (uint32_t)desc);
454
455     /* Emulator reports failure by zeroing libc_pid field of the
456      * descriptor. */
457     return desc->libc_pid != 0 ? 0 : -1;
458 }
459
460 /* Fires up TRACE_DEV_REG_FREE_PTR event in the emulator.
461  * Param:
462  *  ptr - Pointer to the memory block that's being freed.
463  * Return:
464  *  Zero on success, or -1 on failure.
465  */
466 static inline int
467 notify_qemu_free(void* ptr_to_free)
468 {
469     volatile MallocFree free_desc;
470
471     free_desc.ptr = ptr_to_free;
472     free_desc.libc_pid = malloc_pid;
473     free_desc.free_pid = getpid();
474     notify_qemu(TRACE_DEV_REG_FREE_PTR, (uint32_t)&free_desc);
475
476     /* Emulator reports failure by zeroing libc_pid field of the
477      * descriptor. */
478     return free_desc.libc_pid != 0 ? 0 : -1;
479 }
480
481 /* Fires up TRACE_DEV_REG_QUERY_MALLOC event in the emulator.
482  * Param:
483  *  ptr - Pointer to request allocation information for.
484  *  desc - Pointer to MallocDesc instance that will receive allocation
485  *      information.
486  *  routine - Code of the allocation routine, in context of which query is made:
487  *      1 - free
488  *      2 - realloc
489  * Return:
490  *  Zero on success, or -1 on failure.
491  */
492 static inline int
493 query_qemu_malloc_info(void* ptr, MallocDesc* desc, uint32_t routine)
494 {
495     volatile MallocDescQuery query;
496
497     query.ptr = ptr;
498     query.libc_pid = malloc_pid;
499     query.query_pid = getpid();
500     query.routine = routine;
501     query.desc = desc;
502     notify_qemu(TRACE_DEV_REG_QUERY_MALLOC, (uint32_t)&query);
503
504     /* Emulator reports failure by zeroing libc_pid field of the
505      * descriptor. */
506     return query.libc_pid != 0 ? 0 : -1;
507 }
508
509 /* Logs a message to emulator's stdout.
510  * Param:
511  *  prio - Message priority (debug, info, or error)
512  *  fmt + rest - Message format and parameters.
513  */
514 static void
515 qemu_log(int prio, const char* fmt, ...)
516 {
517     va_list ap;
518     char buf[4096];
519     const char* prefix;
520
521     /* Choose message prefix depending on the priority value. */
522     switch (prio) {
523         case ANDROID_LOG_ERROR:
524             if (!tracing_enabled(error)) {
525                 return;
526             }
527             prefix = "E";
528             break;
529         case ANDROID_LOG_INFO:
530             if (!tracing_enabled(info)) {
531                 return;
532             }
533             prefix = "I";
534             break;
535         case ANDROID_LOG_DEBUG:
536         default:
537             if (!tracing_enabled(debug)) {
538                 return;
539             }
540             prefix = "D";
541             break;
542     }
543
544     va_start(ap, fmt);
545     vsnprintf(buf, sizeof(buf), fmt, ap);
546     va_end(ap);
547     buf[sizeof(buf) - 1] = '\0';
548
549     TR("%s/memcheck: %s\n", prefix, buf);
550 }
551
552 /* Dumps content of memory allocation descriptor to a string.
553  * Param:
554  *  str - String to dump descriptor to.
555  *  str_buf_size - Size of string's buffer.
556  *  desc - Descriptor to dump.
557  */
558 static void
559 dump_malloc_descriptor(char* str, size_t str_buf_size, const MallocDesc* desc)
560 {
561     if (str_buf_size) {
562         snprintf(str, str_buf_size,
563             "MDesc: %p: %X <-> %X [%u + %u + %u] by pid=%03u in libc_pid=%03u",
564             mallocdesc_user_ptr(desc), (uint32_t)desc->ptr,
565             (uint32_t)mallocdesc_alloc_end(desc), desc->prefix_size,
566             desc->requested_bytes, desc->suffix_size, desc->allocator_pid,
567             desc->libc_pid);
568         str[str_buf_size - 1] = '\0';
569     }
570 }
571
572 #if TEST_ACCESS_VIOLATIONS
573 /* Causes an access violation on allocation descriptor, and verifies that
574  * violation has been detected by memory checker in the emulator.
575  */
576 static void
577 test_access_violation(const MallocDesc* desc)
578 {
579     MallocDesc desc_chk;
580     char ch;
581     volatile char* prefix = (volatile char*)desc->ptr;
582     volatile char* suffix = (volatile char*)mallocdesc_user_ptr(desc) +
583                                             desc->requested_bytes;
584     /* We're causing AV by reading from the prefix and suffix areas of the
585      * allocated block. This should produce two access violations, so when we
586      * get allocation descriptor from QEMU, av_counter should be bigger than
587      * av_counter of the original descriptor by 2. */
588     ch = *prefix;
589     ch = *suffix;
590     if (!query_qemu_malloc_info(mallocdesc_user_ptr(desc), &desc_chk, 2) &&
591         desc_chk.av_count != (desc->av_count + 2)) {
592         log_mdesc(error, &desc_chk,
593                   "<libc_pid=%03u, pid=%03u>: malloc: Access violation test failed:\n"
594                   "Expected violations count %u is not equal to the actually reported %u",
595                   malloc_pid, getpid(), desc->av_count + 2,
596                   desc_chk.av_count);
597     }
598 }
599 #endif  // TEST_ACCESS_VIOLATIONS
600
601 // =============================================================================
602 // API routines
603 // =============================================================================
604
605 void* qemu_instrumented_malloc(size_t bytes);
606 void  qemu_instrumented_free(void* mem);
607 void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size);
608 void* qemu_instrumented_realloc(void* mem, size_t bytes);
609 void* qemu_instrumented_memalign(size_t alignment, size_t bytes);
610
611 /* Initializes malloc debugging instrumentation for the emulator.
612  * This routine is called from malloc_init_impl routine implemented in
613  * bionic/libc/bionic/malloc_debug_common.c when malloc debugging gets
614  * initialized for a process. The way malloc debugging implementation is
615  * done, it is guaranteed that this routine will be called just once per
616  * process.
617  * Return:
618  *  0 on success, or -1 on failure.
619 */
620 int
621 malloc_debug_initialize(void)
622 {
623     /* We will be using emulator's magic page to report memory allocation
624      * activities. In essence, what magic page does, it translates writes to
625      * the memory mapped spaces into writes to an I/O port that emulator
626      * "listens to" on the other end. Note that until we open and map that
627      * device, logging to emulator's stdout will not be available. */
628     int fd = open("/dev/qemu_trace", O_RDWR);
629     if (fd < 0) {
630         error_log("Unable to open /dev/qemu_trace");
631         return -1;
632     } else {
633         qtrace = mmap(0, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
634         close(fd);
635
636         if (qtrace == MAP_FAILED) {
637             qtrace = NULL;
638             error_log("Unable to mmap /dev/qemu_trace");
639             return -1;
640         }
641     }
642
643     /* Cache pid of the process this library has been initialized for. */
644     malloc_pid = getpid();
645
646     return 0;
647 }
648
649 /* Completes malloc debugging instrumentation for the emulator.
650  * Note that this routine is called after successful return from
651  * malloc_debug_initialize, which means that connection to the emulator via
652  * "magic page" has been established.
653  * Param:
654  *  alignment - Alignment requirement set for memiry allocations.
655  *  memcheck_param - Emulator's -memcheck option parameters. This string
656  *      contains abbreviation for guest events that are enabled for tracing.
657  * Return:
658  *  0 on success, or -1 on failure.
659 */
660 int
661 memcheck_initialize(int alignment, const char* memcheck_param)
662 {
663     malloc_alignment = alignment;
664
665     /* Parse -memcheck parameter for the guest tracing flags. */
666     while (*memcheck_param != '\0') {
667         switch (*memcheck_param) {
668             case 'a':
669                 // Enable all messages from the guest.
670                 tracing_flags |= ALL_TRACING_ENABLED;
671                 break;
672             case 'd':
673                 // Enable debug messages from the guest.
674                 tracing_flags |= DEBUG_TRACING_ENABLED;
675                 break;
676             case 'e':
677                 // Enable error messages from the guest.
678                 tracing_flags |= ERROR_TRACING_ENABLED;
679                 break;
680             case 'i':
681                 // Enable info messages from the guest.
682                 tracing_flags |= INFO_TRACING_ENABLED;
683                 break;
684             default:
685                 break;
686         }
687         if (tracing_flags == ALL_TRACING_ENABLED) {
688             break;
689         }
690         memcheck_param++;
691     }
692
693     notify_qemu_libc_initialized(malloc_pid);
694
695     debug_log("Instrumented for pid=%03u: malloc=%p, free=%p, calloc=%p, realloc=%p, memalign=%p",
696               malloc_pid, qemu_instrumented_malloc, qemu_instrumented_free,
697               qemu_instrumented_calloc, qemu_instrumented_realloc,
698               qemu_instrumented_memalign);
699
700     return 0;
701 }
702
703 /* This routine serves as entry point for 'malloc'.
704  * Primary responsibility of this routine is to allocate requested number of
705  * bytes (plus prefix, and suffix guards), and report allocation to the
706  * emulator.
707  */
708 void*
709 qemu_instrumented_malloc(size_t bytes)
710 {
711     MallocDesc desc;
712
713     /* Initialize block descriptor and allocate memory. Note that dlmalloc
714      * returns a valid pointer on zero allocation. Lets mimic this behavior. */
715     desc.prefix_size = DEFAULT_PREFIX_SIZE;
716     desc.requested_bytes = bytes;
717     desc.suffix_size = DEFAULT_SUFFIX_SIZE;
718     desc.ptr = dlmalloc(mallocdesc_alloc_size(&desc));
719     if (desc.ptr == NULL) {
720         error_log("<libc_pid=%03u, pid=%03u> malloc(%u): dlmalloc(%u) failed.",
721                   malloc_pid, getpid(), bytes, mallocdesc_alloc_size(&desc));
722         return NULL;
723     }
724
725     // Fire up event in the emulator.
726     if (notify_qemu_malloc(&desc)) {
727         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: malloc: notify_malloc failed for ",
728                   malloc_pid, getpid());
729         dlfree(desc.ptr);
730         return NULL;
731     } else {
732 #if TEST_ACCESS_VIOLATIONS
733         test_access_violation(&desc);
734 #endif  // TEST_ACCESS_VIOLATIONS
735         log_mdesc(info, &desc, "+++ <libc_pid=%03u, pid=%03u> malloc(%u) -> ",
736                   malloc_pid, getpid(), bytes);
737         return mallocdesc_user_ptr(&desc);
738     }
739 }
740
741 /* This routine serves as entry point for 'malloc'.
742  * Primary responsibility of this routine is to free requested memory, and
743  * report free block to the emulator.
744  */
745 void
746 qemu_instrumented_free(void* mem)
747 {
748     MallocDesc desc;
749
750     if (mem == NULL) {
751         // Just let go NULL free
752         dlfree(mem);
753         return;
754     }
755
756     // Query emulator for the freeing block information.
757     if (query_qemu_malloc_info(mem, &desc, 1)) {
758         error_log("<libc_pid=%03u, pid=%03u>: free(%p) query_info failed.",
759                   malloc_pid, getpid(), mem);
760         return;
761     }
762
763 #if TEST_ACCESS_VIOLATIONS
764     test_access_violation(&desc);
765 #endif  // TEST_ACCESS_VIOLATIONS
766
767     /* Make sure that pointer that's being freed matches what we expect
768      * for this memory block. Note that this violation should be already
769      * caught in the emulator. */
770     if (mem != mallocdesc_user_ptr(&desc)) {
771         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: free(%p) is invalid for ",
772                   malloc_pid, getpid(), mem);
773         return;
774     }
775
776     // Fire up event in the emulator and free block that was actually allocated.
777     if (notify_qemu_free(mem)) {
778         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: free(%p) notify_free failed for ",
779                   malloc_pid, getpid(), mem);
780     } else {
781         log_mdesc(info, &desc, "--- <libc_pid=%03u, pid=%03u> free(%p) -> ",
782                   malloc_pid, getpid(), mem);
783         dlfree(desc.ptr);
784     }
785 }
786
787 /* This routine serves as entry point for 'calloc'.
788  * This routine behaves similarly to qemu_instrumented_malloc.
789  */
790 void*
791 qemu_instrumented_calloc(size_t n_elements, size_t elem_size)
792 {
793     MallocDesc desc;
794     void* ret;
795     size_t total_size;
796     size_t total_elements;
797
798     if (n_elements == 0 || elem_size == 0) {
799         // Just let go zero bytes allocation.
800         info_log("::: <libc_pid=%03u, pid=%03u>: Zero calloc redir to malloc",
801                  malloc_pid, getpid());
802         return qemu_instrumented_malloc(0);
803     }
804
805     /* Fail on overflow - just to be safe even though this code runs only
806      * within the debugging C library, not the production one */
807     if (n_elements && MAX_SIZE_T / n_elements < elem_size) {
808         return NULL;
809     }
810
811     /* Calculating prefix size. The trick here is to make sure that
812      * first element (returned to the caller) is properly aligned. */
813     if (DEFAULT_PREFIX_SIZE >= elem_size) {
814         /* If default alignment is bigger than element size, we will
815          * set our prefix size to the default alignment size. */
816         desc.prefix_size = DEFAULT_PREFIX_SIZE;
817         /* For the suffix we will use whatever bytes remain from the prefix
818          * allocation size, aligned to the size of an element, plus the usual
819          * default suffix size. */
820         desc.suffix_size = (DEFAULT_PREFIX_SIZE % elem_size) +
821                            DEFAULT_SUFFIX_SIZE;
822     } else {
823         /* Make sure that prefix, and suffix sizes is at least elem_size,
824          * and first element returned to the caller is properly aligned. */
825         desc.prefix_size = elem_size + DEFAULT_PREFIX_SIZE - 1;
826         desc.prefix_size &= ~(malloc_alignment - 1);
827         desc.suffix_size = DEFAULT_SUFFIX_SIZE;
828     }
829     desc.requested_bytes = n_elements * elem_size;
830     total_size = desc.requested_bytes + desc.prefix_size + desc.suffix_size;
831     total_elements = total_size / elem_size;
832     total_size %= elem_size;
833     if (total_size != 0) {
834         // Add extra to the suffix area.
835         total_elements++;
836         desc.suffix_size += (elem_size - total_size);
837     }
838     desc.ptr = dlcalloc(total_elements, elem_size);
839     if (desc.ptr == NULL) {
840         error_log("<libc_pid=%03u, pid=%03u> calloc: dlcalloc(%u(%u), %u) (prx=%u, sfx=%u) failed.",
841                    malloc_pid, getpid(), n_elements, total_elements, elem_size,
842                    desc.prefix_size, desc.suffix_size);
843         return NULL;
844     }
845
846     if (notify_qemu_malloc(&desc)) {
847         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: calloc(%u(%u), %u): notify_malloc failed for ",
848                   malloc_pid, getpid(), n_elements, total_elements, elem_size);
849         dlfree(desc.ptr);
850         return NULL;
851     } else {
852 #if TEST_ACCESS_VIOLATIONS
853         test_access_violation(&desc);
854 #endif  // TEST_ACCESS_VIOLATIONS
855         log_mdesc(info, &desc, "### <libc_pid=%03u, pid=%03u> calloc(%u(%u), %u) -> ",
856                   malloc_pid, getpid(), n_elements, total_elements, elem_size);
857         return mallocdesc_user_ptr(&desc);
858     }
859 }
860
861 /* This routine serves as entry point for 'realloc'.
862  * This routine behaves similarly to qemu_instrumented_free +
863  * qemu_instrumented_malloc. Note that this modifies behavior of "shrinking" an
864  * allocation, but overall it doesn't seem to matter, as caller of realloc
865  * should not expect that pointer returned after shrinking will remain the same.
866  */
867 void*
868 qemu_instrumented_realloc(void* mem, size_t bytes)
869 {
870     MallocDesc new_desc;
871     MallocDesc cur_desc;
872     size_t to_copy;
873     void* ret;
874
875     if (mem == NULL) {
876         // Nothing to realloc. just do regular malloc.
877         info_log("::: <libc_pid=%03u, pid=%03u>: realloc(%p, %u) redir to malloc",
878                  malloc_pid, getpid(), mem, bytes);
879         return qemu_instrumented_malloc(bytes);
880     }
881
882     if (bytes == 0) {
883         // This is a "free" condition.
884         info_log("::: <libc_pid=%03u, pid=%03u>: realloc(%p, %u) redir to free and malloc",
885                  malloc_pid, getpid(), mem, bytes);
886         qemu_instrumented_free(mem);
887
888         // This is what dlrealloc does for a "free" realloc.
889         return NULL;
890     }
891
892     // Query emulator for the reallocating block information.
893     if (query_qemu_malloc_info(mem, &cur_desc, 2)) {
894         // Note that this violation should be already caught in the emulator.
895         error_log("<libc_pid=%03u, pid=%03u>: realloc(%p, %u) query_info failed.",
896                   malloc_pid, getpid(), mem, bytes);
897         return NULL;
898     }
899
900 #if TEST_ACCESS_VIOLATIONS
901     test_access_violation(&cur_desc);
902 #endif  // TEST_ACCESS_VIOLATIONS
903
904     /* Make sure that reallocating pointer value is what we would expect
905      * for this memory block. Note that this violation should be already caught
906      * in the emulator.*/
907     if (mem != mallocdesc_user_ptr(&cur_desc)) {
908         log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u) is invalid for ",
909                   malloc_pid, getpid(), mem, bytes);
910         return NULL;
911     }
912
913     /* TODO: We're a bit inefficient here, always allocating new block from
914      * the heap. If this realloc shrinks current buffer, we can just do the
915      * shrinking "in place", adjusting suffix_size in the allocation descriptor
916      * for this block that is stored in the emulator. */
917
918     // Initialize descriptor for the new block.
919     new_desc.prefix_size = DEFAULT_PREFIX_SIZE;
920     new_desc.requested_bytes = bytes;
921     new_desc.suffix_size = DEFAULT_SUFFIX_SIZE;
922     new_desc.ptr = dlmalloc(mallocdesc_alloc_size(&new_desc));
923     if (new_desc.ptr == NULL) {
924         log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u): dlmalloc(%u) failed on ",
925                   malloc_pid, getpid(), mem, bytes,
926                   mallocdesc_alloc_size(&new_desc));
927         return NULL;
928     }
929     ret = mallocdesc_user_ptr(&new_desc);
930
931     // Copy user data from old block to the new one.
932     to_copy = bytes < cur_desc.requested_bytes ? bytes :
933                                                  cur_desc.requested_bytes;
934     if (to_copy != 0) {
935         memcpy(ret, mallocdesc_user_ptr(&cur_desc), to_copy);
936     }
937
938     // Register new block with emulator.
939     if(notify_qemu_malloc(&new_desc)) {
940         log_mdesc(error, &new_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u) notify_malloc failed -> ",
941                   malloc_pid, getpid(), mem, bytes);
942         log_mdesc(error, &cur_desc, "                                                                <- ");
943         dlfree(new_desc.ptr);
944         return NULL;
945     }
946
947 #if TEST_ACCESS_VIOLATIONS
948     test_access_violation(&new_desc);
949 #endif  // TEST_ACCESS_VIOLATIONS
950
951     // Free old block.
952     if (notify_qemu_free(mem)) {
953         log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u): notify_free failed for ",
954                   malloc_pid, getpid(), mem, bytes);
955         /* Since we registered new decriptor with the emulator, we need
956          * to unregister it before freeing newly allocated block. */
957         notify_qemu_free(mallocdesc_user_ptr(&new_desc));
958         dlfree(new_desc.ptr);
959         return NULL;
960     }
961     dlfree(cur_desc.ptr);
962
963     log_mdesc(info, &new_desc, "=== <libc_pid=%03u, pid=%03u>: realloc(%p, %u) -> ",
964               malloc_pid, getpid(), mem, bytes);
965     log_mdesc(info, &cur_desc, "                                               <- ");
966
967     return ret;
968 }
969
970 /* This routine serves as entry point for 'memalign'.
971  * This routine behaves similarly to qemu_instrumented_malloc.
972  */
973 void*
974 qemu_instrumented_memalign(size_t alignment, size_t bytes)
975 {
976     MallocDesc desc;
977
978     if (bytes == 0) {
979         // Just let go zero bytes allocation.
980         info_log("::: <libc_pid=%03u, pid=%03u>: memalign(%X, %u) redir to malloc",
981                  malloc_pid, getpid(), alignment, bytes);
982         return qemu_instrumented_malloc(0);
983     }
984
985     /* Prefix size for aligned allocation must be equal to the alignment used
986      * for allocation in order to ensure proper alignment of the returned
987      * pointer, in case that alignment requirement is greater than prefix
988      * size. */
989     desc.prefix_size = alignment > DEFAULT_PREFIX_SIZE ? alignment :
990                                                          DEFAULT_PREFIX_SIZE;
991     desc.requested_bytes = bytes;
992     desc.suffix_size = DEFAULT_SUFFIX_SIZE;
993     desc.ptr = dlmemalign(desc.prefix_size, mallocdesc_alloc_size(&desc));
994     if (desc.ptr == NULL) {
995         error_log("<libc_pid=%03u, pid=%03u> memalign(%X, %u): dlmalloc(%u) failed.",
996                   malloc_pid, getpid(), alignment, bytes,
997                   mallocdesc_alloc_size(&desc));
998         return NULL;
999     }
1000     if (notify_qemu_malloc(&desc)) {
1001         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: memalign(%X, %u): notify_malloc failed for ",
1002                   malloc_pid, getpid(), alignment, bytes);
1003         dlfree(desc.ptr);
1004         return NULL;
1005     }
1006
1007 #if TEST_ACCESS_VIOLATIONS
1008     test_access_violation(&desc);
1009 #endif  // TEST_ACCESS_VIOLATIONS
1010
1011     log_mdesc(info, &desc, "@@@ <libc_pid=%03u, pid=%03u> memalign(%X, %u) -> ",
1012               malloc_pid, getpid(), alignment, bytes);
1013     return mallocdesc_user_ptr(&desc);
1014 }