mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
[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:
parent
2091241971
commit
b109e4ce38
13
BUILD.gn
13
BUILD.gn
@ -36,12 +36,12 @@ config("disable_ubsan") {
|
||||
if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
|
||||
test("crashpad_tests") {
|
||||
deps = [
|
||||
"client:client_test",
|
||||
"test:gmock_main",
|
||||
"test:test_test",
|
||||
]
|
||||
if (!crashpad_is_ios) {
|
||||
deps += [
|
||||
"client:client_test",
|
||||
"handler:handler_test",
|
||||
"minidump:minidump_test",
|
||||
"snapshot:snapshot_test",
|
||||
@ -138,9 +138,7 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
|
||||
}
|
||||
|
||||
package("crashpad_database_util") {
|
||||
deps = [
|
||||
"tools:crashpad_database_util",
|
||||
]
|
||||
deps = [ "tools:crashpad_database_util" ]
|
||||
|
||||
binaries = [
|
||||
{
|
||||
@ -156,9 +154,6 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
|
||||
"client:client_test",
|
||||
"test:gmock_main",
|
||||
]
|
||||
if (crashpad_is_ios) {
|
||||
deps -= [ "client:client_test" ]
|
||||
}
|
||||
}
|
||||
|
||||
test("crashpad_handler_test") {
|
||||
@ -212,8 +207,6 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
|
||||
if (crashpad_is_ios) {
|
||||
group("ios_xcuitests") {
|
||||
testonly = true
|
||||
deps = [
|
||||
"test/ios:all_tests",
|
||||
]
|
||||
deps = [ "test/ios:all_tests" ]
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,11 @@ static_library("client") {
|
||||
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) {
|
||||
deps += [ "../third_party/lss" ]
|
||||
}
|
||||
@ -126,6 +131,17 @@ source_set("client_test") {
|
||||
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) {
|
||||
sources += [ "crashpad_client_linux_test.cc" ]
|
||||
}
|
||||
|
@ -436,6 +436,13 @@ class CrashpadClient {
|
||||
//! TODO(justincohen): This method will need to take database, metrics_dir,
|
||||
//! url and annotations eventually.
|
||||
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
|
||||
|
||||
#if defined(OS_MACOSX) || DOXYGEN
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "client/client_argv_handling.h"
|
||||
#include "snapshot/ios/process_snapshot_ios.h"
|
||||
#include "util/posix/signals.h"
|
||||
|
||||
namespace crashpad {
|
||||
@ -39,13 +40,21 @@ class SignalHandler {
|
||||
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:
|
||||
SignalHandler() = default;
|
||||
|
||||
// The base implementation for all signal handlers, suitable for calling
|
||||
// directly to simulate signal delivery.
|
||||
void HandleCrash(int signo, siginfo_t* siginfo, void* context) {
|
||||
// Do Something.
|
||||
void HandleCrashAndReraiseSignal(int signo,
|
||||
siginfo_t* siginfo,
|
||||
void* context) {
|
||||
HandleCrash(signo, siginfo, context);
|
||||
|
||||
// Always call system handler.
|
||||
Signals::RestoreHandlerAndReraiseSignalOnReturn(
|
||||
@ -54,7 +63,7 @@ class SignalHandler {
|
||||
|
||||
// The signal handler installed at OS-level.
|
||||
static void HandleSignal(int signo, siginfo_t* siginfo, void* context) {
|
||||
Get()->HandleCrash(signo, siginfo, context);
|
||||
Get()->HandleCrashAndReraiseSignal(signo, siginfo, context);
|
||||
}
|
||||
|
||||
Signals::OldActions old_actions_ = {};
|
||||
@ -72,4 +81,11 @@ bool CrashpadClient::StartCrashpadInProcessHandler() {
|
||||
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
|
||||
|
32
client/crashpad_client_ios_test.cc
Normal file
32
client/crashpad_client_ios_test.cc
Normal 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
|
@ -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) {
|
||||
set_sources_assignment_filter([])
|
||||
sources += [
|
||||
@ -230,6 +239,10 @@ static_library("snapshot") {
|
||||
"../util",
|
||||
]
|
||||
|
||||
if (crashpad_is_ios) {
|
||||
deps -= [ "../client" ]
|
||||
}
|
||||
|
||||
if (crashpad_is_win) {
|
||||
cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union
|
||||
libs = [ "powrprof.lib" ]
|
||||
|
237
snapshot/ios/module_snapshot_ios.cc
Normal file
237
snapshot/ios/module_snapshot_ios.cc
Normal 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 doesn’t 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
|
112
snapshot/ios/module_snapshot_ios.h
Normal file
112
snapshot/ios/module_snapshot_ios.h
Normal 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 module’s CrashpadInfo structure.
|
||||
//!
|
||||
//! \param[out] options Options set in the module’s 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_
|
162
snapshot/ios/process_snapshot_ios.cc
Normal file
162
snapshot/ios/process_snapshot_ios.cc
Normal 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
|
75
snapshot/ios/process_snapshot_ios.h
Normal file
75
snapshot/ios/process_snapshot_ios.h
Normal 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_
|
Loading…
x
Reference in New Issue
Block a user