blob: fd5161a7e5f1f3b4417a4ed2b1498a792d108b34 [file] [log] [blame]
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -08001/*
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/*
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080030 * Contains implementation of memory allocation routines instrumented for
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -080031 * usage in the emulator to detect memory allocation violations, such as
32 * memory leaks, buffer overruns, etc.
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080033 * 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.
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -080043 */
44
45#include <stdlib.h>
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080046#include <stddef.h>
47#include <stdio.h>
48#include <fcntl.h>
49#include <sys/mman.h>
Christopher Ferris03eebcb2014-06-13 13:57:51 -070050#include <sys/param.h>
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -080051#include <pthread.h>
52#include <unistd.h>
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080053#include <errno.h>
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080054#include "malloc_debug_common.h"
Christopher Ferris03eebcb2014-06-13 13:57:51 -070055#include "private/bionic_macros.h"
56#include "private/libc_logging.h"
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -080057
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080058/* This file should be included into the build only when
59 * MALLOC_QEMU_INSTRUMENT macro is defined. */
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -080060#ifndef MALLOC_QEMU_INSTRUMENT
61#error MALLOC_QEMU_INSTRUMENT is not defined.
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080062#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
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -080069
70// =============================================================================
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080071// Communication structures
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -080072// =============================================================================
73
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080074/* 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 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -070083struct MallocDesc {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080084 /* 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;
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -080090
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -080091 /* 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;
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700119};
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800120
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 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700134struct MallocDescQuery {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800135 /* 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 */
Christopher Ferris885f3b92013-05-21 17:48:01 -0700141 const void* ptr;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800142
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;
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700164};
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800165
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 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700174struct MallocFree {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800175 /* 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;
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700187};
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800188
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.
Elliott Hughes1e980b62013-01-17 18:36:06 -0800261 * In early stages of system loading, logging messages to logcat
262 * is not available, because ADB API has not been
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800263 * 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]; \
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700271 snprintf(tr_str, sizeof(tr_str), __VA_ARGS__); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800272 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 */
Iliyan Malcheve1dd3c22012-05-29 14:22:42 -0700291#define qemu_debug_log(format, ...) \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800292 do { \
Elliott Hughes1e980b62013-01-17 18:36:06 -0800293 __libc_format_log(ANDROID_LOG_DEBUG, "memcheck", (format), ##__VA_ARGS__); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800294 if (tracing_flags & DEBUG_TRACING_ENABLED) { \
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700295 qemu_log(ANDROID_LOG_DEBUG, (format), ##__VA_ARGS__); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800296 } \
297 } while (0)
298
Iliyan Malcheve1dd3c22012-05-29 14:22:42 -0700299#define qemu_error_log(format, ...) \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800300 do { \
Elliott Hughes1e980b62013-01-17 18:36:06 -0800301 __libc_format_log(ANDROID_LOG_ERROR, "memcheck", (format), ##__VA_ARGS__); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800302 if (tracing_flags & ERROR_TRACING_ENABLED) { \
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700303 qemu_log(ANDROID_LOG_ERROR, (format), ##__VA_ARGS__); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800304 } \
305 } while (0)
306
Iliyan Malcheve1dd3c22012-05-29 14:22:42 -0700307#define qemu_info_log(format, ...) \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800308 do { \
Elliott Hughes1e980b62013-01-17 18:36:06 -0800309 __libc_format_log(ANDROID_LOG_INFO, "memcheck", (format), ##__VA_ARGS__); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800310 if (tracing_flags & INFO_TRACING_ENABLED) { \
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700311 qemu_log(ANDROID_LOG_INFO, (format), ##__VA_ARGS__); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800312 } \
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.
Elliott Hughes1e980b62013-01-17 18:36:06 -0800319 * fmt + rest - Formats message preceding dumped descriptor.
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800320*/
Elliott Hughes1e980b62013-01-17 18:36:06 -0800321#define log_mdesc(type, desc, fmt, ...) \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800322 do { \
323 if (tracing_enabled(type)) { \
324 char log_str[4096]; \
Elliott Hughes1e980b62013-01-17 18:36:06 -0800325 __libc_format_buffer(log_str, sizeof(log_str), fmt, ##__VA_ARGS__); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800326 log_str[sizeof(log_str) - 1] = '\0'; \
Elliott Hughes1e980b62013-01-17 18:36:06 -0800327 size_t str_len = strlen(log_str); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800328 dump_malloc_descriptor(log_str + str_len, \
329 sizeof(log_str) - str_len, \
330 (desc)); \
Elliott Hughes1e980b62013-01-17 18:36:06 -0800331 type##_log("%s", log_str); \
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800332 } \
333 } while (0)
334
335// =============================================================================
336// Static data
337// =============================================================================
338
339/* Emulator's magic page address.
340 * This page (mapped on /dev/qemu_trace device) is used to fire up events
341 * in the emulator. */
342static volatile void* qtrace = NULL;
343
344/* Cached PID of the process in context of which this libc instance
345 * has been initialized. */
346static uint32_t malloc_pid = 0;
347
Christopher Ferris72bbd422014-05-08 11:14:03 -0700348/* Memory allocation alignment that is used in the malloc implementation.
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800349 * This variable is updated by memcheck_initialize routine. */
350static uint32_t malloc_alignment = 8;
351
352/* Tracing flags. These flags control which types of logging messages are
353 * enabled by the emulator. See XXX_TRACING_ENABLED for the values of flags
354 * stored in this variable. This variable is updated by memcheck_initialize
355 * routine. */
356static uint32_t tracing_flags = 0;
357
358// =============================================================================
359// Static routines
360// =============================================================================
361
362/* Gets pointer, returned to malloc caller for the given allocation decriptor.
363 * Param:
364 * desc - Allocation descriptor.
365 * Return:
366 * Pointer to the allocated memory returned to the malloc caller.
367 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700368static inline void* mallocdesc_user_ptr(const MallocDesc* desc) {
369 return static_cast<char*>(desc->ptr) + desc->prefix_size;
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -0800370}
371
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800372/* Gets size of memory block actually allocated from the heap for the given
373 * allocation decriptor.
374 * Param:
375 * desc - Allocation descriptor.
376 * Return:
377 * Size of memory block actually allocated from the heap.
378 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700379static inline uint32_t mallocdesc_alloc_size(const MallocDesc* desc) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800380 return desc->prefix_size + desc->requested_bytes + desc->suffix_size;
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -0800381}
382
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800383/* Gets pointer to the end of the allocated block for the given descriptor.
384 * Param:
385 * desc - Descriptor for the memory block, allocated in malloc handler.
386 * Return:
387 * Pointer to the end of (one byte past) the allocated block.
388 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700389static inline void* mallocdesc_alloc_end(const MallocDesc* desc) {
390 return static_cast<char*>(desc->ptr) + mallocdesc_alloc_size(desc);
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -0800391}
392
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800393/* Fires up an event in the emulator.
394 * Param:
395 * code - Event code (one of the TRACE_DEV_XXX).
396 * val - Event's value parameter.
397 */
Elliott Hughesef0696d2013-10-08 16:16:01 -0700398static inline void notify_qemu(uint32_t code, uintptr_t val) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800399 if (NULL != qtrace) {
Elliott Hughesef0696d2013-10-08 16:16:01 -0700400 *(volatile uintptr_t*)((uintptr_t)qtrace + ((code - 1024) << 2)) = val;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800401 }
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -0800402}
403
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800404/* Prints a zero-terminated string to the emulator's stdout (fires up
405 * TRACE_DEV_REG_PRINT_USER_STR event in the emulator).
406 * Param:
407 * str - Zero-terminated string to print.
408 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700409static void notify_qemu_string(const char* str) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800410 if (str != NULL) {
Elliott Hughesef0696d2013-10-08 16:16:01 -0700411 notify_qemu(TRACE_DEV_REG_PRINT_USER_STR, reinterpret_cast<uintptr_t>(str));
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800412 }
413}
414
415/* Fires up TRACE_DEV_REG_LIBC_INIT event in the emulator.
416 * Param:
417 * pid - ID of the process that initialized libc.
418 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700419static void notify_qemu_libc_initialized(uint32_t pid) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800420 notify_qemu(TRACE_DEV_REG_LIBC_INIT, pid);
421}
422
423/* Fires up TRACE_DEV_REG_MALLOC event in the emulator.
424 * Param:
425 * desc - Pointer to MallocDesc instance containing allocated block
426 * information.
427 * Return:
428 * Zero on success, or -1 on failure. Note that on failure libc_pid field of
429 * the desc parameter passed to this routine has been zeroed out by the
430 * emulator.
431 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700432static inline int notify_qemu_malloc(volatile MallocDesc* desc) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800433 desc->libc_pid = malloc_pid;
434 desc->allocator_pid = getpid();
435 desc->av_count = 0;
Elliott Hughesef0696d2013-10-08 16:16:01 -0700436 notify_qemu(TRACE_DEV_REG_MALLOC, reinterpret_cast<uintptr_t>(desc));
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800437
438 /* Emulator reports failure by zeroing libc_pid field of the
439 * descriptor. */
440 return desc->libc_pid != 0 ? 0 : -1;
441}
442
443/* Fires up TRACE_DEV_REG_FREE_PTR event in the emulator.
444 * Param:
445 * ptr - Pointer to the memory block that's being freed.
446 * Return:
447 * Zero on success, or -1 on failure.
448 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700449static inline int notify_qemu_free(void* ptr_to_free) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800450 volatile MallocFree free_desc;
451
452 free_desc.ptr = ptr_to_free;
453 free_desc.libc_pid = malloc_pid;
454 free_desc.free_pid = getpid();
Elliott Hughesef0696d2013-10-08 16:16:01 -0700455 notify_qemu(TRACE_DEV_REG_FREE_PTR, reinterpret_cast<uintptr_t>(&free_desc));
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800456
457 /* Emulator reports failure by zeroing libc_pid field of the
458 * descriptor. */
459 return free_desc.libc_pid != 0 ? 0 : -1;
460}
461
462/* Fires up TRACE_DEV_REG_QUERY_MALLOC event in the emulator.
463 * Param:
464 * ptr - Pointer to request allocation information for.
465 * desc - Pointer to MallocDesc instance that will receive allocation
466 * information.
467 * routine - Code of the allocation routine, in context of which query is made:
468 * 1 - free
469 * 2 - realloc
470 * Return:
471 * Zero on success, or -1 on failure.
472 */
Christopher Ferris885f3b92013-05-21 17:48:01 -0700473static inline int query_qemu_malloc_info(const void* ptr, MallocDesc* desc, uint32_t routine) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800474 volatile MallocDescQuery query;
475
476 query.ptr = ptr;
477 query.libc_pid = malloc_pid;
478 query.query_pid = getpid();
479 query.routine = routine;
480 query.desc = desc;
Elliott Hughesef0696d2013-10-08 16:16:01 -0700481 notify_qemu(TRACE_DEV_REG_QUERY_MALLOC, reinterpret_cast<uintptr_t>(&query));
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800482
483 /* Emulator reports failure by zeroing libc_pid field of the
484 * descriptor. */
485 return query.libc_pid != 0 ? 0 : -1;
486}
487
488/* Logs a message to emulator's stdout.
489 * Param:
490 * prio - Message priority (debug, info, or error)
491 * fmt + rest - Message format and parameters.
492 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700493static void qemu_log(int prio, const char* fmt, ...) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800494 va_list ap;
495 char buf[4096];
496 const char* prefix;
497
498 /* Choose message prefix depending on the priority value. */
499 switch (prio) {
500 case ANDROID_LOG_ERROR:
501 if (!tracing_enabled(error)) {
502 return;
503 }
504 prefix = "E";
505 break;
506 case ANDROID_LOG_INFO:
507 if (!tracing_enabled(info)) {
508 return;
509 }
510 prefix = "I";
511 break;
512 case ANDROID_LOG_DEBUG:
513 default:
514 if (!tracing_enabled(debug)) {
515 return;
516 }
517 prefix = "D";
518 break;
519 }
520
521 va_start(ap, fmt);
522 vsnprintf(buf, sizeof(buf), fmt, ap);
523 va_end(ap);
524 buf[sizeof(buf) - 1] = '\0';
525
526 TR("%s/memcheck: %s\n", prefix, buf);
527}
528
529/* Dumps content of memory allocation descriptor to a string.
530 * Param:
531 * str - String to dump descriptor to.
532 * str_buf_size - Size of string's buffer.
533 * desc - Descriptor to dump.
534 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700535static void dump_malloc_descriptor(char* str, size_t str_buf_size, const MallocDesc* desc) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800536 if (str_buf_size) {
537 snprintf(str, str_buf_size,
Elliott Hughesef0696d2013-10-08 16:16:01 -0700538 "MDesc: %p: %p <-> %p [%u + %u + %u] by pid=%03u in libc_pid=%03u",
539 mallocdesc_user_ptr(desc), desc->ptr,
540 mallocdesc_alloc_end(desc), desc->prefix_size,
541 desc->requested_bytes, desc->suffix_size, desc->allocator_pid,
542 desc->libc_pid);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800543 str[str_buf_size - 1] = '\0';
544 }
545}
546
547#if TEST_ACCESS_VIOLATIONS
548/* Causes an access violation on allocation descriptor, and verifies that
549 * violation has been detected by memory checker in the emulator.
550 */
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700551static void test_access_violation(const MallocDesc* desc) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800552 MallocDesc desc_chk;
553 char ch;
554 volatile char* prefix = (volatile char*)desc->ptr;
555 volatile char* suffix = (volatile char*)mallocdesc_user_ptr(desc) +
556 desc->requested_bytes;
557 /* We're causing AV by reading from the prefix and suffix areas of the
558 * allocated block. This should produce two access violations, so when we
559 * get allocation descriptor from QEMU, av_counter should be bigger than
560 * av_counter of the original descriptor by 2. */
561 ch = *prefix;
562 ch = *suffix;
563 if (!query_qemu_malloc_info(mallocdesc_user_ptr(desc), &desc_chk, 2) &&
564 desc_chk.av_count != (desc->av_count + 2)) {
565 log_mdesc(error, &desc_chk,
566 "<libc_pid=%03u, pid=%03u>: malloc: Access violation test failed:\n"
567 "Expected violations count %u is not equal to the actually reported %u",
568 malloc_pid, getpid(), desc->av_count + 2,
569 desc_chk.av_count);
570 }
571}
572#endif // TEST_ACCESS_VIOLATIONS
573
574// =============================================================================
575// API routines
576// =============================================================================
577
Christopher Ferrisa4037802014-06-09 19:14:11 -0700578extern "C" void* qemu_instrumented_calloc(size_t, size_t);
579extern "C" void qemu_instrumented_free(void*);
580extern "C" struct mallinfo qemu_instrumented_mallinfo();
581extern "C" void* qemu_instrumented_malloc(size_t);
582extern "C" size_t qemu_instrumented_malloc_usable_size(const void*);
583extern "C" void* qemu_instrumented_memalign(size_t, size_t);
584extern "C" int qemu_instrumented_posix_memalign(void**, size_t, size_t);
585extern "C" void* qemu_instrumented_pvalloc(size_t);
586extern "C" void* qemu_instrumented_realloc(void*, size_t);
587extern "C" void* qemu_instrumented_valloc(size_t);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800588
589/* Initializes malloc debugging instrumentation for the emulator.
590 * This routine is called from malloc_init_impl routine implemented in
591 * bionic/libc/bionic/malloc_debug_common.c when malloc debugging gets
592 * initialized for a process. The way malloc debugging implementation is
593 * done, it is guaranteed that this routine will be called just once per
594 * process.
595 * Return:
596 * 0 on success, or -1 on failure.
597*/
Elliott Hughes8e52e8f2014-06-04 12:07:11 -0700598extern "C" bool malloc_debug_initialize(HashTable*) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800599 /* We will be using emulator's magic page to report memory allocation
600 * activities. In essence, what magic page does, it translates writes to
601 * the memory mapped spaces into writes to an I/O port that emulator
602 * "listens to" on the other end. Note that until we open and map that
603 * device, logging to emulator's stdout will not be available. */
604 int fd = open("/dev/qemu_trace", O_RDWR);
605 if (fd < 0) {
606 error_log("Unable to open /dev/qemu_trace");
Elliott Hughes8e52e8f2014-06-04 12:07:11 -0700607 return false;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800608 } else {
Elliott Hughes0d787c12013-04-04 13:46:46 -0700609 qtrace = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800610 close(fd);
611
612 if (qtrace == MAP_FAILED) {
613 qtrace = NULL;
614 error_log("Unable to mmap /dev/qemu_trace");
Elliott Hughes8e52e8f2014-06-04 12:07:11 -0700615 return false;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800616 }
617 }
618
619 /* Cache pid of the process this library has been initialized for. */
620 malloc_pid = getpid();
Elliott Hughes8e52e8f2014-06-04 12:07:11 -0700621 return true;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800622}
623
624/* Completes malloc debugging instrumentation for the emulator.
625 * Note that this routine is called after successful return from
626 * malloc_debug_initialize, which means that connection to the emulator via
627 * "magic page" has been established.
628 * Param:
629 * alignment - Alignment requirement set for memiry allocations.
630 * memcheck_param - Emulator's -memcheck option parameters. This string
631 * contains abbreviation for guest events that are enabled for tracing.
632 * Return:
633 * 0 on success, or -1 on failure.
634*/
Christopher Ferris885f3b92013-05-21 17:48:01 -0700635extern "C" int memcheck_initialize(int alignment, const char* memcheck_param) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800636 malloc_alignment = alignment;
637
638 /* Parse -memcheck parameter for the guest tracing flags. */
639 while (*memcheck_param != '\0') {
640 switch (*memcheck_param) {
641 case 'a':
642 // Enable all messages from the guest.
643 tracing_flags |= ALL_TRACING_ENABLED;
644 break;
645 case 'd':
646 // Enable debug messages from the guest.
647 tracing_flags |= DEBUG_TRACING_ENABLED;
648 break;
649 case 'e':
650 // Enable error messages from the guest.
651 tracing_flags |= ERROR_TRACING_ENABLED;
652 break;
653 case 'i':
654 // Enable info messages from the guest.
655 tracing_flags |= INFO_TRACING_ENABLED;
656 break;
657 default:
658 break;
659 }
660 if (tracing_flags == ALL_TRACING_ENABLED) {
661 break;
662 }
663 memcheck_param++;
664 }
665
666 notify_qemu_libc_initialized(malloc_pid);
667
Iliyan Malcheve1dd3c22012-05-29 14:22:42 -0700668 qemu_debug_log("Instrumented for pid=%03u: malloc=%p, free=%p, calloc=%p, realloc=%p, memalign=%p",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800669 malloc_pid, qemu_instrumented_malloc, qemu_instrumented_free,
670 qemu_instrumented_calloc, qemu_instrumented_realloc,
671 qemu_instrumented_memalign);
672
673 return 0;
674}
675
676/* This routine serves as entry point for 'malloc'.
677 * Primary responsibility of this routine is to allocate requested number of
678 * bytes (plus prefix, and suffix guards), and report allocation to the
679 * emulator.
680 */
Christopher Ferris885f3b92013-05-21 17:48:01 -0700681extern "C" void* qemu_instrumented_malloc(size_t bytes) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800682 MallocDesc desc;
683
Christopher Ferris72bbd422014-05-08 11:14:03 -0700684 /* Initialize block descriptor and allocate memory. Note that malloc
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800685 * returns a valid pointer on zero allocation. Lets mimic this behavior. */
686 desc.prefix_size = DEFAULT_PREFIX_SIZE;
687 desc.requested_bytes = bytes;
688 desc.suffix_size = DEFAULT_SUFFIX_SIZE;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700689 size_t size = mallocdesc_alloc_size(&desc);
690 if (size < bytes) { // Overflow
691 qemu_error_log("<libc_pid=%03u, pid=%03u> malloc: malloc(%zu) overflow caused failure.",
692 malloc_pid, getpid(), bytes);
693 errno = ENOMEM;
694 return NULL;
695 }
696 desc.ptr = Malloc(malloc)(size);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800697 if (desc.ptr == NULL) {
Christopher Ferris580b6e02014-06-12 18:20:44 -0700698 qemu_error_log("<libc_pid=%03u, pid=%03u> malloc(%zu): malloc(%zu) failed.",
Christopher Ferrisa4037802014-06-09 19:14:11 -0700699 malloc_pid, getpid(), bytes, size);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800700 return NULL;
701 }
702
703 // Fire up event in the emulator.
704 if (notify_qemu_malloc(&desc)) {
705 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: malloc: notify_malloc failed for ",
706 malloc_pid, getpid());
Christopher Ferris72bbd422014-05-08 11:14:03 -0700707 Malloc(free)(desc.ptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700708 errno = ENOMEM;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800709 return NULL;
710 } else {
711#if TEST_ACCESS_VIOLATIONS
712 test_access_violation(&desc);
713#endif // TEST_ACCESS_VIOLATIONS
Christopher Ferrisa4037802014-06-09 19:14:11 -0700714 log_mdesc(info, &desc, "+++ <libc_pid=%03u, pid=%03u> malloc(%zu) -> ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800715 malloc_pid, getpid(), bytes);
716 return mallocdesc_user_ptr(&desc);
717 }
718}
719
720/* This routine serves as entry point for 'malloc'.
721 * Primary responsibility of this routine is to free requested memory, and
722 * report free block to the emulator.
723 */
Christopher Ferris885f3b92013-05-21 17:48:01 -0700724extern "C" void qemu_instrumented_free(void* mem) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800725 MallocDesc desc;
726
727 if (mem == NULL) {
728 // Just let go NULL free
Christopher Ferris72bbd422014-05-08 11:14:03 -0700729 Malloc(free)(mem);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800730 return;
731 }
732
733 // Query emulator for the freeing block information.
734 if (query_qemu_malloc_info(mem, &desc, 1)) {
735 error_log("<libc_pid=%03u, pid=%03u>: free(%p) query_info failed.",
736 malloc_pid, getpid(), mem);
737 return;
738 }
739
740#if TEST_ACCESS_VIOLATIONS
741 test_access_violation(&desc);
742#endif // TEST_ACCESS_VIOLATIONS
743
744 /* Make sure that pointer that's being freed matches what we expect
745 * for this memory block. Note that this violation should be already
746 * caught in the emulator. */
747 if (mem != mallocdesc_user_ptr(&desc)) {
748 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: free(%p) is invalid for ",
749 malloc_pid, getpid(), mem);
750 return;
751 }
752
753 // Fire up event in the emulator and free block that was actually allocated.
754 if (notify_qemu_free(mem)) {
755 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: free(%p) notify_free failed for ",
756 malloc_pid, getpid(), mem);
757 } else {
758 log_mdesc(info, &desc, "--- <libc_pid=%03u, pid=%03u> free(%p) -> ",
759 malloc_pid, getpid(), mem);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700760 Malloc(free)(desc.ptr);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800761 }
762}
763
764/* This routine serves as entry point for 'calloc'.
765 * This routine behaves similarly to qemu_instrumented_malloc.
766 */
Christopher Ferris885f3b92013-05-21 17:48:01 -0700767extern "C" void* qemu_instrumented_calloc(size_t n_elements, size_t elem_size) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800768 if (n_elements == 0 || elem_size == 0) {
769 // Just let go zero bytes allocation.
Iliyan Malcheve1dd3c22012-05-29 14:22:42 -0700770 qemu_info_log("::: <libc_pid=%03u, pid=%03u>: Zero calloc redir to malloc",
Christopher Ferrisa4037802014-06-09 19:14:11 -0700771 malloc_pid, getpid());
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800772 return qemu_instrumented_malloc(0);
773 }
774
Elliott Hughes8e52e8f2014-06-04 12:07:11 -0700775 // Fail on overflow - just to be safe even though this code runs only
776 // within the debugging C library, not the production one.
777 if (n_elements && SIZE_MAX / n_elements < elem_size) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700778 qemu_error_log("<libc_pid=%03u, pid=%03u> calloc: calloc(%zu, %zu) overflow caused failure.",
779 malloc_pid, getpid(), n_elements, elem_size);
780 errno = ENOMEM;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800781 return NULL;
782 }
783
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700784 MallocDesc desc;
785
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800786 /* Calculating prefix size. The trick here is to make sure that
787 * first element (returned to the caller) is properly aligned. */
788 if (DEFAULT_PREFIX_SIZE >= elem_size) {
789 /* If default alignment is bigger than element size, we will
790 * set our prefix size to the default alignment size. */
791 desc.prefix_size = DEFAULT_PREFIX_SIZE;
792 /* For the suffix we will use whatever bytes remain from the prefix
793 * allocation size, aligned to the size of an element, plus the usual
794 * default suffix size. */
795 desc.suffix_size = (DEFAULT_PREFIX_SIZE % elem_size) +
796 DEFAULT_SUFFIX_SIZE;
797 } else {
798 /* Make sure that prefix, and suffix sizes is at least elem_size,
799 * and first element returned to the caller is properly aligned. */
800 desc.prefix_size = elem_size + DEFAULT_PREFIX_SIZE - 1;
801 desc.prefix_size &= ~(malloc_alignment - 1);
802 desc.suffix_size = DEFAULT_SUFFIX_SIZE;
803 }
804 desc.requested_bytes = n_elements * elem_size;
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700805 size_t total_size = desc.requested_bytes + desc.prefix_size + desc.suffix_size;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700806 if (total_size < desc.requested_bytes) { // Overflow
807 qemu_error_log("<libc_pid=%03u, pid=%03u> calloc: calloc(%zu, %zu) overflow caused failure.",
808 malloc_pid, getpid(), n_elements, elem_size);
809 errno = ENOMEM;
810 return NULL;
811 }
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700812 size_t total_elements = total_size / elem_size;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800813 total_size %= elem_size;
814 if (total_size != 0) {
815 // Add extra to the suffix area.
816 total_elements++;
817 desc.suffix_size += (elem_size - total_size);
818 }
Christopher Ferris72bbd422014-05-08 11:14:03 -0700819 desc.ptr = Malloc(calloc)(total_elements, elem_size);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800820 if (desc.ptr == NULL) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700821 error_log("<libc_pid=%03u, pid=%03u> calloc: calloc(%zu(%zu), %zu) (prx=%u, sfx=%u) failed.",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800822 malloc_pid, getpid(), n_elements, total_elements, elem_size,
823 desc.prefix_size, desc.suffix_size);
824 return NULL;
825 }
826
827 if (notify_qemu_malloc(&desc)) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700828 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: calloc(%zu(%zu), %zu): notify_malloc failed for ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800829 malloc_pid, getpid(), n_elements, total_elements, elem_size);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700830 Malloc(free)(desc.ptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700831 errno = ENOMEM;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800832 return NULL;
833 } else {
834#if TEST_ACCESS_VIOLATIONS
835 test_access_violation(&desc);
836#endif // TEST_ACCESS_VIOLATIONS
Christopher Ferrisa4037802014-06-09 19:14:11 -0700837 log_mdesc(info, &desc, "### <libc_pid=%03u, pid=%03u> calloc(%zu(%zu), %zu) -> ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800838 malloc_pid, getpid(), n_elements, total_elements, elem_size);
839 return mallocdesc_user_ptr(&desc);
840 }
841}
842
843/* This routine serves as entry point for 'realloc'.
844 * This routine behaves similarly to qemu_instrumented_free +
845 * qemu_instrumented_malloc. Note that this modifies behavior of "shrinking" an
846 * allocation, but overall it doesn't seem to matter, as caller of realloc
847 * should not expect that pointer returned after shrinking will remain the same.
848 */
Christopher Ferris885f3b92013-05-21 17:48:01 -0700849extern "C" void* qemu_instrumented_realloc(void* mem, size_t bytes) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800850 if (mem == NULL) {
851 // Nothing to realloc. just do regular malloc.
Christopher Ferrisa4037802014-06-09 19:14:11 -0700852 qemu_info_log("::: <libc_pid=%03u, pid=%03u>: realloc(%p, %zu) redir to malloc",
853 malloc_pid, getpid(), mem, bytes);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800854 return qemu_instrumented_malloc(bytes);
855 }
856
857 if (bytes == 0) {
858 // This is a "free" condition.
Christopher Ferrisa4037802014-06-09 19:14:11 -0700859 qemu_info_log("::: <libc_pid=%03u, pid=%03u>: realloc(%p, %zu) redir to free and malloc",
860 malloc_pid, getpid(), mem, bytes);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800861 qemu_instrumented_free(mem);
862
Christopher Ferris72bbd422014-05-08 11:14:03 -0700863 // This is what realloc does for a "free" realloc.
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800864 return NULL;
865 }
866
867 // Query emulator for the reallocating block information.
Christopher Ferrisa4037802014-06-09 19:14:11 -0700868 MallocDesc cur_desc;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800869 if (query_qemu_malloc_info(mem, &cur_desc, 2)) {
870 // Note that this violation should be already caught in the emulator.
Christopher Ferrisa4037802014-06-09 19:14:11 -0700871 error_log("<libc_pid=%03u, pid=%03u>: realloc(%p, %zu) query_info failed.",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800872 malloc_pid, getpid(), mem, bytes);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700873 errno = ENOMEM;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800874 return NULL;
875 }
876
877#if TEST_ACCESS_VIOLATIONS
878 test_access_violation(&cur_desc);
879#endif // TEST_ACCESS_VIOLATIONS
880
881 /* Make sure that reallocating pointer value is what we would expect
882 * for this memory block. Note that this violation should be already caught
883 * in the emulator.*/
884 if (mem != mallocdesc_user_ptr(&cur_desc)) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700885 log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu) is invalid for ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800886 malloc_pid, getpid(), mem, bytes);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700887 errno = ENOMEM;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800888 return NULL;
889 }
890
891 /* TODO: We're a bit inefficient here, always allocating new block from
892 * the heap. If this realloc shrinks current buffer, we can just do the
893 * shrinking "in place", adjusting suffix_size in the allocation descriptor
894 * for this block that is stored in the emulator. */
895
896 // Initialize descriptor for the new block.
Christopher Ferrisa4037802014-06-09 19:14:11 -0700897 MallocDesc new_desc;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800898 new_desc.prefix_size = DEFAULT_PREFIX_SIZE;
899 new_desc.requested_bytes = bytes;
900 new_desc.suffix_size = DEFAULT_SUFFIX_SIZE;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700901 size_t new_size = mallocdesc_alloc_size(&new_desc);
902 if (new_size < bytes) { // Overflow
Christopher Ferris580b6e02014-06-12 18:20:44 -0700903 qemu_error_log("<libc_pid=%03u, pid=%03u>: realloc(%p, %zu): malloc(%zu) failed due to overflow",
Christopher Ferrisa4037802014-06-09 19:14:11 -0700904 malloc_pid, getpid(), mem, bytes, new_size);
905 errno = ENOMEM;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800906 return NULL;
907 }
Christopher Ferrisa4037802014-06-09 19:14:11 -0700908 new_desc.ptr = Malloc(malloc)(new_size);
909 if (new_desc.ptr == NULL) {
Christopher Ferris580b6e02014-06-12 18:20:44 -0700910 log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu): malloc(%zu) failed on ",
Christopher Ferrisa4037802014-06-09 19:14:11 -0700911 malloc_pid, getpid(), mem, bytes, new_size);
912 return NULL;
913 }
914 void* new_mem = mallocdesc_user_ptr(&new_desc);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800915
916 // Copy user data from old block to the new one.
Christopher Ferrisa4037802014-06-09 19:14:11 -0700917 size_t to_copy = bytes < cur_desc.requested_bytes ? bytes : cur_desc.requested_bytes;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800918 if (to_copy != 0) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700919 memcpy(new_mem, mallocdesc_user_ptr(&cur_desc), to_copy);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800920 }
921
922 // Register new block with emulator.
Elliott Hughesc4d1fec2012-08-28 14:15:04 -0700923 if (notify_qemu_malloc(&new_desc)) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700924 log_mdesc(error, &new_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu) notify_malloc failed -> ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800925 malloc_pid, getpid(), mem, bytes);
926 log_mdesc(error, &cur_desc, " <- ");
Christopher Ferris72bbd422014-05-08 11:14:03 -0700927 Malloc(free)(new_desc.ptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700928 errno = ENOMEM;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800929 return NULL;
930 }
931
932#if TEST_ACCESS_VIOLATIONS
933 test_access_violation(&new_desc);
934#endif // TEST_ACCESS_VIOLATIONS
935
936 // Free old block.
937 if (notify_qemu_free(mem)) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700938 log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: realloc(%p, %zu): notify_free failed for ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800939 malloc_pid, getpid(), mem, bytes);
940 /* Since we registered new decriptor with the emulator, we need
941 * to unregister it before freeing newly allocated block. */
942 notify_qemu_free(mallocdesc_user_ptr(&new_desc));
Christopher Ferris72bbd422014-05-08 11:14:03 -0700943 Malloc(free)(new_desc.ptr);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700944 errno = ENOMEM;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800945 return NULL;
946 }
Christopher Ferris72bbd422014-05-08 11:14:03 -0700947 Malloc(free)(cur_desc.ptr);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800948
Christopher Ferrisa4037802014-06-09 19:14:11 -0700949 log_mdesc(info, &new_desc, "=== <libc_pid=%03u, pid=%03u>: realloc(%p, %zu) -> ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800950 malloc_pid, getpid(), mem, bytes);
951 log_mdesc(info, &cur_desc, " <- ");
952
Christopher Ferrisa4037802014-06-09 19:14:11 -0700953 return new_mem;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800954}
955
956/* This routine serves as entry point for 'memalign'.
957 * This routine behaves similarly to qemu_instrumented_malloc.
958 */
Christopher Ferris885f3b92013-05-21 17:48:01 -0700959extern "C" void* qemu_instrumented_memalign(size_t alignment, size_t bytes) {
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800960 MallocDesc desc;
961
962 if (bytes == 0) {
963 // Just let go zero bytes allocation.
Christopher Ferrisa4037802014-06-09 19:14:11 -0700964 qemu_info_log("::: <libc_pid=%03u, pid=%03u>: memalign(%zx, %zu) redir to malloc",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800965 malloc_pid, getpid(), alignment, bytes);
966 return qemu_instrumented_malloc(0);
967 }
968
Christopher Ferrisa4037802014-06-09 19:14:11 -0700969 // Prefix size for aligned allocation must be equal to the alignment used
970 // for allocation in order to ensure proper alignment of the returned
971 // pointer. in case that alignment requirement is greater than prefix
972 // size.
973 if (alignment < DEFAULT_PREFIX_SIZE) {
974 alignment = DEFAULT_PREFIX_SIZE;
Christopher Ferris03eebcb2014-06-13 13:57:51 -0700975 } else if (!powerof2(alignment)) {
976 alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
Christopher Ferrisa4037802014-06-09 19:14:11 -0700977 }
978 desc.prefix_size = alignment;
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800979 desc.requested_bytes = bytes;
980 desc.suffix_size = DEFAULT_SUFFIX_SIZE;
Christopher Ferrisa4037802014-06-09 19:14:11 -0700981 size_t size = mallocdesc_alloc_size(&desc);
982 if (size < bytes) { // Overflow
Christopher Ferris580b6e02014-06-12 18:20:44 -0700983 qemu_error_log("<libc_pid=%03u, pid=%03u> memalign(%zx, %zu): malloc(%zu) failed due to overflow.",
Christopher Ferrisa4037802014-06-09 19:14:11 -0700984 malloc_pid, getpid(), alignment, bytes, size);
985
986 return NULL;
987 }
988 desc.ptr = Malloc(memalign)(desc.prefix_size, size);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800989 if (desc.ptr == NULL) {
Christopher Ferris580b6e02014-06-12 18:20:44 -0700990 error_log("<libc_pid=%03u, pid=%03u> memalign(%zx, %zu): malloc(%zu) failed.",
Christopher Ferrisa4037802014-06-09 19:14:11 -0700991 malloc_pid, getpid(), alignment, bytes, size);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800992 return NULL;
993 }
994 if (notify_qemu_malloc(&desc)) {
Christopher Ferrisa4037802014-06-09 19:14:11 -0700995 log_mdesc(error, &desc, "<libc_pid=%03u, pid=%03u>: memalign(%zx, %zu): notify_malloc failed for ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800996 malloc_pid, getpid(), alignment, bytes);
Christopher Ferris72bbd422014-05-08 11:14:03 -0700997 Malloc(free)(desc.ptr);
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -0800998 return NULL;
999 }
1000
1001#if TEST_ACCESS_VIOLATIONS
1002 test_access_violation(&desc);
1003#endif // TEST_ACCESS_VIOLATIONS
1004
Christopher Ferrisa4037802014-06-09 19:14:11 -07001005 log_mdesc(info, &desc, "@@@ <libc_pid=%03u, pid=%03u> memalign(%zx, %zu) -> ",
Vladimir Chtchetkine75fba682010-02-12 08:59:58 -08001006 malloc_pid, getpid(), alignment, bytes);
1007 return mallocdesc_user_ptr(&desc);
Vladimir Chtchetkineb74ceb22009-11-17 14:13:38 -08001008}
Christopher Ferris885f3b92013-05-21 17:48:01 -07001009
1010extern "C" size_t qemu_instrumented_malloc_usable_size(const void* mem) {
1011 MallocDesc cur_desc;
1012
1013 // Query emulator for the reallocating block information.
1014 if (query_qemu_malloc_info(mem, &cur_desc, 2)) {
1015 // Note that this violation should be already caught in the emulator.
1016 error_log("<libc_pid=%03u, pid=%03u>: malloc_usable_size(%p) query_info failed.",
1017 malloc_pid, getpid(), mem);
1018 return 0;
1019 }
1020
1021 /* Make sure that reallocating pointer value is what we would expect
1022 * for this memory block. Note that this violation should be already caught
1023 * in the emulator.*/
1024 if (mem != mallocdesc_user_ptr(&cur_desc)) {
1025 log_mdesc(error, &cur_desc, "<libc_pid=%03u, pid=%03u>: malloc_usable_size(%p) is invalid for ",
1026 malloc_pid, getpid(), mem);
1027 return 0;
1028 }
1029
1030 /* during instrumentation, we can't really report anything more than requested_bytes */
1031 return cur_desc.requested_bytes;
1032}
Christopher Ferrisa4037802014-06-09 19:14:11 -07001033
1034extern "C" struct mallinfo qemu_instrumented_mallinfo() {
1035 return Malloc(mallinfo)();
1036}
1037
1038extern "C" int qemu_instrumented_posix_memalign(void** memptr, size_t alignment, size_t size) {
1039 if ((alignment & (alignment - 1)) != 0) {
1040 qemu_error_log("<libc_pid=%03u, pid=%03u> posix_memalign(%p, %zu, %zu): invalid alignment.",
1041 malloc_pid, getpid(), memptr, alignment, size);
1042 return EINVAL;
1043 }
1044 int saved_errno = errno;
1045 *memptr = qemu_instrumented_memalign(alignment, size);
1046 errno = saved_errno;
1047 return (*memptr != NULL) ? 0 : ENOMEM;
1048}
1049
1050extern "C" void* qemu_instrumented_pvalloc(size_t bytes) {
1051 size_t pagesize = sysconf(_SC_PAGESIZE);
Christopher Ferris03eebcb2014-06-13 13:57:51 -07001052 size_t size = BIONIC_ALIGN(bytes, pagesize);
Christopher Ferrisa4037802014-06-09 19:14:11 -07001053 if (size < bytes) { // Overflow
1054 qemu_error_log("<libc_pid=%03u, pid=%03u> pvalloc(%zu): overflow (%zu).",
1055 malloc_pid, getpid(), bytes, size);
1056 return NULL;
1057 }
1058 return qemu_instrumented_memalign(pagesize, size);
1059}
1060
1061extern "C" void* qemu_instrumented_valloc(size_t size) {
1062 return qemu_instrumented_memalign(sysconf(_SC_PAGESIZE), size);
1063}