• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
av_invalid_pointer(ProcDesc * proc,target_ulong ptr,int routine)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
av_access_violation(ProcDesc * proc,MallocDescEx * desc,target_ulong addr,uint32_t data_size,uint64_t val,target_ulong retaddr,int is_read)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
memcheck_common_access_validation(target_ulong addr,uint32_t data_size,ProcDesc ** proc_ptr,MallocDescEx ** desc_ptr)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
procdesc_contains_allocs(ProcDesc * proc,target_ulong addr,uint32_t buf_size)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
memcheck_init(const char * tracing_flags)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
memcheck_guest_libc_initialized(uint32_t pid)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
memcheck_guest_alloc(target_ulong guest_address)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
memcheck_guest_free(target_ulong guest_address)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
memcheck_guest_query_malloc(target_ulong guest_address)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
memcheck_guest_print_str(target_ulong str)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
memcheck_validate_ld(target_ulong addr,uint32_t data_size,target_ulong retaddr)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
memcheck_validate_st(target_ulong addr,uint32_t data_size,uint64_t value,target_ulong retaddr)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
memcheck_is_checked(target_ulong addr,uint32_t size)640 memcheck_is_checked(target_ulong addr, uint32_t size) {
641     return procdesc_contains_allocs(get_current_process(), addr, size) ? 1 : 0;
642 }
643