• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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