bindings/zig: Fix sample_riscv_zig partial writes and logging (#2133)

- Use full code length (instead of subtracting 1) when writing instructions.
- Uniformly zero-pad addresses in logs and print hexadecimal.
- Correct the instruction-hook callback in test_riscv2.
This commit is contained in:
Fernando
2025-03-16 04:05:17 +01:00
committed by GitHub
parent df75effba3
commit d755a8bed9

View File

@@ -18,18 +18,18 @@ pub fn main() !void {
fn hook_block(uc: ?*unicornC.uc_engine, address: u64, size: u32, user_data: ?*anyopaque) callconv(.C) void {
_ = user_data;
_ = uc;
log.info(">>> Tracing basic block at 0x{}, block size = 0x{}", .{ address, size });
log.info(">>> Tracing basic block at 0x{x:0>4}, block size = 0x{x:0>4}", .{ address, size });
}
fn hook_code(uc: ?*unicornC.uc_engine, address: u64, size: u32, user_data: ?*anyopaque) callconv(.C) void {
_ = user_data;
_ = uc;
log.info(">>> Tracing instruction at 0x{}, instruction size = 0x{}", .{ address, size });
log.info(">>> Tracing instruction at 0x{x:0>4}, instruction size = 0x{x:0>4}", .{ address, size });
}
fn hook_code3(uc: ?*unicornC.uc_engine, address: u64, size: u32, user_data: ?*anyopaque) callconv(.C) void {
_ = user_data;
log.info(">>> Tracing instruction at 0x{}, instruction size = 0x{}", .{ address, size });
log.info(">>> Tracing instruction at 0x{x:0>4}, instruction size = 0x{x:0>4}", .{ address, size });
if (address == ADDRESS) {
log.info("stop emulation");
unicorn.uc_emu_stop(uc) catch |err| log.err("Error: {}", .{err});
@@ -41,7 +41,7 @@ fn hook_memalloc(uc: ?*unicornC.uc_engine, @"type": unicornC.uc_mem_type, addres
const algined_address = address & 0xFFFFFFFFFFFFF000;
const aligned_size = (@as(u32, @intCast(size / 0x1000)) + 1) * 0x1000;
log.info(">>> Allocating block at 0x{} (0x{}), block size = 0x{} (0x{})", .{ address, algined_address, size, aligned_size });
log.info(">>> Allocating block at 0x{x:0>4} (aligned: 0x{x:0>4}), block size = 0x{x:0>4} (aligned: 0x{x:0>4})", .{ address, algined_address, size, aligned_size });
unicorn.uc_mem_map(uc, algined_address, aligned_size, unicornC.UC_PROT_ALL) catch |err| log.err("Error: {}", .{err});
@@ -81,7 +81,7 @@ fn test_recover_from_illegal() !void {
try unicorn.uc_hook_add(uc, &trace2, unicornC.UC_HOOK_CODE, @as(?*anyopaque, @ptrCast(@constCast(&hook_code))), null, 1, 0);
// write machine code to be emulated to memory
try unicorn.uc_mem_write(uc, ADDRESS, RISCV_CODE, RISCV_CODE.len - 1);
try unicorn.uc_mem_write(uc, ADDRESS, RISCV_CODE, RISCV_CODE.len);
// emulate 1 instruction, wrong address, illegal code
unicorn.uc_emu_start(uc, 0x1000, @as(u64, @bitCast(@as(i64, -1))), 0, 1) catch |err|
@@ -97,8 +97,8 @@ fn test_recover_from_illegal() !void {
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A0, @as(?*anyopaque, @ptrCast(@constCast(&a0))));
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
log.info(">>> A0 = 0x{}", .{a0});
log.info(">>> A1 = 0x{}", .{a1});
log.info(">>> A0 = 0x{x:0>4}", .{a0});
log.info(">>> A1 = 0x{x:0>4}", .{a1});
try unicorn.uc_close(uc);
}
@@ -124,7 +124,7 @@ fn test_riscv_func_return() !void {
try unicorn.uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, unicornC.UC_PROT_ALL);
// write machine code to be emulated to memory
try unicorn.uc_mem_write(uc, ADDRESS, CODE, CODE.len - 1);
try unicorn.uc_mem_write(uc, ADDRESS, CODE, CODE.len);
// tracing all basic blocks with customized callback
try unicorn.uc_hook_add(uc, &trace1, unicornC.UC_HOOK_BLOCK, @as(?*anyopaque, @ptrCast(@constCast(&hook_block))), null, 1, 0);
@@ -143,7 +143,7 @@ fn test_riscv_func_return() !void {
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_PC, @as(?*anyopaque, @ptrCast(@constCast(&pc))));
if (pc != ra) {
log.info("Error after execution: PC is: 0x{}, expected was 0x{}", .{ pc, ra });
log.info("Error after execution: PC is: 0x{x:0>4}, expected was 0x{x:0>4}", .{ pc, ra });
if (pc == 0x10004) {
log.info(" PC did not change during execution", .{});
}
@@ -177,7 +177,7 @@ fn test_riscv2() !void {
try unicorn.uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, unicornC.UC_PROT_ALL);
// write machine code to be emulated to memory
try unicorn.uc_mem_write(uc, ADDRESS, RISCV_CODE, RISCV_CODE.len - 1);
try unicorn.uc_mem_write(uc, ADDRESS, RISCV_CODE, RISCV_CODE.len);
// initialize machine registers
try unicorn.uc_reg_write(uc, unicornC.UC_RISCV_REG_A0, @as(?*anyopaque, @ptrCast(@constCast(&a0))));
@@ -187,7 +187,7 @@ fn test_riscv2() !void {
try unicorn.uc_hook_add(uc, &trace1, unicornC.UC_HOOK_BLOCK, @as(?*anyopaque, @ptrCast(@constCast(&hook_block))), null, 1, 0);
// tracing all instruction
try unicorn.uc_hook_add(uc, &trace2, unicornC.UC_HOOK_CODE, @as(?*anyopaque, @ptrCast(@constCast(&hook_block))), null, 1, 0);
try unicorn.uc_hook_add(uc, &trace2, unicornC.UC_HOOK_CODE, @as(?*anyopaque, @ptrCast(@constCast(&hook_code))), null, 1, 0);
// emulate 1 instruction
unicorn.uc_emu_start(uc, ADDRESS, ADDRESS + 4, 0, 0) catch |err| {
@@ -197,8 +197,8 @@ fn test_riscv2() !void {
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A0, @as(?*anyopaque, @ptrCast(@constCast(&a0))));
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
log.info(">>> A0 = 0x{}", .{a0});
log.info(">>> A1 = 0x{}", .{a1});
log.info(">>> A0 = 0x{x:0>4}", .{a0});
log.info(">>> A1 = 0x{x:0>4}", .{a1});
// emulate one more instruction
unicorn.uc_emu_start(uc, ADDRESS + 4, ADDRESS + 8, 0, 0) catch |err| {
@@ -211,8 +211,8 @@ fn test_riscv2() !void {
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A0, @as(?*anyopaque, @ptrCast(@constCast(&a0))));
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
log.info(">>> A0 = 0x{}", .{a0});
log.info(">>> A1 = 0x{}", .{a1});
log.info(">>> A0 = 0x{x:0>4}", .{a0});
log.info(">>> A1 = 0x{x:0>4}", .{a1});
try unicorn.uc_close(uc);
}