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