|
| 1 | +//! Windows AArch64 exception-context remapping. |
| 2 | +//! |
| 3 | +//! Windows ARM64 exposes breakpoint state through the native `CONTEXT` record. |
| 4 | +//! This module copies that record into zighook's stable callback-facing |
| 5 | +//! `HookContext` layout and writes callback edits back into the Windows record |
| 6 | +//! before execution resumes. |
| 7 | + |
| 8 | +const std = @import("std"); |
| 9 | + |
| 10 | +const types = @import("types.zig"); |
| 11 | + |
| 12 | +const windows = std.os.windows; |
| 13 | + |
| 14 | +fn readU128(bytes: []const u8) u128 { |
| 15 | + return std.mem.readInt(u128, bytes[0..16], .little); |
| 16 | +} |
| 17 | + |
| 18 | +fn writeU128(bytes: []u8, value: u128) void { |
| 19 | + std.mem.writeInt(u128, bytes[0..16], value, .little); |
| 20 | +} |
| 21 | + |
| 22 | +fn captureFromContext(context: *const windows.CONTEXT) types.HookContext { |
| 23 | + var ctx = std.mem.zeroes(types.HookContext); |
| 24 | + |
| 25 | + for (context.DUMMYUNIONNAME.X, 0..) |reg, index| { |
| 26 | + ctx.regs.x[index] = reg; |
| 27 | + } |
| 28 | + ctx.sp = context.Sp; |
| 29 | + ctx.pc = context.Pc; |
| 30 | + ctx.cpsr = context.Cpsr; |
| 31 | + ctx.pad = 0; |
| 32 | + |
| 33 | + for (context.V, 0..) |vreg, index| { |
| 34 | + ctx.fpregs.v[index] = readU128(std.mem.asBytes(&vreg)); |
| 35 | + } |
| 36 | + ctx.fpsr = context.Fpsr; |
| 37 | + ctx.fpcr = context.Fpcr; |
| 38 | + |
| 39 | + return ctx; |
| 40 | +} |
| 41 | + |
| 42 | +fn writeBackToContext(context: *windows.CONTEXT, ctx: *const types.HookContext) void { |
| 43 | + for (ctx.regs.x, 0..) |reg, index| { |
| 44 | + context.DUMMYUNIONNAME.X[index] = reg; |
| 45 | + } |
| 46 | + context.Sp = ctx.sp; |
| 47 | + context.Pc = ctx.pc; |
| 48 | + context.Cpsr = ctx.cpsr; |
| 49 | + |
| 50 | + for (ctx.fpregs.v, 0..) |vreg, index| { |
| 51 | + writeU128(std.mem.asBytes(&context.V[index]), vreg); |
| 52 | + } |
| 53 | + context.Fpsr = ctx.fpsr; |
| 54 | + context.Fpcr = ctx.fpcr; |
| 55 | +} |
| 56 | + |
| 57 | +pub fn captureMachineContext(context_opaque: ?*anyopaque) ?types.HookContext { |
| 58 | + if (context_opaque == null) return null; |
| 59 | + |
| 60 | + const context: *align(1) const windows.CONTEXT = @ptrCast(context_opaque.?); |
| 61 | + return captureFromContext(@alignCast(context)); |
| 62 | +} |
| 63 | + |
| 64 | +pub fn writeBackMachineContext(context_opaque: ?*anyopaque, ctx: *const types.HookContext) bool { |
| 65 | + if (context_opaque == null) return false; |
| 66 | + |
| 67 | + const context: *align(1) windows.CONTEXT = @ptrCast(context_opaque.?); |
| 68 | + writeBackToContext(@alignCast(context), ctx); |
| 69 | + return true; |
| 70 | +} |
| 71 | + |
| 72 | +comptime { |
| 73 | + std.debug.assert(@sizeOf(windows.NEON128) == 16); |
| 74 | +} |
0 commit comments