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