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