Skip to content

Commit 018dbc9

Browse files
committed
Unwinding registration for arm64e
1 parent cd76120 commit 018dbc9

3 files changed

Lines changed: 71 additions & 25 deletions

File tree

macOS/debugger.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ uint64_t* Debugger::GetPointerToRegister(Register r) {
220220
case X26:
221221
case X27:
222222
case X28:
223-
case X29:
224223
return &state->__x[r];
225224
#ifndef __arm64e__
226225
case PC:
@@ -229,6 +228,8 @@ uint64_t* Debugger::GetPointerToRegister(Register r) {
229228
return &state->__lr;
230229
case SP:
231230
return &state->__sp;
231+
case FP:
232+
return &state->__fp;
232233
#endif
233234
case CPSR:
234235
return (uint64_t*)&state->__cpsr;
@@ -288,6 +289,8 @@ size_t Debugger::GetRegister(Register r) {
288289
return (size_t)ptrauth_strip(state->__opaque_lr, ptrauth_key_function_pointer);
289290
case SP:
290291
return (size_t)ptrauth_strip((void *)state->__opaque_sp, ptrauth_key_process_independent_data);
292+
case FP:
293+
return (size_t)ptrauth_strip((void *)state->__opaque_fp, ptrauth_key_process_independent_data);
291294
default:
292295
break;
293296
}
@@ -320,6 +323,9 @@ void Debugger::SetRegister(Register r, size_t value) {
320323
case SP:
321324
arm_thread_state64_set_sp(*state, (void *)value);
322325
return;
326+
case FP:
327+
arm_thread_state64_set_fp(*state, (void *)value);
328+
return;
323329
default:
324330
break;
325331
}
@@ -1591,9 +1597,19 @@ void Debugger::SaveRegisters(SavedRegisters *registers) {
15911597

15921598
registers->gpr_count = *(mach_exception->new_state_cnt);
15931599

1600+
#ifdef __arm64e__
1601+
ARCH_THREAD_STATE_T *at_state = (ARCH_THREAD_STATE_T*)(mach_exception->new_state);
1602+
memcpy(registers->gpr_registers.__x, at_state->__x, sizeof(registers->gpr_registers.__x));
1603+
registers->gpr_registers.__opaque_fp = (void *)GetRegister(FP);
1604+
registers->gpr_registers.__opaque_lr = (void *)GetRegister(LR);
1605+
registers->gpr_registers.__opaque_sp = (void *)GetRegister(SP);
1606+
registers->gpr_registers.__opaque_pc = (void *)GetRegister(PC);
1607+
registers->gpr_registers.__cpsr = (uint32_t)GetRegister(CPSR);
1608+
#else
15941609
memcpy(&registers->gpr_registers,
15951610
mach_exception->new_state,
15961611
registers->gpr_count * sizeof(natural_t));
1612+
#endif
15971613

15981614
registers->fpu_count = sizeof(ARCH_FPU_STATE_T) / sizeof(natural_t);
15991615
kern_return_t ret = thread_get_state(mach_exception->thread_port,
@@ -1611,10 +1627,20 @@ void Debugger::RestoreRegisters(SavedRegisters *registers) {
16111627
FATAL("Unexpected thread state size");
16121628
}
16131629

1630+
#ifdef __arm64e__
1631+
ARCH_THREAD_STATE_T *at_state = (ARCH_THREAD_STATE_T*)(mach_exception->new_state);
1632+
memcpy(at_state->__x, registers->gpr_registers.__x, sizeof(registers->gpr_registers.__x));
1633+
SetRegister(FP, (size_t)registers->gpr_registers.__opaque_fp);
1634+
SetRegister(LR, (size_t)registers->gpr_registers.__opaque_lr);
1635+
SetRegister(SP, (size_t)registers->gpr_registers.__opaque_sp);
1636+
SetRegister(PC, (size_t)registers->gpr_registers.__opaque_pc);
1637+
SetRegister(CPSR, (size_t)registers->gpr_registers.__cpsr);
1638+
#else
16141639
memcpy(mach_exception->new_state,
16151640
&registers->gpr_registers,
16161641
registers->gpr_count * sizeof(natural_t));
1617-
1642+
#endif
1643+
16181644
kern_return_t ret = thread_set_state(mach_exception->thread_port,
16191645
ARCH_FPU_STATE,
16201646
(thread_state_t)&registers->fpu_registers,

macOS/unwindmacos.cpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,10 @@ void UnwindGeneratorMacOS::OnReturnAddress(ModuleInfo *module,
176176
{original_address, personality};
177177
}
178178

179-
size_t UnwindGeneratorMacOS::WriteCIE(ModuleInfo *module,
179+
size_t UnwindGeneratorMacOS::WriteCIE(size_t addr,
180180
const char *augmentation,
181-
size_t personality_addr) {
181+
size_t personality_addr,
182+
size_t *personality_remote_ptr) {
182183

183184
ByteStream cie;
184185
cie.PutValue<uint32_t>(0); // CIE id, must be zero
@@ -194,10 +195,13 @@ size_t UnwindGeneratorMacOS::WriteCIE(ModuleInfo *module,
194195

195196
cie.PutValueFront<uint32_t>(cie.size()); // CIE length
196197

197-
size_t cie_address = tinyinst_.GetCurrentInstrumentedAddress(module);
198-
tinyinst_.WriteCode(module, cie.data(), cie.size());
198+
tinyinst_.RemoteWrite((void *)addr, cie.data(), cie.size());
199+
200+
if(personality_remote_ptr) {
201+
*personality_remote_ptr = addr + cie.size() - 8;
202+
}
199203

200-
return cie_address;
204+
return addr + cie.size();
201205
}
202206

203207
void UnwindGeneratorMacOS::ExtractPersonalityArray(ModuleInfo *module) {
@@ -433,24 +437,22 @@ bool UnwindGeneratorMacOS::HandleBreakpoint(ModuleInfo* module, void *address) {
433437
return false;
434438
}
435439

436-
size_t UnwindGeneratorMacOS::WriteFDE(ModuleInfo *module,
440+
size_t UnwindGeneratorMacOS::WriteFDE(size_t addr,
437441
size_t cie_address,
438442
size_t min_address,
439443
size_t max_address)
440444
{
441-
UnwindDataMacOS *unwind_data = (UnwindDataMacOS *)module->unwind_data;
442-
size_t fde_address = tinyinst_.GetCurrentInstrumentedAddress(module);
443-
444445
ByteStream fde;
445-
fde.PutValue<uint32_t>(fde_address - cie_address + 4); // CIE pointer
446+
fde.PutValue<uint32_t>(addr - cie_address + 4); // CIE pointer
446447
fde.PutValue<uint64_t>(min_address); // PC start
447448
fde.PutValue<uint64_t>(max_address - min_address); // PC range
448449
fde.PutULEB128Value(0); // aug length
449450

450451
fde.PutValueFront<uint32_t>(fde.size()); // length
451452

452-
tinyinst_.WriteCode(module, fde.data(), fde.size());
453-
return fde_address;
453+
tinyinst_.RemoteWrite((void *)addr, fde.data(), fde.size());
454+
455+
return addr + fde.size();
454456
}
455457

456458
size_t UnwindGeneratorMacOS::MaybeRedirectExecution(ModuleInfo* module, size_t IP) {
@@ -478,13 +480,16 @@ size_t UnwindGeneratorMacOS::MaybeRedirectExecution(ModuleInfo* module, size_t I
478480
#endif
479481

480482
size_t personality = WriteCustomPersonality(module);
481-
size_t cie_address = WriteCIE(module, "zP", personality);
483+
484+
size_t cie_address = (size_t)tinyinst_.RemoteAllocate(4096, MemoryProtection::READWRITE);
485+
size_t personality_remote_ptr = 0;
486+
size_t fde_address = WriteCIE(cie_address, "zP", personality, &personality_remote_ptr);
482487

483488
std::vector<size_t> fde_addresses;
484-
size_t fde_address = WriteFDE(module, cie_address,
485-
(size_t)module->instrumented_code_remote,
486-
(size_t)module->instrumented_code_remote +
487-
module->instrumented_code_size);
489+
WriteFDE(fde_address, cie_address,
490+
(size_t)module->instrumented_code_remote,
491+
(size_t)module->instrumented_code_remote +
492+
module->instrumented_code_size);
488493
fde_addresses.push_back(fde_address);
489494

490495
size_t fde_array_start = tinyinst_.GetCurrentInstrumentedAddress(module);
@@ -517,6 +522,11 @@ size_t UnwindGeneratorMacOS::MaybeRedirectExecution(ModuleInfo* module, size_t I
517522

518523
// fill out the missing pieces in the assembly snippet
519524
#ifdef ARM64
525+
tinyinst_.WritePointerAtOffset(module,
526+
personality_remote_ptr,
527+
assembly_offset +
528+
register_assembly_arm64_personality_offset);
529+
520530
size_t register_assembly_data_offset = register_assembly_arm64_data_offset;
521531
#else
522532
size_t register_assembly_data_offset = register_assembly_x86_data_offset;
@@ -911,4 +921,4 @@ void UnwindGeneratorMacOS::AlignCodeMemory(ModuleInfo *module) {
911921
tinyinst_.WriteCode(module, (void*)&padding, 4 - ls2b);
912922
}
913923
}
914-
#endif
924+
#endif

macOS/unwindmacos.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,11 @@ class UnwindGeneratorMacOS : public UnwindGenerator {
203203

204204
void ExtractPersonalityArray(ModuleInfo *module);
205205

206-
size_t WriteCIE(ModuleInfo *module,
206+
size_t WriteCIE(size_t addr,
207207
const char *augmentation,
208-
size_t personality_addr);
209-
size_t WriteFDE(ModuleInfo *module,
208+
size_t personality_addr,
209+
size_t *personality_remote_ptr);
210+
size_t WriteFDE(size_t addr,
210211
size_t cie_address,
211212
size_t min_address,
212213
size_t max_address);
@@ -245,10 +246,18 @@ class UnwindGeneratorMacOS : public UnwindGenerator {
245246
0x40, 0x00, 0x00, 0xb4, // cbz x0, skip_alignment
246247
0xff, 0x23, 0x00, 0xd1, // sub sp, sp, #8
247248
// skip_alignment:
249+
// pac sign the personality
250+
0xb4, 0x00, 0x00, 0x58, // ldr x20, #20;
251+
0x93, 0x02, 0x40, 0xf9, // ldr x19, [x20]
252+
0x93, 0x02, 0xc1, 0xda, // pacia x19, x20
253+
0x93, 0x02, 0x00, 0xf9, // str x19, [x20]
254+
0x03, 0x00, 0x00, 0x14, // b #12; loop
255+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // address of personaliy ptr goes here
256+
// load array params
248257
0x93, 0x00, 0x00, 0x58, // ldr x19, #16; x19 becomes the current array pointer
249258
0xb4, 0x00, 0x00, 0x58, // ldr x20, #20; x20 becomes the end array pointer
250259
0xd5, 0x00, 0x00, 0x58, // ldr x21, #24; x21 becomes __register_frame address
251-
0x09, 0x00, 0x00, 0x14, // b #36; loop
260+
0x07, 0x00, 0x00, 0x14, // b #28; loop
252261
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // array start addr goes here
253262
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // array end addr goes here
254263
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // __register_frame addr goes here
@@ -266,7 +275,8 @@ class UnwindGeneratorMacOS : public UnwindGenerator {
266275
0xe0, 0x4f, 0x42, 0xa9, // ldp x0, x19, [sp, #32]
267276
0xff, 0xc3, 0x00, 0x91, // add sp, sp, #48
268277
};
269-
static const size_t register_assembly_arm64_data_offset = 48;
278+
static const size_t register_assembly_arm64_personality_offset = 52;
279+
static const size_t register_assembly_arm64_data_offset = 76;
270280
#else
271281
static constexpr unsigned char register_assembly_x86[] = {
272282
// save registers

0 commit comments

Comments
 (0)