// 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/process_snapshot_win.h" #include "base/logging.h" #include "snapshot/win/module_snapshot_win.h" #include "util/win/registration_protocol_win.h" #include "util/win/time.h" namespace crashpad { ProcessSnapshotWin::ProcessSnapshotWin() : ProcessSnapshot(), system_(), threads_(), modules_(), exception_(), process_reader_(), report_id_(), client_id_(), annotations_simple_map_(), snapshot_time_(), initialized_() { } ProcessSnapshotWin::~ProcessSnapshotWin() { } bool ProcessSnapshotWin::Initialize(HANDLE process, ProcessSuspensionState suspension_state) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); GetTimeOfDay(&snapshot_time_); if (!process_reader_.Initialize(process, suspension_state)) return false; system_.Initialize(&process_reader_); InitializeThreads(); InitializeModules(); INITIALIZATION_STATE_SET_VALID(initialized_); return true; } bool ProcessSnapshotWin::InitializeException( WinVMAddress exception_information_address) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); DCHECK(!exception_); ExceptionInformation exception_information; if (!process_reader_.ReadMemory(exception_information_address, sizeof(exception_information), &exception_information)) { LOG(WARNING) << "ReadMemory ExceptionInformation failed"; return false; } exception_.reset(new internal::ExceptionSnapshotWin()); if (!exception_->Initialize(&process_reader_, exception_information.thread_id, exception_information.exception_pointers)) { exception_.reset(); return false; } return true; } void ProcessSnapshotWin::GetCrashpadOptions( CrashpadInfoClientOptions* options) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); CrashpadInfoClientOptions local_options; for (internal::ModuleSnapshotWin* module : modules_) { CrashpadInfoClientOptions module_options; module->GetCrashpadOptions(&module_options); if (local_options.crashpad_handler_behavior == TriState::kUnset) { local_options.crashpad_handler_behavior = module_options.crashpad_handler_behavior; } if (local_options.system_crash_reporter_forwarding == TriState::kUnset) { local_options.system_crash_reporter_forwarding = module_options.system_crash_reporter_forwarding; } // If non-default values have been found for all options, the loop can end // early. if (local_options.crashpad_handler_behavior != TriState::kUnset && local_options.system_crash_reporter_forwarding != TriState::kUnset) { break; } } *options = local_options; } pid_t ProcessSnapshotWin::ProcessID() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return process_reader_.ProcessID(); } pid_t ProcessSnapshotWin::ParentProcessID() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return process_reader_.ParentProcessID(); } void ProcessSnapshotWin::SnapshotTime(timeval* snapshot_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); *snapshot_time = snapshot_time_; } void ProcessSnapshotWin::ProcessStartTime(timeval* start_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); process_reader_.StartTime(start_time); } void ProcessSnapshotWin::ProcessCPUTimes(timeval* user_time, timeval* system_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); process_reader_.CPUTimes(user_time, system_time); } void ProcessSnapshotWin::ReportID(UUID* report_id) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); *report_id = report_id_; } void ProcessSnapshotWin::ClientID(UUID* client_id) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); *client_id = client_id_; } const std::map& ProcessSnapshotWin::AnnotationsSimpleMap() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return annotations_simple_map_; } const SystemSnapshot* ProcessSnapshotWin::System() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return &system_; } std::vector ProcessSnapshotWin::Threads() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::vector threads; for (internal::ThreadSnapshotWin* thread : threads_) { threads.push_back(thread); } return threads; } std::vector ProcessSnapshotWin::Modules() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::vector modules; for (internal::ModuleSnapshotWin* module : modules_) { modules.push_back(module); } return modules; } const ExceptionSnapshot* ProcessSnapshotWin::Exception() const { return exception_.get(); } void ProcessSnapshotWin::InitializeThreads() { const std::vector& process_reader_threads = process_reader_.Threads(); for (const ProcessReaderWin::Thread& process_reader_thread : process_reader_threads) { auto thread = make_scoped_ptr(new internal::ThreadSnapshotWin()); if (thread->Initialize(&process_reader_, process_reader_thread)) { threads_.push_back(thread.release()); } } } void ProcessSnapshotWin::InitializeModules() { const std::vector& process_reader_modules = process_reader_.Modules(); for (const ProcessInfo::Module& process_reader_module : process_reader_modules) { auto module = make_scoped_ptr(new internal::ModuleSnapshotWin()); if (module->Initialize(&process_reader_, process_reader_module)) { modules_.push_back(module.release()); } } } } // namespace crashpad