Index: snapshot/win/exception_snapshot_win.cc |
diff --git a/snapshot/win/exception_snapshot_win.cc b/snapshot/win/exception_snapshot_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..40ac560bd5f1f17d22aac1e0eaa5a1245d0f9abf |
--- /dev/null |
+++ b/snapshot/win/exception_snapshot_win.cc |
@@ -0,0 +1,150 @@ |
+// Copyright 2015 The Crashpad Authors. All rights reserved. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
+ |
+#include "snapshot/win/exception_snapshot_win.h" |
+ |
+#include "snapshot/win/cpu_context_win.h" |
+#include "snapshot/win/process_reader_win.h" |
+#include "util/win/nt_internals.h" |
+#include "util/win/process_structs.h" |
+ |
+namespace crashpad { |
+namespace internal { |
+ |
+namespace { |
+ |
cpu_(ooo_6.6-7.5)
2015/05/15 01:24:13
I must mention this somewhere but unrelated to thi
scottmg
2015/08/18 05:08:40
Noted. I tried to use PLOG/LOG correctly, it's pos
|
+// ::GetThreadId is not available on XP, so get the thread id via |
+// NtQueryInformationThread. |
+template <class Traits> |
+uint64_t GetThreadId(HANDLE handle) { |
+ process_types::THREAD_BASIC_INFORMATION<Traits> basic_information; |
+ if (!NT_SUCCESS(crashpad::NtQueryInformationThread( |
+ handle, |
+ static_cast<THREADINFOCLASS>(ThreadBasicInformation), |
+ &basic_information, |
+ sizeof(basic_information), |
+ nullptr))) { |
+ LOG(ERROR) << "could not retrieve ThreadBasicInformation"; |
+ return 0; |
+ } |
+ return basic_information.ClientId.UniqueThread; |
cpu_(ooo_6.6-7.5)
2015/05/15 01:24:12
is it really the same as ::GetThreadId() ? I mean
scottmg
2015/08/18 05:08:40
It is by testing (and ProcessHacker-ing, and it's
|
+} |
+ |
+uint64_t GetThreadId(ProcessReaderWin* process_reader, HANDLE handle) { |
+ if (process_reader->Is64Bit()) |
+ return GetThreadId<process_types::internal::Traits64>(handle); |
+ else |
+ return GetThreadId<process_types::internal::Traits32>(handle); |
+} |
+ |
+} // namespace |
+ |
+ExceptionSnapshotWin::ExceptionSnapshotWin() |
+ : ExceptionSnapshot(), |
+ context_union_(), |
+ context_(), |
+ codes_(), |
+ thread_id_(0), |
+ exception_address_(0), |
+ exception_flags_(0), |
+ exception_(0), |
+ initialized_() { |
+} |
+ |
+ExceptionSnapshotWin::~ExceptionSnapshotWin() { |
+} |
+ |
+bool ExceptionSnapshotWin::Initialize(ProcessReaderWin* process_reader, |
+ HANDLE thread_handle, |
+ EXCEPTION_POINTERS* exception_pointers) { |
+ INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
+ DCHECK(exception_pointers); |
+ if (!exception_pointers->ExceptionRecord) { |
+ LOG(WARNING) << "null ExceptionRecord"; |
+ return false; |
+ } |
+ const EXCEPTION_RECORD& first_record = *exception_pointers->ExceptionRecord; |
+ exception_ = first_record.ExceptionCode; |
+ exception_flags_ = first_record.ExceptionFlags; |
+ exception_address_ = |
+ reinterpret_cast<uint64_t>(first_record.ExceptionAddress); |
+ for (DWORD i = 0; i < first_record.NumberParameters; ++i) |
+ codes_.push_back(first_record.ExceptionInformation[i]); |
+ |
+ thread_id_ = GetThreadId(process_reader, thread_handle); |
+ |
+ bool found_thread = false; |
+ for (const auto& loop_thread : process_reader->Threads()) { |
+ if (thread_id_ == loop_thread.id) { |
+ found_thread = true; |
+ break; |
+ } |
+ } |
+ |
+ if (!found_thread) { |
+ LOG(ERROR) << "thread_handle not found in process"; |
+ return false; |
+ } |
+ |
+#if defined(ARCH_CPU_X86_FAMILY) |
+ if (process_reader->Is64Bit()) { |
+ context_.architecture = kCPUArchitectureX86_64; |
+ context_.x86_64 = &context_union_.x86_64; |
+ InitializeX64Context(*exception_pointers->ContextRecord, context_.x86_64); |
+ } else { |
+ context_.architecture = kCPUArchitectureX86; |
+ context_.x86 = &context_union_.x86; |
+ InitializeX86Context(*exception_pointers->ContextRecord, context_.x86); |
+ } |
+#endif |
+ |
+ if (first_record.ExceptionRecord) |
+ LOG(WARNING) << "dropping chained ExceptionRecord"; |
+ |
+ INITIALIZATION_STATE_SET_VALID(initialized_); |
+ return true; |
+} |
+ |
+const CPUContext* ExceptionSnapshotWin::Context() const { |
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
+ return &context_; |
+} |
+ |
+uint64_t ExceptionSnapshotWin::ThreadID() const { |
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
+ return thread_id_; |
+} |
+ |
+uint32_t ExceptionSnapshotWin::Exception() const { |
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
+ return exception_; |
+} |
+ |
+uint32_t ExceptionSnapshotWin::ExceptionInfo() const { |
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
+ return exception_flags_; |
+} |
+ |
+uint64_t ExceptionSnapshotWin::ExceptionAddress() const { |
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
+ return exception_address_; |
+} |
+ |
+const std::vector<uint64_t>& ExceptionSnapshotWin::Codes() const { |
+ INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
+ return codes_; |
+} |
+ |
+} // namespace internal |
+} // namespace crashpad |