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