1// Copyright (c) 2007, Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above 11// copyright notice, this list of conditions and the following disclaimer 12// in the documentation and/or other materials provided with the 13// distribution. 14// * Neither the name of Google Inc. nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30// Author: Alfred Peng 31 32#ifndef CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__ 33#define CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__ 34 35#if defined(sparc) || defined(__sparc) 36#define TARGET_CPU_SPARC 1 37#elif defined(i386) || defined(__i386) 38#define TARGET_CPU_X86 1 39#else 40#error "cannot determine cpu type" 41#endif 42 43#include <signal.h> 44#include <stdint.h> 45#include <sys/user.h> 46#include <ucontext.h> 47 48#ifndef _KERNEL 49#define _KERNEL 50#define MUST_UNDEF_KERNEL 51#endif // _KERNEL 52#include <sys/procfs.h> 53#ifdef MUST_UNDEF_KERNEL 54#undef _KERNEL 55#undef MUST_UNDEF_KERNEL 56#endif // MUST_UNDEF_KERNEL 57 58namespace google_breakpad { 59 60// Max module path name length. 61static const int kMaxModuleNameLength = 256; 62 63// Holding infomaton about a module in the process. 64struct ModuleInfo { 65 char name[kMaxModuleNameLength]; 66 uintptr_t start_addr; 67 int size; 68}; 69 70// A callback to run when getting a lwp in the process. 71// Return true will go on to the next lwp while return false will stop the 72// iteration. 73typedef bool (*LwpCallback)(lwpstatus_t* lsp, void *context); 74 75// A callback to run when a new module is found in the process. 76// Return true will go on to the next module while return false will stop the 77// iteration. 78typedef bool (*ModuleCallback)(const ModuleInfo &module_info, void *context); 79 80// A callback to run when getting a lwpid in the process. 81// Return true will go on to the next lwp while return false will stop the 82// iteration. 83typedef bool (*LwpidCallback)(int lwpid, void *context); 84 85// Holding the callback information. 86template<class CallbackFunc> 87struct CallbackParam { 88 // Callback function address. 89 CallbackFunc call_back; 90 // Callback context; 91 void *context; 92 93 CallbackParam() : call_back(NULL), context(NULL) { 94 } 95 96 CallbackParam(CallbackFunc func, void *func_context) : 97 call_back(func), context(func_context) { 98 } 99}; 100 101/////////////////////////////////////////////////////////////////////////////// 102 103// 104// SolarisLwp 105// 106// Provides handy support for operation on Solaris lwps. 107// It uses proc file system to get lwp information. 108// 109// TODO(Alfred): Currently it only supports x86. Add SPARC support. 110// 111class SolarisLwp { 112 public: 113 // Create a SolarisLwp instance to list all the lwps in a process. 114 explicit SolarisLwp(int pid); 115 ~SolarisLwp(); 116 117 int getpid() const { return this->pid_; } 118 119 // Control all the lwps in the process. 120 // Return the number of suspended/resumed lwps in the process. 121 // Return -1 means failed to control lwps. 122 int ControlAllLwps(bool suspend); 123 124 // Get the count of lwps in the process. 125 // Return -1 means error. 126 int GetLwpCount() const; 127 128 // Iterate the lwps of process. 129 // Whenever there is a lwp found, the callback will be invoked to process 130 // the information. 131 // Return the callback return value or -1 on error. 132 int Lwp_iter_all(int pid, CallbackParam<LwpCallback> *callback_param) const; 133 134 // Get the module count of the current process. 135 int GetModuleCount() const; 136 137 // Get the mapped modules in the address space. 138 // Whenever a module is found, the callback will be invoked to process the 139 // information. 140 // Return how may modules are found. 141 int ListModules(CallbackParam<ModuleCallback> *callback_param) const; 142 143 // Get the bottom of the stack from esp. 144 uintptr_t GetLwpStackBottom(uintptr_t current_esp) const; 145 146 // Finds a signal context on the stack given the ebp of our signal handler. 147 bool FindSigContext(uintptr_t sighandler_ebp, ucontext_t **sig_ctx); 148 149 private: 150 // Check if the address is a valid virtual address. 151 bool IsAddressMapped(uintptr_t address) const; 152 153 private: 154 // The pid of the process we are listing lwps. 155 int pid_; 156}; 157 158} // namespace google_breakpad 159 160#endif // CLIENT_SOLARIS_HANDLER_SOLARIS_LWP_H__ 161