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. related to process
     15  * management in memchecker framework.
     16  */
     17 
     18 #ifndef QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H
     19 #define QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_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 "sys-queue.h"
     28 #include "memcheck_common.h"
     29 #include "memcheck_malloc_map.h"
     30 #include "memcheck_mmrange_map.h"
     31 
     32 #ifdef __cplusplus
     33 extern "C" {
     34 #endif
     35 
     36 // =============================================================================
     37 // Process management structures
     38 // =============================================================================
     39 
     40 /* Describes a process that is monitored by memchecker framework. */
     41 typedef struct ProcDesc {
     42     /* Map of memory blocks allocated in context of this process. */
     43     AllocMap                                    alloc_map;
     44 
     45     /* Map of memory mapped modules loaded in context of this process. */
     46     MMRangeMap                                  mmrange_map;
     47 
     48     /* Descriptor's entry in the global process list. */
     49     LIST_ENTRY(ProcDesc)                        global_entry;
     50 
     51     /* List of threads running in context of this process. */
     52     LIST_HEAD(threads, ThreadDesc)              threads;
     53 
     54     /* Path to the process' image file. */
     55     char*                                       image_path;
     56 
     57     /* Process id. */
     58     uint32_t                                    pid;
     59 
     60     /* Parent process id. */
     61     uint32_t                                    parent_pid;
     62 
     63     /* Misc. process flags. See PROC_FLAG_XXX */
     64     uint32_t                                    flags;
     65 } ProcDesc;
     66 
     67 /* Process is executing. */
     68 #define PROC_FLAG_EXECUTING             0x00000001
     69 /* Process is exiting. */
     70 #define PROC_FLAG_EXITING               0x00000002
     71 /* ProcDesc->image_path has been replaced during process execution. */
     72 #define PROC_FLAG_IMAGE_PATH_REPLACED   0x00000004
     73 /* libc.so instance has been initialized for this process. */
     74 #define PROC_FLAG_LIBC_INITIALIZED      0x00000008
     75 
     76 /* Entry in the thread's calling stack array. */
     77 typedef struct ThreadCallStackEntry {
     78     /* Guest PC where call has been made. */
     79     target_ulong    call_address;
     80     /* Guest PC where call has been made, relative to the beginning of the
     81      * mapped module that contains call_address. */
     82     target_ulong    call_address_rel;
     83     /* Guest PC where call will return. */
     84     target_ulong    ret_address;
     85     /* Guest PC where call will return, relative to the beginning of the
     86      * mapped module that contains ret_address. */
     87     target_ulong    ret_address_rel;
     88     /* Path to the image file of the module containing call_address. */
     89     char*           module_path;
     90 } ThreadCallStackEntry;
     91 
     92 /* Describes a thread that is monitored by memchecker framework. */
     93 typedef struct ThreadDesc {
     94     /* Descriptor's entry in the global thread list. */
     95     LIST_ENTRY(ThreadDesc)  global_entry;
     96 
     97     /* Descriptor's entry in the process' thread list. */
     98     LIST_ENTRY(ThreadDesc)  proc_entry;
     99 
    100     /* Descriptor of the process this thread belongs to. */
    101     ProcDesc*               process;
    102 
    103     /* Calling stack for this thread. */
    104     ThreadCallStackEntry*   call_stack;
    105 
    106     /* Number of entries in the call_stack array. */
    107     uint32_t                call_stack_count;
    108 
    109     /* Maximum number of entries that can fit into call_stack buffer. */
    110     uint32_t                call_stack_max;
    111 
    112     /* Thread id. */
    113     uint32_t                tid;
    114 } ThreadDesc;
    115 
    116 // =============================================================================
    117 // Inlines
    118 // =============================================================================
    119 
    120 /* Checks if process has been forked, rather than created from a "fresh" PID.
    121  * Param:
    122  *  proc - Descriptor for the process to check.
    123  * Return:
    124  *  boolean: 1 if process has been forked, or 0 if it was
    125  *  created from a "fresh" PID.
    126  */
    127 static inline int
    128 procdesc_is_forked(const ProcDesc* proc)
    129 {
    130     return proc->parent_pid != 0;
    131 }
    132 
    133 /* Checks if process is executing.
    134  * Param:
    135  *  proc - Descriptor for the process to check.
    136  * Return:
    137  *  boolean: 1 if process is executing, or 0 if it is not executing.
    138  */
    139 static inline int
    140 procdesc_is_executing(const ProcDesc* proc)
    141 {
    142     return (proc->flags & PROC_FLAG_EXECUTING) != 0;
    143 }
    144 
    145 /* Checks if process is exiting.
    146  * Param:
    147  *  proc - Descriptor for the process to check.
    148  * Return:
    149  *  boolean: 1 if process is exiting, or 0 if it is still alive.
    150  */
    151 static inline int
    152 procdesc_is_exiting(const ProcDesc* proc)
    153 {
    154     return (proc->flags & PROC_FLAG_EXITING) != 0;
    155 }
    156 
    157 /* Checks if process has initialized its libc.so instance.
    158  * Param:
    159  *  proc - Descriptor for the process to check.
    160  * Return:
    161  *  boolean: 1 if process has initialized its libc.so instance, or 0 otherwise.
    162  */
    163 static inline int
    164 procdesc_is_libc_initialized(const ProcDesc* proc)
    165 {
    166     return (proc->flags & PROC_FLAG_LIBC_INITIALIZED) != 0;
    167 }
    168 
    169 /* Checks if process image path has been replaced.
    170  * Param:
    171  *  proc - Descriptor for the process to check.
    172  * Return:
    173  *  boolean: 1 if process image path has been replaced,
    174  *  or 0 if it was not replaced.
    175  */
    176 static inline int
    177 procdesc_is_image_path_replaced(const ProcDesc* proc)
    178 {
    179     return (proc->flags & PROC_FLAG_IMAGE_PATH_REPLACED) != 0;
    180 }
    181 
    182 // =============================================================================
    183 // Process management API
    184 // =============================================================================
    185 
    186 /* Gets thread descriptor for the current thread.
    187  * Return:
    188  *  Found thread descriptor, or NULL if thread descriptor has not been found.
    189  */
    190 ThreadDesc* get_current_thread(void);
    191 
    192 /* Initializes process management API. */
    193 void memcheck_init_proc_management(void);
    194 
    195 /* Gets process descriptor for the current process.
    196  * Return:
    197  *  Process descriptor for the current process, or NULL, if process descriptor
    198  *  has not been found.
    199  */
    200 ProcDesc* get_current_process(void);
    201 
    202 /* Finds process descriptor for a process id.
    203  * Param:
    204  *  pid - Process ID to look up process descriptor for.
    205  * Return:
    206  *  Process descriptor for the PID, or NULL, if process descriptor
    207  *  has not been found.
    208  */
    209 ProcDesc* get_process_from_pid(uint32_t pid);
    210 
    211 /* Inserts new (or replaces existing) entry in the allocation descriptors map
    212  * for the given process.
    213  * See allocmap_insert for more information on this routine, its parameters
    214  * and returning value.
    215  * Param:
    216  *  proc - Process descriptor where to add new allocation entry info.
    217  */
    218 static inline RBTMapResult
    219 procdesc_add_malloc(ProcDesc* proc,
    220                     const MallocDescEx* desc,
    221                     MallocDescEx* replaced)
    222 {
    223     return allocmap_insert(&proc->alloc_map, desc, replaced);
    224 }
    225 
    226 /* Finds an entry in the allocation descriptors map for the given process,
    227  * matching given address range.
    228  * See allocmap_find for more information on this routine, its parameters
    229  * and returning value.
    230  * Param:
    231  *  proc - Process descriptor where to find an allocation entry.
    232  */
    233 static inline MallocDescEx*
    234 procdesc_find_malloc_for_range(ProcDesc* proc,
    235                                target_ulong address,
    236                                uint32_t block_size)
    237 {
    238     return allocmap_find(&proc->alloc_map, address, block_size);
    239 }
    240 
    241 /* Finds an entry in the allocation descriptors map for the given process,
    242  * matching given address.
    243  * See allocmap_find for more information on this routine, its parameters
    244  * and returning value.
    245  * Param:
    246  *  proc - Process descriptor where to find an allocation entry.
    247  */
    248 static inline MallocDescEx*
    249 procdesc_find_malloc(ProcDesc* proc, target_ulong address)
    250 {
    251     return procdesc_find_malloc_for_range(proc, address, 1);
    252 }
    253 
    254 /* Pulls (finds and removes) an entry from the allocation descriptors map for
    255  * the given process, matching given address.
    256  * See allocmap_pull for more information on this routine, its parameters
    257  * and returning value.
    258  * Param:
    259  *  proc - Process descriptor where to pull an allocation entry from.
    260  */
    261 static inline int
    262 procdesc_pull_malloc(ProcDesc* proc, target_ulong address, MallocDescEx* pulled)
    263 {
    264     return allocmap_pull(&proc->alloc_map, address, pulled);
    265 }
    266 
    267 /* Empties allocation descriptors map for the process.
    268  * Param:
    269  *  proc - Process to empty allocation map for.
    270  * Return:
    271  *  Number of entries deleted from the allocation map.
    272  */
    273 static inline int
    274 procdesc_empty_alloc_map(ProcDesc* proc)
    275 {
    276     return allocmap_empty(&proc->alloc_map);
    277 }
    278 
    279 /* Finds mmapping entry for the given address in the given process.
    280  * Param:
    281  *  proc - Descriptor of the process where to look for an entry.
    282  *  addr - Address in the guest space for which to find an entry.
    283  * Return:
    284  *  Mapped entry, or NULL if no mapping for teh given address exists in the
    285  *  process address space.
    286  */
    287 static inline MMRangeDesc*
    288 procdesc_find_mapentry(const ProcDesc* proc, target_ulong addr)
    289 {
    290     return mmrangemap_find(&proc->mmrange_map, addr, addr + 1);
    291 }
    292 
    293 /* Gets module descriptor for the given address.
    294  * Param:
    295  *  proc - Descriptor of the process where to look for a module.
    296  *  addr - Address in the guest space for which to find a module descriptor.
    297  * Return:
    298  *  module descriptor for the module containing the given address, or NULL if no
    299  *  such module has been found in the process' map of mmaped modules.
    300  */
    301 static inline const MMRangeDesc*
    302 procdesc_get_range_desc(const ProcDesc* proc, target_ulong addr)
    303 {
    304     return procdesc_find_mapentry(proc, addr);
    305 }
    306 
    307 /* Gets name of the module mmaped in context of the given process for the
    308  * given address.
    309  * Param:
    310  *  proc - Descriptor of the process where to look for a module.
    311  *  addr - Address in the guest space for which to find a module.
    312  * Return:
    313  *  Image path to the module containing the given address, or NULL if no such
    314  *  module has been found in the process' map of mmaped modules.
    315  */
    316 static inline const char*
    317 procdesc_get_module_path(const ProcDesc* proc, target_ulong addr)
    318 {
    319     MMRangeDesc* rdesc = procdesc_find_mapentry(proc, addr);
    320     return rdesc != NULL ? rdesc->path : NULL;
    321 }
    322 
    323 #ifdef __cplusplus
    324 };  /* end of extern "C" */
    325 #endif
    326 
    327 #endif  // QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H
    328