Home | History | Annotate | Download | only in bionic
      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 "libc_logging.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 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 };
    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 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     const 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 };
    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 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 };
    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 messages to logcat
    261  * 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 qemu_debug_log(format, ...)                                         \
    291     do {                                                                    \
    292         __libc_format_log(ANDROID_LOG_DEBUG, "memcheck", (format), ##__VA_ARGS__); \
    293         if (tracing_flags & DEBUG_TRACING_ENABLED) {                        \
    294             qemu_log(ANDROID_LOG_DEBUG, (format), ##__VA_ARGS__);           \
    295         }                                                                   \
    296     } while (0)
    297 
    298 #define qemu_error_log(format, ...)                                         \
    299     do {                                                                    \
    300         __libc_format_log(ANDROID_LOG_ERROR, "memcheck", (format), ##__VA_ARGS__); \
    301         if (tracing_flags & ERROR_TRACING_ENABLED) {                        \
    302             qemu_log(ANDROID_LOG_ERROR, (format), ##__VA_ARGS__);           \
    303         }                                                                   \
    304     } while (0)
    305 
    306 #define qemu_info_log(format, ...)                                          \
    307     do {                                                                    \
    308         __libc_format_log(ANDROID_LOG_INFO, "memcheck", (format), ##__VA_ARGS__); \
    309         if (tracing_flags & INFO_TRACING_ENABLED) {                         \
    310             qemu_log(ANDROID_LOG_INFO, (format), ##__VA_ARGS__);            \
    311         }                                                                   \
    312     } while (0)
    313 
    314 /* Logs message dumping MallocDesc instance at the end of the message.
    315  * Param:
    316  *  type - Message type: debug, error, or info
    317  *  desc - MallocDesc instance to dump.
    318  *  fmt + rest - Formats message preceding dumped descriptor.
    319 */
    320 #define log_mdesc(type, desc, fmt, ...)                                    \
    321     do {                                                                    \
    322         if (tracing_enabled(type)) {                                        \
    323             char log_str[4096];                                             \
    324             __libc_format_buffer(log_str, sizeof(log_str), fmt, ##__VA_ARGS__); \
    325             log_str[sizeof(log_str) - 1] = '\0';                            \
    326             size_t str_len = strlen(log_str);                               \
    327             dump_malloc_descriptor(log_str + str_len,                       \
    328                                    sizeof(log_str) - str_len,               \
    329                                    (desc));                                 \
    330             type##_log("%s", log_str);                                      \
    331         }                                                                   \
    332     } while (0)
    333 
    334 // =============================================================================
    335 // Static data
    336 // =============================================================================
    337 
    338 /* Emulator's magic page address.
    339  * This page (mapped on /dev/qemu_trace device) is used to fire up events
    340  * in the emulator. */
    341 static volatile void* qtrace = NULL;
    342 
    343 /* Cached PID of the process in context of which this libc instance
    344  * has been initialized. */
    345 static uint32_t malloc_pid = 0;
    346 
    347 /* Memory allocation alignment that is used in dlmalloc.
    348  * This variable is updated by memcheck_initialize routine. */
    349 static uint32_t malloc_alignment = 8;
    350 
    351 /* Tracing flags. These flags control which types of logging messages are
    352  * enabled by the emulator. See XXX_TRACING_ENABLED for the values of flags
    353  * stored in this variable. This variable is updated by memcheck_initialize
    354  * routine. */
    355 static uint32_t tracing_flags = 0;
    356 
    357 // =============================================================================
    358 // Static routines
    359 // =============================================================================
    360 
    361 /* Gets pointer, returned to malloc caller for the given allocation decriptor.
    362  * Param:
    363  *  desc - Allocation descriptor.
    364  * Return:
    365  *  Pointer to the allocated memory returned to the malloc caller.
    366  */
    367 static inline void* mallocdesc_user_ptr(const MallocDesc* desc) {
    368     return static_cast<char*>(desc->ptr) + desc->prefix_size;
    369 }
    370 
    371 /* Gets size of memory block actually allocated from the heap for the given
    372  * allocation decriptor.
    373  * Param:
    374  *  desc - Allocation descriptor.
    375  * Return:
    376  *  Size of memory block actually allocated from the heap.
    377  */
    378 static inline uint32_t mallocdesc_alloc_size(const MallocDesc* desc) {
    379     return desc->prefix_size + desc->requested_bytes + desc->suffix_size;
    380 }
    381 
    382 /* Gets pointer to the end of the allocated block for the given descriptor.
    383  * Param:
    384  *  desc - Descriptor for the memory block, allocated in malloc handler.
    385  * Return:
    386  *  Pointer to the end of (one byte past) the allocated block.
    387  */
    388 static inline void* mallocdesc_alloc_end(const MallocDesc* desc) {
    389     return static_cast<char*>(desc->ptr) + mallocdesc_alloc_size(desc);
    390 }
    391 
    392 /* Fires up an event in the emulator.
    393  * Param:
    394  *  code - Event code (one of the TRACE_DEV_XXX).
    395  *  val  - Event's value parameter.
    396  */
    397 static inline void notify_qemu(uint32_t code, uint32_t val) {
    398     if (NULL != qtrace) {
    399         *(volatile uint32_t*)((uint32_t)qtrace + ((code - 1024) << 2)) = val;
    400     }
    401 }
    402 
    403 /* Prints a zero-terminated string to the emulator's stdout (fires up
    404  * TRACE_DEV_REG_PRINT_USER_STR event in the emulator).
    405  * Param:
    406  *  str - Zero-terminated string to print.
    407  */
    408 static void notify_qemu_string(const char* str) {
    409     if (str != NULL) {
    410         notify_qemu(TRACE_DEV_REG_PRINT_USER_STR, (uint32_t)str);
    411     }
    412 }
    413 
    414 /* Fires up TRACE_DEV_REG_LIBC_INIT event in the emulator.
    415  * Param:
    416  *  pid - ID of the process that initialized libc.
    417  */
    418 static void notify_qemu_libc_initialized(uint32_t pid) {
    419     notify_qemu(TRACE_DEV_REG_LIBC_INIT, pid);
    420 }
    421 
    422 /* Fires up TRACE_DEV_REG_MALLOC event in the emulator.
    423  * Param:
    424  *  desc - Pointer to MallocDesc instance containing allocated block
    425  *      information.
    426  * Return:
    427  *  Zero on success, or -1 on failure. Note that on failure libc_pid field of
    428  *  the desc parameter passed to this routine has been zeroed out by the
    429  *  emulator.
    430  */
    431 static inline int notify_qemu_malloc(volatile MallocDesc* desc) {
    432     desc->libc_pid = malloc_pid;
    433     desc->allocator_pid = getpid();
    434     desc->av_count = 0;
    435     notify_qemu(TRACE_DEV_REG_MALLOC, (uint32_t)desc);
    436 
    437     /* Emulator reports failure by zeroing libc_pid field of the
    438      * descriptor. */
    439     return desc->libc_pid != 0 ? 0 : -1;
    440 }
    441 
    442 /* Fires up TRACE_DEV_REG_FREE_PTR event in the emulator.
    443  * Param:
    444  *  ptr - Pointer to the memory block that's being freed.
    445  * Return:
    446  *  Zero on success, or -1 on failure.
    447  */
    448 static inline int notify_qemu_free(void* ptr_to_free) {
    449     volatile MallocFree free_desc;
    450 
    451     free_desc.ptr = ptr_to_free;
    452     free_desc.libc_pid = malloc_pid;
    453     free_desc.free_pid = getpid();
    454     notify_qemu(TRACE_DEV_REG_FREE_PTR, (uint32_t)&free_desc);
    455 
    456     /* Emulator reports failure by zeroing libc_pid field of the
    457      * descriptor. */
    458     return free_desc.libc_pid != 0 ? 0 : -1;
    459 }
    460 
    461 /* Fires up TRACE_DEV_REG_QUERY_MALLOC event in the emulator.
    462  * Param:
    463  *  ptr - Pointer to request allocation information for.
    464  *  desc - Pointer to MallocDesc instance that will receive allocation
    465  *      information.
    466  *  routine - Code of the allocation routine, in context of which query is made:
    467  *      1 - free
    468  *      2 - realloc
    469  * Return:
    470  *  Zero on success, or -1 on failure.
    471  */
    472 static inline int query_qemu_malloc_info(const void* ptr, MallocDesc* desc, uint32_t routine) {
    473     volatile MallocDescQuery query;
    474 
    475     query.ptr = ptr;
    476     query.libc_pid = malloc_pid;
    477     query.query_pid = getpid();
    478     query.routine = routine;
    479     query.desc = desc;
    480     notify_qemu(TRACE_DEV_REG_QUERY_MALLOC, (uint32_t)&query);
    481 
    482     /* Emulator reports failure by zeroing libc_pid field of the
    483      * descriptor. */
    484     return query.libc_pid != 0 ? 0 : -1;
    485 }
    486 
    487 /* Logs a message to emulator's stdout.
    488  * Param:
    489  *  prio - Message priority (debug, info, or error)
    490  *  fmt + rest - Message format and parameters.
    491  */
    492 static void qemu_log(int prio, const char* fmt, ...) {
    493     va_list ap;
    494     char buf[4096];
    495     const char* prefix;
    496 
    497     /* Choose message prefix depending on the priority value. */
    498     switch (prio) {
    499         case ANDROID_LOG_ERROR:
    500             if (!tracing_enabled(error)) {
    501                 return;
    502             }
    503             prefix = "E";
    504             break;
    505         case ANDROID_LOG_INFO:
    506             if (!tracing_enabled(info)) {
    507                 return;
    508             }
    509             prefix = "I";
    510             break;
    511         case ANDROID_LOG_DEBUG:
    512         default:
    513             if (!tracing_enabled(debug)) {
    514                 return;
    515             }
    516             prefix = "D";
    517             break;
    518     }
    519 
    520     va_start(ap, fmt);
    521     vsnprintf(buf, sizeof(buf), fmt, ap);
    522     va_end(ap);
    523     buf[sizeof(buf) - 1] = '\0';
    524 
    525     TR("%s/memcheck: %s\n", prefix, buf);
    526 }
    527 
    528 /* Dumps content of memory allocation descriptor to a string.
    529  * Param:
    530  *  str - String to dump descriptor to.
    531  *  str_buf_size - Size of string's buffer.
    532  *  desc - Descriptor to dump.
    533  */
    534 static void dump_malloc_descriptor(char* str, size_t str_buf_size, const MallocDesc* desc) {
    535     if (str_buf_size) {
    536         snprintf(str, str_buf_size,
    537             "MDesc: %p: %X <-> %X [%u + %u + %u] by pid=%03u in libc_pid=%03u",
    538             mallocdesc_user_ptr(desc), (uint32_t)desc->ptr,
    539             (uint32_t)mallocdesc_alloc_end(desc), desc->prefix_size,
    540             desc->requested_bytes, desc->suffix_size, desc->allocator_pid,
    541             desc->libc_pid);
    542         str[str_buf_size - 1] = '\0';
    543     }
    544 }
    545 
    546 #if TEST_ACCESS_VIOLATIONS
    547 /* Causes an access violation on allocation descriptor, and verifies that
    548  * violation has been detected by memory checker in the emulator.
    549  */
    550 static void test_access_violation(const MallocDesc* desc) {
    551     MallocDesc desc_chk;
    552     char ch;
    553     volatile char* prefix = (volatile char*)desc->ptr;
    554     volatile char* suffix = (volatile char*)mallocdesc_user_ptr(desc) +
    555                                             desc->requested_bytes;
    556     /* We're causing AV by reading from the prefix and suffix areas of the
    557      * allocated block. This should produce two access violations, so when we
    558      * get allocation descriptor from QEMU, av_counter should be bigger than
    559      * av_counter of the original descriptor by 2. */
    560     ch = *prefix;
    561     ch = *suffix;
    562     if (!query_qemu_malloc_info(mallocdesc_user_ptr(desc), &desc_chk, 2) &&
    563         desc_chk.av_count != (desc->av_count + 2)) {
    564         log_mdesc(error, &desc_chk,
    565                   "<libc_pid=%03u, pid=%03u>: malloc: Access violation test failed:\n"
    566                   "Expected violations count %u is not equal to the actually reported %u",
    567                   malloc_pid, getpid(), desc->av_count + 2,
    568                   desc_chk.av_count);
    569     }
    570 }
    571 #endif  // TEST_ACCESS_VIOLATIONS
    572 
    573 // =============================================================================
    574 // API routines
    575 // =============================================================================
    576 
    577 extern "C" void* qemu_instrumented_malloc(size_t bytes);
    578 extern "C" void  qemu_instrumented_free(void* mem);
    579 extern "C" void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size);
    580 extern "C" void* qemu_instrumented_realloc(void* mem, size_t bytes);
    581 extern "C" void* qemu_instrumented_memalign(size_t alignment, size_t bytes);
    582 extern "C" size_t qemu_instrumented_malloc_usable_size(const void* mem);
    583 
    584 /* Initializes malloc debugging instrumentation for the emulator.
    585  * This routine is called from malloc_init_impl routine implemented in
    586  * bionic/libc/bionic/malloc_debug_common.c when malloc debugging gets
    587  * initialized for a process. The way malloc debugging implementation is
    588  * done, it is guaranteed that this routine will be called just once per
    589  * process.
    590  * Return:
    591  *  0 on success, or -1 on failure.
    592 */
    593 extern "C" int malloc_debug_initialize() {
    594     /* We will be using emulator's magic page to report memory allocation
    595      * activities. In essence, what magic page does, it translates writes to
    596      * the memory mapped spaces into writes to an I/O port that emulator
    597      * "listens to" on the other end. Note that until we open and map that
    598      * device, logging to emulator's stdout will not be available. */
    599     int fd = open("/dev/qemu_trace", O_RDWR);
    600     if (fd < 0) {
    601         error_log("Unable to open /dev/qemu_trace");
    602         return -1;
    603     } else {
    604         qtrace = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    605         close(fd);
    606 
    607         if (qtrace == MAP_FAILED) {
    608             qtrace = NULL;
    609             error_log("Unable to mmap /dev/qemu_trace");
    610             return -1;
    611         }
    612     }
    613 
    614     /* Cache pid of the process this library has been initialized for. */
    615     malloc_pid = getpid();
    616 
    617     return 0;
    618 }
    619 
    620 /* Completes malloc debugging instrumentation for the emulator.
    621  * Note that this routine is called after successful return from
    622  * malloc_debug_initialize, which means that connection to the emulator via
    623  * "magic page" has been established.
    624  * Param:
    625  *  alignment - Alignment requirement set for memiry allocations.
    626  *  memcheck_param - Emulator's -memcheck option parameters. This string
    627  *      contains abbreviation for guest events that are enabled for tracing.
    628  * Return:
    629  *  0 on success, or -1 on failure.
    630 */
    631 extern "C" int memcheck_initialize(int alignment, const char* memcheck_param) {
    632     malloc_alignment = alignment;
    633 
    634     /* Parse -memcheck parameter for the guest tracing flags. */
    635     while (*memcheck_param != '\0') {
    636         switch (*memcheck_param) {
    637             case 'a':
    638                 // Enable all messages from the guest.
    639                 tracing_flags |= ALL_TRACING_ENABLED;
    640                 break;
    641             case 'd':
    642                 // Enable debug messages from the guest.
    643                 tracing_flags |= DEBUG_TRACING_ENABLED;
    644                 break;
    645             case 'e':
    646                 // Enable error messages from the guest.
    647                 tracing_flags |= ERROR_TRACING_ENABLED;
    648                 break;
    649             case 'i':
    650                 // Enable info messages from the guest.
    651                 tracing_flags |= INFO_TRACING_ENABLED;
    652                 break;
    653             default:
    654                 break;
    655         }
    656         if (tracing_flags == ALL_TRACING_ENABLED) {
    657             break;
    658         }
    659         memcheck_param++;
    660     }
    661 
    662     notify_qemu_libc_initialized(malloc_pid);
    663 
    664     qemu_debug_log("Instrumented for pid=%03u: malloc=%p, free=%p, calloc=%p, realloc=%p, memalign=%p",
    665               malloc_pid, qemu_instrumented_malloc, qemu_instrumented_free,
    666               qemu_instrumented_calloc, qemu_instrumented_realloc,
    667               qemu_instrumented_memalign);
    668 
    669     return 0;
    670 }
    671 
    672 /* This routine serves as entry point for 'malloc'.
    673  * Primary responsibility of this routine is to allocate requested number of
    674  * bytes (plus prefix, and suffix guards), and report allocation to the
    675  * emulator.
    676  */
    677 extern "C" void* qemu_instrumented_malloc(size_t bytes) {
    678     MallocDesc desc;
    679 
    680     /* Initialize block descriptor and allocate memory. Note that dlmalloc
    681      * returns a valid pointer on zero allocation. Lets mimic this behavior. */
    682     desc.prefix_size = DEFAULT_PREFIX_SIZE;
    683     desc.requested_bytes = bytes;
    684     desc.suffix_size = DEFAULT_SUFFIX_SIZE;
    685     desc.ptr = dlmalloc(mallocdesc_alloc_size(&desc));
    686     if (desc.ptr == NULL) {
    687         qemu_error_log("<libc_pid=%03u, pid=%03u> malloc(%u): dlmalloc(%u) failed.",
    688                   malloc_pid, getpid(), bytes, mallocdesc_alloc_size(&desc));
    689         return NULL;
    690     }
    691 
    692     // Fire up event in the emulator.
    693     if (notify_qemu_malloc(&desc)) {
    694         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: malloc: notify_malloc failed for ",
    695                   malloc_pid, getpid());
    696         dlfree(desc.ptr);
    697         return NULL;
    698     } else {
    699 #if TEST_ACCESS_VIOLATIONS
    700         test_access_violation(&desc);
    701 #endif  // TEST_ACCESS_VIOLATIONS
    702         log_mdesc(info, &desc, "+++ <libc_pid=%03u, pid=%03u> malloc(%u) -> ",
    703                   malloc_pid, getpid(), bytes);
    704         return mallocdesc_user_ptr(&desc);
    705     }
    706 }
    707 
    708 /* This routine serves as entry point for 'malloc'.
    709  * Primary responsibility of this routine is to free requested memory, and
    710  * report free block to the emulator.
    711  */
    712 extern "C" void qemu_instrumented_free(void* mem) {
    713     MallocDesc desc;
    714 
    715     if (mem == NULL) {
    716         // Just let go NULL free
    717         dlfree(mem);
    718         return;
    719     }
    720 
    721     // Query emulator for the freeing block information.
    722     if (query_qemu_malloc_info(mem, &desc, 1)) {
    723         error_log("<libc_pid=%03u, pid=%03u>: free(%p) query_info failed.",
    724                   malloc_pid, getpid(), mem);
    725         return;
    726     }
    727 
    728 #if TEST_ACCESS_VIOLATIONS
    729     test_access_violation(&desc);
    730 #endif  // TEST_ACCESS_VIOLATIONS
    731 
    732     /* Make sure that pointer that's being freed matches what we expect
    733      * for this memory block. Note that this violation should be already
    734      * caught in the emulator. */
    735     if (mem != mallocdesc_user_ptr(&desc)) {
    736         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: free(%p) is invalid for ",
    737                   malloc_pid, getpid(), mem);
    738         return;
    739     }
    740 
    741     // Fire up event in the emulator and free block that was actually allocated.
    742     if (notify_qemu_free(mem)) {
    743         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: free(%p) notify_free failed for ",
    744                   malloc_pid, getpid(), mem);
    745     } else {
    746         log_mdesc(info, &desc, "--- <libc_pid=%03u, pid=%03u> free(%p) -> ",
    747                   malloc_pid, getpid(), mem);
    748         dlfree(desc.ptr);
    749     }
    750 }
    751 
    752 /* This routine serves as entry point for 'calloc'.
    753  * This routine behaves similarly to qemu_instrumented_malloc.
    754  */
    755 extern "C" void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size) {
    756     if (n_elements == 0 || elem_size == 0) {
    757         // Just let go zero bytes allocation.
    758         qemu_info_log("::: <libc_pid=%03u, pid=%03u>: Zero calloc redir to malloc",
    759                  malloc_pid, getpid());
    760         return qemu_instrumented_malloc(0);
    761     }
    762 
    763     /* Fail on overflow - just to be safe even though this code runs only
    764      * within the debugging C library, not the production one */
    765     if (n_elements && MAX_SIZE_T / n_elements < elem_size) {
    766         return NULL;
    767     }
    768 
    769     MallocDesc desc;
    770 
    771     /* Calculating prefix size. The trick here is to make sure that
    772      * first element (returned to the caller) is properly aligned. */
    773     if (DEFAULT_PREFIX_SIZE >= elem_size) {
    774         /* If default alignment is bigger than element size, we will
    775          * set our prefix size to the default alignment size. */
    776         desc.prefix_size = DEFAULT_PREFIX_SIZE;
    777         /* For the suffix we will use whatever bytes remain from the prefix
    778          * allocation size, aligned to the size of an element, plus the usual
    779          * default suffix size. */
    780         desc.suffix_size = (DEFAULT_PREFIX_SIZE % elem_size) +
    781                            DEFAULT_SUFFIX_SIZE;
    782     } else {
    783         /* Make sure that prefix, and suffix sizes is at least elem_size,
    784          * and first element returned to the caller is properly aligned. */
    785         desc.prefix_size = elem_size + DEFAULT_PREFIX_SIZE - 1;
    786         desc.prefix_size &= ~(malloc_alignment - 1);
    787         desc.suffix_size = DEFAULT_SUFFIX_SIZE;
    788     }
    789     desc.requested_bytes = n_elements * elem_size;
    790     size_t total_size = desc.requested_bytes + desc.prefix_size + desc.suffix_size;
    791     size_t total_elements = total_size / elem_size;
    792     total_size %= elem_size;
    793     if (total_size != 0) {
    794         // Add extra to the suffix area.
    795         total_elements++;
    796         desc.suffix_size += (elem_size - total_size);
    797     }
    798     desc.ptr = dlcalloc(total_elements, elem_size);
    799     if (desc.ptr == NULL) {
    800         error_log("<libc_pid=%03u, pid=%03u> calloc: dlcalloc(%u(%u), %u) (prx=%u, sfx=%u) failed.",
    801                    malloc_pid, getpid(), n_elements, total_elements, elem_size,
    802                    desc.prefix_size, desc.suffix_size);
    803         return NULL;
    804     }
    805 
    806     if (notify_qemu_malloc(&desc)) {
    807         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: calloc(%u(%u), %u): notify_malloc failed for ",
    808                   malloc_pid, getpid(), n_elements, total_elements, elem_size);
    809         dlfree(desc.ptr);
    810         return NULL;
    811     } else {
    812 #if TEST_ACCESS_VIOLATIONS
    813         test_access_violation(&desc);
    814 #endif  // TEST_ACCESS_VIOLATIONS
    815         log_mdesc(info, &desc, "### <libc_pid=%03u, pid=%03u> calloc(%u(%u), %u) -> ",
    816                   malloc_pid, getpid(), n_elements, total_elements, elem_size);
    817         return mallocdesc_user_ptr(&desc);
    818     }
    819 }
    820 
    821 /* This routine serves as entry point for 'realloc'.
    822  * This routine behaves similarly to qemu_instrumented_free +
    823  * qemu_instrumented_malloc. Note that this modifies behavior of "shrinking" an
    824  * allocation, but overall it doesn't seem to matter, as caller of realloc
    825  * should not expect that pointer returned after shrinking will remain the same.
    826  */
    827 extern "C" void* qemu_instrumented_realloc(void* mem, size_t bytes) {
    828     MallocDesc new_desc;
    829     MallocDesc cur_desc;
    830     size_t to_copy;
    831     void* ret;
    832 
    833     if (mem == NULL) {
    834         // Nothing to realloc. just do regular malloc.
    835         qemu_info_log("::: <libc_pid=%03u, pid=%03u>: realloc(%p, %u) redir to malloc",
    836                  malloc_pid, getpid(), mem, bytes);
    837         return qemu_instrumented_malloc(bytes);
    838     }
    839 
    840     if (bytes == 0) {
    841         // This is a "free" condition.
    842         qemu_info_log("::: <libc_pid=%03u, pid=%03u>: realloc(%p, %u) redir to free and malloc",
    843                  malloc_pid, getpid(), mem, bytes);
    844         qemu_instrumented_free(mem);
    845 
    846         // This is what dlrealloc does for a "free" realloc.
    847         return NULL;
    848     }
    849 
    850     // Query emulator for the reallocating block information.
    851     if (query_qemu_malloc_info(mem, &cur_desc, 2)) {
    852         // Note that this violation should be already caught in the emulator.
    853         error_log("<libc_pid=%03u, pid=%03u>: realloc(%p, %u) query_info failed.",
    854                   malloc_pid, getpid(), mem, bytes);
    855         return NULL;
    856     }
    857 
    858 #if TEST_ACCESS_VIOLATIONS
    859     test_access_violation(&cur_desc);
    860 #endif  // TEST_ACCESS_VIOLATIONS
    861 
    862     /* Make sure that reallocating pointer value is what we would expect
    863      * for this memory block. Note that this violation should be already caught
    864      * in the emulator.*/
    865     if (mem != mallocdesc_user_ptr(&cur_desc)) {
    866         log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u) is invalid for ",
    867                   malloc_pid, getpid(), mem, bytes);
    868         return NULL;
    869     }
    870 
    871     /* TODO: We're a bit inefficient here, always allocating new block from
    872      * the heap. If this realloc shrinks current buffer, we can just do the
    873      * shrinking "in place", adjusting suffix_size in the allocation descriptor
    874      * for this block that is stored in the emulator. */
    875 
    876     // Initialize descriptor for the new block.
    877     new_desc.prefix_size = DEFAULT_PREFIX_SIZE;
    878     new_desc.requested_bytes = bytes;
    879     new_desc.suffix_size = DEFAULT_SUFFIX_SIZE;
    880     new_desc.ptr = dlmalloc(mallocdesc_alloc_size(&new_desc));
    881     if (new_desc.ptr == NULL) {
    882         log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u): dlmalloc(%u) failed on ",
    883                   malloc_pid, getpid(), mem, bytes,
    884                   mallocdesc_alloc_size(&new_desc));
    885         return NULL;
    886     }
    887     ret = mallocdesc_user_ptr(&new_desc);
    888 
    889     // Copy user data from old block to the new one.
    890     to_copy = bytes < cur_desc.requested_bytes ? bytes :
    891                                                  cur_desc.requested_bytes;
    892     if (to_copy != 0) {
    893         memcpy(ret, mallocdesc_user_ptr(&cur_desc), to_copy);
    894     }
    895 
    896     // Register new block with emulator.
    897     if (notify_qemu_malloc(&new_desc)) {
    898         log_mdesc(error, &new_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u) notify_malloc failed -> ",
    899                   malloc_pid, getpid(), mem, bytes);
    900         log_mdesc(error, &cur_desc, "                                                                <- ");
    901         dlfree(new_desc.ptr);
    902         return NULL;
    903     }
    904 
    905 #if TEST_ACCESS_VIOLATIONS
    906     test_access_violation(&new_desc);
    907 #endif  // TEST_ACCESS_VIOLATIONS
    908 
    909     // Free old block.
    910     if (notify_qemu_free(mem)) {
    911         log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u): notify_free failed for ",
    912                   malloc_pid, getpid(), mem, bytes);
    913         /* Since we registered new decriptor with the emulator, we need
    914          * to unregister it before freeing newly allocated block. */
    915         notify_qemu_free(mallocdesc_user_ptr(&new_desc));
    916         dlfree(new_desc.ptr);
    917         return NULL;
    918     }
    919     dlfree(cur_desc.ptr);
    920 
    921     log_mdesc(info, &new_desc, "=== <libc_pid=%03u, pid=%03u>: realloc(%p, %u) -> ",
    922               malloc_pid, getpid(), mem, bytes);
    923     log_mdesc(info, &cur_desc, "                                               <- ");
    924 
    925     return ret;
    926 }
    927 
    928 /* This routine serves as entry point for 'memalign'.
    929  * This routine behaves similarly to qemu_instrumented_malloc.
    930  */
    931 extern "C" void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
    932     MallocDesc desc;
    933 
    934     if (bytes == 0) {
    935         // Just let go zero bytes allocation.
    936         qemu_info_log("::: <libc_pid=%03u, pid=%03u>: memalign(%X, %u) redir to malloc",
    937                  malloc_pid, getpid(), alignment, bytes);
    938         return qemu_instrumented_malloc(0);
    939     }
    940 
    941     /* Prefix size for aligned allocation must be equal to the alignment used
    942      * for allocation in order to ensure proper alignment of the returned
    943      * pointer, in case that alignment requirement is greater than prefix
    944      * size. */
    945     desc.prefix_size = alignment > DEFAULT_PREFIX_SIZE ? alignment :
    946                                                          DEFAULT_PREFIX_SIZE;
    947     desc.requested_bytes = bytes;
    948     desc.suffix_size = DEFAULT_SUFFIX_SIZE;
    949     desc.ptr = dlmemalign(desc.prefix_size, mallocdesc_alloc_size(&desc));
    950     if (desc.ptr == NULL) {
    951         error_log("<libc_pid=%03u, pid=%03u> memalign(%X, %u): dlmalloc(%u) failed.",
    952                   malloc_pid, getpid(), alignment, bytes,
    953                   mallocdesc_alloc_size(&desc));
    954         return NULL;
    955     }
    956     if (notify_qemu_malloc(&desc)) {
    957         log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: memalign(%X, %u): notify_malloc failed for ",
    958                   malloc_pid, getpid(), alignment, bytes);
    959         dlfree(desc.ptr);
    960         return NULL;
    961     }
    962 
    963 #if TEST_ACCESS_VIOLATIONS
    964     test_access_violation(&desc);
    965 #endif  // TEST_ACCESS_VIOLATIONS
    966 
    967     log_mdesc(info, &desc, "@@@ <libc_pid=%03u, pid=%03u> memalign(%X, %u) -> ",
    968               malloc_pid, getpid(), alignment, bytes);
    969     return mallocdesc_user_ptr(&desc);
    970 }
    971 
    972 extern "C" size_t qemu_instrumented_malloc_usable_size(const void* mem) {
    973     MallocDesc cur_desc;
    974 
    975     // Query emulator for the reallocating block information.
    976     if (query_qemu_malloc_info(mem, &cur_desc, 2)) {
    977         // Note that this violation should be already caught in the emulator.
    978         error_log("<libc_pid=%03u, pid=%03u>: malloc_usable_size(%p) query_info failed.",
    979                   malloc_pid, getpid(), mem);
    980         return 0;
    981     }
    982 
    983     /* Make sure that reallocating pointer value is what we would expect
    984      * for this memory block. Note that this violation should be already caught
    985      * in the emulator.*/
    986     if (mem != mallocdesc_user_ptr(&cur_desc)) {
    987         log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: malloc_usable_size(%p) is invalid for ",
    988                   malloc_pid, getpid(), mem);
    989         return 0;
    990     }
    991 
    992     /* during instrumentation, we can't really report anything more than requested_bytes */
    993     return cur_desc.requested_bytes;
    994 }
    995