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 declarations of structures, routines, etc. that are commonly used
15 * in memechecker framework.
16 */
17
18 #ifndef QEMU_MEMCHECK_MEMCHECK_COMMON_H
19 #define QEMU_MEMCHECK_MEMCHECK_COMMON_H
20
21 /* This file should compile iff qemu is built with memory checking
22 * configuration turned on. */
23 #ifndef CONFIG_MEMCHECK
24 #error CONFIG_MEMCHECK is not defined.
25 #endif // CONFIG_MEMCHECK
26
27 #include "qemu-common.h"
28 #include "cpu.h"
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 // =============================================================================
35 // Events generated by the guest system.
36 // =============================================================================
37
38 /* Notifies the emulator that libc has been initialized for a process.
39 * Event's value parameter is PID for the process in context of which libc has
40 * been initialized.
41 */
42 #define TRACE_DEV_REG_LIBC_INIT 1536
43
44 /* Notifies the emulator about new memory block being allocated.
45 * Event's value parameter points to MallocDesc instance in the guest's address
46 * space that contains allocated block information. Note that 'libc_pid' field
47 * of the descriptor is used by emulator to report failure in handling this
48 * event. In case of failure emulator will zero that filed before completing
49 * this event.
50 */
51 #define TRACE_DEV_REG_MALLOC 1537
52
53 /* Notifies the emulator about memory block being freed.
54 * Event's value parameter points to MallocFree descriptor instance in the
55 * guest's address space that contains information about block that's being
56 * freed. Note that 'libc_pid' field of the descriptor is used by emulator to
57 * report failure in handling this event. In case of failure emulator will zero
58 * that filed before completing this event.
59 */
60 #define TRACE_DEV_REG_FREE_PTR 1538
61
62 /* Queries the emulator about memory block information.
63 * Event's value parameter points to MallocDescQuery descriptor instance in the
64 * guest's address space that contains query parameters. Note that 'libc_pid'
65 * field of the descriptor is used by emulator to report failure in handling
66 * this event. In case of failure emulator will zero that filed before
67 * completing this event.
68 */
69 #define TRACE_DEV_REG_QUERY_MALLOC 1539
70
71 /* Queries the emulator to print a string to its stdout.
72 * Event's value parameter points to zero-terminated string to be printed. Note
73 * that this string is located in the guest's address space.
74 */
75 #define TRACE_DEV_REG_PRINT_USER_STR 1540
76
77 // =============================================================================
78 // Communication structures
79 // =============================================================================
80
81 /* Describes memory block allocated from the heap. This structure is passed
82 * along with TRACE_DEV_REG_MALLOC event. This descriptor is used to inform
83 * the emulator about new memory block being allocated from the heap. The entire
84 * structure is initialized by the guest system before event is fired up. It is
85 * important to remember that same structure (an exact copy) is also declared
86 * in the libc's sources. So, every time a change is made to any of these
87 * two declaration, another one must be also updated accordingly. */
88 typedef struct MallocDesc {
89 /* Poniter to the memory block actually allocated from the heap. Note that
90 * this is not the pointer that is returned to the malloc's caller. Pointer
91 * returned to the caller is calculated by adding value stored in this field
92 * to the value stored in prefix_size field of this structure.
93 */
94 target_ulong ptr;
95
96 /* Nuber of bytes requested by the malloc's caller. */
97 uint32_t requested_bytes;
98
99 /* Byte size of the prefix data. Actual pointer returned to the malloc's
100 * caller is calculated by adding value stored in this field to the value
101 * stored in in the ptr field of this structure.
102 */
103 uint32_t prefix_size;
104
105 /* Byte size of the suffix data. */
106 uint32_t suffix_size;
107
108 /* Id of the process that initialized libc instance, in which allocation
109 * has occurred. This field is used by the emulator to report errors in
110 * the course of TRACE_DEV_REG_MALLOC event handling. In case of an error,
111 * emulator sets this field to zero (invalid value for a process ID).
112 */
113 uint32_t libc_pid;
114
115 /* Id of the process in context of which allocation has occurred.
116 * Value in this field may differ from libc_pid value, if process that
117 * is doing allocation has been forked from the process that initialized
118 * libc instance.
119 */
120 uint32_t allocator_pid;
121
122 /* Number of access violations detected on this allocation. */
123 uint32_t av_count;
124 } MallocDesc;
125 /* Helpers for addressing field in MallocDesc structure, using which emulator
126 * reports an error back to the guest.
127 */
128 #define ALLOC_RES_OFFSET ((uint32_t)&(((MallocDesc*)0)->libc_pid))
129 #define ALLOC_RES_ADDRESS(p) (p + ALLOC_RES_OFFSET)
130
131 /* Describes memory block info queried from emulator. This structure is passed
132 * along with TRACE_DEV_REG_QUERY_MALLOC event. When handling free and realloc
133 * calls, it is required that we have information about memory blocks that were
134 * actually allocated in previous calls to malloc, memalign, or realloc. Since
135 * we don't keep this information directlry in the allocated block, but rather
136 * we keep it in the emulator, we need to query emulator for that information
137 * with TRACE_DEV_REG_QUERY_MALLOC query. The entire structure is initialized
138 * by the guest system before event is fired up It is important to remember that
139 * same structure (an exact copy) is also declared in the libc's sources. So,
140 * every time a change is made to any of these two declaration, another one
141 * must be also updated accordingly.
142 */
143 typedef struct MallocDescQuery {
144 /* Pointer for which information is queried. Note that this pointer doesn't
145 * have to be exact pointer returned to malloc's caller, but can point
146 * anywhere inside an allocated block, including guarding areas. Emulator
147 * will respond with information about allocated block that contains this
148 * pointer.
149 */
150 target_ulong ptr;
151
152 /* Id of the process that initialized libc instance, in which this query
153 * is called. This field is used by the emulator to report errors in
154 * the course of TRACE_DEV_REG_QUERY_MALLOC event handling. In case of an
155 * error, emulator sets this field to zero (invalid value for a process ID).
156 */
157 uint32_t libc_pid;
158
159 /* Process ID in context of which query is made. */
160 uint32_t query_pid;
161
162 /* Code of the allocation routine, in context of which query has been made:
163 * 1 - free
164 * 2 - realloc
165 */
166 uint32_t routine;
167
168 /* Address in guest's virtual space of memory allocation descriptor for the
169 * queried pointer. Descriptor, addressed by this field is initialized by
170 * the emulator in response to the query.
171 */
172 target_ulong desc;
173 } MallocDescQuery;
174 /* Helpers for addressing field in MallocDescQuery structure using which
175 * emulator reports an error back to the guest.
176 */
177 #define QUERY_RES_OFFSET ((uint32_t)&(((MallocDescQuery*)0)->libc_pid))
178 #define QUERY_RES_ADDRESS(p) (p + QUERY_RES_OFFSET)
179
180 /* Describes memory block that is being freed back to the heap. This structure
181 * is passed along with TRACE_DEV_REG_FREE_PTR event. The entire structure is
182 * initialized by the guest system before event is fired up. It is important to
183 * remember that same structure (an exact copy) is also declared in the libc's
184 * sources. So, every time a change is made to any of these two declaration,
185 * another one must be also updated accordingly.
186 */
187 typedef struct MallocFree {
188 /* Pointer to be freed. */
189 uint32_t ptr;
190
191 /* Id of the process that initialized libc instance, in which this free
192 * is called. This field is used by the emulator to report errors in
193 * the course of TRACE_DEV_REG_FREE_PTR event handling. In case of an
194 * error, emulator sets this field to zero (invalid value for a process ID).
195 */
196 uint32_t libc_pid;
197
198 /* Process ID in context of which memory is being freed. */
199 uint32_t free_pid;
200 } MallocFree;
201 /* Helpers for addressing field in MallocFree structure, using which emulator
202 * reports an error back to the guest.
203 */
204 #define FREE_RES_OFFSET ((uint32_t)&(((MallocFree*)0)->libc_pid))
205 #define FREE_RES_ADDRESS(p) (p + FREE_RES_OFFSET)
206
207 /* Extends MallocDesc structure with additional information, used by memchecker.
208 */
209 typedef struct MallocDescEx {
210 /* Allocation descriptor this structure extends. */
211 MallocDesc malloc_desc;
212
213 /* Call stack that lead to memory allocation. The array is arranged in
214 * accending order, where entry at index 0 corresponds to the routine
215 * that allocated memory. */
216 target_ulong* call_stack;
217
218 /* Number of entries in call_stack array. */
219 uint32_t call_stack_count;
220
221 /* Set of misc. flags. See MDESC_FLAG_XXX bellow. */
222 uint32_t flags;
223 } MallocDescEx;
224
225 /* Indicates that memory has been allocated before process started execution.
226 * After a process has been forked, but before it actually starts executing,
227 * allocations can be made in context of that process PID. This flag marks such
228 * allocations in the process' allocation descriptors map.
229 */
230 #define MDESC_FLAG_TRANSITION_ENTRY 0x00000001
231
232 /* Indicates that memory block has been inherited from the parent process.
233 * When a process is forked from its parent process, the forked process inherits
234 * a copy of the parent process' heap. Thus, all allocations that were recorded
235 * for the parent process must be also recorded for the forked process. This
236 * flag marks entries in the forked process' allocation descriptors map that
237 * were copied over from the parent process' allocation descriptors map.
238 */
239 #define MDESC_FLAG_INHERITED_ON_FORK 0x00000002
240
241 /* Describes a memory mapping of an execution module in the guest system. */
242 typedef struct MMRangeDesc {
243 /* Starting address of mmapping of a module in the guest's address space. */
244 target_ulong map_start;
245
246 /* Ending address of mmapping of a module in the guest's address space. */
247 target_ulong map_end;
248
249 /* Mmapping's execution offset. */
250 target_ulong exec_offset;
251
252 /* Image path of the module that has been mapped with this mmapping. */
253 char* path;
254 } MMRangeDesc;
255
256 /* Enumerates returned values for insert routines implemeted for red-black
257 * tree maps.
258 */
259 typedef enum {
260 /* New entry has been inserted into the map. */
261 RBT_MAP_RESULT_ENTRY_INSERTED = 0,
262
263 /* An entry, matching the new one already exists in the map. */
264 RBT_MAP_RESULT_ENTRY_ALREADY_EXISTS,
265
266 /* An existing entry, matching the new one has been replaced
267 * with the new entry.
268 */
269 RBT_MAP_RESULT_ENTRY_REPLACED,
270
271 /* An error has occurred when inserting entry into the map. */
272 RBT_MAP_RESULT_ERROR = -1,
273 } RBTMapResult;
274
275 /* Encapsulates an array of guest addresses, sorted in accending order. */
276 typedef struct AddrArray {
277 /* Array of addresses. */
278 target_ulong* addr;
279
280 /* Number of elements in the array. */
281 int num;
282 } AddrArray;
283
284 // =============================================================================
285 // Inlines
286 // =============================================================================
287
288 /* Gets pointer returned to malloc caller for the given allocation decriptor.
289 * Param:
290 * desc - Allocation descriptor.
291 * Return:
292 * Pointer to the allocated memory returned to the malloc caller.
293 */
294 static inline target_ulong
mallocdesc_get_user_ptr(const MallocDesc * desc)295 mallocdesc_get_user_ptr(const MallocDesc* desc)
296 {
297 return desc->ptr + desc->prefix_size;
298 }
299
300 /* Gets total size of the allocated block for the given descriptor.
301 * Param:
302 * desc - Descriptor for the memory block, allocated in malloc handler.
303 * Return:
304 * Total size of memory block allocated in malloc handler.
305 */
306 static inline uint32_t
mallocdesc_get_alloc_size(const MallocDesc * desc)307 mallocdesc_get_alloc_size(const MallocDesc* desc)
308 {
309 return desc->prefix_size + desc->requested_bytes + desc->suffix_size;
310 }
311
312 /* Gets the end of the allocated block for the given descriptor.
313 * Param:
314 * desc - Descriptor for the memory block, allocated in malloc handler.
315 * Return:
316 * Pointer to the end of the allocated block (next byte past the block).
317 */
318 static inline target_ulong
mallocdesc_get_alloc_end(const MallocDesc * desc)319 mallocdesc_get_alloc_end(const MallocDesc* desc)
320 {
321 return desc->ptr + mallocdesc_get_alloc_size(desc);
322 }
323
324 /* Gets the end of the allocated block available to the user for the given
325 * descriptor.
326 * Param:
327 * desc - Descriptor for the memory block, allocated in malloc handler.
328 * Return:
329 * Pointer to the end of the allocated block available to the user (next byte
330 * past the block - suffix guarding area).
331 */
332 static inline target_ulong
mallocdesc_get_user_alloc_end(const MallocDesc * desc)333 mallocdesc_get_user_alloc_end(const MallocDesc* desc)
334 {
335 return mallocdesc_get_user_ptr(desc) + desc->requested_bytes;
336 }
337
338 /* Checks if allocation has been made before process started execution.
339 * Param:
340 * desc - Allocation descriptor to check.
341 * Return:
342 * boolean: 1 if allocation has been made before process started execution,
343 * or 0 if allocation has been made after process started execution.
344 */
345 static inline int
mallocdescex_is_transition_entry(const MallocDescEx * desc)346 mallocdescex_is_transition_entry(const MallocDescEx* desc)
347 {
348 return (desc->flags & MDESC_FLAG_TRANSITION_ENTRY) != 0;
349 }
350
351 /* Checks if allocation block has been inherited on fork.
352 * Param:
353 * desc - Allocation descriptor to check.
354 * Return:
355 * boolean: 1 if allocation has been inherited on fork, or 0 if allocation
356 * has been made by this process..
357 */
358 static inline int
mallocdescex_is_inherited_on_fork(const MallocDescEx * desc)359 mallocdescex_is_inherited_on_fork(const MallocDescEx* desc)
360 {
361 return (desc->flags & MDESC_FLAG_INHERITED_ON_FORK) != 0;
362 }
363
364 /* Gets offset for the given address inside a mapped module.
365 * Param:
366 * address - Address to get offset for.
367 * Return:
368 * Offset of the given address inside a mapped module, represented with the
369 * given mmaping range descriptor.
370 */
371 static inline target_ulong
mmrangedesc_get_module_offset(const MMRangeDesc * rdesc,target_ulong address)372 mmrangedesc_get_module_offset(const MMRangeDesc* rdesc, target_ulong address)
373 {
374 return address - rdesc->map_start + rdesc->exec_offset;
375 }
376
377 /* Checks if given address is contained in the given address array.
378 * Return:
379 * boolean: 1 if address is contained in the array, or zero if it's not.
380 */
381 static inline int
addrarray_check(const AddrArray * addr_array,target_ulong addr)382 addrarray_check(const AddrArray* addr_array, target_ulong addr)
383 {
384 if (addr_array->num != 0) {
385 int m_min = 0;
386 int m_max = addr_array->num - 1;
387
388 /* May be odd for THUMB mode. */
389 addr &= ~1;
390 /* Since array is sorted we can do binary search here. */
391 while (m_min <= m_max) {
392 const int m = (m_min + m_max) >> 1;
393 const target_ulong saved = addr_array->addr[m];
394 if (addr == saved) {
395 return 1;
396 }
397 if (addr < saved) {
398 m_max = m - 1;
399 } else {
400 m_min = m + 1;
401 }
402 }
403 }
404 return 0;
405 }
406
407 /* Adds an address to the address array.
408 * Return:
409 * 1 - Address has been added to the array.
410 * -1 - Address already exists in the array.
411 * 0 - Unable to expand the array.
412 */
413 static inline int
addrarray_add(AddrArray * addr_array,target_ulong addr)414 addrarray_add(AddrArray* addr_array, target_ulong addr)
415 {
416 target_ulong* new_arr;
417 int m_min;
418 int m_max;
419
420 /* May be odd for THUMB mode. */
421 addr &= ~1;
422 if (addr_array->num == 0) {
423 /* First element. */
424 addr_array->addr = qemu_malloc(sizeof(target_ulong));
425 assert(addr_array->addr != NULL);
426 if (addr_array->addr == NULL) {
427 return 0;
428 }
429 *addr_array->addr = addr;
430 addr_array->num++;
431 return 1;
432 }
433
434 /* Using binary search find the place where to insert new address. */
435 m_min = 0;
436 m_max = addr_array->num - 1;
437 while (m_min <= m_max) {
438 const int m = (m_min + m_max) >> 1;
439 const target_ulong saved = addr_array->addr[m];
440 if (addr == saved) {
441 return -1;
442 }
443 if (addr < saved) {
444 m_max = m - 1;
445 } else {
446 m_min = m + 1;
447 }
448 }
449 if (m_max < 0) {
450 m_max = 0;
451 }
452 /* Expand the array. */
453 new_arr = qemu_malloc(sizeof(target_ulong) * (addr_array->num + 1));
454 assert(new_arr != NULL);
455 if (new_arr == NULL) {
456 return 0;
457 }
458 /* Copy preceding elements to the new array. */
459 if (m_max != 0) {
460 memcpy(new_arr, addr_array->addr, m_max * sizeof(target_ulong));
461 }
462 if (addr > addr_array->addr[m_max]) {
463 new_arr[m_max] = addr_array->addr[m_max];
464 m_max++;
465 }
466 /* Insert new address. */
467 new_arr[m_max] = addr;
468 /* Copy remaining elements to the new array. */
469 if (m_max < addr_array->num) {
470 memcpy(new_arr + m_max + 1, addr_array->addr + m_max,
471 (addr_array->num - m_max) * sizeof(target_ulong));
472 }
473 /* Swap arrays. */
474 qemu_free(addr_array->addr);
475 addr_array->addr = new_arr;
476 addr_array->num++;
477 return 1;
478 }
479
480 #ifdef __cplusplus
481 }; /* end of extern "C" */
482 #endif
483
484 #endif // QEMU_MEMCHECK_MEMCHECK_COMMON_H
485