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