Index: third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc |
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc |
index ea44f0fcceca94d738049f2f21404d815c71eb6d..ca29e1f0e80125cc5baecabbbb3725cd9c0cf66e 100644 |
--- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc |
+++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc |
@@ -14,6 +14,7 @@ |
#include "snapshot/win/exception_snapshot_win.h" |
+#include "client/crashpad_client.h" |
#include "snapshot/capture_memory.h" |
#include "snapshot/memory_snapshot.h" |
#include "snapshot/win/cpu_context_win.h" |
@@ -25,6 +26,34 @@ |
namespace crashpad { |
namespace internal { |
+namespace { |
+ |
+#if defined(ARCH_CPU_32_BITS) |
+using Context32 = CONTEXT; |
+#elif defined(ARCH_CPU_64_BITS) |
+using Context32 = WOW64_CONTEXT; |
+#endif |
+ |
+#if defined(ARCH_CPU_64_BITS) |
+void NativeContextToCPUContext64(const CONTEXT& context_record, |
+ CPUContext* context, |
+ CPUContextUnion* context_union) { |
+ context->architecture = kCPUArchitectureX86_64; |
+ context->x86_64 = &context_union->x86_64; |
+ InitializeX64Context(context_record, context->x86_64); |
+} |
+#endif |
+ |
+void NativeContextToCPUContext32(const Context32& context_record, |
+ CPUContext* context, |
+ CPUContextUnion* context_union) { |
+ context->architecture = kCPUArchitectureX86; |
+ context->x86 = &context_union->x86; |
+ InitializeX86Context(context_record, context->x86); |
+} |
+ |
+} // namespace |
+ |
ExceptionSnapshotWin::ExceptionSnapshotWin() |
: ExceptionSnapshot(), |
context_union_(), |
@@ -40,9 +69,11 @@ ExceptionSnapshotWin::ExceptionSnapshotWin() |
ExceptionSnapshotWin::~ExceptionSnapshotWin() { |
} |
-bool ExceptionSnapshotWin::Initialize(ProcessReaderWin* process_reader, |
- DWORD thread_id, |
- WinVMAddress exception_pointers_address) { |
+bool ExceptionSnapshotWin::Initialize( |
+ ProcessReaderWin* process_reader, |
+ DWORD thread_id, |
+ WinVMAddress exception_pointers_address, |
+ const PointerVector<internal::ThreadSnapshotWin>& threads) { |
INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
const ProcessReaderWin::Thread* thread = nullptr; |
@@ -62,36 +93,32 @@ bool ExceptionSnapshotWin::Initialize(ProcessReaderWin* process_reader, |
#if defined(ARCH_CPU_32_BITS) |
const bool is_64_bit = false; |
- using Context32 = CONTEXT; |
#elif defined(ARCH_CPU_64_BITS) |
const bool is_64_bit = process_reader->Is64Bit(); |
- using Context32 = WOW64_CONTEXT; |
if (is_64_bit) { |
- CONTEXT context_record; |
if (!InitializeFromExceptionPointers<EXCEPTION_RECORD64, |
process_types::EXCEPTION_POINTERS64>( |
- *process_reader, exception_pointers_address, &context_record)) { |
+ *process_reader, |
+ exception_pointers_address, |
+ threads, |
+ &NativeContextToCPUContext64)) { |
return false; |
} |
- context_.architecture = kCPUArchitectureX86_64; |
- context_.x86_64 = &context_union_.x86_64; |
- InitializeX64Context(context_record, context_.x86_64); |
} |
#endif |
if (!is_64_bit) { |
- Context32 context_record; |
if (!InitializeFromExceptionPointers<EXCEPTION_RECORD32, |
process_types::EXCEPTION_POINTERS32>( |
- *process_reader, exception_pointers_address, &context_record)) { |
+ *process_reader, |
+ exception_pointers_address, |
+ threads, |
+ &NativeContextToCPUContext32)) { |
return false; |
} |
- context_.architecture = kCPUArchitectureX86; |
- context_.x86 = &context_union_.x86; |
- InitializeX86Context(context_record, context_.x86); |
} |
CaptureMemoryDelegateWin capture_memory_delegate( |
- process_reader, *thread, &extra_memory_); |
+ process_reader, *thread, &extra_memory_, nullptr); |
CaptureMemory::PointedToByContext(context_, &capture_memory_delegate); |
INITIALIZATION_STATE_SET_VALID(initialized_); |
@@ -143,7 +170,10 @@ template <class ExceptionRecordType, |
bool ExceptionSnapshotWin::InitializeFromExceptionPointers( |
const ProcessReaderWin& process_reader, |
WinVMAddress exception_pointers_address, |
- ContextType* context_record) { |
+ const PointerVector<internal::ThreadSnapshotWin>& threads, |
+ void (*native_to_cpu_context)(const ContextType& context_record, |
+ CPUContext* context, |
+ CPUContextUnion* context_union)) { |
ExceptionPointersType exception_pointers; |
if (!process_reader.ReadMemory(exception_pointers_address, |
sizeof(exception_pointers), |
@@ -164,22 +194,60 @@ bool ExceptionSnapshotWin::InitializeFromExceptionPointers( |
LOG(ERROR) << "ExceptionRecord"; |
return false; |
} |
- exception_code_ = first_record.ExceptionCode; |
- exception_flags_ = first_record.ExceptionFlags; |
- exception_address_ = first_record.ExceptionAddress; |
- for (DWORD i = 0; i < first_record.NumberParameters; ++i) |
- codes_.push_back(first_record.ExceptionInformation[i]); |
- if (first_record.ExceptionRecord) { |
- // https://crashpad.chromium.org/bug/43 |
- LOG(WARNING) << "dropping chained ExceptionRecord"; |
- } |
- if (!process_reader.ReadMemory( |
- static_cast<WinVMAddress>(exception_pointers.ContextRecord), |
- sizeof(*context_record), |
- context_record)) { |
- LOG(ERROR) << "ContextRecord"; |
- return false; |
+ if (first_record.ExceptionCode == CrashpadClient::kTriggeredExceptionCode && |
+ first_record.NumberParameters == 2 && |
+ first_record.ExceptionInformation[0] != 0) { |
+ // This special exception code indicates that the target was crashed by |
+ // another client calling CrashpadClient::DumpAndCrashTargetProcess(). In |
+ // this case the parameters are a thread id and an exception code which we |
+ // use to fabricate a new exception record. |
+ using ArgumentType = decltype(first_record.ExceptionInformation[0]); |
+ const ArgumentType thread_id = first_record.ExceptionInformation[0]; |
+ exception_code_ = static_cast<DWORD>(first_record.ExceptionInformation[1]); |
+ exception_flags_ = EXCEPTION_NONCONTINUABLE; |
+ for (const auto* thread : threads) { |
+ if (thread->ThreadID() == thread_id) { |
+ thread_id_ = thread_id; |
+ exception_address_ = thread->Context()->InstructionPointer(); |
+ context_.architecture = thread->Context()->architecture; |
+ if (context_.architecture == kCPUArchitectureX86_64) { |
+ context_union_.x86_64 = *thread->Context()->x86_64; |
+ context_.x86_64 = &context_union_.x86_64; |
+ } else { |
+ context_union_.x86 = *thread->Context()->x86; |
+ context_.x86 = &context_union_.x86; |
+ } |
+ break; |
+ } |
+ } |
+ |
+ if (exception_address_ == 0) { |
+ LOG(WARNING) << "thread " << thread_id << " not found"; |
+ return false; |
+ } |
+ } else { |
+ // Normal case. |
+ exception_code_ = first_record.ExceptionCode; |
+ exception_flags_ = first_record.ExceptionFlags; |
+ exception_address_ = first_record.ExceptionAddress; |
+ for (DWORD i = 0; i < first_record.NumberParameters; ++i) |
+ codes_.push_back(first_record.ExceptionInformation[i]); |
+ if (first_record.ExceptionRecord) { |
+ // https://crashpad.chromium.org/bug/43 |
+ LOG(WARNING) << "dropping chained ExceptionRecord"; |
+ } |
+ |
+ ContextType context_record; |
+ if (!process_reader.ReadMemory( |
+ static_cast<WinVMAddress>(exception_pointers.ContextRecord), |
+ sizeof(context_record), |
+ &context_record)) { |
+ LOG(ERROR) << "ContextRecord"; |
+ return false; |
+ } |
+ |
+ native_to_cpu_context(context_record, &context_, &context_union_); |
} |
return true; |