Chromium Code Reviews| 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 |