// Copyright 2017 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/fuchsia/process_snapshot_fuchsia.h" #include "base/logging.h" #include "util/fuchsia/koid_utilities.h" namespace crashpad { ProcessSnapshotFuchsia::ProcessSnapshotFuchsia() = default; ProcessSnapshotFuchsia::~ProcessSnapshotFuchsia() = default; bool ProcessSnapshotFuchsia::Initialize(const zx::process& process) { INITIALIZATION_STATE_SET_INITIALIZING(initialized_); if (gettimeofday(&snapshot_time_, nullptr) != 0) { PLOG(ERROR) << "gettimeofday"; return false; } if (!process_reader_.Initialize(process) || !memory_range_.Initialize(process_reader_.Memory(), true)) { return false; } client_id_.InitializeToZero(); system_.Initialize(&snapshot_time_); InitializeThreads(); InitializeModules(); const MemoryMapFuchsia* memory_map = process_reader_.MemoryMap(); if (memory_map) { for (const auto& entry : memory_map->Entries()) { if (entry.type == ZX_INFO_MAPS_TYPE_MAPPING) { memory_map_.push_back( std::make_unique(entry)); } } } INITIALIZATION_STATE_SET_VALID(initialized_); return true; } bool ProcessSnapshotFuchsia::InitializeException( zx_koid_t thread_id, const zx_exception_report_t& report) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::unique_ptr exception( new internal::ExceptionSnapshotFuchsia()); if (exception->Initialize(&process_reader_, thread_id, report)) { exception_.swap(exception); return true; } return false; } void ProcessSnapshotFuchsia::GetCrashpadOptions( CrashpadInfoClientOptions* options) { INITIALIZATION_STATE_DCHECK_VALID(initialized_); CrashpadInfoClientOptions local_options; for (const auto& 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 (local_options.gather_indirectly_referenced_memory == TriState::kUnset) { local_options.gather_indirectly_referenced_memory = module_options.gather_indirectly_referenced_memory; local_options.indirectly_referenced_memory_cap = module_options.indirectly_referenced_memory_cap; } // 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 && local_options.gather_indirectly_referenced_memory != TriState::kUnset) { break; } } *options = local_options; } crashpad::ProcessID ProcessSnapshotFuchsia::ProcessID() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return GetKoidForHandle(*zx::process::self()); } crashpad::ProcessID ProcessSnapshotFuchsia::ParentProcessID() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); NOTREACHED(); // TODO(scottmg): https://crashpad.chromium.org/bug/196 return 0; } void ProcessSnapshotFuchsia::SnapshotTime(timeval* snapshot_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); *snapshot_time = snapshot_time_; } void ProcessSnapshotFuchsia::ProcessStartTime(timeval* start_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); // TODO(scottmg): https://crashpad.chromium.org/bug/196. Nothing available. *start_time = timeval{}; } void ProcessSnapshotFuchsia::ProcessCPUTimes(timeval* user_time, timeval* system_time) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); // TODO(scottmg): https://crashpad.chromium.org/bug/196. Nothing available. *user_time = timeval{}; *system_time = timeval{}; } void ProcessSnapshotFuchsia::ReportID(UUID* report_id) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); *report_id = report_id_; } void ProcessSnapshotFuchsia::ClientID(UUID* client_id) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); *client_id = client_id_; } const std::map& ProcessSnapshotFuchsia::AnnotationsSimpleMap() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return annotations_simple_map_; } const SystemSnapshot* ProcessSnapshotFuchsia::System() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return &system_; } std::vector ProcessSnapshotFuchsia::Threads() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::vector threads; for (const auto& thread : threads_) { threads.push_back(thread.get()); } return threads; } std::vector ProcessSnapshotFuchsia::Modules() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::vector modules; for (const auto& module : modules_) { modules.push_back(module.get()); } return modules; } std::vector ProcessSnapshotFuchsia::UnloadedModules() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); // dlclose() never unloads on Fuchsia. ZX-1728 upstream. return std::vector(); } const ExceptionSnapshot* ProcessSnapshotFuchsia::Exception() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return exception_.get(); } std::vector ProcessSnapshotFuchsia::MemoryMap() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::vector memory_map; for (const auto& item : memory_map_) { memory_map.push_back(item.get()); } return memory_map; } std::vector ProcessSnapshotFuchsia::Handles() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return std::vector(); } std::vector ProcessSnapshotFuchsia::ExtraMemory() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return std::vector(); } const ProcessMemory* ProcessSnapshotFuchsia::Memory() const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); return process_reader_.Memory(); } void ProcessSnapshotFuchsia::InitializeThreads() { const std::vector& process_reader_threads = process_reader_.Threads(); for (const ProcessReaderFuchsia::Thread& process_reader_thread : process_reader_threads) { auto thread = std::make_unique(); if (thread->Initialize(&process_reader_, process_reader_thread)) { threads_.push_back(std::move(thread)); } } } void ProcessSnapshotFuchsia::InitializeModules() { for (const ProcessReaderFuchsia::Module& reader_module : process_reader_.Modules()) { auto module = std::make_unique(reader_module.name, reader_module.reader, reader_module.type, &memory_range_, process_reader_.Memory()); if (module->Initialize()) { modules_.push_back(std::move(module)); } } } } // namespace crashpad