mirror of
https://github.com/chromium/crashpad.git
synced 2025-01-14 09:17:57 +08:00
mac: Crashpad for macOS on arm64, phase 1: build it
This gets all production code for Chrome building, excluding tests. There aren’t any guarantees that anything works yet. This is mostly a lot of CPU context shuffling. In contrast to macOS on x86, there’s no need to support 32-bit arm on macOS, because this new platform is 64-bit-only from its inception. Bug: crashpad:345 Change-Id: I187239b6a969005a3458af7fe30c44147a57f95f Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2285961 Reviewed-by: Robert Sesek <rsesek@chromium.org> Commit-Queue: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
b9c828ea83
commit
809939c9d1
@ -95,6 +95,15 @@ bool DeliverException(thread_t thread,
|
||||
state_count = cpu_context.tsh.count;
|
||||
break;
|
||||
#endif
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
case ARM_UNIFIED_THREAD_STATE:
|
||||
state = reinterpret_cast<ConstThreadState>(&cpu_context);
|
||||
state_count = ARM_UNIFIED_THREAD_STATE_COUNT;
|
||||
break;
|
||||
case ARM_THREAD_STATE64:
|
||||
state = reinterpret_cast<ConstThreadState>(&cpu_context.ts_64);
|
||||
state_count = cpu_context.ash.count;
|
||||
break;
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
#endif
|
||||
@ -187,6 +196,13 @@ void SimulateCrash(const NativeCPUContext& cpu_context) {
|
||||
implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64));
|
||||
DCHECK_EQ(implicit_cast<mach_msg_type_number_t>(cpu_context.tsh.count),
|
||||
x86_THREAD_STATE64_COUNT);
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
DCHECK_EQ(implicit_cast<thread_state_flavor_t>(cpu_context.ash.flavor),
|
||||
implicit_cast<thread_state_flavor_t>(ARM_THREAD_STATE64));
|
||||
DCHECK_EQ(implicit_cast<mach_msg_type_number_t>(cpu_context.ash.count),
|
||||
ARM_THREAD_STATE64_COUNT);
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
#endif
|
||||
|
||||
base::mac::ScopedMachSendRight thread(mach_thread_self());
|
||||
|
@ -56,12 +56,16 @@ void ExceptionSnapshotIOS::InitializeFromSignal(const siginfo_t* siginfo,
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
context_.architecture = kCPUArchitectureARM64;
|
||||
context_.arm64 = &context_arm64_;
|
||||
arm_debug_state64_t empty_debug_state = {};
|
||||
InitializeCPUContextARM64(&context_arm64_,
|
||||
THREAD_STATE_NONE,
|
||||
nullptr,
|
||||
0,
|
||||
&mcontext->__ss,
|
||||
&mcontext->__ns);
|
||||
&mcontext->__ns,
|
||||
&empty_debug_state);
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
#endif
|
||||
|
||||
// Thread ID.
|
||||
@ -127,10 +131,13 @@ void ExceptionSnapshotIOS::InitializeFromMachException(
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
arm_thread_state64_t thread_state;
|
||||
arm_neon_state64_t float_state;
|
||||
arm_debug_state64_t debug_state;
|
||||
mach_msg_type_number_t float_state_count = ARM_NEON_STATE64_COUNT;
|
||||
mach_msg_type_number_t thread_state_count = ARM_THREAD_STATE64_COUNT;
|
||||
mach_msg_type_number_t debug_state_count = ARM_DEBUG_STATE64_COUNT;
|
||||
const thread_state_flavor_t kThreadStateFlavor = ARM_THREAD_STATE64;
|
||||
const thread_state_flavor_t kFloatStateFlavor = ARM_NEON_STATE64;
|
||||
const thread_state_flavor_t kDebugStateFlavor = ARM_DEBUG_STATE64;
|
||||
#endif
|
||||
|
||||
kern_return_t kr =
|
||||
@ -150,7 +157,6 @@ void ExceptionSnapshotIOS::InitializeFromMachException(
|
||||
MACH_LOG(ERROR, kr) << "thread_get_state(" << kFloatStateFlavor << ")";
|
||||
}
|
||||
|
||||
#if defined(ARCH_CPU_X86_64)
|
||||
kr = thread_get_state(exception_thread,
|
||||
kDebugStateFlavor,
|
||||
reinterpret_cast<thread_state_t>(&debug_state),
|
||||
@ -158,7 +164,6 @@ void ExceptionSnapshotIOS::InitializeFromMachException(
|
||||
if (kr != KERN_SUCCESS) {
|
||||
MACH_LOG(ERROR, kr) << "thread_get_state(" << kDebugStateFlavor << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_CPU_X86_64)
|
||||
context_.architecture = kCPUArchitectureX86_64;
|
||||
@ -173,8 +178,15 @@ void ExceptionSnapshotIOS::InitializeFromMachException(
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
context_.architecture = kCPUArchitectureARM64;
|
||||
context_.arm64 = &context_arm64_;
|
||||
InitializeCPUContextARM64(
|
||||
&context_arm64_, flavor, state, state_count, &thread_state, &float_state);
|
||||
InitializeCPUContextARM64(&context_arm64_,
|
||||
flavor,
|
||||
state,
|
||||
state_count,
|
||||
&thread_state,
|
||||
&float_state,
|
||||
&debug_state);
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
#endif
|
||||
|
||||
// Thread ID.
|
||||
|
@ -26,6 +26,7 @@ const thread_state_flavor_t kDebugStateFlavor = x86_DEBUG_STATE64;
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
const thread_state_flavor_t kThreadStateFlavor = ARM_THREAD_STATE64;
|
||||
const thread_state_flavor_t kFloatStateFlavor = ARM_NEON_STATE64;
|
||||
const thread_state_flavor_t kDebugStateFlavor = ARM_DEBUG_STATE64;
|
||||
#endif
|
||||
|
||||
kern_return_t MachVMRegionRecurseDeepest(task_t task,
|
||||
@ -324,8 +325,10 @@ bool ThreadSnapshotIOS::Initialize(thread_t thread) {
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
arm_thread_state64_t thread_state;
|
||||
arm_neon_state64_t float_state;
|
||||
arm_debug_state64_t debug_state;
|
||||
mach_msg_type_number_t thread_state_count = ARM_THREAD_STATE64_COUNT;
|
||||
mach_msg_type_number_t float_state_count = ARM_NEON_STATE64_COUNT;
|
||||
mach_msg_type_number_t debug_state_count = ARM_DEBUG_STATE64_COUNT;
|
||||
#endif
|
||||
|
||||
kern_return_t kr =
|
||||
@ -345,7 +348,6 @@ bool ThreadSnapshotIOS::Initialize(thread_t thread) {
|
||||
MACH_LOG(ERROR, kr) << "thread_get_state(" << kFloatStateFlavor << ")";
|
||||
}
|
||||
|
||||
#if defined(ARCH_CPU_X86_64)
|
||||
kr = thread_get_state(thread,
|
||||
kDebugStateFlavor,
|
||||
reinterpret_cast<thread_state_t>(&debug_state),
|
||||
@ -353,7 +355,6 @@ bool ThreadSnapshotIOS::Initialize(thread_t thread) {
|
||||
if (kr != KERN_SUCCESS) {
|
||||
MACH_LOG(ERROR, kr) << "thread_get_state(" << kDebugStateFlavor << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
||||
kr = thread_info(thread,
|
||||
@ -388,7 +389,7 @@ bool ThreadSnapshotIOS::Initialize(thread_t thread) {
|
||||
#if defined(ARCH_CPU_X86_64)
|
||||
vm_address_t stack_pointer = thread_state.__rsp;
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
vm_address_t stack_pointer = thread_state.__sp;
|
||||
vm_address_t stack_pointer = arm_thread_state64_get_sp(thread_state);
|
||||
#endif
|
||||
stack_region_address =
|
||||
CalculateStackRegion(stack_pointer, &stack_region_size);
|
||||
@ -432,7 +433,10 @@ bool ThreadSnapshotIOS::Initialize(thread_t thread) {
|
||||
nullptr,
|
||||
0,
|
||||
&thread_state,
|
||||
&float_state);
|
||||
&float_state,
|
||||
&debug_state);
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
#endif
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
|
@ -437,20 +437,22 @@ void InitializeCPUContextX86_64(CPUContextX86_64* context,
|
||||
|
||||
} // namespace internal
|
||||
|
||||
#elif defined(ARCH_CPU_ARM_FAMILY)
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
|
||||
namespace {
|
||||
|
||||
void InitializeCPUContextARM64Thread(
|
||||
CPUContextARM64* context,
|
||||
const arm_thread_state64_t* arm_thread_state64) {
|
||||
// The structures of context->regs and arm_thread_state64->__x are laid out
|
||||
// identically for this copy, even though the members are organized
|
||||
// differently. Because of this difference, there can't be a static assert
|
||||
// similar to the one below for fpsimd.
|
||||
memcpy(context->regs, arm_thread_state64->__x, sizeof(context->regs));
|
||||
context->sp = arm_thread_state64->__sp;
|
||||
context->pc = arm_thread_state64->__pc;
|
||||
// The first 29 fields of context->regs is laid out identically to
|
||||
// arm_thread_state64->__x.
|
||||
memcpy(
|
||||
context->regs, arm_thread_state64->__x, sizeof(arm_thread_state64->__x));
|
||||
|
||||
context->regs[29] = arm_thread_state64_get_fp(*arm_thread_state64);
|
||||
context->regs[30] = arm_thread_state64_get_lr(*arm_thread_state64);
|
||||
context->sp = arm_thread_state64_get_sp(*arm_thread_state64);
|
||||
context->pc = arm_thread_state64_get_pc(*arm_thread_state64);
|
||||
context->spsr =
|
||||
static_cast<decltype(context->spsr)>(arm_thread_state64->__cpsr);
|
||||
}
|
||||
@ -464,6 +466,12 @@ void InitializeCPUContextARM64Neon(CPUContextARM64* context,
|
||||
context->fpcr = arm_neon_state64->__fpcr;
|
||||
}
|
||||
|
||||
void InitializeCPUContextARM64Debug(
|
||||
CPUContextARM64* context,
|
||||
const arm_debug_state64_t* arm_debug_state64) {
|
||||
// TODO(macos_arm64): Create a spot in CPUContextARM64 to keep this.
|
||||
}
|
||||
|
||||
thread_state_flavor_t InitializeCPUContextARM64Flavor(
|
||||
CPUContextARM64* context,
|
||||
thread_state_flavor_t flavor,
|
||||
@ -471,8 +479,8 @@ thread_state_flavor_t InitializeCPUContextARM64Flavor(
|
||||
mach_msg_type_number_t state_count) {
|
||||
mach_msg_type_number_t expected_state_count;
|
||||
switch (flavor) {
|
||||
case ARM_THREAD_STATE:
|
||||
expected_state_count = ARM_THREAD_STATE_COUNT;
|
||||
case ARM_UNIFIED_THREAD_STATE:
|
||||
expected_state_count = ARM_UNIFIED_THREAD_STATE_COUNT;
|
||||
break;
|
||||
case ARM_THREAD_STATE64:
|
||||
expected_state_count = ARM_THREAD_STATE64_COUNT;
|
||||
@ -480,6 +488,9 @@ thread_state_flavor_t InitializeCPUContextARM64Flavor(
|
||||
case ARM_NEON_STATE64:
|
||||
expected_state_count = ARM_NEON_STATE64_COUNT;
|
||||
break;
|
||||
case ARM_DEBUG_STATE64:
|
||||
expected_state_count = ARM_DEBUG_STATE64_COUNT;
|
||||
break;
|
||||
case THREAD_STATE_NONE: {
|
||||
// This may happen without error when called without exception-style
|
||||
// flavor data, or even from an exception handler when the exception
|
||||
@ -498,7 +509,7 @@ thread_state_flavor_t InitializeCPUContextARM64Flavor(
|
||||
}
|
||||
|
||||
switch (flavor) {
|
||||
case ARM_THREAD_STATE: {
|
||||
case ARM_UNIFIED_THREAD_STATE: {
|
||||
const arm_unified_thread_state_t* arm_thread_state =
|
||||
reinterpret_cast<const arm_unified_thread_state_t*>(state);
|
||||
if (arm_thread_state->ash.flavor != ARM_THREAD_STATE64) {
|
||||
@ -527,6 +538,13 @@ thread_state_flavor_t InitializeCPUContextARM64Flavor(
|
||||
return ARM_NEON_STATE64;
|
||||
}
|
||||
|
||||
case ARM_DEBUG_STATE64: {
|
||||
const arm_debug_state64_t* arm_debug_state =
|
||||
reinterpret_cast<const arm_debug_state64_t*>(state);
|
||||
InitializeCPUContextARM64Debug(context, arm_debug_state);
|
||||
return ARM_DEBUG_STATE64;
|
||||
}
|
||||
|
||||
case THREAD_STATE_NONE: {
|
||||
// This may happen without error when called without exception-style
|
||||
// flavor data, or even from an exception handler when the exception
|
||||
@ -550,7 +568,8 @@ void InitializeCPUContextARM64(CPUContextARM64* context,
|
||||
ConstThreadState state,
|
||||
mach_msg_type_number_t state_count,
|
||||
const arm_thread_state64_t* arm_thread_state64,
|
||||
const arm_neon_state64_t* arm_neon_state64) {
|
||||
const arm_neon_state64_t* arm_neon_state64,
|
||||
const arm_debug_state64_t* arm_debug_state64) {
|
||||
thread_state_flavor_t set_flavor = THREAD_STATE_NONE;
|
||||
if (flavor != THREAD_STATE_NONE) {
|
||||
set_flavor =
|
||||
@ -563,6 +582,9 @@ void InitializeCPUContextARM64(CPUContextARM64* context,
|
||||
if (set_flavor != ARM_NEON_STATE64) {
|
||||
InitializeCPUContextARM64Neon(context, arm_neon_state64);
|
||||
}
|
||||
if (set_flavor != ARM_DEBUG_STATE64) {
|
||||
InitializeCPUContextARM64Debug(context, arm_debug_state64);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -108,9 +108,9 @@ void InitializeCPUContextX86_64(CPUContextX86_64* context,
|
||||
const x86_float_state64_t* x86_float_state64,
|
||||
const x86_debug_state64_t* x86_debug_state64);
|
||||
|
||||
#elif defined(ARCH_CPU_ARM_FAMILY) || DOXYGEN
|
||||
#elif defined(ARCH_CPU_ARM64) || DOXYGEN
|
||||
//! \brief Initializes a CPUContextARM64 structure from native context
|
||||
//! structures on iOS.
|
||||
//! structures on macOS or iOS.
|
||||
//!
|
||||
//! \a flavor, \a state, and \a state_count may be supplied by exception
|
||||
//! handlers in order for the \a context parameter to be initialized by the
|
||||
@ -140,12 +140,14 @@ void InitializeCPUContextX86_64(CPUContextX86_64* context,
|
||||
//! \param[in] arm_thread_state64 The state of the thread’s integer registers.
|
||||
//! \param[in] arm_neon_state64 The state of the thread’s floating-point
|
||||
//! registers.
|
||||
//! \param[in] arm_debug_state64 The state of the thread’s debug registers.
|
||||
void InitializeCPUContextARM64(CPUContextARM64* context,
|
||||
thread_state_flavor_t flavor,
|
||||
ConstThreadState state,
|
||||
mach_msg_type_number_t state_count,
|
||||
const arm_thread_state64_t* arm_thread_state64,
|
||||
const arm_neon_state64_t* arm_neon_state64);
|
||||
const arm_neon_state64_t* arm_neon_state64,
|
||||
const arm_debug_state64_t* arm_debug_state64);
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
|
@ -187,6 +187,18 @@ bool ExceptionSnapshotMac::Initialize(ProcessReaderMac* process_reader,
|
||||
exception_code_0_ == (VM_PROT_READ | VM_PROT_EXECUTE))) {
|
||||
code_1_is_exception_address = false;
|
||||
}
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
context_.architecture = kCPUArchitectureARM64;
|
||||
context_.arm64 = &context_union_.arm64;
|
||||
InitializeCPUContextARM64(context_.arm64,
|
||||
flavor,
|
||||
state,
|
||||
state_count,
|
||||
&thread->thread_context,
|
||||
&thread->float_context,
|
||||
&thread->debug_context);
|
||||
#else
|
||||
#error Port to your architecture
|
||||
#endif
|
||||
|
||||
if (code_1_is_exception_address) {
|
||||
|
@ -79,12 +79,16 @@ class ExceptionSnapshotMac final : public ExceptionSnapshot {
|
||||
virtual std::vector<const MemorySnapshot*> ExtraMemory() const override;
|
||||
|
||||
private:
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
union {
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
CPUContextX86 x86;
|
||||
CPUContextX86_64 x86_64;
|
||||
} context_union_;
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
CPUContextARM64 arm64;
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
#endif
|
||||
} context_union_;
|
||||
CPUContext context_;
|
||||
std::vector<uint64_t> codes_;
|
||||
uint64_t thread_id_;
|
||||
|
@ -280,6 +280,15 @@ void ProcessReaderMac::InitializeThreads() {
|
||||
Is64Bit() ? x86_DEBUG_STATE64 : x86_DEBUG_STATE32;
|
||||
mach_msg_type_number_t debug_state_count =
|
||||
Is64Bit() ? x86_DEBUG_STATE64_COUNT : x86_DEBUG_STATE32_COUNT;
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
const thread_state_flavor_t kThreadStateFlavor = ARM_THREAD_STATE64;
|
||||
mach_msg_type_number_t thread_state_count = ARM_THREAD_STATE64_COUNT;
|
||||
|
||||
const thread_state_flavor_t kFloatStateFlavor = ARM_NEON_STATE64;
|
||||
mach_msg_type_number_t float_state_count = ARM_NEON_STATE64_COUNT;
|
||||
|
||||
const thread_state_flavor_t kDebugStateFlavor = ARM_DEBUG_STATE64;
|
||||
mach_msg_type_number_t debug_state_count = ARM_DEBUG_STATE64_COUNT;
|
||||
#endif
|
||||
|
||||
kr = thread_get_state(
|
||||
@ -366,6 +375,9 @@ void ProcessReaderMac::InitializeThreads() {
|
||||
mach_vm_address_t stack_pointer = Is64Bit()
|
||||
? thread.thread_context.t64.__rsp
|
||||
: thread.thread_context.t32.__esp;
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
mach_vm_address_t stack_pointer =
|
||||
arm_thread_state64_get_sp(thread.thread_context);
|
||||
#endif
|
||||
|
||||
thread.stack_region_address =
|
||||
|
@ -55,6 +55,10 @@ class ProcessReaderMac {
|
||||
x86_debug_state64_t d64;
|
||||
x86_debug_state32_t d32;
|
||||
};
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
using ThreadContext = arm_thread_state64_t;
|
||||
using FloatContext = arm_neon_state64_t;
|
||||
using DebugContext = arm_debug_state64_t;
|
||||
#endif
|
||||
|
||||
Thread();
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/scoped_clear_last_error.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "build/build_config.h"
|
||||
@ -157,6 +158,8 @@ CPUArchitecture SystemSnapshotMac::GetCPUArchitecture() const {
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
return process_reader_->Is64Bit() ? kCPUArchitectureX86_64
|
||||
: kCPUArchitectureX86;
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
return kCPUArchitectureARM64;
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
@ -174,6 +177,11 @@ uint32_t SystemSnapshotMac::CPURevision() const {
|
||||
uint8_t stepping = CastIntSysctlByName<uint8_t>("machdep.cpu.stepping", 0);
|
||||
|
||||
return (family << 16) | (model << 8) | stepping;
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
// TODO(macos_arm64): Verify that this is correct, and pack more information
|
||||
// if feasible. The Apple A12Z returns hw.cputype = 0x100000c and
|
||||
// hw.cpusubtype = 2.
|
||||
return CastIntSysctlByName<uint32_t>("hw.cputype", 0);
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
@ -189,6 +197,8 @@ std::string SystemSnapshotMac::CPUVendor() const {
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
return ReadStringSysctlByName("machdep.cpu.vendor");
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
return ReadStringSysctlByName("machdep.cpu.brand_string");
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
|
@ -75,6 +75,18 @@ bool ThreadSnapshotMac::Initialize(
|
||||
&process_reader_thread.float_context.f32,
|
||||
&process_reader_thread.debug_context.d32);
|
||||
}
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
context_.architecture = kCPUArchitectureARM64;
|
||||
context_.arm64 = &context_union_.arm64;
|
||||
InitializeCPUContextARM64(context_.arm64,
|
||||
THREAD_STATE_NONE,
|
||||
nullptr,
|
||||
0,
|
||||
&process_reader_thread.thread_context,
|
||||
&process_reader_thread.float_context,
|
||||
&process_reader_thread.debug_context);
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
#endif
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
|
@ -63,12 +63,16 @@ class ThreadSnapshotMac final : public ThreadSnapshot {
|
||||
std::vector<const MemorySnapshot*> ExtraMemory() const override;
|
||||
|
||||
private:
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
union {
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
CPUContextX86 x86;
|
||||
CPUContextX86_64 x86_64;
|
||||
} context_union_;
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
CPUContextARM64 arm64;
|
||||
#else
|
||||
#error Port to your CPU architecture
|
||||
#endif
|
||||
} context_union_;
|
||||
CPUContext context_;
|
||||
MemorySnapshotGeneric stack_;
|
||||
uint64_t thread_id_;
|
||||
|
@ -91,6 +91,8 @@ NSString* UserAgentString() {
|
||||
NSString* arch = @"i386";
|
||||
#elif defined(ARCH_CPU_X86_64)
|
||||
NSString* arch = @"x86_64";
|
||||
#elif defined(ARCH_CPU_ARM64)
|
||||
NSString* arch = @"arm64";
|
||||
#else
|
||||
#error Port
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user