| 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..a32c929487a51548521d9b505b8f32ff27bd7671
|
| --- /dev/null
|
| +++ b/snapshot/win/exception_snapshot_win.cc
|
| @@ -0,0 +1,144 @@
|
| +// 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 {
|
| +
|
| +ExceptionSnapshotWin::ExceptionSnapshotWin()
|
| + : ExceptionSnapshot(),
|
| + context_union_(),
|
| + context_(),
|
| + codes_(),
|
| + thread_id_(0),
|
| + exception_address_(0),
|
| + exception_flags_(0),
|
| + exception_code_(0),
|
| + initialized_() {
|
| +}
|
| +
|
| +ExceptionSnapshotWin::~ExceptionSnapshotWin() {
|
| +}
|
| +
|
| +bool ExceptionSnapshotWin::Initialize(ProcessReaderWin* process_reader,
|
| + DWORD thread_id,
|
| + WinVMAddress exception_pointers_address) {
|
| + INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
| +
|
| + 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 ID " << thread_id << "not found in process";
|
| + return false;
|
| + } else {
|
| + thread_id_ = thread_id;
|
| + }
|
| +
|
| + EXCEPTION_POINTERS exception_pointers;
|
| + if (!process_reader->ReadMemory(exception_pointers_address,
|
| + sizeof(EXCEPTION_POINTERS),
|
| + &exception_pointers)) {
|
| + LOG(ERROR) << "EXCEPTION_POINTERS read failed";
|
| + return false;
|
| + }
|
| + if (!exception_pointers.ExceptionRecord) {
|
| + LOG(ERROR) << "null ExceptionRecord";
|
| + return false;
|
| + }
|
| +
|
| + if (process_reader->Is64Bit()) {
|
| + EXCEPTION_RECORD64 first_record;
|
| + if (!process_reader->ReadMemory(
|
| + reinterpret_cast<WinVMAddress>(exception_pointers.ExceptionRecord),
|
| + sizeof(first_record),
|
| + &first_record)) {
|
| + 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://code.google.com/p/crashpad/issues/detail?id=43
|
| + LOG(WARNING) << "dropping chained ExceptionRecord";
|
| + }
|
| +
|
| + context_.architecture = kCPUArchitectureX86_64;
|
| + context_.x86_64 = &context_union_.x86_64;
|
| + // We assume 64-on-64 here in that we're relying on the CONTEXT definition
|
| + // to be the x64 one.
|
| + CONTEXT context_record;
|
| + if (!process_reader->ReadMemory(
|
| + reinterpret_cast<WinVMAddress>(exception_pointers.ContextRecord),
|
| + sizeof(context_record),
|
| + &context_record)) {
|
| + LOG(ERROR) << "ContextRecord";
|
| + return false;
|
| + }
|
| + InitializeX64Context(context_record, context_.x86_64);
|
| + } else {
|
| + CHECK(false) << "TODO(scottmg) x86";
|
| + return false;
|
| + }
|
| +
|
| + 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_code_;
|
| +}
|
| +
|
| +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
|
|
|