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
procdesc_is_forked(const ProcDesc * proc)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
procdesc_is_executing(const ProcDesc * proc)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
procdesc_is_exiting(const ProcDesc * proc)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
procdesc_is_libc_initialized(const ProcDesc * proc)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
procdesc_is_image_path_replaced(const ProcDesc * proc)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
procdesc_add_malloc(ProcDesc * proc,const MallocDescEx * desc,MallocDescEx * replaced)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*
procdesc_find_malloc_for_range(ProcDesc * proc,target_ulong address,uint32_t block_size)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*
procdesc_find_malloc(ProcDesc * proc,target_ulong address)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
procdesc_pull_malloc(ProcDesc * proc,target_ulong address,MallocDescEx * pulled)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
procdesc_empty_alloc_map(ProcDesc * proc)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*
procdesc_find_mapentry(const ProcDesc * proc,target_ulong addr)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*
procdesc_get_range_desc(const ProcDesc * proc,target_ulong addr)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*
procdesc_get_module_path(const ProcDesc * proc,target_ulong addr)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