| OLD | NEW |
| 1 // Copyright (c) 2014, Google Inc. | 1 // Copyright (c) 2014, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 using google_breakpad::UContextReader; | 53 using google_breakpad::UContextReader; |
| 54 | 54 |
| 55 const size_t kLineBufferSize = 2048; | 55 const size_t kLineBufferSize = 2048; |
| 56 | 56 |
| 57 class MicrodumpWriter { | 57 class MicrodumpWriter { |
| 58 public: | 58 public: |
| 59 MicrodumpWriter(const ExceptionHandler::CrashContext* context, | 59 MicrodumpWriter(const ExceptionHandler::CrashContext* context, |
| 60 const MappingList& mappings, | 60 const MappingList& mappings, |
| 61 const char* build_fingerprint, | 61 const char* build_fingerprint, |
| 62 const char* product_info, | 62 const char* product_info, |
| 63 const char* gpu_fingerprint, |
| 63 LinuxDumper* dumper) | 64 LinuxDumper* dumper) |
| 64 : ucontext_(context ? &context->context : NULL), | 65 : ucontext_(context ? &context->context : NULL), |
| 65 #if !defined(__ARM_EABI__) && !defined(__mips__) | 66 #if !defined(__ARM_EABI__) && !defined(__mips__) |
| 66 float_state_(context ? &context->float_state : NULL), | 67 float_state_(context ? &context->float_state : NULL), |
| 67 #endif | 68 #endif |
| 68 dumper_(dumper), | 69 dumper_(dumper), |
| 69 mapping_list_(mappings), | 70 mapping_list_(mappings), |
| 70 build_fingerprint_(build_fingerprint), | 71 build_fingerprint_(build_fingerprint), |
| 71 product_info_(product_info), | 72 product_info_(product_info), |
| 73 gpu_fingerprint_(gpu_fingerprint), |
| 72 log_line_(NULL) { | 74 log_line_(NULL) { |
| 73 log_line_ = reinterpret_cast<char*>(Alloc(kLineBufferSize)); | 75 log_line_ = reinterpret_cast<char*>(Alloc(kLineBufferSize)); |
| 74 if (log_line_) | 76 if (log_line_) |
| 75 log_line_[0] = '\0'; // Clear out the log line buffer. | 77 log_line_[0] = '\0'; // Clear out the log line buffer. |
| 76 } | 78 } |
| 77 | 79 |
| 78 ~MicrodumpWriter() { dumper_->ThreadsResume(); } | 80 ~MicrodumpWriter() { dumper_->ThreadsResume(); } |
| 79 | 81 |
| 80 bool Init() { | 82 bool Init() { |
| 81 // In the exceptional case where the system was out of memory and there | 83 // In the exceptional case where the system was out of memory and there |
| 82 // wasn't even room to allocate the line buffer, bail out. There is nothing | 84 // wasn't even room to allocate the line buffer, bail out. There is nothing |
| 83 // useful we can possibly achieve without the ability to Log. At least let's | 85 // useful we can possibly achieve without the ability to Log. At least let's |
| 84 // try to not crash. | 86 // try to not crash. |
| 85 if (!dumper_->Init() || !log_line_) | 87 if (!dumper_->Init() || !log_line_) |
| 86 return false; | 88 return false; |
| 87 return dumper_->ThreadsSuspend() && dumper_->LateInit(); | 89 return dumper_->ThreadsSuspend() && dumper_->LateInit(); |
| 88 } | 90 } |
| 89 | 91 |
| 90 bool Dump() { | 92 bool Dump() { |
| 91 bool success; | 93 bool success; |
| 92 LogLine("-----BEGIN BREAKPAD MICRODUMP-----"); | 94 LogLine("-----BEGIN BREAKPAD MICRODUMP-----"); |
| 93 DumpProductInformation(); | 95 DumpProductInformation(); |
| 94 DumpOSInformation(); | 96 DumpOSInformation(); |
| 97 DumpGPUInformation(); |
| 95 success = DumpCrashingThread(); | 98 success = DumpCrashingThread(); |
| 96 if (success) | 99 if (success) |
| 97 success = DumpMappings(); | 100 success = DumpMappings(); |
| 98 LogLine("-----END BREAKPAD MICRODUMP-----"); | 101 LogLine("-----END BREAKPAD MICRODUMP-----"); |
| 99 dumper_->ThreadsResume(); | 102 dumper_->ThreadsResume(); |
| 100 return success; | 103 return success; |
| 101 } | 104 } |
| 102 | 105 |
| 103 private: | 106 private: |
| 104 // Writes one line to the system log. | 107 // Writes one line to the system log. |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 } else if (has_uts_info) { | 208 } else if (has_uts_info) { |
| 206 LogAppend(uts.release); | 209 LogAppend(uts.release); |
| 207 LogAppend(" "); | 210 LogAppend(" "); |
| 208 LogAppend(uts.version); | 211 LogAppend(uts.version); |
| 209 } else { | 212 } else { |
| 210 LogAppend("no build fingerprint available"); | 213 LogAppend("no build fingerprint available"); |
| 211 } | 214 } |
| 212 LogCommitLine(); | 215 LogCommitLine(); |
| 213 } | 216 } |
| 214 | 217 |
| 218 void DumpGPUInformation() { |
| 219 LogAppend("G "); |
| 220 if (gpu_fingerprint_) { |
| 221 LogAppend(gpu_fingerprint_); |
| 222 } else { |
| 223 LogAppend("UNKNOWN"); |
| 224 } |
| 225 LogCommitLine(); |
| 226 } |
| 227 |
| 215 bool DumpThreadStack(uint32_t thread_id, | 228 bool DumpThreadStack(uint32_t thread_id, |
| 216 uintptr_t stack_pointer, | 229 uintptr_t stack_pointer, |
| 217 int max_stack_len, | 230 int max_stack_len, |
| 218 uint8_t** stack_copy) { | 231 uint8_t** stack_copy) { |
| 219 *stack_copy = NULL; | 232 *stack_copy = NULL; |
| 220 const void* stack; | 233 const void* stack; |
| 221 size_t stack_len; | 234 size_t stack_len; |
| 222 | 235 |
| 223 if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) { | 236 if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) { |
| 224 // The stack pointer might not be available. In this case we don't hard | 237 // The stack pointer might not be available. In this case we don't hard |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 void* Alloc(unsigned bytes) { return dumper_->allocator()->Alloc(bytes); } | 398 void* Alloc(unsigned bytes) { return dumper_->allocator()->Alloc(bytes); } |
| 386 | 399 |
| 387 const struct ucontext* const ucontext_; | 400 const struct ucontext* const ucontext_; |
| 388 #if !defined(__ARM_EABI__) && !defined(__mips__) | 401 #if !defined(__ARM_EABI__) && !defined(__mips__) |
| 389 const google_breakpad::fpstate_t* const float_state_; | 402 const google_breakpad::fpstate_t* const float_state_; |
| 390 #endif | 403 #endif |
| 391 LinuxDumper* dumper_; | 404 LinuxDumper* dumper_; |
| 392 const MappingList& mapping_list_; | 405 const MappingList& mapping_list_; |
| 393 const char* const build_fingerprint_; | 406 const char* const build_fingerprint_; |
| 394 const char* const product_info_; | 407 const char* const product_info_; |
| 408 const char* const gpu_fingerprint_; |
| 395 char* log_line_; | 409 char* log_line_; |
| 396 }; | 410 }; |
| 397 } // namespace | 411 } // namespace |
| 398 | 412 |
| 399 namespace google_breakpad { | 413 namespace google_breakpad { |
| 400 | 414 |
| 401 bool WriteMicrodump(pid_t crashing_process, | 415 bool WriteMicrodump(pid_t crashing_process, |
| 402 const void* blob, | 416 const void* blob, |
| 403 size_t blob_size, | 417 size_t blob_size, |
| 404 const MappingList& mappings, | 418 const MappingList& mappings, |
| 405 const char* build_fingerprint, | 419 const char* build_fingerprint, |
| 406 const char* product_info) { | 420 const char* product_info, |
| 421 const char* gpu_fingerprint) { |
| 407 LinuxPtraceDumper dumper(crashing_process); | 422 LinuxPtraceDumper dumper(crashing_process); |
| 408 const ExceptionHandler::CrashContext* context = NULL; | 423 const ExceptionHandler::CrashContext* context = NULL; |
| 409 if (blob) { | 424 if (blob) { |
| 410 if (blob_size != sizeof(ExceptionHandler::CrashContext)) | 425 if (blob_size != sizeof(ExceptionHandler::CrashContext)) |
| 411 return false; | 426 return false; |
| 412 context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob); | 427 context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob); |
| 413 dumper.set_crash_address( | 428 dumper.set_crash_address( |
| 414 reinterpret_cast<uintptr_t>(context->siginfo.si_addr)); | 429 reinterpret_cast<uintptr_t>(context->siginfo.si_addr)); |
| 415 dumper.set_crash_signal(context->siginfo.si_signo); | 430 dumper.set_crash_signal(context->siginfo.si_signo); |
| 416 dumper.set_crash_thread(context->tid); | 431 dumper.set_crash_thread(context->tid); |
| 417 } | 432 } |
| 418 MicrodumpWriter writer(context, mappings, build_fingerprint, product_info, | 433 MicrodumpWriter writer(context, mappings, build_fingerprint, product_info, |
| 419 &dumper); | 434 gpu_fingerprint, &dumper); |
| 420 if (!writer.Init()) | 435 if (!writer.Init()) |
| 421 return false; | 436 return false; |
| 422 return writer.Dump(); | 437 return writer.Dump(); |
| 423 } | 438 } |
| 424 | 439 |
| 425 } // namespace google_breakpad | 440 } // namespace google_breakpad |
| OLD | NEW |