1 /* Copyright (C) 2007-2010 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 13 /* 14 * Contains implementation of memory checking framework in the emulator. 15 */ 16 17 /* This file should compile iff qemu is built with memory checking 18 * configuration turned on. */ 19 #ifndef CONFIG_MEMCHECK 20 #error CONFIG_MEMCHECK is not defined. 21 #endif // CONFIG_MEMCHECK 22 23 #include "qemu-queue.h" 24 #include "qemu_file.h" 25 #include "elff_api.h" 26 #include "memcheck.h" 27 #include "memcheck_proc_management.h" 28 #include "memcheck_util.h" 29 #include "memcheck_logging.h" 30 31 // ============================================================================= 32 // Global data 33 // ============================================================================= 34 35 /* Controls what messages from the guest should be printed to emulator's 36 * stdout. This variable holds a combinations of TRACE_LIBC_XXX flags. */ 37 uint32_t trace_flags = 0; 38 39 /* Global flag, indicating whether or not memchecking has been enabled 40 * for the current emulator session. 1 means that memchecking has been enabled, 41 * 0 means that memchecking has not been enabled. */ 42 int memcheck_enabled = 0; 43 44 /* Global flag, indicating whether or not __ld/__stx_mmu should be instrumented 45 * for checking for access violations. If read / write access violation check 46 * has been disabled by -memcheck flags, there is no need to instrument mmu 47 * routines and waste performance. 48 * 1 means that instrumenting is required, 0 means that instrumenting is not 49 * required. */ 50 int memcheck_instrument_mmu = 0; 51 52 /* Global flag, indicating whether or not memchecker is collecting call stack. 53 * 1 - call stack is being collected, 0 means that stack is not being 54 * collected. */ 55 int memcheck_watch_call_stack = 1; 56 57 // ============================================================================= 58 // Static routines. 59 // ============================================================================= 60 61 /* Prints invalid pointer access violation information. 62 * Param: 63 * proc - Process that caused access violation. 64 * ptr - Pointer that caused access violation. 65 * routine - If 1, access violation has occurred in 'free' routine. 66 * If 2, access violation has occurred in 'realloc' routine. 67 */ 68 static void 69 av_invalid_pointer(ProcDesc* proc, target_ulong ptr, int routine) 70 { 71 if (trace_flags & TRACE_CHECK_INVALID_PTR_ENABLED) { 72 printf("memcheck: Access violation is detected in process %s[pid=%u]:\n" 73 " INVALID POINTER 0x%08X is used in '%s' operation.\n" 74 " Allocation descriptor for this pointer has not been found in the\n" 75 " allocation map for the process. Most likely, this is an attempt\n" 76 " to %s a pointer that has been freed.\n", 77 proc->image_path, proc->pid, ptr, routine == 1 ? "free" : "realloc", 78 routine == 1 ? "free" : "reallocate"); 79 } 80 } 81 82 /* Prints read / write access violation information. 83 * Param: 84 * proc - Process that caused access violation. 85 * desc - Allocation descriptor for the violation. 86 * addr - Address at which vilation has occurred. 87 * data_size - Size of data accessed at the 'addr'. 88 * val - If access violation has occurred at write operation, this parameter 89 * contains value that's being written to 'addr'. For read violation this 90 * parameter is not used. 91 * retaddr - Code address (in TB) where access violation has occurred. 92 * is_read - If 1, access violation has occurred when memory at 'addr' has been 93 * read. If 0, access violation has occurred when memory was written. 94 */ 95 static void 96 av_access_violation(ProcDesc* proc, 97 MallocDescEx* desc, 98 target_ulong addr, 99 uint32_t data_size, 100 uint64_t val, 101 target_ulong retaddr, 102 int is_read) 103 { 104 target_ulong vaddr; 105 Elf_AddressInfo elff_info; 106 ELFF_HANDLE elff_handle = NULL; 107 108 desc->malloc_desc.av_count++; 109 if ((is_read && !(trace_flags & TRACE_CHECK_READ_VIOLATION_ENABLED)) || 110 (!is_read && !(trace_flags & TRACE_CHECK_WRITE_VIOLATION_ENABLED))) { 111 return; 112 } 113 114 /* Convert host address to guest address. */ 115 vaddr = memcheck_tpc_to_gpc(retaddr); 116 printf("memcheck: Access violation is detected in process %s[pid=%u]:\n", 117 proc->image_path, proc->pid); 118 119 /* Obtain routine, filename / line info for the address. */ 120 const MMRangeDesc* rdesc = procdesc_get_range_desc(proc, vaddr); 121 if (rdesc != NULL) { 122 int elff_res; 123 printf(" In module %s at address 0x%08X\n", rdesc->path, vaddr); 124 elff_res = 125 memcheck_get_address_info(vaddr, rdesc, &elff_info, &elff_handle); 126 if (elff_res == 0) { 127 printf(" In routine %s in %s/%s:%u\n", 128 elff_info.routine_name, elff_info.dir_name, 129 elff_info.file_name, elff_info.line_number); 130 if (elff_info.inline_stack != NULL) { 131 const Elf_InlineInfo* inl = elff_info.inline_stack; 132 int index = 0; 133 for (; inl[index].routine_name != NULL; index++) { 134 char align[64]; 135 size_t set_align = 4 + index * 2; 136 if (set_align >= sizeof(align)) { 137 set_align = sizeof(align) -1; 138 } 139 memset(align, ' ', set_align); 140 align[set_align] = '\0'; 141 printf(align); 142 if (inl[index].inlined_in_file == NULL) { 143 printf("inlined to %s in unknown location\n", 144 inl[index].routine_name); 145 } else { 146 printf("inlined to %s in %s/%s:%u\n", 147 inl[index].routine_name, 148 inl[index].inlined_in_file_dir, 149 inl[index].inlined_in_file, 150 inl[index].inlined_at_line); 151 } 152 } 153 } 154 elff_free_pc_address_info(elff_handle, &elff_info); 155 elff_close(elff_handle); 156 } else if (elff_res == 1) { 157 printf(" Unable to obtain routine information. Symbols file is not found.\n"); 158 } else { 159 printf(" Unable to obtain routine information.\n" 160 " Symbols file doesn't contain debugging information for address 0x%08X.\n", 161 mmrangedesc_get_module_offset(rdesc, vaddr)); 162 } 163 } else { 164 printf(" In unknown module at address 0x%08X\n", vaddr); 165 } 166 167 printf(" Process attempts to %s %u bytes %s address 0x%08X\n", 168 is_read ? "read" : "write", data_size, 169 is_read ? "from" : "to", addr); 170 printf(" Accessed range belongs to the %s guarding area of allocated block.\n", 171 addr < (target_ulong)mallocdesc_get_user_ptr(&desc->malloc_desc) ? 172 "prefix" : "suffix"); 173 printf(" Allocation descriptor for this violation:\n"); 174 memcheck_dump_malloc_desc(desc, 1, 0); 175 } 176 177 /* Validates access to a guest address. 178 * Param: 179 * addr - Virtual address in the guest space where memory is accessed. 180 * data_size - Size of the accessed data. 181 * proc_ptr - Upon exit from this routine contains pointer to the process 182 * descriptor for the current process, or NULL, if no such descriptor has 183 * been found. 184 * desc_ptr - Upon exit from this routine contains pointer to the allocation 185 * descriptor matching given address range, or NULL, if allocation 186 * descriptor for the validated memory range has not been found. 187 * Return: 188 * 0 if access to the given guest address range doesn't violate anything, or 189 * 1 if given guest address range doesn't match any entry in the current 190 * process allocation descriptors map, or 191 * -1 if a violation has been detected. 192 */ 193 static int 194 memcheck_common_access_validation(target_ulong addr, 195 uint32_t data_size, 196 ProcDesc** proc_ptr, 197 MallocDescEx** desc_ptr) 198 { 199 MallocDescEx* desc; 200 target_ulong validating_range_end; 201 target_ulong user_range_end; 202 203 ProcDesc* proc = get_current_process(); 204 *proc_ptr = proc; 205 if (proc == NULL) { 206 *desc_ptr = NULL; 207 return 1; 208 } 209 210 desc = procdesc_find_malloc_for_range(proc, addr, data_size); 211 *desc_ptr = desc; 212 if (desc == NULL) { 213 return 1; 214 } 215 216 /* Verify that validating address range doesn't start before the address 217 * available to the user. */ 218 if (addr < mallocdesc_get_user_ptr(&desc->malloc_desc)) { 219 // Stepped on the prefix guarding area. 220 return -1; 221 } 222 223 validating_range_end = addr + data_size; 224 user_range_end = mallocdesc_get_user_alloc_end(&desc->malloc_desc); 225 226 /* Verify that validating address range ends inside the user block. 227 * We may step on the suffix guarding area because of alignment issue. 228 * For example, the application code reads last byte in the allocated block 229 * with something like this: 230 * 231 * char last_byte_value = *(char*)last_byte_address; 232 * 233 * and this code got compiled into something like this: 234 * 235 * mov eax, [last_byte_address]; 236 * mov [last_byte_value], al; 237 * 238 * In this case we will catch a read from the suffix area, even though 239 * there were no errors in the code. So, in order to prevent such "false 240 * negative" alarms, lets "forgive" this violation. 241 * There is one bad thing about this "forgivness" though, as it may very 242 * well be, that in real life some of these "out of bound" bytes will cross 243 * page boundaries, marching into a page that has not been mapped to the 244 * process. 245 */ 246 if (validating_range_end <= user_range_end) { 247 // Validating address range is fully contained inside the user block. 248 return 0; 249 } 250 251 /* Lets see if this AV is caused by an alignment issue.*/ 252 if ((validating_range_end - user_range_end) < data_size) { 253 /* Could be an alignment. */ 254 return 0; 255 } 256 257 return -1; 258 } 259 260 /* Checks if process has allocation descriptors for pages defined by a buffer. 261 * Param: 262 * addr - Starting address of a buffer. 263 * buf_size - Buffer size. 264 * Return: 265 * 1 if process has allocations descriptors for pages defined by a buffer, or 266 * 0 if pages containing given buffer don't have any memory allocations in 267 * them. 268 */ 269 static inline int 270 procdesc_contains_allocs(ProcDesc* proc, target_ulong addr, uint32_t buf_size) { 271 if (proc != NULL) { 272 // Beginning of the page containing last byte in range. 273 const target_ulong end_page = (addr + buf_size - 1) & TARGET_PAGE_MASK; 274 // Adjust beginning of the range to the beginning of the page. 275 addr &= TARGET_PAGE_MASK; 276 // Total size of range to check for descriptors. 277 buf_size = end_page - addr + TARGET_PAGE_SIZE + 1; 278 return procdesc_find_malloc_for_range(proc, addr, buf_size) ? 1 : 0; 279 } else { 280 return 0; 281 } 282 } 283 284 // ============================================================================= 285 // Memchecker API. 286 // ============================================================================= 287 288 void 289 memcheck_init(const char* tracing_flags) 290 { 291 if (*tracing_flags == '0') { 292 // Memchecker is disabled. 293 return; 294 } else if (*tracing_flags == '1') { 295 // Set default tracing. 296 trace_flags = TRACE_CHECK_LEAK_ENABLED | 297 TRACE_CHECK_READ_VIOLATION_ENABLED | 298 TRACE_CHECK_INVALID_PTR_ENABLED | 299 TRACE_CHECK_WRITE_VIOLATION_ENABLED; 300 } 301 302 // Parse -memcheck option params, converting them into tracing flags. 303 while (*tracing_flags) { 304 switch (*tracing_flags) { 305 case 'A': 306 // Enable all emulator's tracing messages. 307 trace_flags |= TRACE_ALL_ENABLED; 308 break; 309 case 'F': 310 // Enable fork() tracing. 311 trace_flags |= TRACE_PROC_FORK_ENABLED; 312 break; 313 case 'S': 314 // Enable guest process staring tracing. 315 trace_flags |= TRACE_PROC_START_ENABLED; 316 break; 317 case 'E': 318 // Enable guest process exiting tracing. 319 trace_flags |= TRACE_PROC_EXIT_ENABLED; 320 break; 321 case 'C': 322 // Enable clone() tracing. 323 trace_flags |= TRACE_PROC_CLONE_ENABLED; 324 break; 325 case 'N': 326 // Enable new PID allocation tracing. 327 trace_flags |= TRACE_PROC_NEW_PID_ENABLED; 328 break; 329 case 'B': 330 // Enable libc.so initialization tracing. 331 trace_flags |= TRACE_PROC_LIBC_INIT_ENABLED; 332 break; 333 case 'L': 334 // Enable memory leaks tracing. 335 trace_flags |= TRACE_CHECK_LEAK_ENABLED; 336 break; 337 case 'I': 338 // Enable invalid free / realloc pointer tracing. 339 trace_flags |= TRACE_CHECK_INVALID_PTR_ENABLED; 340 break; 341 case 'R': 342 // Enable reading violations tracing. 343 trace_flags |= TRACE_CHECK_READ_VIOLATION_ENABLED; 344 break; 345 case 'W': 346 // Enable writing violations tracing. 347 trace_flags |= TRACE_CHECK_WRITE_VIOLATION_ENABLED; 348 break; 349 case 'M': 350 // Enable module mapping tracing. 351 trace_flags |= TRACE_PROC_MMAP_ENABLED; 352 break; 353 default: 354 break; 355 } 356 if (trace_flags == TRACE_ALL_ENABLED) { 357 break; 358 } 359 tracing_flags++; 360 } 361 362 /* Lets see if we need to instrument MMU, injecting memory access checking. 363 * We instrument MMU only if we monitor read, or write memory access. */ 364 if (trace_flags & (TRACE_CHECK_READ_VIOLATION_ENABLED | 365 TRACE_CHECK_WRITE_VIOLATION_ENABLED)) { 366 memcheck_instrument_mmu = 1; 367 } else { 368 memcheck_instrument_mmu = 0; 369 } 370 371 memcheck_init_proc_management(); 372 373 /* Lets check env. variables needed for memory checking. */ 374 if (getenv("ANDROID_PROJECT_OUT") == NULL) { 375 printf("memcheck: Missing ANDROID_PROJECT_OUT environment variable, that is used\n" 376 "to calculate path to symbol files.\n"); 377 } 378 379 // Always set this flag at the very end of the initialization! 380 memcheck_enabled = 1; 381 } 382 383 void 384 memcheck_guest_libc_initialized(uint32_t pid) 385 { 386 ProcDesc* proc = get_process_from_pid(pid); 387 if (proc == NULL) { 388 ME("memcheck: Unable to obtain process for libc_init pid=%u", pid); 389 return; 390 } 391 proc->flags |= PROC_FLAG_LIBC_INITIALIZED; 392 393 /* When process initializes its own libc.so instance, it means that now 394 * it has fresh heap. So, at this point we must get rid of all entries 395 * (inherited and transition) that were collected in this process' 396 * allocation descriptors map. */ 397 procdesc_empty_alloc_map(proc); 398 T(PROC_LIBC_INIT, "memcheck: libc.so has been initialized for %s[pid=%u]\n", 399 proc->image_path, proc->pid); 400 } 401 402 void 403 memcheck_guest_alloc(target_ulong guest_address) 404 { 405 MallocDescEx desc; 406 MallocDescEx replaced; 407 RBTMapResult insert_res; 408 ProcDesc* proc; 409 ThreadDesc* thread; 410 uint32_t indx; 411 412 // Copy allocation descriptor from guest to emulator. 413 memcheck_get_malloc_descriptor(&desc.malloc_desc, guest_address); 414 desc.flags = 0; 415 desc.call_stack = NULL; 416 desc.call_stack_count = 0; 417 418 proc = get_process_from_pid(desc.malloc_desc.allocator_pid); 419 if (proc == NULL) { 420 ME("memcheck: Unable to obtain process for allocation pid=%u", 421 desc.malloc_desc.allocator_pid); 422 memcheck_fail_alloc(guest_address); 423 return; 424 } 425 426 if (!procdesc_is_executing(proc)) { 427 desc.flags |= MDESC_FLAG_TRANSITION_ENTRY; 428 } 429 430 /* Copy thread's calling stack to the allocation descriptor. */ 431 thread = get_current_thread(); 432 desc.call_stack_count = thread->call_stack_count; 433 if (desc.call_stack_count) { 434 desc.call_stack = qemu_malloc(desc.call_stack_count * sizeof(target_ulong)); 435 if (desc.call_stack == NULL) { 436 ME("memcheck: Unable to allocate %u bytes for the calling stack", 437 desc.call_stack_count * sizeof(target_ulong)); 438 return; 439 } 440 } 441 442 /* Thread's calling stack is in descending order (i.e. first entry in the 443 * thread's stack is the most distant routine from the current one). On the 444 * other hand, we keep calling stack entries in allocation descriptor in 445 * assending order. */ 446 for (indx = 0; indx < thread->call_stack_count; indx++) { 447 desc.call_stack[indx] = 448 thread->call_stack[thread->call_stack_count - 1 - indx].call_address; 449 } 450 451 // Save malloc descriptor in the map. 452 insert_res = procdesc_add_malloc(proc, &desc, &replaced); 453 if (insert_res == RBT_MAP_RESULT_ENTRY_INSERTED) { 454 // Invalidate TLB cache for the allocated block. 455 if (memcheck_instrument_mmu) { 456 invalidate_tlb_cache(desc.malloc_desc.ptr, 457 mallocdesc_get_alloc_end(&desc.malloc_desc)); 458 } 459 } else if (insert_res == RBT_MAP_RESULT_ENTRY_REPLACED) { 460 /* We don't expect to have another entry in the map that matches 461 * inserting entry. This is an error condition for us, indicating 462 * that we somehow lost track of memory allocations. */ 463 ME("memcheck: Duplicate allocation blocks:"); 464 if (VERBOSE_CHECK(memcheck)) { 465 printf(" New block:\n"); 466 memcheck_dump_malloc_desc(&desc, 1, 1); 467 printf(" Replaced block:\n"); 468 memcheck_dump_malloc_desc(&replaced, 1, 1); 469 } 470 if (replaced.call_stack != NULL) { 471 qemu_free(replaced.call_stack); 472 } 473 } else { 474 ME("memcheck: Unable to insert an entry to the allocation map:"); 475 if (VERBOSE_CHECK(memcheck)) { 476 memcheck_dump_malloc_desc(&desc, 1, 1); 477 } 478 memcheck_fail_alloc(guest_address); 479 return; 480 } 481 } 482 483 void 484 memcheck_guest_free(target_ulong guest_address) 485 { 486 MallocFree desc; 487 MallocDescEx pulled; 488 int pull_res; 489 ProcDesc* proc; 490 491 // Copy free descriptor from guest to emulator. 492 memcheck_get_free_descriptor(&desc, guest_address); 493 494 proc = get_process_from_pid(desc.free_pid); 495 if (proc == NULL) { 496 ME("memcheck: Unable to obtain process for pid=%u on free", 497 desc.free_pid); 498 memcheck_fail_free(guest_address); 499 return; 500 } 501 502 // Pull matching entry from the map. 503 pull_res = procdesc_pull_malloc(proc, desc.ptr, &pulled); 504 if (pull_res) { 505 av_invalid_pointer(proc, desc.ptr, 1); 506 memcheck_fail_free(guest_address); 507 return; 508 } 509 510 // Make sure that ptr has expected value 511 if (desc.ptr != mallocdesc_get_user_ptr(&pulled.malloc_desc)) { 512 if (trace_flags & TRACE_CHECK_INVALID_PTR_ENABLED) { 513 printf("memcheck: Access violation is detected in process %s[pid=%u]:\n", 514 proc->image_path, proc->pid); 515 printf(" INVALID POINTER 0x%08X is used in 'free' operation.\n" 516 " This pointer is unexpected for 'free' operation, as allocation\n" 517 " descriptor found for this pointer in the process' allocation map\n" 518 " suggests that 0x%08X is the pointer to be used to free this block.\n" 519 " Allocation descriptor matching the pointer:\n", 520 desc.ptr, 521 (uint32_t)mallocdesc_get_user_ptr(&pulled.malloc_desc)); 522 memcheck_dump_malloc_desc(&pulled, 1, 0); 523 } 524 } 525 if (pulled.call_stack != NULL) { 526 qemu_free(pulled.call_stack); 527 } 528 } 529 530 void 531 memcheck_guest_query_malloc(target_ulong guest_address) 532 { 533 MallocDescQuery qdesc; 534 MallocDescEx* found; 535 ProcDesc* proc; 536 537 // Copy free descriptor from guest to emulator. 538 memcheck_get_query_descriptor(&qdesc, guest_address); 539 540 proc = get_process_from_pid(qdesc.query_pid); 541 if (proc == NULL) { 542 ME("memcheck: Unable to obtain process for pid=%u on query_%s", 543 qdesc.query_pid, qdesc.routine == 1 ? "free" : "realloc"); 544 memcheck_fail_query(guest_address); 545 return; 546 } 547 548 // Find allocation entry for the given address. 549 found = procdesc_find_malloc(proc, qdesc.ptr); 550 if (found == NULL) { 551 av_invalid_pointer(proc, qdesc.ptr, qdesc.routine); 552 memcheck_fail_query(guest_address); 553 return; 554 } 555 556 // Copy allocation descriptor back to the guest's space. 557 memcheck_set_malloc_descriptor(qdesc.desc, &found->malloc_desc); 558 } 559 560 void 561 memcheck_guest_print_str(target_ulong str) { 562 char str_copy[4096]; 563 memcheck_get_guest_string(str_copy, str, sizeof(str_copy)); 564 printf(str_copy); 565 } 566 567 /* Validates read operations, detected in __ldx_mmu routine. 568 * This routine is called from __ldx_mmu wrapper implemented in 569 * softmmu_template.h on condition that loading is occurring from user memory. 570 * Param: 571 * addr - Virtual address in the guest space where memory is read. 572 * data_size - Size of the read. 573 * retaddr - Code address (in TB) that accesses memory. 574 * Return: 575 * 1 if TLB record for the accessed page should be invalidated in order to 576 * ensure that subsequent attempts to access data in this page will cause 577 * __ld/stx_mmu to be used. If memchecker is no longer interested in monitoring 578 * access to this page, this routine returns 0. 579 */ 580 int 581 memcheck_validate_ld(target_ulong addr, 582 uint32_t data_size, 583 target_ulong retaddr) 584 { 585 ProcDesc* proc; 586 MallocDescEx* desc; 587 588 int res = memcheck_common_access_validation(addr, data_size, &proc, &desc); 589 if (res == -1) { 590 av_access_violation(proc, desc, addr, data_size, 0, retaddr, 1); 591 return 1; 592 } 593 594 /* Even though descriptor for the given address range has not been found, 595 * we need to make sure that pages containing the given address range 596 * don't contain other descriptors. */ 597 return res ? procdesc_contains_allocs(proc, addr, data_size) : 0; 598 } 599 600 /* Validates write operations, detected in __stx_mmu routine. 601 * This routine is called from __stx_mmu wrapper implemented in 602 * softmmu_template.h on condition that storing is occurring from user memory. 603 * Param: 604 * addr - Virtual address in the guest space where memory is written. 605 * data_size - Size of the write. 606 * value - Value to be written. Note that we typecast all values to 64 bits, 607 * since this will fit all data sizes. 608 * retaddr - Code address (in TB) that accesses memory. 609 * Return: 610 * 1 if TLB record for the accessed page should be invalidated in order to 611 * ensure that subsequent attempts to access data in this page will cause 612 * __ld/stx_mmu to be used. If memchecker is no longer interested in monitoring 613 * access to this page, this routine returns 0. 614 */ 615 int 616 memcheck_validate_st(target_ulong addr, 617 uint32_t data_size, 618 uint64_t value, 619 target_ulong retaddr) 620 { 621 MallocDescEx* desc; 622 ProcDesc* proc; 623 624 int res = memcheck_common_access_validation(addr, data_size, &proc, &desc); 625 if (res == -1) { 626 av_access_violation(proc, desc, addr, data_size, value, retaddr, 0); 627 return 1; 628 } 629 630 /* Even though descriptor for the given address range has not been found, 631 * we need to make sure that pages containing the given address range 632 * don't contain other descriptors. */ 633 return res ? procdesc_contains_allocs(proc, addr, data_size) : 0; 634 } 635 636 /* Checks if given address range in the context of the current process is under 637 * surveillance. 638 * Param: 639 * addr - Starting address of a range. 640 * size - Range size. 641 * Return: 642 * boolean: 1 if address range contains memory that require access violation 643 * detection, or 0 if given address range is in no interest to the memchecker. 644 */ 645 int 646 memcheck_is_checked(target_ulong addr, uint32_t size) { 647 return procdesc_contains_allocs(get_current_process(), addr, size) ? 1 : 0; 648 } 649