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