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