authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-14 02:50:43-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:16-04:00
logba813d00f57542483cac108223c7b2c4353c14e0
treefc2e1e789b084afe26f608a174eee9696c96d6f4
parentec96095efd8671ae280df15eaf73f63bf029fbfa

dwarf: add abi.stripInstructionPtrAuthCode


3 files changed, 34 insertions(+), 6 deletions(-)

lib/std/dwarf.zig+7-3
...@@ -1758,12 +1758,16 @@ pub const DwarfInfo = struct {...@@ -1758,12 +1758,16 @@ pub const DwarfInfo = struct {
1758 }1758 }
17591759
1760 if (has_next_ip) {1760 if (has_next_ip) {
1761 context.pc = mem.readIntSliceNative(usize, try abi.regBytes(context.thread_context, cie.return_address_register, context.reg_context));1761 context.pc = abi.stripInstructionPtrAuthCode(mem.readIntSliceNative(usize, try abi.regBytes(
1762 context.thread_context,
1763 cie.return_address_register,
1764 context.reg_context,
1765 )));
1762 } else {1766 } else {
1763 context.pc = 0;1767 context.pc = 0;
1764 }1768 }
17651769
1766 mem.writeIntSliceNative(usize, try abi.regBytes(context.thread_context, abi.spRegNum(context.reg_context), context.reg_context), context.cfa.?);1770 (try abi.regValueNative(usize, context.thread_context, abi.spRegNum(context.reg_context), context.reg_context)).* = context.cfa.?;
17671771
1768 // The call instruction will have pushed the address of the instruction that follows the call as the return address1772 // The call instruction will have pushed the address of the instruction that follows the call as the return address
1769 // However, this return address may be past the end of the function if the caller was `noreturn`. By subtracting one,1773 // However, this return address may be past the end of the function if the caller was `noreturn`. By subtracting one,
...@@ -1786,7 +1790,7 @@ pub const UnwindContext = struct {...@@ -1786,7 +1790,7 @@ pub const UnwindContext = struct {
1786 stack_machine: expressions.StackMachine(.{ .call_frame_context = true }) = .{},1790 stack_machine: expressions.StackMachine(.{ .call_frame_context = true }) = .{},
17871791
1788 pub fn init(allocator: mem.Allocator, thread_context: *const debug.ThreadContext, isValidMemory: *const fn (address: usize) bool) !UnwindContext {1792 pub fn init(allocator: mem.Allocator, thread_context: *const debug.ThreadContext, isValidMemory: *const fn (address: usize) bool) !UnwindContext {
1789 const pc = mem.readIntSliceNative(usize, try abi.regBytes(thread_context, abi.ipRegNum(), null));1793 const pc = abi.stripInstructionPtrAuthCode((try abi.regValueNative(usize, thread_context, abi.ipRegNum(), null)).*);
17901794
1791 const context_copy = try allocator.create(debug.ThreadContext);1795 const context_copy = try allocator.create(debug.ThreadContext);
1792 debug.copyContext(thread_context, context_copy);1796 debug.copyContext(thread_context, context_copy);
lib/std/dwarf/abi.zig+26-2
...@@ -45,6 +45,27 @@ pub fn spRegNum(reg_context: RegisterContext) u8 {...@@ -45,6 +45,27 @@ pub fn spRegNum(reg_context: RegisterContext) u8 {
45 };45 };
46}46}
4747
48/// Some platforms use pointer authentication - the upper bits of instruction pointers contain a signature.
49/// This function clears these signature bits to make the pointer usable.
50pub inline fn stripInstructionPtrAuthCode(ptr: usize) usize {
51 if (builtin.cpu.arch == .aarch64) {
52 // `hint 0x07` maps to `xpaclri` (or `nop` if the hardware doesn't support it)
53 // The save / restore is because `xpaclri` operates on x30 (LR)
54 return asm (
55 \\mov x16, x30
56 \\mov x30, x15
57 \\hint 0x07
58 \\mov x15, x30
59 \\mov x30, x16
60 : [ret] "={x15}" (-> usize),
61 : [ptr] "{x15}" (ptr),
62 : "x16"
63 );
64 }
65
66 return ptr;
67}
68
48pub const RegisterContext = struct {69pub const RegisterContext = struct {
49 eh_frame: bool,70 eh_frame: bool,
50 is_macho: bool,71 is_macho: bool,
...@@ -160,7 +181,6 @@ pub fn regBytes(...@@ -160,7 +181,6 @@ pub fn regBytes(
160 if (!std.debug.have_ucontext) return error.ThreadContextNotSupported;181 if (!std.debug.have_ucontext) return error.ThreadContextNotSupported;
161182
162 const ucontext_ptr = thread_context_ptr;183 const ucontext_ptr = thread_context_ptr;
163 var m = &ucontext_ptr.mcontext;
164 return switch (builtin.cpu.arch) {184 return switch (builtin.cpu.arch) {
165 .x86 => switch (builtin.os.tag) {185 .x86 => switch (builtin.os.tag) {
166 .linux, .netbsd, .solaris => switch (reg_number) {186 .linux, .netbsd, .solaris => switch (reg_number) {
...@@ -216,7 +236,7 @@ pub fn regBytes(...@@ -216,7 +236,7 @@ pub fn regBytes(
216 14 => mem.asBytes(&ucontext_ptr.mcontext.gregs[os.REG.R14]),236 14 => mem.asBytes(&ucontext_ptr.mcontext.gregs[os.REG.R14]),
217 15 => mem.asBytes(&ucontext_ptr.mcontext.gregs[os.REG.R15]),237 15 => mem.asBytes(&ucontext_ptr.mcontext.gregs[os.REG.R15]),
218 16 => mem.asBytes(&ucontext_ptr.mcontext.gregs[os.REG.RIP]),238 16 => mem.asBytes(&ucontext_ptr.mcontext.gregs[os.REG.RIP]),
219 17...32 => |i| mem.asBytes(&m.fpregs.xmm[i - 17]),239 17...32 => |i| mem.asBytes(&ucontext_ptr.mcontext.fpregs.xmm[i - 17]),
220 else => error.InvalidRegister,240 else => error.InvalidRegister,
221 },241 },
222 .freebsd => switch (reg_number) {242 .freebsd => switch (reg_number) {
...@@ -313,6 +333,10 @@ pub fn regBytes(...@@ -313,6 +333,10 @@ pub fn regBytes(
313 30 => mem.asBytes(&ucontext_ptr.mcontext.ss.lr),333 30 => mem.asBytes(&ucontext_ptr.mcontext.ss.lr),
314 31 => mem.asBytes(&ucontext_ptr.mcontext.ss.sp),334 31 => mem.asBytes(&ucontext_ptr.mcontext.ss.sp),
315 32 => mem.asBytes(&ucontext_ptr.mcontext.ss.pc),335 32 => mem.asBytes(&ucontext_ptr.mcontext.ss.pc),
336
337 // TODO: Find storage for this state
338 //34 => mem.asBytes(&ucontext_ptr.ra_sign_state),
339
316 // V0-V31340 // V0-V31
317 64...95 => mem.asBytes(&ucontext_ptr.mcontext.ns.q[reg_number - 64]),341 64...95 => mem.asBytes(&ucontext_ptr.mcontext.ns.q[reg_number - 64]),
318 else => error.InvalidRegister,342 else => error.InvalidRegister,
lib/std/macho.zig+1-1
...@@ -2459,7 +2459,7 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul...@@ -2459,7 +2459,7 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul
2459 else => return error.UnimplementedArch,2459 else => return error.UnimplementedArch,
2460 };2460 };
24612461
2462 context.pc = new_ip;2462 context.pc = dwarf.abi.stripInstructionPtrAuthCode(new_ip);
2463 if (context.pc > 0) context.pc -= 1;2463 if (context.pc > 0) context.pc -= 1;
2464 return new_ip;2464 return new_ip;
2465}2465}