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