1 // Copyright (c) 2010 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 #ifndef CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ 31 #define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ 32 33 #include <string> 34 #include <vector> 35 36 #include <pthread.h> 37 #include <signal.h> 38 #include <stdint.h> 39 #include <stdio.h> 40 41 #if defined(__ANDROID__) 42 #include "client/linux/android_ucontext.h" 43 #endif 44 #include "client/linux/crash_generation/crash_generation_client.h" 45 #include "client/linux/minidump_writer/minidump_writer.h" 46 #include "google_breakpad/common/minidump_format.h" 47 #include "processor/scoped_ptr.h" 48 49 struct sigaction; 50 51 namespace google_breakpad { 52 53 class ExceptionHandler; 54 55 // ExceptionHandler 56 // 57 // ExceptionHandler can write a minidump file when an exception occurs, 58 // or when WriteMinidump() is called explicitly by your program. 59 // 60 // To have the exception handler write minidumps when an uncaught exception 61 // (crash) occurs, you should create an instance early in the execution 62 // of your program, and keep it around for the entire time you want to 63 // have crash handling active (typically, until shutdown). 64 // (NOTE): There should be only be one this kind of exception handler 65 // object per process. 66 // 67 // If you want to write minidumps without installing the exception handler, 68 // you can create an ExceptionHandler with install_handler set to false, 69 // then call WriteMinidump. You can also use this technique if you want to 70 // use different minidump callbacks for different call sites. 71 // 72 // In either case, a callback function is called when a minidump is written, 73 // which receives the unqiue id of the minidump. The caller can use this 74 // id to collect and write additional application state, and to launch an 75 // external crash-reporting application. 76 // 77 // Caller should try to make the callbacks as crash-friendly as possible, 78 // it should avoid use heap memory allocation as much as possible. 79 class ExceptionHandler { 80 public: 81 // A callback function to run before Breakpad performs any substantial 82 // processing of an exception. A FilterCallback is called before writing 83 // a minidump. context is the parameter supplied by the user as 84 // callback_context when the handler was created. 85 // 86 // If a FilterCallback returns true, Breakpad will continue processing, 87 // attempting to write a minidump. If a FilterCallback returns false, 88 // Breakpad will immediately report the exception as unhandled without 89 // writing a minidump, allowing another handler the opportunity to handle it. 90 typedef bool (*FilterCallback)(void *context); 91 92 // A callback function to run after the minidump has been written. 93 // minidump_id is a unique id for the dump, so the minidump 94 // file is <dump_path>\<minidump_id>.dmp. context is the parameter supplied 95 // by the user as callback_context when the handler was created. succeeded 96 // indicates whether a minidump file was successfully written. 97 // 98 // If an exception occurred and the callback returns true, Breakpad will 99 // treat the exception as fully-handled, suppressing any other handlers from 100 // being notified of the exception. If the callback returns false, Breakpad 101 // will treat the exception as unhandled, and allow another handler to handle 102 // it. If there are no other handlers, Breakpad will report the exception to 103 // the system as unhandled, allowing a debugger or native crash dialog the 104 // opportunity to handle the exception. Most callback implementations 105 // should normally return the value of |succeeded|, or when they wish to 106 // not report an exception of handled, false. Callbacks will rarely want to 107 // return true directly (unless |succeeded| is true). 108 typedef bool (*MinidumpCallback)(const char *dump_path, 109 const char *minidump_id, 110 void *context, 111 bool succeeded); 112 113 // In certain cases, a user may wish to handle the generation of the minidump 114 // themselves. In this case, they can install a handler callback which is 115 // called when a crash has occurred. If this function returns true, no other 116 // processing of occurs and the process will shortly be crashed. If this 117 // returns false, the normal processing continues. 118 typedef bool (*HandlerCallback)(const void* crash_context, 119 size_t crash_context_size, 120 void* context); 121 122 // Creates a new ExceptionHandler instance to handle writing minidumps. 123 // Before writing a minidump, the optional filter callback will be called. 124 // Its return value determines whether or not Breakpad should write a 125 // minidump. Minidump files will be written to dump_path, and the optional 126 // callback is called after writing the dump file, as described above. 127 // If install_handler is true, then a minidump will be written whenever 128 // an unhandled exception occurs. If it is false, minidumps will only 129 // be written when WriteMinidump is called. 130 ExceptionHandler(const std::string &dump_path, 131 FilterCallback filter, MinidumpCallback callback, 132 void *callback_context, 133 bool install_handler); 134 135 // Creates a new ExceptionHandler instance that can attempt to 136 // perform out-of-process dump generation if server_fd is valid. If 137 // server_fd is invalid, in-process dump generation will be 138 // used. See the above ctor for a description of the other 139 // parameters. 140 ExceptionHandler(const std::string& dump_path, 141 FilterCallback filter, MinidumpCallback callback, 142 void* callback_context, 143 bool install_handler, 144 const int server_fd); 145 146 ~ExceptionHandler(); 147 148 // Get and set the minidump path. dump_path()149 std::string dump_path() const { return dump_path_; } set_dump_path(const std::string & dump_path)150 void set_dump_path(const std::string &dump_path) { 151 dump_path_ = dump_path; 152 dump_path_c_ = dump_path_.c_str(); 153 UpdateNextID(); 154 } 155 set_crash_handler(HandlerCallback callback)156 void set_crash_handler(HandlerCallback callback) { 157 crash_handler_ = callback; 158 } 159 160 // Writes a minidump immediately. This can be used to capture the 161 // execution state independently of a crash. Returns true on success. 162 bool WriteMinidump(); 163 164 // Convenience form of WriteMinidump which does not require an 165 // ExceptionHandler instance. 166 static bool WriteMinidump(const std::string &dump_path, 167 MinidumpCallback callback, 168 void *callback_context); 169 170 // This structure is passed to minidump_writer.h:WriteMinidump via an opaque 171 // blob. It shouldn't be needed in any user code. 172 struct CrashContext { 173 siginfo_t siginfo; 174 pid_t tid; // the crashing thread. 175 struct ucontext context; 176 #if !defined(__ARM_EABI__) 177 // #ifdef this out because FP state is not part of user ABI for Linux ARM. 178 struct _libc_fpstate float_state; 179 #endif 180 }; 181 182 // Returns whether out-of-process dump generation is used or not. IsOutOfProcess()183 bool IsOutOfProcess() const { 184 return crash_generation_client_.get() != NULL; 185 } 186 187 // Add information about a memory mapping. This can be used if 188 // a custom library loader is used that maps things in a way 189 // that the linux dumper can't handle by reading the maps file. 190 void AddMappingInfo(const std::string& name, 191 const u_int8_t identifier[sizeof(MDGUID)], 192 uintptr_t start_address, 193 size_t mapping_size, 194 size_t file_offset); 195 196 private: 197 void Init(const std::string &dump_path, 198 const int server_fd); 199 bool InstallHandlers(); 200 void UninstallHandlers(); 201 void PreresolveSymbols(); 202 bool GenerateDump(CrashContext *context); 203 void SendContinueSignalToChild(); 204 void WaitForContinueSignal(); 205 206 void UpdateNextID(); 207 static void SignalHandler(int sig, siginfo_t* info, void* uc); 208 bool HandleSignal(int sig, siginfo_t* info, void* uc); 209 static int ThreadEntry(void* arg); 210 bool DoDump(pid_t crashing_process, const void* context, 211 size_t context_size); 212 213 const FilterCallback filter_; 214 const MinidumpCallback callback_; 215 void* const callback_context_; 216 217 scoped_ptr<CrashGenerationClient> crash_generation_client_; 218 219 std::string dump_path_; 220 std::string next_minidump_path_; 221 std::string next_minidump_id_; 222 223 // Pointers to C-string representations of the above. These are set 224 // when the above are set so we can avoid calling c_str during 225 // an exception. 226 const char* dump_path_c_; 227 const char* next_minidump_path_c_; 228 const char* next_minidump_id_c_; 229 230 const bool handler_installed_; 231 void* signal_stack; // the handler stack. 232 HandlerCallback crash_handler_; 233 234 // The global exception handler stack. This is need becuase there may exist 235 // multiple ExceptionHandler instances in a process. Each will have itself 236 // registered in this stack. 237 static std::vector<ExceptionHandler*> *handler_stack_; 238 // The index of the handler that should handle the next exception. 239 static unsigned handler_stack_index_; 240 static pthread_mutex_t handler_stack_mutex_; 241 242 // A vector of the old signal handlers. 243 std::vector<std::pair<int, struct sigaction *> > old_handlers_; 244 245 // We need to explicitly enable ptrace of parent processes on some 246 // kernels, but we need to know the PID of the cloned process before we 247 // can do this. We create a pipe which we can use to block the 248 // cloned process after creating it, until we have explicitly enabled 249 // ptrace. This is used to store the file descriptors for the pipe 250 int fdes[2]; 251 252 // Callers can add extra info about mappings for cases where the 253 // dumper code cannot extract enough information from /proc/<pid>/maps. 254 MappingList mapping_list_; 255 }; 256 257 } // namespace google_breakpad 258 259 #endif // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ 260