mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
6278690abe
sed -i '' -E -e 's/Copyright (.+) The Crashpad Authors\. All rights reserved\.$/Copyright \1 The Crashpad Authors/' $(git grep -El 'Copyright (.+) The Crashpad Authors\. All rights reserved\.$') Bug: chromium:1098010 Change-Id: I8d6138469ddbe3d281a5d83f64cf918ec2491611 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3878262 Reviewed-by: Joshua Peraza <jperaza@chromium.org> Commit-Queue: Mark Mentovai <mark@chromium.org>
314 lines
10 KiB
C++
314 lines
10 KiB
C++
// Copyright 2020 The Crashpad Authors
|
|
//
|
|
// 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/ios/process_snapshot_ios_intermediate_dump.h"
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include "base/logging.h"
|
|
#include "snapshot/ios/intermediate_dump_reader_util.h"
|
|
#include "util/ios/ios_intermediate_dump_data.h"
|
|
#include "util/ios/ios_intermediate_dump_list.h"
|
|
#include "util/ios/ios_intermediate_dump_map.h"
|
|
|
|
namespace {
|
|
|
|
void MachTimeValueToTimeval(const time_value& mach, timeval* tv) {
|
|
tv->tv_sec = mach.seconds;
|
|
tv->tv_usec = mach.microseconds;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace crashpad {
|
|
namespace internal {
|
|
|
|
using Key = internal::IntermediateDumpKey;
|
|
|
|
bool ProcessSnapshotIOSIntermediateDump::InitializeWithFilePath(
|
|
const base::FilePath& dump_path,
|
|
const std::map<std::string, std::string>& annotations) {
|
|
IOSIntermediateDumpFilePath dump_interface;
|
|
if (!dump_interface.Initialize(dump_path))
|
|
return false;
|
|
|
|
return InitializeWithFileInterface(dump_interface, annotations);
|
|
}
|
|
|
|
bool ProcessSnapshotIOSIntermediateDump::InitializeWithFileInterface(
|
|
const IOSIntermediateDumpInterface& dump_interface,
|
|
const std::map<std::string, std::string>& annotations) {
|
|
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
|
|
|
annotations_simple_map_ = annotations;
|
|
client_id_.InitializeToZero();
|
|
|
|
IOSIntermediateDumpReaderInitializeResult result =
|
|
reader_.Initialize(dump_interface);
|
|
if (result == IOSIntermediateDumpReaderInitializeResult::kFailure) {
|
|
return false;
|
|
} else if (result == IOSIntermediateDumpReaderInitializeResult::kIncomplete) {
|
|
annotations_simple_map_["crashpad_intermediate_dump_incomplete"] = "yes";
|
|
}
|
|
|
|
const IOSIntermediateDumpMap* root_map = reader_.RootMap();
|
|
if (root_map->empty())
|
|
return false;
|
|
|
|
uint8_t version;
|
|
if (!GetDataValueFromMap(root_map, Key::kVersion, &version) || version != 1) {
|
|
LOG(ERROR) << "Root map version mismatch";
|
|
return false;
|
|
}
|
|
|
|
const internal::IOSIntermediateDumpMap* process_info =
|
|
GetMapFromMap(root_map, Key::kProcessInfo);
|
|
if (!process_info) {
|
|
LOG(ERROR) << "Process snapshot missing required process info map.";
|
|
return false;
|
|
}
|
|
|
|
GetDataValueFromMap(process_info, Key::kPID, &p_pid_);
|
|
GetDataValueFromMap(process_info, Key::kParentPID, &e_ppid_);
|
|
GetDataValueFromMap(process_info, Key::kStartTime, &p_starttime_);
|
|
const IOSIntermediateDumpMap* basic_info =
|
|
process_info->GetAsMap(Key::kTaskBasicInfo);
|
|
if (basic_info) {
|
|
GetDataValueFromMap(basic_info, Key::kUserTime, &basic_info_user_time_);
|
|
GetDataValueFromMap(basic_info, Key::kSystemTime, &basic_info_system_time_);
|
|
}
|
|
|
|
const IOSIntermediateDumpMap* thread_times =
|
|
process_info->GetAsMap(Key::kTaskThreadTimes);
|
|
if (thread_times) {
|
|
GetDataValueFromMap(thread_times, Key::kUserTime, &thread_times_user_time_);
|
|
GetDataValueFromMap(
|
|
thread_times, Key::kSystemTime, &thread_times_system_time_);
|
|
}
|
|
|
|
GetDataValueFromMap(process_info, Key::kSnapshotTime, &snapshot_time_);
|
|
|
|
const IOSIntermediateDumpList* simple_map_dump =
|
|
process_info->GetAsList(IntermediateDumpKey::kAnnotationsSimpleMap);
|
|
if (simple_map_dump) {
|
|
for (auto& annotation : *simple_map_dump) {
|
|
const IOSIntermediateDumpData* name_dump =
|
|
annotation->GetAsData(IntermediateDumpKey::kAnnotationName);
|
|
const IOSIntermediateDumpData* value_dump =
|
|
annotation->GetAsData(IntermediateDumpKey::kAnnotationValue);
|
|
if (name_dump && value_dump) {
|
|
annotations_simple_map_.insert(
|
|
make_pair(name_dump->GetString(), value_dump->GetString()));
|
|
}
|
|
}
|
|
}
|
|
|
|
const IOSIntermediateDumpMap* system_info =
|
|
GetMapFromMap(root_map, Key::kSystemInfo);
|
|
if (!system_info) {
|
|
LOG(ERROR) << "Process snapshot missing required system info map.";
|
|
return false;
|
|
}
|
|
system_.Initialize(system_info);
|
|
|
|
// Threads
|
|
const IOSIntermediateDumpList* thread_list =
|
|
GetListFromMap(root_map, Key::kThreads);
|
|
if (thread_list) {
|
|
for (const auto& value : *thread_list) {
|
|
auto thread =
|
|
std::make_unique<internal::ThreadSnapshotIOSIntermediateDump>();
|
|
if (thread->Initialize(value.get())) {
|
|
threads_.push_back(std::move(thread));
|
|
}
|
|
}
|
|
}
|
|
|
|
const IOSIntermediateDumpList* module_list =
|
|
GetListFromMap(root_map, Key::kModules);
|
|
if (module_list) {
|
|
for (const auto& value : *module_list) {
|
|
auto module =
|
|
std::make_unique<internal::ModuleSnapshotIOSIntermediateDump>();
|
|
if (module->Initialize(value.get())) {
|
|
modules_.push_back(std::move(module));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Exceptions
|
|
const IOSIntermediateDumpMap* signal_exception =
|
|
root_map->GetAsMap(Key::kSignalException);
|
|
const IOSIntermediateDumpMap* mach_exception =
|
|
root_map->GetAsMap(Key::kMachException);
|
|
const IOSIntermediateDumpMap* ns_exception =
|
|
root_map->GetAsMap(Key::kNSException);
|
|
if (signal_exception) {
|
|
exception_.reset(new internal::ExceptionSnapshotIOSIntermediateDump());
|
|
if (!exception_->InitializeFromSignal(signal_exception)) {
|
|
LOG(ERROR) << "Process snapshot could not initialize signal exception.";
|
|
return false;
|
|
}
|
|
} else if (mach_exception) {
|
|
exception_.reset(new internal::ExceptionSnapshotIOSIntermediateDump());
|
|
if (!exception_->InitializeFromMachException(
|
|
mach_exception, GetListFromMap(root_map, Key::kThreads))) {
|
|
LOG(ERROR) << "Process snapshot could not initialize Mach exception.";
|
|
return false;
|
|
}
|
|
} else if (ns_exception) {
|
|
exception_.reset(new internal::ExceptionSnapshotIOSIntermediateDump());
|
|
if (!exception_->InitializeFromNSException(
|
|
ns_exception, GetListFromMap(root_map, Key::kThreads))) {
|
|
LOG(ERROR) << "Process snapshot could not initialize NSException.";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
INITIALIZATION_STATE_SET_VALID(initialized_);
|
|
return true;
|
|
}
|
|
|
|
void ProcessSnapshotIOSIntermediateDump::SetClientID(const UUID& client_id) {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
client_id_ = client_id;
|
|
}
|
|
|
|
void ProcessSnapshotIOSIntermediateDump::SetReportID(const UUID& report_id) {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
report_id_ = report_id;
|
|
}
|
|
|
|
pid_t ProcessSnapshotIOSIntermediateDump::ProcessID() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return p_pid_;
|
|
}
|
|
|
|
pid_t ProcessSnapshotIOSIntermediateDump::ParentProcessID() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return e_ppid_;
|
|
}
|
|
|
|
void ProcessSnapshotIOSIntermediateDump::SnapshotTime(
|
|
timeval* snapshot_time) const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
*snapshot_time = snapshot_time_;
|
|
}
|
|
|
|
void ProcessSnapshotIOSIntermediateDump::ProcessStartTime(
|
|
timeval* start_time) const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
*start_time = p_starttime_;
|
|
}
|
|
|
|
void ProcessSnapshotIOSIntermediateDump::ProcessCPUTimes(
|
|
timeval* user_time,
|
|
timeval* system_time) const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
|
|
// Calculate user and system time the same way the kernel does for
|
|
// getrusage(). See 10.15.0 xnu-6153.11.26/bsd/kern/kern_resource.c calcru().
|
|
timerclear(user_time);
|
|
timerclear(system_time);
|
|
|
|
MachTimeValueToTimeval(basic_info_user_time_, user_time);
|
|
MachTimeValueToTimeval(basic_info_system_time_, system_time);
|
|
|
|
timeval thread_user_time;
|
|
MachTimeValueToTimeval(thread_times_user_time_, &thread_user_time);
|
|
timeval thread_system_time;
|
|
MachTimeValueToTimeval(thread_times_system_time_, &thread_system_time);
|
|
|
|
timeradd(user_time, &thread_user_time, user_time);
|
|
timeradd(system_time, &thread_system_time, system_time);
|
|
}
|
|
|
|
void ProcessSnapshotIOSIntermediateDump::ReportID(UUID* report_id) const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
*report_id = report_id_;
|
|
}
|
|
|
|
void ProcessSnapshotIOSIntermediateDump::ClientID(UUID* client_id) const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
*client_id = client_id_;
|
|
}
|
|
|
|
const std::map<std::string, std::string>&
|
|
ProcessSnapshotIOSIntermediateDump::AnnotationsSimpleMap() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return annotations_simple_map_;
|
|
}
|
|
|
|
const SystemSnapshot* ProcessSnapshotIOSIntermediateDump::System() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return &system_;
|
|
}
|
|
|
|
std::vector<const ThreadSnapshot*> ProcessSnapshotIOSIntermediateDump::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*> ProcessSnapshotIOSIntermediateDump::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>
|
|
ProcessSnapshotIOSIntermediateDump::UnloadedModules() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return std::vector<UnloadedModuleSnapshot>();
|
|
}
|
|
|
|
const ExceptionSnapshot* ProcessSnapshotIOSIntermediateDump::Exception() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return exception_.get();
|
|
}
|
|
|
|
std::vector<const MemoryMapRegionSnapshot*>
|
|
ProcessSnapshotIOSIntermediateDump::MemoryMap() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return std::vector<const MemoryMapRegionSnapshot*>();
|
|
}
|
|
|
|
std::vector<HandleSnapshot> ProcessSnapshotIOSIntermediateDump::Handles()
|
|
const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return std::vector<HandleSnapshot>();
|
|
}
|
|
|
|
std::vector<const MemorySnapshot*>
|
|
ProcessSnapshotIOSIntermediateDump::ExtraMemory() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return std::vector<const MemorySnapshot*>();
|
|
}
|
|
|
|
const ProcessMemory* ProcessSnapshotIOSIntermediateDump::Memory() const {
|
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
|
return nullptr;
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace crashpad
|