Bug 1658375 - add support for arm64 macOS to profiler sampling and unwinding; r=mstange

The registers referenced in this patch and the assembly have been tested to
compile; the code changes have not been tested to actually work.

Differential Revision: https://phabricator.services.mozilla.com/D86612
This commit is contained in:
Nathan Froyd 2020-08-11 14:09:20 +00:00
parent 7951ffdf2e
commit 3c32012822
2 changed files with 74 additions and 8 deletions

View File

@ -106,22 +106,43 @@ void Sampler::SuspendAndSampleAndResumeThread(
// what we do here, or risk deadlock. See the corresponding comment in
// platform-linux-android.cpp for details.
#if defined(__x86_64__)
thread_state_flavor_t flavor = x86_THREAD_STATE64;
x86_thread_state64_t state;
mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
#if __DARWIN_UNIX03
# define REGISTER_FIELD(name) __r##name
# if __DARWIN_UNIX03
# define REGISTER_FIELD(name) __r##name
# else
# define REGISTER_FIELD(name) r##name
# endif // __DARWIN_UNIX03
#elif defined(__aarch64__)
thread_state_flavor_t flavor = ARM_THREAD_STATE64;
arm_thread_state64_t state;
mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT;
# if __DARWIN_UNIX03
# define REGISTER_FIELD(name) __##name
# else
# define REGISTER_FIELD(name) name
# endif // __DARWIN_UNIX03
#else
# define REGISTER_FIELD(name) r##name
#endif // __DARWIN_UNIX03
# error "unknown architecture"
#endif
if (thread_get_state(samplee_thread, flavor,
reinterpret_cast<natural_t*>(&state),
&count) == KERN_SUCCESS) {
Registers regs;
#if defined(__x86_64__)
regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
#elif defined(__aarch64__)
regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(pc));
regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(fp));
#else
# error "unknown architecture"
#endif
regs.mLR = 0;
aProcessRegs(regs, aNow);
@ -183,6 +204,7 @@ static void PlatformInit(PSLockRef aLock) {}
#if defined(HAVE_NATIVE_UNWIND)
void Registers::SyncPopulate() {
#if defined(__x86_64__)
asm(
// Compute caller's %rsp by adding to %rbp:
// 8 bytes for previous %rbp, 8 bytes for return address
@ -190,6 +212,17 @@ void Registers::SyncPopulate() {
// Dereference %rbp to get previous %rbp
"movq (%%rbp), %1\n\t"
: "=r"(mSP), "=r"(mFP));
#elif defined(__aarch64__)
asm(
// Compute caller's sp by adding to fp:
// 8 bytes for previous fp, 8 bytes for return address
"add %0, x29, #0x10\n\t"
// Dereference fp to get previous fp
"ldr %1, [x29]\n\t"
: "=r"(mSP), "=r"(mFP));
#else
# error "unknown architecture"
#endif
mPC = reinterpret_cast<Address>(
__builtin_extract_return_addr(__builtin_return_address(0)));
mLR = 0;

View File

@ -101,22 +101,43 @@ void Sampler::SuspendAndSampleAndResumeThread(
// what we do here, or risk deadlock. See the corresponding comment in
// platform-linux-android.cpp for details.
#if defined(__x86_64__)
thread_state_flavor_t flavor = x86_THREAD_STATE64;
x86_thread_state64_t state;
mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
#if __DARWIN_UNIX03
# define REGISTER_FIELD(name) __r##name
# if __DARWIN_UNIX03
# define REGISTER_FIELD(name) __r##name
# else
# define REGISTER_FIELD(name) r##name
# endif // __DARWIN_UNIX03
#elif defined(__aarch64__)
thread_state_flavor_t flavor = ARM_THREAD_STATE64;
arm_thread_state64_t state;
mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT;
# if __DARWIN_UNIX03
# define REGISTER_FIELD(name) __##name
# else
# define REGISTER_FIELD(name) name
# endif // __DARWIN_UNIX03
#else
# define REGISTER_FIELD(name) r##name
#endif // __DARWIN_UNIX03
# error "unknown architecture"
#endif
if (thread_get_state(samplee_thread, flavor,
reinterpret_cast<natural_t*>(&state),
&count) == KERN_SUCCESS) {
Registers regs;
#if defined(__x86_64__)
regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
#elif defined(__aarch64__)
regs.mPC = reinterpret_cast<Address>(state.REGISTER_FIELD(pc));
regs.mSP = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
regs.mFP = reinterpret_cast<Address>(state.REGISTER_FIELD(fp));
#else
# error "unknown architecture"
#endif
regs.mLR = 0;
aProcessRegs(regs, aNow);
@ -184,6 +205,7 @@ static void PlatformInit(PSLockRef aLock) {}
#if defined(HAVE_NATIVE_UNWIND)
void Registers::SyncPopulate() {
#if defined(__x86_64__)
asm(
// Compute caller's %rsp by adding to %rbp:
// 8 bytes for previous %rbp, 8 bytes for return address
@ -191,6 +213,17 @@ void Registers::SyncPopulate() {
// Dereference %rbp to get previous %rbp
"movq (%%rbp), %1\n\t"
: "=r"(mSP), "=r"(mFP));
#elif defined(__aarch64__)
asm(
// Compute caller's sp by adding to fp:
// 8 bytes for previous fp, 8 bytes for return address
"add %0, x29, #0x10\n\t"
// Dereference fp to get previous fp
"ldr %1, [x29]\n\t"
: "=r"(mSP), "=r"(mFP));
#else
# error "unknown architecture"
#endif
mPC = reinterpret_cast<Address>(
__builtin_extract_return_addr(__builtin_return_address(0)));
mLR = 0;