2 * Copyright (C) 2009 The Android Open Source Project
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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
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.
55 #include "malloc_debug_common.h"
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
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
69 // =============================================================================
70 // Communication structures
71 // =============================================================================
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.
82 typedef struct MallocDesc {
83 /* Pointer to the memory block actually allocated from the heap. Note that
84 * this is not the pointer that is returned to the malloc's caller. Pointer
85 * returned to the caller is calculated by adding value stored in this field
86 * to the value stored in prefix_size field of this structure.
90 /* Number of bytes requested by the malloc's caller. */
91 uint32_t requested_bytes;
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.
99 /* Byte size of the suffix data. */
100 uint32_t suffix_size;
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).
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
114 uint32_t allocator_pid;
116 /* Number of access violations detected on this allocation. */
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.
133 typedef struct MallocDescQuery {
134 /* Pointer, for which information is queried. Note that this pointer doesn't
135 * have to be exact pointer returned to malloc's caller, but can point
136 * anywhere inside an allocated block, including guarding areas. Emulator
137 * will respond with information about allocated block that contains this
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).
149 /* Process ID in context of which query is made. */
152 /* Code of the allocation routine, in context of which query has been made:
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.
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.
173 typedef struct MallocFree {
174 /* Pointer to be freed. */
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).
184 /* Process ID in context of which memory is being freed. */
188 // =============================================================================
189 // Communication events
190 // =============================================================================
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
196 #define TRACE_DEV_REG_LIBC_INIT 1536
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.
204 #define TRACE_DEV_REG_MALLOC 1537
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
213 #define TRACE_DEV_REG_FREE_PTR 1538
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.
221 #define TRACE_DEV_REG_QUERY_MALLOC 1539
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.
226 #define TRACE_DEV_REG_PRINT_USER_STR 1540
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,
232 const MallocDesc* desc);
234 // =============================================================================
236 // =============================================================================
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)
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)
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)
259 /* Prints a string to the emulator's stdout.
260 * In early stages of system loading, logging mesages via
261 * __libc_android_log_print API is not available, because ADB API has not been
262 * hooked up yet. So, in order to see such messages we need to print them to
263 * the emulator's stdout.
264 * Parameters passed to this macro are the same as parameters for printf
270 snprintf(tr_str, sizeof(tr_str), __VA_ARGS__ ); \
271 tr_str[sizeof(tr_str) - 1] = '\0'; \
272 notify_qemu_string(&tr_str[0]); \
275 // =============================================================================
276 // Logging macros. Note that we simultaneously log messages to ADB and emulator.
277 // =============================================================================
280 * Helper macros for checking if particular trace level is enabled.
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)
288 * Logging helper macros.
290 #define debug_log(format, ...) \
292 __libc_android_log_print(ANDROID_LOG_DEBUG, "memcheck", \
293 (format), ##__VA_ARGS__ ); \
294 if (tracing_flags & DEBUG_TRACING_ENABLED) { \
295 qemu_log(ANDROID_LOG_DEBUG, (format), ##__VA_ARGS__ ); \
299 #define error_log(format, ...) \
301 __libc_android_log_print(ANDROID_LOG_ERROR, "memcheck", \
302 (format), ##__VA_ARGS__ ); \
303 if (tracing_flags & ERROR_TRACING_ENABLED) { \
304 qemu_log(ANDROID_LOG_ERROR, (format), ##__VA_ARGS__ ); \
308 #define info_log(format, ...) \
310 __libc_android_log_print(ANDROID_LOG_INFO, "memcheck", \
311 (format), ##__VA_ARGS__ ); \
312 if (tracing_flags & INFO_TRACING_ENABLED) { \
313 qemu_log(ANDROID_LOG_INFO, (format), ##__VA_ARGS__ ); \
317 /* Logs message dumping MallocDesc instance at the end of the message.
319 * type - Message type: debug, error, or info
320 * desc - MallocDesc instance to dump.
321 * frmt + rest - Formats message preceding dumped descriptor.
323 #define log_mdesc(type, desc, frmt, ...) \
325 if (tracing_enabled(type)) { \
326 char log_str[4096]; \
328 snprintf(log_str, sizeof(log_str), frmt, ##__VA_ARGS__); \
329 log_str[sizeof(log_str) - 1] = '\0'; \
330 str_len = strlen(log_str); \
331 dump_malloc_descriptor(log_str + str_len, \
332 sizeof(log_str) - str_len, \
334 type##_log(log_str); \
338 // =============================================================================
340 // =============================================================================
342 /* Emulator's magic page address.
343 * This page (mapped on /dev/qemu_trace device) is used to fire up events
344 * in the emulator. */
345 static volatile void* qtrace = NULL;
347 /* Cached PID of the process in context of which this libc instance
348 * has been initialized. */
349 static uint32_t malloc_pid = 0;
351 /* Memory allocation alignment that is used in dlmalloc.
352 * This variable is updated by memcheck_initialize routine. */
353 static uint32_t malloc_alignment = 8;
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
359 static uint32_t tracing_flags = 0;
361 // =============================================================================
363 // =============================================================================
365 /* Gets pointer, returned to malloc caller for the given allocation decriptor.
367 * desc - Allocation descriptor.
369 * Pointer to the allocated memory returned to the malloc caller.
372 mallocdesc_user_ptr(const MallocDesc* desc)
374 return (char*)desc->ptr + desc->prefix_size;
377 /* Gets size of memory block actually allocated from the heap for the given
378 * allocation decriptor.
380 * desc - Allocation descriptor.
382 * Size of memory block actually allocated from the heap.
384 static inline uint32_t
385 mallocdesc_alloc_size(const MallocDesc* desc)
387 return desc->prefix_size + desc->requested_bytes + desc->suffix_size;
390 /* Gets pointer to the end of the allocated block for the given descriptor.
392 * desc - Descriptor for the memory block, allocated in malloc handler.
394 * Pointer to the end of (one byte past) the allocated block.
397 mallocdesc_alloc_end(const MallocDesc* desc)
399 return (char*)desc->ptr + mallocdesc_alloc_size(desc);
402 /* Fires up an event in the emulator.
404 * code - Event code (one of the TRACE_DEV_XXX).
405 * val - Event's value parameter.
408 notify_qemu(uint32_t code, uint32_t val)
410 if (NULL != qtrace) {
411 *(volatile uint32_t*)((uint32_t)qtrace + ((code - 1024) << 2)) = val;
415 /* Prints a zero-terminated string to the emulator's stdout (fires up
416 * TRACE_DEV_REG_PRINT_USER_STR event in the emulator).
418 * str - Zero-terminated string to print.
421 notify_qemu_string(const char* str)
424 notify_qemu(TRACE_DEV_REG_PRINT_USER_STR, (uint32_t)str);
428 /* Fires up TRACE_DEV_REG_LIBC_INIT event in the emulator.
430 * pid - ID of the process that initialized libc.
433 notify_qemu_libc_initialized(uint32_t pid)
435 notify_qemu(TRACE_DEV_REG_LIBC_INIT, pid);
438 /* Fires up TRACE_DEV_REG_MALLOC event in the emulator.
440 * desc - Pointer to MallocDesc instance containing allocated block
443 * Zero on success, or -1 on failure. Note that on failure libc_pid field of
444 * the desc parameter passed to this routine has been zeroed out by the
448 notify_qemu_malloc(volatile MallocDesc* desc)
450 desc->libc_pid = malloc_pid;
451 desc->allocator_pid = getpid();
453 notify_qemu(TRACE_DEV_REG_MALLOC, (uint32_t)desc);
455 /* Emulator reports failure by zeroing libc_pid field of the
457 return desc->libc_pid != 0 ? 0 : -1;
460 /* Fires up TRACE_DEV_REG_FREE_PTR event in the emulator.
462 * ptr - Pointer to the memory block that's being freed.
464 * Zero on success, or -1 on failure.
467 notify_qemu_free(void* ptr_to_free)
469 volatile MallocFree free_desc;
471 free_desc.ptr = ptr_to_free;
472 free_desc.libc_pid = malloc_pid;
473 free_desc.free_pid = getpid();
474 notify_qemu(TRACE_DEV_REG_FREE_PTR, (uint32_t)&free_desc);
476 /* Emulator reports failure by zeroing libc_pid field of the
478 return free_desc.libc_pid != 0 ? 0 : -1;
481 /* Fires up TRACE_DEV_REG_QUERY_MALLOC event in the emulator.
483 * ptr - Pointer to request allocation information for.
484 * desc - Pointer to MallocDesc instance that will receive allocation
486 * routine - Code of the allocation routine, in context of which query is made:
490 * Zero on success, or -1 on failure.
493 query_qemu_malloc_info(void* ptr, MallocDesc* desc, uint32_t routine)
495 volatile MallocDescQuery query;
498 query.libc_pid = malloc_pid;
499 query.query_pid = getpid();
500 query.routine = routine;
502 notify_qemu(TRACE_DEV_REG_QUERY_MALLOC, (uint32_t)&query);
504 /* Emulator reports failure by zeroing libc_pid field of the
506 return query.libc_pid != 0 ? 0 : -1;
509 /* Logs a message to emulator's stdout.
511 * prio - Message priority (debug, info, or error)
512 * fmt + rest - Message format and parameters.
515 qemu_log(int prio, const char* fmt, ...)
521 /* Choose message prefix depending on the priority value. */
523 case ANDROID_LOG_ERROR:
524 if (!tracing_enabled(error)) {
529 case ANDROID_LOG_INFO:
530 if (!tracing_enabled(info)) {
535 case ANDROID_LOG_DEBUG:
537 if (!tracing_enabled(debug)) {
545 vsnprintf(buf, sizeof(buf), fmt, ap);
547 buf[sizeof(buf) - 1] = '\0';
549 TR("%s/memcheck: %s\n", prefix, buf);
552 /* Dumps content of memory allocation descriptor to a string.
554 * str - String to dump descriptor to.
555 * str_buf_size - Size of string's buffer.
556 * desc - Descriptor to dump.
559 dump_malloc_descriptor(char* str, size_t str_buf_size, const MallocDesc* desc)
562 snprintf(str, str_buf_size,
563 "MDesc: %p: %X <-> %X [%u + %u + %u] by pid=%03u in libc_pid=%03u",
564 mallocdesc_user_ptr(desc), (uint32_t)desc->ptr,
565 (uint32_t)mallocdesc_alloc_end(desc), desc->prefix_size,
566 desc->requested_bytes, desc->suffix_size, desc->allocator_pid,
568 str[str_buf_size - 1] = '\0';
572 #if TEST_ACCESS_VIOLATIONS
573 /* Causes an access violation on allocation descriptor, and verifies that
574 * violation has been detected by memory checker in the emulator.
577 test_access_violation(const MallocDesc* desc)
581 volatile char* prefix = (volatile char*)desc->ptr;
582 volatile char* suffix = (volatile char*)mallocdesc_user_ptr(desc) +
583 desc->requested_bytes;
584 /* We're causing AV by reading from the prefix and suffix areas of the
585 * allocated block. This should produce two access violations, so when we
586 * get allocation descriptor from QEMU, av_counter should be bigger than
587 * av_counter of the original descriptor by 2. */
590 if (!query_qemu_malloc_info(mallocdesc_user_ptr(desc), &desc_chk, 2) &&
591 desc_chk.av_count != (desc->av_count + 2)) {
592 log_mdesc(error, &desc_chk,
593 "<libc_pid=%03u, pid=%03u>: malloc: Access violation test failed:\n"
594 "Expected violations count %u is not equal to the actually reported %u",
595 malloc_pid, getpid(), desc->av_count + 2,
599 #endif // TEST_ACCESS_VIOLATIONS
601 // =============================================================================
603 // =============================================================================
605 void* qemu_instrumented_malloc(size_t bytes);
606 void qemu_instrumented_free(void* mem);
607 void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size);
608 void* qemu_instrumented_realloc(void* mem, size_t bytes);
609 void* qemu_instrumented_memalign(size_t alignment, size_t bytes);
611 /* Initializes malloc debugging instrumentation for the emulator.
612 * This routine is called from malloc_init_impl routine implemented in
613 * bionic/libc/bionic/malloc_debug_common.c when malloc debugging gets
614 * initialized for a process. The way malloc debugging implementation is
615 * done, it is guaranteed that this routine will be called just once per
618 * 0 on success, or -1 on failure.
621 malloc_debug_initialize(void)
623 /* We will be using emulator's magic page to report memory allocation
624 * activities. In essence, what magic page does, it translates writes to
625 * the memory mapped spaces into writes to an I/O port that emulator
626 * "listens to" on the other end. Note that until we open and map that
627 * device, logging to emulator's stdout will not be available. */
628 int fd = open("/dev/qemu_trace", O_RDWR);
630 error_log("Unable to open /dev/qemu_trace");
633 qtrace = mmap(0, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
636 if (qtrace == MAP_FAILED) {
638 error_log("Unable to mmap /dev/qemu_trace");
643 /* Cache pid of the process this library has been initialized for. */
644 malloc_pid = getpid();
649 /* Completes malloc debugging instrumentation for the emulator.
650 * Note that this routine is called after successful return from
651 * malloc_debug_initialize, which means that connection to the emulator via
652 * "magic page" has been established.
654 * alignment - Alignment requirement set for memiry allocations.
655 * memcheck_param - Emulator's -memcheck option parameters. This string
656 * contains abbreviation for guest events that are enabled for tracing.
658 * 0 on success, or -1 on failure.
661 memcheck_initialize(int alignment, const char* memcheck_param)
663 malloc_alignment = alignment;
665 /* Parse -memcheck parameter for the guest tracing flags. */
666 while (*memcheck_param != '\0') {
667 switch (*memcheck_param) {
669 // Enable all messages from the guest.
670 tracing_flags |= ALL_TRACING_ENABLED;
673 // Enable debug messages from the guest.
674 tracing_flags |= DEBUG_TRACING_ENABLED;
677 // Enable error messages from the guest.
678 tracing_flags |= ERROR_TRACING_ENABLED;
681 // Enable info messages from the guest.
682 tracing_flags |= INFO_TRACING_ENABLED;
687 if (tracing_flags == ALL_TRACING_ENABLED) {
693 notify_qemu_libc_initialized(malloc_pid);
695 debug_log("Instrumented for pid=%03u: malloc=%p, free=%p, calloc=%p, realloc=%p, memalign=%p",
696 malloc_pid, qemu_instrumented_malloc, qemu_instrumented_free,
697 qemu_instrumented_calloc, qemu_instrumented_realloc,
698 qemu_instrumented_memalign);
703 /* This routine serves as entry point for 'malloc'.
704 * Primary responsibility of this routine is to allocate requested number of
705 * bytes (plus prefix, and suffix guards), and report allocation to the
709 qemu_instrumented_malloc(size_t bytes)
713 /* Initialize block descriptor and allocate memory. Note that dlmalloc
714 * returns a valid pointer on zero allocation. Lets mimic this behavior. */
715 desc.prefix_size = DEFAULT_PREFIX_SIZE;
716 desc.requested_bytes = bytes;
717 desc.suffix_size = DEFAULT_SUFFIX_SIZE;
718 desc.ptr = dlmalloc(mallocdesc_alloc_size(&desc));
719 if (desc.ptr == NULL) {
720 error_log("<libc_pid=%03u, pid=%03u> malloc(%u): dlmalloc(%u) failed.",
721 malloc_pid, getpid(), bytes, mallocdesc_alloc_size(&desc));
725 // Fire up event in the emulator.
726 if (notify_qemu_malloc(&desc)) {
727 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: malloc: notify_malloc failed for ",
728 malloc_pid, getpid());
732 #if TEST_ACCESS_VIOLATIONS
733 test_access_violation(&desc);
734 #endif // TEST_ACCESS_VIOLATIONS
735 log_mdesc(info, &desc, "+++ <libc_pid=%03u, pid=%03u> malloc(%u) -> ",
736 malloc_pid, getpid(), bytes);
737 return mallocdesc_user_ptr(&desc);
741 /* This routine serves as entry point for 'malloc'.
742 * Primary responsibility of this routine is to free requested memory, and
743 * report free block to the emulator.
746 qemu_instrumented_free(void* mem)
751 // Just let go NULL free
756 // Query emulator for the freeing block information.
757 if (query_qemu_malloc_info(mem, &desc, 1)) {
758 error_log("<libc_pid=%03u, pid=%03u>: free(%p) query_info failed.",
759 malloc_pid, getpid(), mem);
763 #if TEST_ACCESS_VIOLATIONS
764 test_access_violation(&desc);
765 #endif // TEST_ACCESS_VIOLATIONS
767 /* Make sure that pointer that's being freed matches what we expect
768 * for this memory block. Note that this violation should be already
769 * caught in the emulator. */
770 if (mem != mallocdesc_user_ptr(&desc)) {
771 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: free(%p) is invalid for ",
772 malloc_pid, getpid(), mem);
776 // Fire up event in the emulator and free block that was actually allocated.
777 if (notify_qemu_free(mem)) {
778 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: free(%p) notify_free failed for ",
779 malloc_pid, getpid(), mem);
781 log_mdesc(info, &desc, "--- <libc_pid=%03u, pid=%03u> free(%p) -> ",
782 malloc_pid, getpid(), mem);
787 /* This routine serves as entry point for 'calloc'.
788 * This routine behaves similarly to qemu_instrumented_malloc.
791 qemu_instrumented_calloc(size_t n_elements, size_t elem_size)
796 size_t total_elements;
798 if (n_elements == 0 || elem_size == 0) {
799 // Just let go zero bytes allocation.
800 info_log("::: <libc_pid=%03u, pid=%03u>: Zero calloc redir to malloc",
801 malloc_pid, getpid());
802 return qemu_instrumented_malloc(0);
805 /* Fail on overflow - just to be safe even though this code runs only
806 * within the debugging C library, not the production one */
807 if (n_elements && MAX_SIZE_T / n_elements < elem_size) {
811 /* Calculating prefix size. The trick here is to make sure that
812 * first element (returned to the caller) is properly aligned. */
813 if (DEFAULT_PREFIX_SIZE >= elem_size) {
814 /* If default alignment is bigger than element size, we will
815 * set our prefix size to the default alignment size. */
816 desc.prefix_size = DEFAULT_PREFIX_SIZE;
817 /* For the suffix we will use whatever bytes remain from the prefix
818 * allocation size, aligned to the size of an element, plus the usual
819 * default suffix size. */
820 desc.suffix_size = (DEFAULT_PREFIX_SIZE % elem_size) +
823 /* Make sure that prefix, and suffix sizes is at least elem_size,
824 * and first element returned to the caller is properly aligned. */
825 desc.prefix_size = elem_size + DEFAULT_PREFIX_SIZE - 1;
826 desc.prefix_size &= ~(malloc_alignment - 1);
827 desc.suffix_size = DEFAULT_SUFFIX_SIZE;
829 desc.requested_bytes = n_elements * elem_size;
830 total_size = desc.requested_bytes + desc.prefix_size + desc.suffix_size;
831 total_elements = total_size / elem_size;
832 total_size %= elem_size;
833 if (total_size != 0) {
834 // Add extra to the suffix area.
836 desc.suffix_size += (elem_size - total_size);
838 desc.ptr = dlcalloc(total_elements, elem_size);
839 if (desc.ptr == NULL) {
840 error_log("<libc_pid=%03u, pid=%03u> calloc: dlcalloc(%u(%u), %u) (prx=%u, sfx=%u) failed.",
841 malloc_pid, getpid(), n_elements, total_elements, elem_size,
842 desc.prefix_size, desc.suffix_size);
846 if (notify_qemu_malloc(&desc)) {
847 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: calloc(%u(%u), %u): notify_malloc failed for ",
848 malloc_pid, getpid(), n_elements, total_elements, elem_size);
852 #if TEST_ACCESS_VIOLATIONS
853 test_access_violation(&desc);
854 #endif // TEST_ACCESS_VIOLATIONS
855 log_mdesc(info, &desc, "### <libc_pid=%03u, pid=%03u> calloc(%u(%u), %u) -> ",
856 malloc_pid, getpid(), n_elements, total_elements, elem_size);
857 return mallocdesc_user_ptr(&desc);
861 /* This routine serves as entry point for 'realloc'.
862 * This routine behaves similarly to qemu_instrumented_free +
863 * qemu_instrumented_malloc. Note that this modifies behavior of "shrinking" an
864 * allocation, but overall it doesn't seem to matter, as caller of realloc
865 * should not expect that pointer returned after shrinking will remain the same.
868 qemu_instrumented_realloc(void* mem, size_t bytes)
876 // Nothing to realloc. just do regular malloc.
877 info_log("::: <libc_pid=%03u, pid=%03u>: realloc(%p, %u) redir to malloc",
878 malloc_pid, getpid(), mem, bytes);
879 return qemu_instrumented_malloc(bytes);
883 // This is a "free" condition.
884 info_log("::: <libc_pid=%03u, pid=%03u>: realloc(%p, %u) redir to free and malloc",
885 malloc_pid, getpid(), mem, bytes);
886 qemu_instrumented_free(mem);
888 // This is what dlrealloc does for a "free" realloc.
892 // Query emulator for the reallocating block information.
893 if (query_qemu_malloc_info(mem, &cur_desc, 2)) {
894 // Note that this violation should be already caught in the emulator.
895 error_log("<libc_pid=%03u, pid=%03u>: realloc(%p, %u) query_info failed.",
896 malloc_pid, getpid(), mem, bytes);
900 #if TEST_ACCESS_VIOLATIONS
901 test_access_violation(&cur_desc);
902 #endif // TEST_ACCESS_VIOLATIONS
904 /* Make sure that reallocating pointer value is what we would expect
905 * for this memory block. Note that this violation should be already caught
907 if (mem != mallocdesc_user_ptr(&cur_desc)) {
908 log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u) is invalid for ",
909 malloc_pid, getpid(), mem, bytes);
913 /* TODO: We're a bit inefficient here, always allocating new block from
914 * the heap. If this realloc shrinks current buffer, we can just do the
915 * shrinking "in place", adjusting suffix_size in the allocation descriptor
916 * for this block that is stored in the emulator. */
918 // Initialize descriptor for the new block.
919 new_desc.prefix_size = DEFAULT_PREFIX_SIZE;
920 new_desc.requested_bytes = bytes;
921 new_desc.suffix_size = DEFAULT_SUFFIX_SIZE;
922 new_desc.ptr = dlmalloc(mallocdesc_alloc_size(&new_desc));
923 if (new_desc.ptr == NULL) {
924 log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u): dlmalloc(%u) failed on ",
925 malloc_pid, getpid(), mem, bytes,
926 mallocdesc_alloc_size(&new_desc));
929 ret = mallocdesc_user_ptr(&new_desc);
931 // Copy user data from old block to the new one.
932 to_copy = bytes < cur_desc.requested_bytes ? bytes :
933 cur_desc.requested_bytes;
935 memcpy(ret, mallocdesc_user_ptr(&cur_desc), to_copy);
938 // Register new block with emulator.
939 if(notify_qemu_malloc(&new_desc)) {
940 log_mdesc(error, &new_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u) notify_malloc failed -> ",
941 malloc_pid, getpid(), mem, bytes);
942 log_mdesc(error, &cur_desc, " <- ");
943 dlfree(new_desc.ptr);
947 #if TEST_ACCESS_VIOLATIONS
948 test_access_violation(&new_desc);
949 #endif // TEST_ACCESS_VIOLATIONS
952 if (notify_qemu_free(mem)) {
953 log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %u): notify_free failed for ",
954 malloc_pid, getpid(), mem, bytes);
955 /* Since we registered new decriptor with the emulator, we need
956 * to unregister it before freeing newly allocated block. */
957 notify_qemu_free(mallocdesc_user_ptr(&new_desc));
958 dlfree(new_desc.ptr);
961 dlfree(cur_desc.ptr);
963 log_mdesc(info, &new_desc, "=== <libc_pid=%03u, pid=%03u>: realloc(%p, %u) -> ",
964 malloc_pid, getpid(), mem, bytes);
965 log_mdesc(info, &cur_desc, " <- ");
970 /* This routine serves as entry point for 'memalign'.
971 * This routine behaves similarly to qemu_instrumented_malloc.
974 qemu_instrumented_memalign(size_t alignment, size_t bytes)
979 // Just let go zero bytes allocation.
980 info_log("::: <libc_pid=%03u, pid=%03u>: memalign(%X, %u) redir to malloc",
981 malloc_pid, getpid(), alignment, bytes);
982 return qemu_instrumented_malloc(0);
985 /* Prefix size for aligned allocation must be equal to the alignment used
986 * for allocation in order to ensure proper alignment of the returned
987 * pointer, in case that alignment requirement is greater than prefix
989 desc.prefix_size = alignment > DEFAULT_PREFIX_SIZE ? alignment :
991 desc.requested_bytes = bytes;
992 desc.suffix_size = DEFAULT_SUFFIX_SIZE;
993 desc.ptr = dlmemalign(desc.prefix_size, mallocdesc_alloc_size(&desc));
994 if (desc.ptr == NULL) {
995 error_log("<libc_pid=%03u, pid=%03u> memalign(%X, %u): dlmalloc(%u) failed.",
996 malloc_pid, getpid(), alignment, bytes,
997 mallocdesc_alloc_size(&desc));
1000 if (notify_qemu_malloc(&desc)) {
1001 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: memalign(%X, %u): notify_malloc failed for ",
1002 malloc_pid, getpid(), alignment, bytes);
1007 #if TEST_ACCESS_VIOLATIONS
1008 test_access_violation(&desc);
1009 #endif // TEST_ACCESS_VIOLATIONS
1011 log_mdesc(info, &desc, "@@@ <libc_pid=%03u, pid=%03u> memalign(%X, %u) -> ",
1012 malloc_pid, getpid(), alignment, bytes);
1013 return mallocdesc_user_ptr(&desc);