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 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
    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
    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
    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
    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
    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
    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
    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
    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
    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