mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 22:26:06 +00:00
[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:
parent
d9c1ca1216
commit
faae6470cf
@ -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);
|
||||
}
|
||||
|
@ -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",
|
||||
|
122
snapshot/ios/exception_snapshot_ios.cc
Normal file
122
snapshot/ios/exception_snapshot_ios.cc
Normal 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
|
79
snapshot/ios/exception_snapshot_ios.h
Normal file
79
snapshot/ios/exception_snapshot_ios.h
Normal 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_
|
@ -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()
|
||||
|
@ -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_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user