/* Copyright (C) 2007-2010 The Android Open Source Project ** ** This software is licensed under the terms of the GNU General Public ** License version 2, as published by the Free Software Foundation, and ** may be copied, distributed, and modified under those terms. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. */ /* * Contains declarations of structures, routines, etc. related to process * management in memchecker framework. */ #ifndef QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H #define QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H #include "qemu-queue.h" #include "memcheck_common.h" #include "memcheck_malloc_map.h" #include "memcheck_mmrange_map.h" #ifdef __cplusplus extern "C" { #endif // ============================================================================= // Process management structures // ============================================================================= /* Describes a process that is monitored by memchecker framework. */ typedef struct ProcDesc { /* Map of memory blocks allocated in context of this process. */ AllocMap alloc_map; /* Map of memory mapped modules loaded in context of this process. */ MMRangeMap mmrange_map; /* Descriptor's entry in the global process list. */ QLIST_ENTRY(ProcDesc) global_entry; /* List of threads running in context of this process. */ QLIST_HEAD(threads, ThreadDesc) threads; /* Path to the process' image file. */ char* image_path; /* Process id. */ uint32_t pid; /* Parent process id. */ uint32_t parent_pid; /* Misc. process flags. See PROC_FLAG_XXX */ uint32_t flags; } ProcDesc; /* Process is executing. */ #define PROC_FLAG_EXECUTING 0x00000001 /* Process is exiting. */ #define PROC_FLAG_EXITING 0x00000002 /* ProcDesc->image_path has been replaced during process execution. */ #define PROC_FLAG_IMAGE_PATH_REPLACED 0x00000004 /* libc.so instance has been initialized for this process. */ #define PROC_FLAG_LIBC_INITIALIZED 0x00000008 /* Entry in the thread's calling stack array. */ typedef struct ThreadCallStackEntry { /* Guest PC where call has been made. */ target_ulong call_address; /* Guest PC where call has been made, relative to the beginning of the * mapped module that contains call_address. */ target_ulong call_address_rel; /* Guest PC where call will return. */ target_ulong ret_address; /* Guest PC where call will return, relative to the beginning of the * mapped module that contains ret_address. */ target_ulong ret_address_rel; /* Path to the image file of the module containing call_address. */ char* module_path; } ThreadCallStackEntry; /* Describes a thread that is monitored by memchecker framework. */ typedef struct ThreadDesc { /* Descriptor's entry in the global thread list. */ QLIST_ENTRY(ThreadDesc) global_entry; /* Descriptor's entry in the process' thread list. */ QLIST_ENTRY(ThreadDesc) proc_entry; /* Descriptor of the process this thread belongs to. */ ProcDesc* process; /* Calling stack for this thread. */ ThreadCallStackEntry* call_stack; /* Number of entries in the call_stack array. */ uint32_t call_stack_count; /* Maximum number of entries that can fit into call_stack buffer. */ uint32_t call_stack_max; /* Thread id. */ uint32_t tid; } ThreadDesc; // ============================================================================= // Inlines // ============================================================================= /* Checks if process has been forked, rather than created from a "fresh" PID. * Param: * proc - Descriptor for the process to check. * Return: * boolean: 1 if process has been forked, or 0 if it was * created from a "fresh" PID. */ static inline int procdesc_is_forked(const ProcDesc* proc) { return proc->parent_pid != 0; } /* Checks if process is executing. * Param: * proc - Descriptor for the process to check. * Return: * boolean: 1 if process is executing, or 0 if it is not executing. */ static inline int procdesc_is_executing(const ProcDesc* proc) { return (proc->flags & PROC_FLAG_EXECUTING) != 0; } /* Checks if process is exiting. * Param: * proc - Descriptor for the process to check. * Return: * boolean: 1 if process is exiting, or 0 if it is still alive. */ static inline int procdesc_is_exiting(const ProcDesc* proc) { return (proc->flags & PROC_FLAG_EXITING) != 0; } /* Checks if process has initialized its libc.so instance. * Param: * proc - Descriptor for the process to check. * Return: * boolean: 1 if process has initialized its libc.so instance, or 0 otherwise. */ static inline int procdesc_is_libc_initialized(const ProcDesc* proc) { return (proc->flags & PROC_FLAG_LIBC_INITIALIZED) != 0; } /* Checks if process image path has been replaced. * Param: * proc - Descriptor for the process to check. * Return: * boolean: 1 if process image path has been replaced, * or 0 if it was not replaced. */ static inline int procdesc_is_image_path_replaced(const ProcDesc* proc) { return (proc->flags & PROC_FLAG_IMAGE_PATH_REPLACED) != 0; } // ============================================================================= // Process management API // ============================================================================= /* Gets thread descriptor for the current thread. * Return: * Found thread descriptor, or NULL if thread descriptor has not been found. */ ThreadDesc* get_current_thread(void); /* Initializes process management API. */ void memcheck_init_proc_management(void); /* Gets process descriptor for the current process. * Return: * Process descriptor for the current process, or NULL, if process descriptor * has not been found. */ ProcDesc* get_current_process(void); /* Finds process descriptor for a process id. * Param: * pid - Process ID to look up process descriptor for. * Return: * Process descriptor for the PID, or NULL, if process descriptor * has not been found. */ ProcDesc* get_process_from_pid(uint32_t pid); /* Inserts new (or replaces existing) entry in the allocation descriptors map * for the given process. * See allocmap_insert for more information on this routine, its parameters * and returning value. * Param: * proc - Process descriptor where to add new allocation entry info. */ static inline RBTMapResult procdesc_add_malloc(ProcDesc* proc, const MallocDescEx* desc, MallocDescEx* replaced) { return allocmap_insert(&proc->alloc_map, desc, replaced); } /* Finds an entry in the allocation descriptors map for the given process, * matching given address range. * See allocmap_find for more information on this routine, its parameters * and returning value. * Param: * proc - Process descriptor where to find an allocation entry. */ static inline MallocDescEx* procdesc_find_malloc_for_range(ProcDesc* proc, target_ulong address, uint32_t block_size) { return allocmap_find(&proc->alloc_map, address, block_size); } /* Finds an entry in the allocation descriptors map for the given process, * matching given address. * See allocmap_find for more information on this routine, its parameters * and returning value. * Param: * proc - Process descriptor where to find an allocation entry. */ static inline MallocDescEx* procdesc_find_malloc(ProcDesc* proc, target_ulong address) { return procdesc_find_malloc_for_range(proc, address, 1); } /* Pulls (finds and removes) an entry from the allocation descriptors map for * the given process, matching given address. * See allocmap_pull for more information on this routine, its parameters * and returning value. * Param: * proc - Process descriptor where to pull an allocation entry from. */ static inline int procdesc_pull_malloc(ProcDesc* proc, target_ulong address, MallocDescEx* pulled) { return allocmap_pull(&proc->alloc_map, address, pulled); } /* Empties allocation descriptors map for the process. * Param: * proc - Process to empty allocation map for. * Return: * Number of entries deleted from the allocation map. */ static inline int procdesc_empty_alloc_map(ProcDesc* proc) { return allocmap_empty(&proc->alloc_map); } /* Finds mmapping entry for the given address in the given process. * Param: * proc - Descriptor of the process where to look for an entry. * addr - Address in the guest space for which to find an entry. * Return: * Mapped entry, or NULL if no mapping for teh given address exists in the * process address space. */ static inline MMRangeDesc* procdesc_find_mapentry(const ProcDesc* proc, target_ulong addr) { return mmrangemap_find(&proc->mmrange_map, addr, addr + 1); } /* Gets module descriptor for the given address. * Param: * proc - Descriptor of the process where to look for a module. * addr - Address in the guest space for which to find a module descriptor. * Return: * module descriptor for the module containing the given address, or NULL if no * such module has been found in the process' map of mmaped modules. */ static inline const MMRangeDesc* procdesc_get_range_desc(const ProcDesc* proc, target_ulong addr) { return procdesc_find_mapentry(proc, addr); } /* Gets name of the module mmaped in context of the given process for the * given address. * Param: * proc - Descriptor of the process where to look for a module. * addr - Address in the guest space for which to find a module. * Return: * Image path to the module containing the given address, or NULL if no such * module has been found in the process' map of mmaped modules. */ static inline const char* procdesc_get_module_path(const ProcDesc* proc, target_ulong addr) { MMRangeDesc* rdesc = procdesc_find_mapentry(proc, addr); return rdesc != NULL ? rdesc->path : NULL; } #ifdef __cplusplus }; /* end of extern "C" */ #endif #endif // QEMU_MEMCHECK_MEMCHECK_PROC_MANAGEMENT_H