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
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. */
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. */
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. */
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 */
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
322