blob: d5525b1a055865035cc92acaf1a8c0686813773c [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
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
33extern "C" {
34#endif
35
36// =============================================================================
37// Process management structures
38// =============================================================================
39
40/* Describes a process that is monitored by memchecker framework. */
41typedef 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. */
77typedef 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. */
93typedef 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 */
127static inline int
128procdesc_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 */
139static inline int
140procdesc_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 */
151static inline int
152procdesc_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 */
163static inline int
164procdesc_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 */
176static inline int
177procdesc_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 */
190ThreadDesc* get_current_thread(void);
191
192/* Initializes process management API. */
193void 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 */
200ProcDesc* 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 */
209ProcDesc* 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 */
218static inline RBTMapResult
219procdesc_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 */
233static inline MallocDescEx*
234procdesc_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 */
248static inline MallocDescEx*
249procdesc_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 */
261static inline int
262procdesc_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 */
273static inline int
274procdesc_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 */
287static inline MMRangeDesc*
288procdesc_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 */
301static inline const MMRangeDesc*
302procdesc_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 */
316static inline const char*
317procdesc_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