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