From d3788d132d571cae89b716276a439c50609fa824 Mon Sep 17 00:00:00 2001 From: Pascal Zittlau Date: Tue, 2 Dec 2025 17:45:39 +0100 Subject: [PATCH] save instruction starts --- src/Patcher.zig | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Patcher.zig b/src/Patcher.zig index 18b5cb6..5bfdf18 100644 --- a/src/Patcher.zig +++ b/src/Patcher.zig @@ -178,15 +178,24 @@ pub fn patchRegion(patcher: *Patcher, region: []align(page_size) u8) !void { defer arena_impl.deinit(); var patch_requests: std.ArrayListUnmanaged(PatchRequest) = .empty; + // We save the bytes where instructions start to be able to disassemble them on the fly. This is + // necessary for the neighbor eviction, since we can't just iterate forwards from a target + // instruction and disassemble happily. This is because some bytes may already be the patched + // ones which means that we might disassemble garbage or something different that wasn't there + // before. This means that we would need to stop disassembling on the first byte that is locked, + // which kind of defeats the purpose of neighbor eviction. + var instruction_starts = try std.DynamicBitSetUnmanaged.initEmpty(arena, region.len); { // Get where to patch. var instruction_iterator = InstructionIterator.init(region); while (instruction_iterator.next()) |instruction| { - const should_patch = instruction.instruction.attributes & zydis.ZYDIS_ATTRIB_HAS_LOCK > 0 or - instruction.instruction.mnemonic == zydis.ZYDIS_MNEMONIC_SYSCALL; + const offset = instruction.address - @intFromPtr(region.ptr); + instruction_starts.set(offset); + + const should_patch = instruction.instruction.mnemonic == zydis.ZYDIS_MNEMONIC_SYSCALL or + instruction.instruction.attributes & zydis.ZYDIS_ATTRIB_HAS_LOCK > 0; if (should_patch) { - const offset = instruction.address - @intFromPtr(region.ptr); const request: PatchRequest = .{ .flicken = .nop, .offset = offset,