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:
@@ -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 {
|
fn hook_block(uc: ?*unicornC.uc_engine, address: u64, size: u32, user_data: ?*anyopaque) callconv(.C) void {
|
||||||
_ = user_data;
|
_ = user_data;
|
||||||
_ = uc;
|
_ = 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 {
|
fn hook_code(uc: ?*unicornC.uc_engine, address: u64, size: u32, user_data: ?*anyopaque) callconv(.C) void {
|
||||||
_ = user_data;
|
_ = user_data;
|
||||||
_ = uc;
|
_ = 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 {
|
fn hook_code3(uc: ?*unicornC.uc_engine, address: u64, size: u32, user_data: ?*anyopaque) callconv(.C) void {
|
||||||
_ = user_data;
|
_ = 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) {
|
if (address == ADDRESS) {
|
||||||
log.info("stop emulation");
|
log.info("stop emulation");
|
||||||
unicorn.uc_emu_stop(uc) catch |err| log.err("Error: {}", .{err});
|
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 algined_address = address & 0xFFFFFFFFFFFFF000;
|
||||||
const aligned_size = (@as(u32, @intCast(size / 0x1000)) + 1) * 0x1000;
|
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});
|
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);
|
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
|
// 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
|
// emulate 1 instruction, wrong address, illegal code
|
||||||
unicorn.uc_emu_start(uc, 0x1000, @as(u64, @bitCast(@as(i64, -1))), 0, 1) catch |err|
|
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_A0, @as(?*anyopaque, @ptrCast(@constCast(&a0))));
|
||||||
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
|
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
|
||||||
|
|
||||||
log.info(">>> A0 = 0x{}", .{a0});
|
log.info(">>> A0 = 0x{x:0>4}", .{a0});
|
||||||
log.info(">>> A1 = 0x{}", .{a1});
|
log.info(">>> A1 = 0x{x:0>4}", .{a1});
|
||||||
|
|
||||||
try unicorn.uc_close(uc);
|
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);
|
try unicorn.uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, unicornC.UC_PROT_ALL);
|
||||||
|
|
||||||
// write machine code to be emulated to memory
|
// 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
|
// 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);
|
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))));
|
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_PC, @as(?*anyopaque, @ptrCast(@constCast(&pc))));
|
||||||
if (pc != ra) {
|
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) {
|
if (pc == 0x10004) {
|
||||||
log.info(" PC did not change during execution", .{});
|
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);
|
try unicorn.uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, unicornC.UC_PROT_ALL);
|
||||||
|
|
||||||
// write machine code to be emulated to memory
|
// 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
|
// initialize machine registers
|
||||||
try unicorn.uc_reg_write(uc, unicornC.UC_RISCV_REG_A0, @as(?*anyopaque, @ptrCast(@constCast(&a0))));
|
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);
|
try unicorn.uc_hook_add(uc, &trace1, unicornC.UC_HOOK_BLOCK, @as(?*anyopaque, @ptrCast(@constCast(&hook_block))), null, 1, 0);
|
||||||
|
|
||||||
// tracing all instruction
|
// 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
|
// emulate 1 instruction
|
||||||
unicorn.uc_emu_start(uc, ADDRESS, ADDRESS + 4, 0, 0) catch |err| {
|
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_A0, @as(?*anyopaque, @ptrCast(@constCast(&a0))));
|
||||||
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
|
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
|
||||||
|
|
||||||
log.info(">>> A0 = 0x{}", .{a0});
|
log.info(">>> A0 = 0x{x:0>4}", .{a0});
|
||||||
log.info(">>> A1 = 0x{}", .{a1});
|
log.info(">>> A1 = 0x{x:0>4}", .{a1});
|
||||||
|
|
||||||
// emulate one more instruction
|
// emulate one more instruction
|
||||||
unicorn.uc_emu_start(uc, ADDRESS + 4, ADDRESS + 8, 0, 0) catch |err| {
|
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_A0, @as(?*anyopaque, @ptrCast(@constCast(&a0))));
|
||||||
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
|
try unicorn.uc_reg_read(uc, unicornC.UC_RISCV_REG_A1, @as(?*anyopaque, @ptrCast(@constCast(&a1))));
|
||||||
|
|
||||||
log.info(">>> A0 = 0x{}", .{a0});
|
log.info(">>> A0 = 0x{x:0>4}", .{a0});
|
||||||
log.info(">>> A1 = 0x{}", .{a1});
|
log.info(">>> A1 = 0x{x:0>4}", .{a1});
|
||||||
|
|
||||||
try unicorn.uc_close(uc);
|
try unicorn.uc_close(uc);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user