blob: 7f489cf4089451c1df1ed83ec21656f03bf6c160 [file] [log] [blame]
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -08001/* 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
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070021#include "qemu-queue.h"
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080022#include "memcheck_common.h"
23#include "memcheck_malloc_map.h"
24#include "memcheck_mmrange_map.h"
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30// =============================================================================
31// Process management structures
32// =============================================================================
33
34/* Describes a process that is monitored by memchecker framework. */
35typedef 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. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070043 QLIST_ENTRY(ProcDesc) global_entry;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080044
45 /* List of threads running in context of this process. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070046 QLIST_HEAD(threads, ThreadDesc) threads;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080047
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. */
71typedef 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. */
87typedef struct ThreadDesc {
88 /* Descriptor's entry in the global thread list. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070089 QLIST_ENTRY(ThreadDesc) global_entry;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080090
91 /* Descriptor's entry in the process' thread list. */
David 'Digit' Turnera5d41202010-05-10 18:37:10 -070092 QLIST_ENTRY(ThreadDesc) proc_entry;
Vladimir Chtchetkine5389aa12010-02-16 10:38:35 -080093
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 */
121static inline int
122procdesc_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 */
133static inline int
134procdesc_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 */
145static inline int
146procdesc_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 */
157static inline int
158procdesc_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 */
170static inline int
171procdesc_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 */
184ThreadDesc* get_current_thread(void);
185
186/* Initializes process management API. */
187void 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 */
194ProcDesc* 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 */
203ProcDesc* 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 */
212static inline RBTMapResult
213procdesc_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 */
227static inline MallocDescEx*
228procdesc_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 */
242static inline MallocDescEx*
243procdesc_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 */
255static inline int
256procdesc_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 */
267static inline int
268procdesc_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 */
281static inline MMRangeDesc*
282procdesc_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 */
295static inline const MMRangeDesc*
296procdesc_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 */
310static inline const char*
311procdesc_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