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