[ios] Bring up first draft process and module snapshot.

Gather most of the necessary information for the module snapshot.

Note that:
 - The 'capture' portion of this CL will be moved out of the snapshot
   interface and into a separate in-process dump to disk location.
 - All of the pointer dereferences need to be wrapped in vm_read.
 - The read-fast-and-dump logic in module_snapshot may end up in a
   different file completely, but until we pick a
   serialization/deserialization method, keep it in module_snapshot_ios.

Change-Id: Ie80c739c167634520d13ec920a29a80116aa3bfe
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2079196
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
This commit is contained in:
Justin Cohen 2020-03-04 15:19:46 -05:00 committed by Commit Bot
parent 2091241971
commit b109e4ce38
10 changed files with 676 additions and 13 deletions

View File

@ -36,12 +36,12 @@ config("disable_ubsan") {
if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) { if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
test("crashpad_tests") { test("crashpad_tests") {
deps = [ deps = [
"client:client_test",
"test:gmock_main", "test:gmock_main",
"test:test_test", "test:test_test",
] ]
if (!crashpad_is_ios) { if (!crashpad_is_ios) {
deps += [ deps += [
"client:client_test",
"handler:handler_test", "handler:handler_test",
"minidump:minidump_test", "minidump:minidump_test",
"snapshot:snapshot_test", "snapshot:snapshot_test",
@ -138,9 +138,7 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
} }
package("crashpad_database_util") { package("crashpad_database_util") {
deps = [ deps = [ "tools:crashpad_database_util" ]
"tools:crashpad_database_util",
]
binaries = [ binaries = [
{ {
@ -156,9 +154,6 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
"client:client_test", "client:client_test",
"test:gmock_main", "test:gmock_main",
] ]
if (crashpad_is_ios) {
deps -= [ "client:client_test" ]
}
} }
test("crashpad_handler_test") { test("crashpad_handler_test") {
@ -212,8 +207,6 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
if (crashpad_is_ios) { if (crashpad_is_ios) {
group("ios_xcuitests") { group("ios_xcuitests") {
testonly = true testonly = true
deps = [ deps = [ "test/ios:all_tests" ]
"test/ios:all_tests",
]
} }
} }

View File

@ -93,6 +93,11 @@ static_library("client") {
cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union
} }
# TODO(justincohen): Temporary dependency to bring up the iOS client.
if (crashpad_is_ios) {
deps += [ "../snapshot" ]
}
if (crashpad_is_linux || crashpad_is_android) { if (crashpad_is_linux || crashpad_is_android) {
deps += [ "../third_party/lss" ] deps += [ "../third_party/lss" ]
} }
@ -126,6 +131,17 @@ source_set("client_test") {
sources += [ "crashpad_client_win_test.cc" ] sources += [ "crashpad_client_win_test.cc" ]
} }
if (crashpad_is_ios) {
sources += [ "crashpad_client_ios_test.cc" ]
sources -= [
"annotation_list_test.cc",
"annotation_test.cc",
"crash_report_database_test.cc",
"prune_crash_reports_test.cc",
"settings_test.cc",
]
}
if (crashpad_is_linux || crashpad_is_android) { if (crashpad_is_linux || crashpad_is_android) {
sources += [ "crashpad_client_linux_test.cc" ] sources += [ "crashpad_client_linux_test.cc" ]
} }

View File

@ -436,6 +436,13 @@ class CrashpadClient {
//! TODO(justincohen): This method will need to take database, metrics_dir, //! TODO(justincohen): This method will need to take database, metrics_dir,
//! url and annotations eventually. //! url and annotations eventually.
bool StartCrashpadInProcessHandler(); bool StartCrashpadInProcessHandler();
// TODO(justincohen): This method is purely for bringing up iOS interfaces.
//! \brief Requests that the handler capture a dump even though there hasn't
//! been a crash.
//!
//! A handler must have already been installed before calling this method.
static void DumpWithoutCrash();
#endif #endif
#if defined(OS_MACOSX) || DOXYGEN #if defined(OS_MACOSX) || DOXYGEN

View File

@ -19,6 +19,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "client/client_argv_handling.h" #include "client/client_argv_handling.h"
#include "snapshot/ios/process_snapshot_ios.h"
#include "util/posix/signals.h" #include "util/posix/signals.h"
namespace crashpad { namespace crashpad {
@ -39,13 +40,21 @@ class SignalHandler {
HandleSignal, 0, &old_actions_, unhandled_signals); HandleSignal, 0, &old_actions_, unhandled_signals);
} }
void HandleCrash(int signo, siginfo_t* siginfo, void* context) {
// TODO(justincohen): This is incomplete.
ProcessSnapshotIOS process_snapshot;
process_snapshot.Initialize();
}
private: private:
SignalHandler() = default; SignalHandler() = default;
// The base implementation for all signal handlers, suitable for calling // The base implementation for all signal handlers, suitable for calling
// directly to simulate signal delivery. // directly to simulate signal delivery.
void HandleCrash(int signo, siginfo_t* siginfo, void* context) { void HandleCrashAndReraiseSignal(int signo,
// Do Something. siginfo_t* siginfo,
void* context) {
HandleCrash(signo, siginfo, context);
// Always call system handler. // Always call system handler.
Signals::RestoreHandlerAndReraiseSignalOnReturn( Signals::RestoreHandlerAndReraiseSignalOnReturn(
@ -54,7 +63,7 @@ class SignalHandler {
// The signal handler installed at OS-level. // The signal handler installed at OS-level.
static void HandleSignal(int signo, siginfo_t* siginfo, void* context) { static void HandleSignal(int signo, siginfo_t* siginfo, void* context) {
Get()->HandleCrash(signo, siginfo, context); Get()->HandleCrashAndReraiseSignal(signo, siginfo, context);
} }
Signals::OldActions old_actions_ = {}; Signals::OldActions old_actions_ = {};
@ -72,4 +81,11 @@ bool CrashpadClient::StartCrashpadInProcessHandler() {
return SignalHandler::Get()->Install(nullptr); return SignalHandler::Get()->Install(nullptr);
} }
// static
void CrashpadClient::DumpWithoutCrash() {
DCHECK(SignalHandler::Get());
siginfo_t siginfo = {};
SignalHandler::Get()->HandleCrash(siginfo.si_signo, &siginfo, nullptr);
}
} // namespace crashpad } // namespace crashpad

View File

@ -0,0 +1,32 @@
// 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 "client/crashpad_client.h"
#include "gtest/gtest.h"
namespace crashpad {
namespace test {
namespace {
// TODO(justincohen): This is a placeholder.
TEST(CrashpadIOSClient, DumpWithoutCrash) {
crashpad::CrashpadClient client;
client.StartCrashpadInProcessHandler();
client.DumpWithoutCrash();
}
} // namespace
} // namespace test
} // namespace crashpad

View File

@ -108,6 +108,15 @@ static_library("snapshot") {
] ]
} }
if (crashpad_is_ios) {
sources += [
"ios/module_snapshot_ios.cc",
"ios/module_snapshot_ios.h",
"ios/process_snapshot_ios.cc",
"ios/process_snapshot_ios.h",
]
}
if (crashpad_is_linux || crashpad_is_android) { if (crashpad_is_linux || crashpad_is_android) {
set_sources_assignment_filter([]) set_sources_assignment_filter([])
sources += [ sources += [
@ -230,6 +239,10 @@ static_library("snapshot") {
"../util", "../util",
] ]
if (crashpad_is_ios) {
deps -= [ "../client" ]
}
if (crashpad_is_win) { if (crashpad_is_win) {
cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union
libs = [ "powrprof.lib" ] libs = [ "powrprof.lib" ]

View File

@ -0,0 +1,237 @@
// 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/module_snapshot_ios.h"
#include <mach-o/loader.h>
#include <mach/mach.h>
#include "base/files/file_path.h"
#include "base/mac/mach_logging.h"
#include "util/misc/from_pointer_cast.h"
#include "util/misc/uuid.h"
namespace crashpad {
namespace internal {
ModuleSnapshotIOS::ModuleSnapshotIOS()
: ModuleSnapshot(),
name_(),
address_(0),
size_(0),
timestamp_(0),
dylib_version_(0),
source_version_(0),
filetype_(0),
initialized_() {}
ModuleSnapshotIOS::~ModuleSnapshotIOS() {}
// static.
const dyld_all_image_infos* ModuleSnapshotIOS::DyldAllImageInfo() {
task_dyld_info_data_t dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
kern_return_t kr = task_info(mach_task_self(),
TASK_DYLD_INFO,
reinterpret_cast<task_info_t>(&dyld_info),
&count);
if (kr != KERN_SUCCESS) {
MACH_LOG(WARNING, kr) << "task_info";
return 0;
}
return reinterpret_cast<dyld_all_image_infos*>(dyld_info.all_image_info_addr);
}
bool ModuleSnapshotIOS::InitializeDyld(const dyld_all_image_infos* images) {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
name_ = images->dyldPath;
address_ = FromPointerCast<uint64_t>(images->dyldImageLoadAddress);
return FinishInitialization();
}
bool ModuleSnapshotIOS::Initialize(const dyld_image_info* image) {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
name_ = image->imageFilePath;
address_ = FromPointerCast<uint64_t>(image->imageLoadAddress);
timestamp_ = image->imageFileModDate;
return FinishInitialization();
}
bool ModuleSnapshotIOS::FinishInitialization() {
#ifndef ARCH_CPU_64_BITS
#error Only 64-bit Mach-O is supported
#endif
DCHECK(address_);
const mach_header_64* header =
reinterpret_cast<const mach_header_64*>(address_);
const load_command* command =
reinterpret_cast<const load_command*>(header + 1);
// Make sure that the basic load command structure doesnt overflow the
// space allotted for load commands, as well as iterating through ncmds.
for (uint32_t cmd_index = 0, cumulative_cmd_size = 0;
cmd_index <= header->ncmds && cumulative_cmd_size < header->sizeofcmds;
++cmd_index, cumulative_cmd_size += command->cmdsize) {
if (command->cmd == LC_SEGMENT_64) {
segment_command_64* segment =
reinterpret_cast<segment_command_64*>(&command);
if (strcmp(segment->segname, SEG_TEXT) == 0) {
size_ = segment->vmsize;
}
} else if (command->cmd == LC_ID_DYLIB) {
dylib_command* dylib = reinterpret_cast<dylib_command*>(&command);
dylib_version_ = dylib->dylib.current_version;
} else if (command->cmd == LC_SOURCE_VERSION) {
source_version_command* source_version =
reinterpret_cast<source_version_command*>(&command);
source_version_ = source_version->version;
} else if (command->cmd == LC_UUID) {
uuid_command* uuid = reinterpret_cast<uuid_command*>(&command);
uuid_.InitializeFromBytes(uuid->uuid);
}
command = reinterpret_cast<const load_command*>(
reinterpret_cast<const uint8_t*>(command + command->cmdsize));
// TODO(justincohen): Warn-able things:
// - Bad Mach-O magic (and give up trying to process the module)
// - Unrecognized Mach-O type
// - No SEG_TEXT
// - More than one SEG_TEXT
// - More than one LC_ID_DYLIB, LC_SOURCE_VERSION, or LC_UUID
// - No LC_ID_DYLIB in a dylib file
// - LC_ID_DYLIB in a non-dylib file
// And more optional:
// - Missing LC_UUID (although it leaves us with a big "?")
// - Missing LC_SOURCE_VERSION.
}
filetype_ = header->filetype;
INITIALIZATION_STATE_SET_VALID(initialized_);
return true;
}
std::string ModuleSnapshotIOS::Name() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return name_;
}
uint64_t ModuleSnapshotIOS::Address() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return address_;
}
uint64_t ModuleSnapshotIOS::Size() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return size_;
}
time_t ModuleSnapshotIOS::Timestamp() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return timestamp_;
}
void ModuleSnapshotIOS::FileVersion(uint16_t* version_0,
uint16_t* version_1,
uint16_t* version_2,
uint16_t* version_3) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
if (filetype_ == MH_DYLIB) {
*version_0 = (dylib_version_ & 0xffff0000) >> 16;
*version_1 = (dylib_version_ & 0x0000ff00) >> 8;
*version_2 = (dylib_version_ & 0x000000ff);
*version_3 = 0;
} else {
*version_0 = 0;
*version_1 = 0;
*version_2 = 0;
*version_3 = 0;
}
}
void ModuleSnapshotIOS::SourceVersion(uint16_t* version_0,
uint16_t* version_1,
uint16_t* version_2,
uint16_t* version_3) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
*version_0 = (source_version_ & 0xffff000000000000u) >> 48;
*version_1 = (source_version_ & 0x0000ffff00000000u) >> 32;
*version_2 = (source_version_ & 0x00000000ffff0000u) >> 16;
*version_3 = source_version_ & 0x000000000000ffffu;
}
ModuleSnapshot::ModuleType ModuleSnapshotIOS::GetModuleType() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
switch (filetype_) {
case MH_EXECUTE:
return kModuleTypeExecutable;
case MH_DYLIB:
return kModuleTypeSharedLibrary;
case MH_DYLINKER:
return kModuleTypeDynamicLoader;
case MH_BUNDLE:
return kModuleTypeLoadableModule;
default:
return kModuleTypeUnknown;
}
}
void ModuleSnapshotIOS::UUIDAndAge(crashpad::UUID* uuid, uint32_t* age) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
*uuid = uuid_;
*age = 0;
}
std::string ModuleSnapshotIOS::DebugFileName() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return base::FilePath(Name()).BaseName().value();
}
std::vector<uint8_t> ModuleSnapshotIOS::BuildID() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<uint8_t>();
}
std::vector<std::string> ModuleSnapshotIOS::AnnotationsVector() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<std::string>();
}
std::map<std::string, std::string> ModuleSnapshotIOS::AnnotationsSimpleMap()
const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::map<std::string, std::string>();
}
std::vector<AnnotationSnapshot> ModuleSnapshotIOS::AnnotationObjects() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<AnnotationSnapshot>();
}
std::set<CheckedRange<uint64_t>> ModuleSnapshotIOS::ExtraMemoryRanges() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::set<CheckedRange<uint64_t>>();
}
std::vector<const UserMinidumpStream*>
ModuleSnapshotIOS::CustomMinidumpStreams() const {
return std::vector<const UserMinidumpStream*>();
}
} // namespace internal
} // namespace crashpad

View File

@ -0,0 +1,112 @@
// 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.
#ifndef CRASHPAD_SNAPSHOT_IOS_MODULE_SNAPSHOT_IOS_H_
#define CRASHPAD_SNAPSHOT_IOS_MODULE_SNAPSHOT_IOS_H_
#include <mach-o/dyld_images.h>
#include <stdint.h>
#include <sys/types.h>
#include <map>
#include <string>
#include <vector>
#include "base/macros.h"
#include "client/crashpad_info.h"
#include "snapshot/crashpad_info_client_options.h"
#include "snapshot/module_snapshot.h"
#include "util/misc/initialization_state_dcheck.h"
namespace crashpad {
namespace internal {
//! \brief A ModuleSnapshot of a code module (binary image) loaded into a
//! running (or crashed) process on an iOS system.
class ModuleSnapshotIOS final : public ModuleSnapshot {
public:
ModuleSnapshotIOS();
~ModuleSnapshotIOS() override;
// TODO(justincohen): This function is temporary, and will be broken into two
// parts. One to do an in-process dump of all the relevant information, and
// two to initialize the snapshot after the in-process dump is loaded.
//! \brief Initializes the object.
//!
//! \param[in] image The mach-o image to be loaded.
//!
//! \return `true` if the snapshot could be created.
bool Initialize(const dyld_image_info* image);
// TODO(justincohen): This function is temporary, and will be broken into two
// parts. One to do an in-process dump of all the relevant information, and
// two to initialize the snapshot after the in-process dump is loaded.
//! \brief Initializes the object specifically for the dyld module.
//!
//! \param[in] images The structure containing the necessary dyld information.
//!
//! \return `true` if the snapshot could be created.
bool InitializeDyld(const dyld_all_image_infos* images);
//! \brief Returns options from the modules CrashpadInfo structure.
//!
//! \param[out] options Options set in the modules CrashpadInfo structure.
void GetCrashpadOptions(CrashpadInfoClientOptions* options);
static const dyld_all_image_infos* DyldAllImageInfo();
// ModuleSnapshot:
std::string Name() const override;
uint64_t Address() const override;
uint64_t Size() const override;
time_t Timestamp() const override;
void FileVersion(uint16_t* version_0,
uint16_t* version_1,
uint16_t* version_2,
uint16_t* version_3) const override;
void SourceVersion(uint16_t* version_0,
uint16_t* version_1,
uint16_t* version_2,
uint16_t* version_3) const override;
ModuleType GetModuleType() const override;
void UUIDAndAge(UUID* uuid, uint32_t* age) const override;
std::string DebugFileName() const override;
std::vector<uint8_t> BuildID() const override;
std::vector<std::string> AnnotationsVector() const override;
std::map<std::string, std::string> AnnotationsSimpleMap() const override;
std::vector<AnnotationSnapshot> AnnotationObjects() const override;
std::set<CheckedRange<uint64_t>> ExtraMemoryRanges() const override;
std::vector<const UserMinidumpStream*> CustomMinidumpStreams() const override;
private:
// Gather the the module information based off of a mach_header_64 |address_|.
bool FinishInitialization();
std::string name_;
uint64_t address_;
uint64_t size_;
time_t timestamp_;
uint32_t dylib_version_;
uint64_t source_version_;
uint32_t filetype_;
UUID uuid_;
InitializationStateDcheck initialized_;
DISALLOW_COPY_AND_ASSIGN(ModuleSnapshotIOS);
};
} // namespace internal
} // namespace crashpad
#endif // CRASHPAD_SNAPSHOT_IOS_MODULE_SNAPSHOT_IOS_H_

View File

@ -0,0 +1,162 @@
// 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.h"
#include <mach-o/loader.h>
#include <mach/mach.h>
#include <utility>
#include "base/logging.h"
#include "base/mac/mach_logging.h"
namespace crashpad {
ProcessSnapshotIOS::ProcessSnapshotIOS()
: ProcessSnapshot(),
modules_(),
report_id_(),
client_id_(),
annotations_simple_map_(),
snapshot_time_(),
initialized_() {}
ProcessSnapshotIOS::~ProcessSnapshotIOS() {}
bool ProcessSnapshotIOS::Initialize() {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
if (gettimeofday(&snapshot_time_, nullptr) != 0) {
PLOG(ERROR) << "gettimeofday";
return false;
}
InitializeModules();
INITIALIZATION_STATE_SET_VALID(initialized_);
return true;
}
pid_t ProcessSnapshotIOS::ProcessID() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return getpid();
}
pid_t ProcessSnapshotIOS::ParentProcessID() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return 0;
}
void ProcessSnapshotIOS::SnapshotTime(timeval* snapshot_time) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
*snapshot_time = snapshot_time_;
}
void ProcessSnapshotIOS::ProcessStartTime(timeval* start_time) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
}
void ProcessSnapshotIOS::ProcessCPUTimes(timeval* user_time,
timeval* system_time) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
}
void ProcessSnapshotIOS::ReportID(UUID* report_id) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
*report_id = report_id_;
}
void ProcessSnapshotIOS::ClientID(UUID* client_id) const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
*client_id = client_id_;
}
const std::map<std::string, std::string>&
ProcessSnapshotIOS::AnnotationsSimpleMap() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return annotations_simple_map_;
}
const SystemSnapshot* ProcessSnapshotIOS::System() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return nullptr;
}
std::vector<const ThreadSnapshot*> ProcessSnapshotIOS::Threads() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<const ThreadSnapshot*>();
}
std::vector<const ModuleSnapshot*> ProcessSnapshotIOS::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> ProcessSnapshotIOS::UnloadedModules()
const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<UnloadedModuleSnapshot>();
}
const ExceptionSnapshot* ProcessSnapshotIOS::Exception() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return nullptr;
}
std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotIOS::MemoryMap()
const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<const MemoryMapRegionSnapshot*>();
}
std::vector<HandleSnapshot> ProcessSnapshotIOS::Handles() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<HandleSnapshot>();
}
std::vector<const MemorySnapshot*> ProcessSnapshotIOS::ExtraMemory() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<const MemorySnapshot*>();
}
const ProcessMemory* ProcessSnapshotIOS::Memory() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return nullptr;
}
void ProcessSnapshotIOS::InitializeModules() {
const dyld_all_image_infos* image_infos =
internal::ModuleSnapshotIOS::DyldAllImageInfo();
uint32_t image_count = image_infos->infoArrayCount;
const dyld_image_info* image_array = image_infos->infoArray;
for (uint32_t image_index = 0; image_index < image_count; ++image_index) {
const dyld_image_info* image = &image_array[image_index];
auto module = std::make_unique<internal::ModuleSnapshotIOS>();
if (module->Initialize(image)) {
modules_.push_back(std::move(module));
}
}
auto module = std::make_unique<internal::ModuleSnapshotIOS>();
if (module->InitializeDyld(image_infos)) {
modules_.push_back(std::move(module));
}
}
} // namespace crashpad

View File

@ -0,0 +1,75 @@
// 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.
#ifndef CRASHPAD_SNAPSHOT_IOS_PROCESS_SNAPSHOT_IOS_H_
#define CRASHPAD_SNAPSHOT_IOS_PROCESS_SNAPSHOT_IOS_H_
#include <vector>
#include "snapshot/ios/module_snapshot_ios.h"
#include "snapshot/process_snapshot.h"
#include "snapshot/unloaded_module_snapshot.h"
namespace crashpad {
//! \brief A ProcessSnapshot of a running (or crashed) process running on a
//! iphoneOS system.
class ProcessSnapshotIOS final : public ProcessSnapshot {
public:
ProcessSnapshotIOS();
~ProcessSnapshotIOS() override;
//! \brief Initializes the object.
//!
//! \return `true` if the snapshot could be created, `false` otherwise with
//! an appropriate message logged.
bool Initialize();
// ProcessSnapshot:
pid_t ProcessID() const override;
pid_t ParentProcessID() const override;
void SnapshotTime(timeval* snapshot_time) const override;
void ProcessStartTime(timeval* start_time) const override;
void ProcessCPUTimes(timeval* user_time, timeval* system_time) const override;
void ReportID(UUID* report_id) const override;
void ClientID(UUID* client_id) const override;
const std::map<std::string, std::string>& AnnotationsSimpleMap()
const override;
const SystemSnapshot* System() const override;
std::vector<const ThreadSnapshot*> Threads() const override;
std::vector<const ModuleSnapshot*> Modules() const override;
std::vector<UnloadedModuleSnapshot> UnloadedModules() const override;
const ExceptionSnapshot* Exception() const override;
std::vector<const MemoryMapRegionSnapshot*> MemoryMap() const override;
std::vector<HandleSnapshot> Handles() const override;
std::vector<const MemorySnapshot*> ExtraMemory() const override;
const ProcessMemory* Memory() const override;
private:
// Initializes modules_ on behalf of Initialize().
void InitializeModules();
std::vector<std::unique_ptr<internal::ModuleSnapshotIOS>> modules_;
UUID report_id_;
UUID client_id_;
std::map<std::string, std::string> annotations_simple_map_;
timeval snapshot_time_;
InitializationStateDcheck initialized_;
DISALLOW_COPY_AND_ASSIGN(ProcessSnapshotIOS);
};
} // namespace crashpad
#endif // CRASHPAD_SNAPSHOT_IOS_PROCESS_SNAPSHOT_IOS_H_