mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-29 00:00:08 +08:00
d4bdb997a6
The iOS crashpad client was mistakenly setting the process annotations (typically things like version and product name) when converting the intermediate dump into a minidump. This is incorrect, as those annotations are determined at intermediate dump creation time. Instead, correctly write those annotations during intermediate dump creation. Passing extra annotations during intermediate dump to minidump is still supported. Bug: crashpad: 31 Change-Id: Ic5e29debdc123011d130f75a48345071575466d9 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3266127 Commit-Queue: Justin Cohen <justincohen@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org>
289 lines
9.4 KiB
C++
289 lines
9.4 KiB
C++
// Copyright 2020 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/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::Initialize(
|
|
const base::FilePath& dump_path,
|
|
const std::map<std::string, std::string>& annotations) {
|
|
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
|
|
|
annotations_simple_map_ = annotations;
|
|
|
|
if (!reader_.Initialize(dump_path)) {
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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
|