| // 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; |
| } |
| |
| 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<internal::MemoryMapRegionSnapshotFuchsia>(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_); |
| exception_.reset(new internal::ExceptionSnapshotFuchsia()); |
| exception_->Initialize(&process_reader_, thread_id, report); |
| return true; |
| } |
| |
| 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<std::string, std::string>& |
| 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<const ThreadSnapshot*> ProcessSnapshotFuchsia::Threads() const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| std::vector<const ThreadSnapshot*> threads; |
| for (const auto& thread : threads_) { |
| threads.push_back(thread.get()); |
| } |
| return threads; |
| } |
| |
| std::vector<const ModuleSnapshot*> ProcessSnapshotFuchsia::Modules() const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| std::vector<const ModuleSnapshot*> modules; |
| for (const auto& module : modules_) { |
| modules.push_back(module.get()); |
| } |
| return modules; |
| } |
| |
| std::vector<UnloadedModuleSnapshot> ProcessSnapshotFuchsia::UnloadedModules() |
| const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| // dlclose() never unloads on Fuchsia. ZX-1728 upstream. |
| return std::vector<UnloadedModuleSnapshot>(); |
| } |
| |
| const ExceptionSnapshot* ProcessSnapshotFuchsia::Exception() const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| return exception_.get(); |
| } |
| |
| std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotFuchsia::MemoryMap() |
| const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| std::vector<const MemoryMapRegionSnapshot*> memory_map; |
| for (const auto& item : memory_map_) { |
| memory_map.push_back(item.get()); |
| } |
| return memory_map; |
| } |
| |
| std::vector<HandleSnapshot> ProcessSnapshotFuchsia::Handles() const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| return std::vector<HandleSnapshot>(); |
| } |
| |
| std::vector<const MemorySnapshot*> ProcessSnapshotFuchsia::ExtraMemory() const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| return std::vector<const MemorySnapshot*>(); |
| } |
| |
| const ProcessMemory* ProcessSnapshotFuchsia::Memory() const { |
| INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
| return process_reader_.Memory(); |
| } |
| |
| void ProcessSnapshotFuchsia::InitializeThreads() { |
| const std::vector<ProcessReaderFuchsia::Thread>& process_reader_threads = |
| process_reader_.Threads(); |
| for (const ProcessReaderFuchsia::Thread& process_reader_thread : |
| process_reader_threads) { |
| auto thread = std::make_unique<internal::ThreadSnapshotFuchsia>(); |
| 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<internal::ModuleSnapshotElf>(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 |