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