michael@0: // Copyright (c) 2007, Google Inc. michael@0: // All rights reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: // Author: Alfred Peng michael@0: michael@0: #ifndef CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__ michael@0: #define CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__ michael@0: michael@0: #if defined(sparc) || defined(__sparc) michael@0: #define TARGET_CPU_SPARC 1 michael@0: #elif defined(i386) || defined(__i386) michael@0: #define TARGET_CPU_X86 1 michael@0: #else michael@0: #error "cannot determine cpu type" michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #ifndef _KERNEL michael@0: #define _KERNEL michael@0: #define MUST_UNDEF_KERNEL michael@0: #endif // _KERNEL michael@0: #include michael@0: #ifdef MUST_UNDEF_KERNEL michael@0: #undef _KERNEL michael@0: #undef MUST_UNDEF_KERNEL michael@0: #endif // MUST_UNDEF_KERNEL michael@0: michael@0: namespace google_breakpad { michael@0: michael@0: // Max module path name length. michael@0: static const int kMaxModuleNameLength = 256; michael@0: michael@0: // Holding infomaton about a module in the process. michael@0: struct ModuleInfo { michael@0: char name[kMaxModuleNameLength]; michael@0: uintptr_t start_addr; michael@0: int size; michael@0: }; michael@0: michael@0: // A callback to run when getting a lwp in the process. michael@0: // Return true will go on to the next lwp while return false will stop the michael@0: // iteration. michael@0: typedef bool (*LwpCallback)(lwpstatus_t* lsp, void *context); michael@0: michael@0: // A callback to run when a new module is found in the process. michael@0: // Return true will go on to the next module while return false will stop the michael@0: // iteration. michael@0: typedef bool (*ModuleCallback)(const ModuleInfo &module_info, void *context); michael@0: michael@0: // A callback to run when getting a lwpid in the process. michael@0: // Return true will go on to the next lwp while return false will stop the michael@0: // iteration. michael@0: typedef bool (*LwpidCallback)(int lwpid, void *context); michael@0: michael@0: // Holding the callback information. michael@0: template michael@0: struct CallbackParam { michael@0: // Callback function address. michael@0: CallbackFunc call_back; michael@0: // Callback context; michael@0: void *context; michael@0: michael@0: CallbackParam() : call_back(NULL), context(NULL) { michael@0: } michael@0: michael@0: CallbackParam(CallbackFunc func, void *func_context) : michael@0: call_back(func), context(func_context) { michael@0: } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: // michael@0: // SolarisLwp michael@0: // michael@0: // Provides handy support for operation on Solaris lwps. michael@0: // It uses proc file system to get lwp information. michael@0: // michael@0: // TODO(Alfred): Currently it only supports x86. Add SPARC support. michael@0: // michael@0: class SolarisLwp { michael@0: public: michael@0: // Create a SolarisLwp instance to list all the lwps in a process. michael@0: explicit SolarisLwp(int pid); michael@0: ~SolarisLwp(); michael@0: michael@0: int getpid() const { return this->pid_; } michael@0: michael@0: // Control all the lwps in the process. michael@0: // Return the number of suspended/resumed lwps in the process. michael@0: // Return -1 means failed to control lwps. michael@0: int ControlAllLwps(bool suspend); michael@0: michael@0: // Get the count of lwps in the process. michael@0: // Return -1 means error. michael@0: int GetLwpCount() const; michael@0: michael@0: // Iterate the lwps of process. michael@0: // Whenever there is a lwp found, the callback will be invoked to process michael@0: // the information. michael@0: // Return the callback return value or -1 on error. michael@0: int Lwp_iter_all(int pid, CallbackParam *callback_param) const; michael@0: michael@0: // Get the module count of the current process. michael@0: int GetModuleCount() const; michael@0: michael@0: // Get the mapped modules in the address space. michael@0: // Whenever a module is found, the callback will be invoked to process the michael@0: // information. michael@0: // Return how may modules are found. michael@0: int ListModules(CallbackParam *callback_param) const; michael@0: michael@0: // Get the bottom of the stack from esp. michael@0: uintptr_t GetLwpStackBottom(uintptr_t current_esp) const; michael@0: michael@0: // Finds a signal context on the stack given the ebp of our signal handler. michael@0: bool FindSigContext(uintptr_t sighandler_ebp, ucontext_t **sig_ctx); michael@0: michael@0: private: michael@0: // Check if the address is a valid virtual address. michael@0: bool IsAddressMapped(uintptr_t address) const; michael@0: michael@0: private: michael@0: // The pid of the process we are listing lwps. michael@0: int pid_; michael@0: }; michael@0: michael@0: } // namespace google_breakpad michael@0: michael@0: #endif // CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__