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