[ios] Bring up first draft exceptions snapshot.

Gather most of the necessary information for the exceptions 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 thread_snapshot may end up in a
   different file completely, but until we pick a
   serialization/deserialization method, keep it as-is.

Bug: crashpad:31
Change-Id: Iae4af436cddabd2302689b76c8a4574eb8e48c0e
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2098744
Commit-Queue: Justin Cohen <justincohen@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Justin Cohen 2020-03-25 16:13:42 -04:00 committed by Commit Bot
parent d9c1ca1216
commit faae6470cf
6 changed files with 219 additions and 2 deletions

View File

@ -45,6 +45,8 @@ class SignalHandler {
// TODO(justincohen): This is incomplete.
ProcessSnapshotIOS process_snapshot;
process_snapshot.Initialize(system_data);
process_snapshot.SetException(siginfo,
reinterpret_cast<ucontext_t*>(context));
}
private:
@ -88,7 +90,6 @@ bool CrashpadClient::StartCrashpadInProcessHandler() {
// static
void CrashpadClient::DumpWithoutCrash() {
DCHECK(SignalHandler::Get());
siginfo_t siginfo = {};
SignalHandler::Get()->HandleCrash(siginfo.si_signo, &siginfo, nullptr);
}

View File

@ -113,6 +113,8 @@ static_library("snapshot") {
if (crashpad_is_ios) {
sources += [
"ios/exception_snapshot_ios.cc",
"ios/exception_snapshot_ios.h",
"ios/memory_snapshot_ios.cc",
"ios/memory_snapshot_ios.h",
"ios/module_snapshot_ios.cc",

View File

@ -0,0 +1,122 @@
// 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/exception_snapshot_ios.h"
#include "base/logging.h"
#include "base/mac/mach_logging.h"
#include "base/strings/stringprintf.h"
#include "snapshot/cpu_context.h"
#include "snapshot/mac/cpu_context_mac.h"
#include "util/misc/from_pointer_cast.h"
namespace crashpad {
namespace internal {
ExceptionSnapshotIOS::ExceptionSnapshotIOS()
: ExceptionSnapshot(),
context_(),
codes_(),
thread_id_(0),
exception_address_(0),
signal_number_(0),
signal_code_(0),
initialized_() {}
ExceptionSnapshotIOS::~ExceptionSnapshotIOS() {}
bool ExceptionSnapshotIOS::Initialize(const siginfo_t* siginfo,
const ucontext_t* context) {
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
if (!context)
return false;
mcontext_t mcontext = context->uc_mcontext;
#if defined(ARCH_CPU_X86_64)
context_.architecture = kCPUArchitectureX86_64;
context_.x86_64 = &context_x86_64_;
x86_debug_state64_t empty_debug_state;
InitializeCPUContextX86_64(&context_x86_64_,
THREAD_STATE_NONE,
nullptr,
0,
&mcontext->__ss,
&mcontext->__fs,
&empty_debug_state);
#elif defined(ARCH_CPU_ARM64)
context_.architecture = kCPUArchitectureARM64;
context_.arm64 = &context_arm64_;
InitializeCPUContextARM64(&context_arm64_, &mcontext->__ss, &mcontext->__ns);
#endif
// Thread ID.
thread_identifier_info identifier_info;
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
kern_return_t kr =
thread_info(mach_thread_self(),
THREAD_IDENTIFIER_INFO,
reinterpret_cast<thread_info_t>(&identifier_info),
&count);
if (kr != KERN_SUCCESS) {
MACH_LOG(ERROR, kr) << "thread_identifier_info";
} else {
thread_id_ = identifier_info.thread_id;
}
signal_number_ = siginfo->si_signo;
signal_code_ = siginfo->si_code;
exception_address_ = FromPointerCast<uintptr_t>(siginfo->si_addr);
INITIALIZATION_STATE_SET_VALID(initialized_);
return true;
}
const CPUContext* ExceptionSnapshotIOS::Context() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return &context_;
}
uint64_t ExceptionSnapshotIOS::ThreadID() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return thread_id_;
}
uint32_t ExceptionSnapshotIOS::Exception() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return signal_number_;
}
uint32_t ExceptionSnapshotIOS::ExceptionInfo() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return signal_code_;
}
uint64_t ExceptionSnapshotIOS::ExceptionAddress() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return exception_address_;
}
const std::vector<uint64_t>& ExceptionSnapshotIOS::Codes() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return codes_;
}
std::vector<const MemorySnapshot*> ExceptionSnapshotIOS::ExtraMemory() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<const MemorySnapshot*>();
}
} // namespace internal
} // namespace crashpad

View File

@ -0,0 +1,79 @@
// 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_EXCEPTION_SNAPSHOT_IOS_H_
#define CRASHPAD_SNAPSHOT_IOS_EXCEPTION_SNAPSHOT_IOS_H_
#include <mach/mach.h>
#include <stdint.h>
#include <vector>
#include "base/macros.h"
#include "build/build_config.h"
#include "snapshot/cpu_context.h"
#include "snapshot/exception_snapshot.h"
#include "util/mach/mach_extensions.h"
#include "util/misc/initialization_state_dcheck.h"
namespace crashpad {
namespace internal {
//! \brief An ExceptionSnapshot of an exception sustained by a running (or
//! crashed) process on an iOS system.
class ExceptionSnapshotIOS final : public ExceptionSnapshot {
public:
ExceptionSnapshotIOS();
~ExceptionSnapshotIOS() override;
//! \brief Initializes the object.
//!
//! \return `true` if the snapshot could be created, `false` otherwise with
//! an appropriate message logged.
bool Initialize(const siginfo_t* siginfo, const ucontext_t* context);
// ExceptionSnapshot:
const CPUContext* Context() const override;
uint64_t ThreadID() const override;
uint32_t Exception() const override;
uint32_t ExceptionInfo() const override;
uint64_t ExceptionAddress() const override;
const std::vector<uint64_t>& Codes() const override;
virtual std::vector<const MemorySnapshot*> ExtraMemory() const override;
private:
#if defined(ARCH_CPU_X86_64)
CPUContextX86_64 context_x86_64_;
#elif defined(ARCH_CPU_ARM64)
CPUContextARM64 context_arm64_;
#else
#error Port.
#endif // ARCH_CPU_X86_64
CPUContext context_;
std::vector<uint64_t> codes_;
uint64_t thread_id_;
uintptr_t exception_address_;
int signal_number_;
int signal_code_;
InitializationStateDcheck initialized_;
DISALLOW_COPY_AND_ASSIGN(ExceptionSnapshotIOS);
};
} // namespace internal
} // namespace crashpad
#endif // CRASHPAD_SNAPSHOT_IOS_EXCEPTION_SNAPSHOT_IOS_H_

View File

@ -42,6 +42,7 @@ ProcessSnapshotIOS::ProcessSnapshotIOS()
system_(),
threads_(),
modules_(),
exception_(),
report_id_(),
client_id_(),
annotations_simple_map_(),
@ -101,6 +102,15 @@ bool ProcessSnapshotIOS::Initialize(const IOSSystemDataCollector& system_data) {
return true;
}
void ProcessSnapshotIOS::SetException(const siginfo_t* siginfo,
const ucontext_t* context) {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
exception_.reset(new internal::ExceptionSnapshotIOS());
if (!exception_->Initialize(siginfo, context)) {
exception_.reset();
}
}
pid_t ProcessSnapshotIOS::ProcessID() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return kern_proc_info_.kp_proc.p_pid;
@ -189,7 +199,7 @@ std::vector<UnloadedModuleSnapshot> ProcessSnapshotIOS::UnloadedModules()
const ExceptionSnapshot* ProcessSnapshotIOS::Exception() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return nullptr;
return exception_.get();
}
std::vector<const MemoryMapRegionSnapshot*> ProcessSnapshotIOS::MemoryMap()

View File

@ -19,6 +19,7 @@
#include <vector>
#include "snapshot/ios/exception_snapshot_ios.h"
#include "snapshot/ios/module_snapshot_ios.h"
#include "snapshot/ios/system_snapshot_ios.h"
#include "snapshot/ios/thread_snapshot_ios.h"
@ -43,6 +44,7 @@ class ProcessSnapshotIOS final : public ProcessSnapshot {
//! an appropriate message logged.
bool Initialize(const IOSSystemDataCollector& system_data);
void SetException(const siginfo_t* siginfo, const ucontext_t* context);
//! \brief Sets the value to be returned by ClientID().
//!
//! On iOS, the client ID is under the control of the snapshot producer,
@ -92,6 +94,7 @@ class ProcessSnapshotIOS final : public ProcessSnapshot {
internal::SystemSnapshotIOS system_;
std::vector<std::unique_ptr<internal::ThreadSnapshotIOS>> threads_;
std::vector<std::unique_ptr<internal::ModuleSnapshotIOS>> modules_;
std::unique_ptr<internal::ExceptionSnapshotIOS> exception_;
UUID report_id_;
UUID client_id_;
std::map<std::string, std::string> annotations_simple_map_;