15389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Copyright (C) 2007-2010 The Android Open Source Project 25389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** 35389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** This software is licensed under the terms of the GNU General Public 45389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** License version 2, as published by the Free Software Foundation, and 55389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** may be copied, distributed, and modified under those terms. 65389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** 75389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** This program is distributed in the hope that it will be useful, 85389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** but WITHOUT ANY WARRANTY; without even the implied warranty of 95389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine** GNU General Public License for more details. 115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine*/ 125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* 145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Contains implementation of memory checking framework in the emulator. 155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 17a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#include "qemu-queue.h" 185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "qemu_file.h" 195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "elff_api.h" 205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "memcheck.h" 215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "memcheck_proc_management.h" 225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "memcheck_util.h" 235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "memcheck_logging.h" 245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// ============================================================================= 265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// Global data 275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// ============================================================================= 285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Controls what messages from the guest should be printed to emulator's 305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * stdout. This variable holds a combinations of TRACE_LIBC_XXX flags. */ 315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineuint32_t trace_flags = 0; 325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Global flag, indicating whether or not memchecking has been enabled 345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * for the current emulator session. 1 means that memchecking has been enabled, 355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 0 means that memchecking has not been enabled. */ 365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineint memcheck_enabled = 0; 375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Global flag, indicating whether or not __ld/__stx_mmu should be instrumented 395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * for checking for access violations. If read / write access violation check 405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * has been disabled by -memcheck flags, there is no need to instrument mmu 415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * routines and waste performance. 425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 1 means that instrumenting is required, 0 means that instrumenting is not 435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * required. */ 445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineint memcheck_instrument_mmu = 0; 455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Global flag, indicating whether or not memchecker is collecting call stack. 475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 1 - call stack is being collected, 0 means that stack is not being 485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * collected. */ 495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineint memcheck_watch_call_stack = 1; 505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// ============================================================================= 525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// Static routines. 535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// ============================================================================= 545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Prints invalid pointer access violation information. 565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Param: 575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * proc - Process that caused access violation. 585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * ptr - Pointer that caused access violation. 595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * routine - If 1, access violation has occurred in 'free' routine. 605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * If 2, access violation has occurred in 'realloc' routine. 615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinestatic void 635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineav_invalid_pointer(ProcDesc* proc, target_ulong ptr, int routine) 645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (trace_flags & TRACE_CHECK_INVALID_PTR_ENABLED) { 665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf("memcheck: Access violation is detected in process %s[pid=%u]:\n" 675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " INVALID POINTER 0x%08X is used in '%s' operation.\n" 685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " Allocation descriptor for this pointer has not been found in the\n" 695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " allocation map for the process. Most likely, this is an attempt\n" 705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " to %s a pointer that has been freed.\n", 715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine proc->image_path, proc->pid, ptr, routine == 1 ? "free" : "realloc", 725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine routine == 1 ? "free" : "reallocate"); 735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Prints read / write access violation information. 775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Param: 785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * proc - Process that caused access violation. 795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * desc - Allocation descriptor for the violation. 805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * addr - Address at which vilation has occurred. 815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * data_size - Size of data accessed at the 'addr'. 825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * val - If access violation has occurred at write operation, this parameter 835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * contains value that's being written to 'addr'. For read violation this 845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * parameter is not used. 855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * retaddr - Code address (in TB) where access violation has occurred. 865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * is_read - If 1, access violation has occurred when memory at 'addr' has been 875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * read. If 0, access violation has occurred when memory was written. 885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinestatic void 905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineav_access_violation(ProcDesc* proc, 915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx* desc, 925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine target_ulong addr, 935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine uint32_t data_size, 945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine uint64_t val, 955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine target_ulong retaddr, 965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine int is_read) 975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine target_ulong vaddr; 995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine Elf_AddressInfo elff_info; 1005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ELFF_HANDLE elff_handle = NULL; 1015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc->malloc_desc.av_count++; 1035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if ((is_read && !(trace_flags & TRACE_CHECK_READ_VIOLATION_ENABLED)) || 1045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine (!is_read && !(trace_flags & TRACE_CHECK_WRITE_VIOLATION_ENABLED))) { 1055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 1065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Convert host address to guest address. */ 1095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine vaddr = memcheck_tpc_to_gpc(retaddr); 1105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf("memcheck: Access violation is detected in process %s[pid=%u]:\n", 1115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine proc->image_path, proc->pid); 1125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Obtain routine, filename / line info for the address. */ 1145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const MMRangeDesc* rdesc = procdesc_get_range_desc(proc, vaddr); 1155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (rdesc != NULL) { 1165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine int elff_res; 1175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" In module %s at address 0x%08X\n", rdesc->path, vaddr); 1185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elff_res = 1195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_get_address_info(vaddr, rdesc, &elff_info, &elff_handle); 1205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (elff_res == 0) { 1215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" In routine %s in %s/%s:%u\n", 1225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elff_info.routine_name, elff_info.dir_name, 1235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elff_info.file_name, elff_info.line_number); 1245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (elff_info.inline_stack != NULL) { 1255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const Elf_InlineInfo* inl = elff_info.inline_stack; 1265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine int index = 0; 1275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine for (; inl[index].routine_name != NULL; index++) { 1285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine char align[64]; 1295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine size_t set_align = 4 + index * 2; 1305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (set_align >= sizeof(align)) { 1315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine set_align = sizeof(align) -1; 1325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memset(align, ' ', set_align); 1345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine align[set_align] = '\0'; 1354e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner printf("%s", align); 1365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (inl[index].inlined_in_file == NULL) { 1375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf("inlined to %s in unknown location\n", 1385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine inl[index].routine_name); 1395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 1405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf("inlined to %s in %s/%s:%u\n", 1415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine inl[index].routine_name, 1425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine inl[index].inlined_in_file_dir, 1435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine inl[index].inlined_in_file, 1445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine inl[index].inlined_at_line); 1455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elff_free_pc_address_info(elff_handle, &elff_info); 1495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine elff_close(elff_handle); 1505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else if (elff_res == 1) { 1515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" Unable to obtain routine information. Symbols file is not found.\n"); 1525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 1535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" Unable to obtain routine information.\n" 1545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " Symbols file doesn't contain debugging information for address 0x%08X.\n", 1555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine mmrangedesc_get_module_offset(rdesc, vaddr)); 1565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 1585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" In unknown module at address 0x%08X\n", vaddr); 1595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 1605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" Process attempts to %s %u bytes %s address 0x%08X\n", 1625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine is_read ? "read" : "write", data_size, 1635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine is_read ? "from" : "to", addr); 1645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" Accessed range belongs to the %s guarding area of allocated block.\n", 1655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine addr < (target_ulong)mallocdesc_get_user_ptr(&desc->malloc_desc) ? 1665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine "prefix" : "suffix"); 1675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" Allocation descriptor for this violation:\n"); 1685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_dump_malloc_desc(desc, 1, 0); 1695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 1705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Validates access to a guest address. 1725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Param: 1735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * addr - Virtual address in the guest space where memory is accessed. 1745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * data_size - Size of the accessed data. 1755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * proc_ptr - Upon exit from this routine contains pointer to the process 1765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * descriptor for the current process, or NULL, if no such descriptor has 1775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * been found. 1785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * desc_ptr - Upon exit from this routine contains pointer to the allocation 1795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * descriptor matching given address range, or NULL, if allocation 1805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * descriptor for the validated memory range has not been found. 1815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Return: 1825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 0 if access to the given guest address range doesn't violate anything, or 1835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 1 if given guest address range doesn't match any entry in the current 1845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * process allocation descriptors map, or 1855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * -1 if a violation has been detected. 1865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 1875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinestatic int 1885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_common_access_validation(target_ulong addr, 1895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine uint32_t data_size, 1905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ProcDesc** proc_ptr, 1915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx** desc_ptr) 1925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 1935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx* desc; 1945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine target_ulong validating_range_end; 1955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine target_ulong user_range_end; 1965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 1975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ProcDesc* proc = get_current_process(); 1985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine *proc_ptr = proc; 1995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (proc == NULL) { 2005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine *desc_ptr = NULL; 2015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return 1; 2025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc = procdesc_find_malloc_for_range(proc, addr, data_size); 2055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine *desc_ptr = desc; 2065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (desc == NULL) { 2075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return 1; 2085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Verify that validating address range doesn't start before the address 2115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * available to the user. */ 2125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (addr < mallocdesc_get_user_ptr(&desc->malloc_desc)) { 2135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Stepped on the prefix guarding area. 2145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return -1; 2155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine validating_range_end = addr + data_size; 2185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine user_range_end = mallocdesc_get_user_alloc_end(&desc->malloc_desc); 2195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Verify that validating address range ends inside the user block. 2215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * We may step on the suffix guarding area because of alignment issue. 2225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * For example, the application code reads last byte in the allocated block 2235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * with something like this: 2245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 2255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * char last_byte_value = *(char*)last_byte_address; 2265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 2275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * and this code got compiled into something like this: 2285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 2295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * mov eax, [last_byte_address]; 2305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * mov [last_byte_value], al; 2315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 2325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * In this case we will catch a read from the suffix area, even though 2335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * there were no errors in the code. So, in order to prevent such "false 2345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * negative" alarms, lets "forgive" this violation. 2355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * There is one bad thing about this "forgivness" though, as it may very 2365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * well be, that in real life some of these "out of bound" bytes will cross 2375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * page boundaries, marching into a page that has not been mapped to the 2385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * process. 2395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 2405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (validating_range_end <= user_range_end) { 2415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Validating address range is fully contained inside the user block. 2425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return 0; 2435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets see if this AV is caused by an alignment issue.*/ 2465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if ((validating_range_end - user_range_end) < data_size) { 2475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Could be an alignment. */ 2485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return 0; 2495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return -1; 2525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 2535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Checks if process has allocation descriptors for pages defined by a buffer. 2555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Param: 2565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * addr - Starting address of a buffer. 2575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * buf_size - Buffer size. 2585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Return: 2595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 1 if process has allocations descriptors for pages defined by a buffer, or 2605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 0 if pages containing given buffer don't have any memory allocations in 2615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * them. 2625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 2635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinestatic inline int 2645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineprocdesc_contains_allocs(ProcDesc* proc, target_ulong addr, uint32_t buf_size) { 2655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (proc != NULL) { 2665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Beginning of the page containing last byte in range. 2675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine const target_ulong end_page = (addr + buf_size - 1) & TARGET_PAGE_MASK; 2685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Adjust beginning of the range to the beginning of the page. 2695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine addr &= TARGET_PAGE_MASK; 2705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Total size of range to check for descriptors. 2715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine buf_size = end_page - addr + TARGET_PAGE_SIZE + 1; 2725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return procdesc_find_malloc_for_range(proc, addr, buf_size) ? 1 : 0; 2735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 2745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return 0; 2755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 2775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// ============================================================================= 2795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// Memchecker API. 2805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine// ============================================================================= 2815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinevoid 2835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_init(const char* tracing_flags) 2845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 2855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (*tracing_flags == '0') { 2865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Memchecker is disabled. 2875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 2885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else if (*tracing_flags == '1') { 2895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Set default tracing. 2905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags = TRACE_CHECK_LEAK_ENABLED | 2915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine TRACE_CHECK_READ_VIOLATION_ENABLED | 2925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine TRACE_CHECK_INVALID_PTR_ENABLED | 2935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine TRACE_CHECK_WRITE_VIOLATION_ENABLED; 2945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 2955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 2965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Parse -memcheck option params, converting them into tracing flags. 2975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine while (*tracing_flags) { 2985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine switch (*tracing_flags) { 2995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'A': 3005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable all emulator's tracing messages. 3015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_ALL_ENABLED; 3025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'F': 3045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable fork() tracing. 3055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_PROC_FORK_ENABLED; 3065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'S': 3085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable guest process staring tracing. 3095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_PROC_START_ENABLED; 3105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'E': 3125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable guest process exiting tracing. 3135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_PROC_EXIT_ENABLED; 3145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'C': 3165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable clone() tracing. 3175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_PROC_CLONE_ENABLED; 3185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'N': 3205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable new PID allocation tracing. 3215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_PROC_NEW_PID_ENABLED; 3225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'B': 3245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable libc.so initialization tracing. 3255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_PROC_LIBC_INIT_ENABLED; 3265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'L': 3285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable memory leaks tracing. 3295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_CHECK_LEAK_ENABLED; 3305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'I': 3325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable invalid free / realloc pointer tracing. 3335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_CHECK_INVALID_PTR_ENABLED; 3345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'R': 3365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable reading violations tracing. 3375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_CHECK_READ_VIOLATION_ENABLED; 3385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'W': 3405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable writing violations tracing. 3415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_CHECK_WRITE_VIOLATION_ENABLED; 3425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine case 'M': 3445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Enable module mapping tracing. 3455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine trace_flags |= TRACE_PROC_MMAP_ENABLED; 3465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine default: 3485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (trace_flags == TRACE_ALL_ENABLED) { 3515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine break; 3525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine tracing_flags++; 3545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets see if we need to instrument MMU, injecting memory access checking. 3575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * We instrument MMU only if we monitor read, or write memory access. */ 3585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (trace_flags & (TRACE_CHECK_READ_VIOLATION_ENABLED | 3595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine TRACE_CHECK_WRITE_VIOLATION_ENABLED)) { 3605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_instrument_mmu = 1; 3615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 3625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_instrument_mmu = 0; 3635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_init_proc_management(); 3665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Lets check env. variables needed for memory checking. */ 3685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (getenv("ANDROID_PROJECT_OUT") == NULL) { 3695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf("memcheck: Missing ANDROID_PROJECT_OUT environment variable, that is used\n" 3705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine "to calculate path to symbol files.\n"); 3715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Always set this flag at the very end of the initialization! 3745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_enabled = 1; 3755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 3765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinevoid 3785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_guest_libc_initialized(uint32_t pid) 3795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 3805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ProcDesc* proc = get_process_from_pid(pid); 3815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (proc == NULL) { 3825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ME("memcheck: Unable to obtain process for libc_init pid=%u", pid); 3835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 3845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 3855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine proc->flags |= PROC_FLAG_LIBC_INITIALIZED; 3865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* When process initializes its own libc.so instance, it means that now 3885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * it has fresh heap. So, at this point we must get rid of all entries 3895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * (inherited and transition) that were collected in this process' 3905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * allocation descriptors map. */ 3915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine procdesc_empty_alloc_map(proc); 3925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine T(PROC_LIBC_INIT, "memcheck: libc.so has been initialized for %s[pid=%u]\n", 3935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine proc->image_path, proc->pid); 3945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 3955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 3965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinevoid 3975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_guest_alloc(target_ulong guest_address) 3985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 3995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx desc; 4005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx replaced; 4015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine RBTMapResult insert_res; 4025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ProcDesc* proc; 4035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ThreadDesc* thread; 4045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine uint32_t indx; 4055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Copy allocation descriptor from guest to emulator. 4075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_get_malloc_descriptor(&desc.malloc_desc, guest_address); 4085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.flags = 0; 4095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.call_stack = NULL; 4105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.call_stack_count = 0; 4115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine proc = get_process_from_pid(desc.malloc_desc.allocator_pid); 4135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (proc == NULL) { 4145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ME("memcheck: Unable to obtain process for allocation pid=%u", 4155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.malloc_desc.allocator_pid); 4165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_fail_alloc(guest_address); 4175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 4185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (!procdesc_is_executing(proc)) { 4215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.flags |= MDESC_FLAG_TRANSITION_ENTRY; 4225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Copy thread's calling stack to the allocation descriptor. */ 4255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine thread = get_current_thread(); 4265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.call_stack_count = thread->call_stack_count; 4275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (desc.call_stack_count) { 4285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.call_stack = qemu_malloc(desc.call_stack_count * sizeof(target_ulong)); 4295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (desc.call_stack == NULL) { 4305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ME("memcheck: Unable to allocate %u bytes for the calling stack", 4315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.call_stack_count * sizeof(target_ulong)); 4325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 4335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Thread's calling stack is in descending order (i.e. first entry in the 4375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * thread's stack is the most distant routine from the current one). On the 4385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * other hand, we keep calling stack entries in allocation descriptor in 4395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * assending order. */ 4405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine for (indx = 0; indx < thread->call_stack_count; indx++) { 4415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.call_stack[indx] = 4425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine thread->call_stack[thread->call_stack_count - 1 - indx].call_address; 4435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Save malloc descriptor in the map. 4465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine insert_res = procdesc_add_malloc(proc, &desc, &replaced); 4475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (insert_res == RBT_MAP_RESULT_ENTRY_INSERTED) { 4485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Invalidate TLB cache for the allocated block. 4495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (memcheck_instrument_mmu) { 4505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine invalidate_tlb_cache(desc.malloc_desc.ptr, 4515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine mallocdesc_get_alloc_end(&desc.malloc_desc)); 4525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else if (insert_res == RBT_MAP_RESULT_ENTRY_REPLACED) { 4545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* We don't expect to have another entry in the map that matches 4555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * inserting entry. This is an error condition for us, indicating 4565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * that we somehow lost track of memory allocations. */ 4575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ME("memcheck: Duplicate allocation blocks:"); 4585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (VERBOSE_CHECK(memcheck)) { 4595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" New block:\n"); 4605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_dump_malloc_desc(&desc, 1, 1); 4615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" Replaced block:\n"); 4625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_dump_malloc_desc(&replaced, 1, 1); 4635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (replaced.call_stack != NULL) { 4655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine qemu_free(replaced.call_stack); 4665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } else { 4685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ME("memcheck: Unable to insert an entry to the allocation map:"); 4695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (VERBOSE_CHECK(memcheck)) { 4705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_dump_malloc_desc(&desc, 1, 1); 4715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_fail_alloc(guest_address); 4735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 4745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 4765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinevoid 4785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_guest_free(target_ulong guest_address) 4795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 4805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocFree desc; 4815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx pulled; 4825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine int pull_res; 4835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ProcDesc* proc; 4845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Copy free descriptor from guest to emulator. 4865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_get_free_descriptor(&desc, guest_address); 4875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine proc = get_process_from_pid(desc.free_pid); 4895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (proc == NULL) { 4905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ME("memcheck: Unable to obtain process for pid=%u on free", 4915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.free_pid); 4925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_fail_free(guest_address); 4935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 4945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 4955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 4965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Pull matching entry from the map. 4975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine pull_res = procdesc_pull_malloc(proc, desc.ptr, &pulled); 4985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (pull_res) { 4995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine av_invalid_pointer(proc, desc.ptr, 1); 5005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_fail_free(guest_address); 5015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 5025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 5035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Make sure that ptr has expected value 5055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (desc.ptr != mallocdesc_get_user_ptr(&pulled.malloc_desc)) { 5065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (trace_flags & TRACE_CHECK_INVALID_PTR_ENABLED) { 5075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf("memcheck: Access violation is detected in process %s[pid=%u]:\n", 5085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine proc->image_path, proc->pid); 5095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine printf(" INVALID POINTER 0x%08X is used in 'free' operation.\n" 5105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " This pointer is unexpected for 'free' operation, as allocation\n" 5115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " descriptor found for this pointer in the process' allocation map\n" 5125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " suggests that 0x%08X is the pointer to be used to free this block.\n" 5135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine " Allocation descriptor matching the pointer:\n", 5145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine desc.ptr, 5155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine (uint32_t)mallocdesc_get_user_ptr(&pulled.malloc_desc)); 5165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_dump_malloc_desc(&pulled, 1, 0); 5175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 5185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 5195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (pulled.call_stack != NULL) { 5205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine qemu_free(pulled.call_stack); 5215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 5225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 5235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinevoid 5255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_guest_query_malloc(target_ulong guest_address) 5265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 5275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescQuery qdesc; 5285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx* found; 5295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ProcDesc* proc; 5305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Copy free descriptor from guest to emulator. 5325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_get_query_descriptor(&qdesc, guest_address); 5335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine proc = get_process_from_pid(qdesc.query_pid); 5355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (proc == NULL) { 5365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ME("memcheck: Unable to obtain process for pid=%u on query_%s", 5375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine qdesc.query_pid, qdesc.routine == 1 ? "free" : "realloc"); 5385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_fail_query(guest_address); 5395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 5405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 5415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Find allocation entry for the given address. 5435389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine found = procdesc_find_malloc(proc, qdesc.ptr); 5445389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (found == NULL) { 5455389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine av_invalid_pointer(proc, qdesc.ptr, qdesc.routine); 5465389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_fail_query(guest_address); 5475389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return; 5485389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 5495389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5505389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine // Copy allocation descriptor back to the guest's space. 5515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_set_malloc_descriptor(qdesc.desc, &found->malloc_desc); 5525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 5535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinevoid 5555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_guest_print_str(target_ulong str) { 5565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine char str_copy[4096]; 5575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine memcheck_get_guest_string(str_copy, str, sizeof(str_copy)); 5584e024bb4f5c8aa8b07459f7fbd65c35122127fd1David 'Digit' Turner printf("%s", str_copy); 5595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 5605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Validates read operations, detected in __ldx_mmu routine. 5625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * This routine is called from __ldx_mmu wrapper implemented in 5635389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * softmmu_template.h on condition that loading is occurring from user memory. 5645389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Param: 5655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * addr - Virtual address in the guest space where memory is read. 5665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * data_size - Size of the read. 5675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * retaddr - Code address (in TB) that accesses memory. 5685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Return: 5695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 1 if TLB record for the accessed page should be invalidated in order to 5705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * ensure that subsequent attempts to access data in this page will cause 5715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * __ld/stx_mmu to be used. If memchecker is no longer interested in monitoring 5725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * access to this page, this routine returns 0. 5735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 5745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineint 5755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_validate_ld(target_ulong addr, 5765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine uint32_t data_size, 5775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine target_ulong retaddr) 5785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 5795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ProcDesc* proc; 5805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx* desc; 5815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine int res = memcheck_common_access_validation(addr, data_size, &proc, &desc); 5835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (res == -1) { 5845389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine av_access_violation(proc, desc, addr, data_size, 0, retaddr, 1); 5855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return 1; 5865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 5875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Even though descriptor for the given address range has not been found, 5895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * we need to make sure that pages containing the given address range 5905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * don't contain other descriptors. */ 5915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return res ? procdesc_contains_allocs(proc, addr, data_size) : 0; 5925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 5935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 5945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Validates write operations, detected in __stx_mmu routine. 5955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * This routine is called from __stx_mmu wrapper implemented in 5965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * softmmu_template.h on condition that storing is occurring from user memory. 5975389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Param: 5985389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * addr - Virtual address in the guest space where memory is written. 5995389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * data_size - Size of the write. 6005389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * value - Value to be written. Note that we typecast all values to 64 bits, 6015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * since this will fit all data sizes. 6025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * retaddr - Code address (in TB) that accesses memory. 6035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Return: 6045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * 1 if TLB record for the accessed page should be invalidated in order to 6055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * ensure that subsequent attempts to access data in this page will cause 6065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * __ld/stx_mmu to be used. If memchecker is no longer interested in monitoring 6075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * access to this page, this routine returns 0. 6085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 6095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineint 6105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_validate_st(target_ulong addr, 6115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine uint32_t data_size, 6125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine uint64_t value, 6135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine target_ulong retaddr) 6145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine{ 6155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine MallocDescEx* desc; 6165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine ProcDesc* proc; 6175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 6185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine int res = memcheck_common_access_validation(addr, data_size, &proc, &desc); 6195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine if (res == -1) { 6205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine av_access_violation(proc, desc, addr, data_size, value, retaddr, 0); 6215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return 1; 6225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine } 6235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 6245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine /* Even though descriptor for the given address range has not been found, 6255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * we need to make sure that pages containing the given address range 6265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * don't contain other descriptors. */ 6275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return res ? procdesc_contains_allocs(proc, addr, data_size) : 0; 6285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 6295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 6305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine/* Checks if given address range in the context of the current process is under 6315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * surveillance. 6325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Param: 6335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * addr - Starting address of a range. 6345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * size - Range size. 6355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * Return: 6365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * boolean: 1 if address range contains memory that require access violation 6375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine * detection, or 0 if given address range is in no interest to the memchecker. 6385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine */ 6395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineint 6405389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkinememcheck_is_checked(target_ulong addr, uint32_t size) { 6415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine return procdesc_contains_allocs(get_current_process(), addr, size) ? 1 : 0; 6425389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine} 643