mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 22:26:06 +00:00
This allows partial reading of the current process (e.g. modules or
CrashpadInfo), even though the memory map read (and so thread retrieval)
will fail if ProcessSnapshotFuchsia is used on the current process.
This is a follow up to
db6f51d3fc
which broke the CrashpadInfoClientOptions.* tests.
Bug: fuchsia:34598
Change-Id: Ifa17b4dbefcd198ff67ecea91f946cfa2439ca4c
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/1776936
Reviewed-by: Joshua Peraza <jperaza@chromium.org>
Commit-Queue: Scott Graham <scottmg@chromium.org>
238 lines
7.8 KiB
C++
238 lines
7.8 KiB
C++
// 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
|