diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 302945db..16089d88 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -50,4 +50,66 @@ static void test_arm64_until() OK(uc_close(uc)); } -TEST_LIST = {{"test_arm64_until", test_arm64_until}, {NULL, NULL}}; + +static void test_arm64_code_patching() { + uc_engine *uc; + char code[] = "\x00\x04\x00\x11"; // add w0, w0, 0x1 + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); + // zero out x0 + uint64_t r_x0 = 0x0; + OK(uc_reg_write(uc, UC_ARM64_REG_X0, &r_x0)); + // emulate the instruction + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) -1, 0, 0)); + // check value + OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0)); + TEST_CHECK(r_x0 == 0x1); + // patch instruction + char patch_code[] = "\x00\xfc\x1f\x11"; // add w0, w0, 0x7FF + OK(uc_mem_write(uc, code_start, patch_code, sizeof(patch_code) - 1)); + // zero out x0 + r_x0 = 0x0; + OK(uc_reg_write(uc, UC_ARM64_REG_X0, &r_x0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(patch_code) -1, 0, 0)); + // check value + OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0)); + TEST_CHECK(r_x0 != 0x1); + TEST_CHECK(r_x0 == 0x7ff); + + OK(uc_close(uc)); +} + +// Need to flush the cache before running the emulation after patching +static void test_arm64_code_patching_count() { + uc_engine *uc; + char code[] = "\x00\x04\x00\x11"; // add w0, w0, 0x1 + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); + // zero out x0 + uint64_t r_x0 = 0x0; + OK(uc_reg_write(uc, UC_ARM64_REG_X0, &r_x0)); + // emulate the instruction + OK(uc_emu_start(uc, code_start, -1, 0, 1)); + // check value + OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0)); + TEST_CHECK(r_x0 == 0x1); + // patch instruction + char patch_code[] = "\x00\xfc\x1f\x11"; // add w0, w0, 0x7FF + OK(uc_mem_write(uc, code_start, patch_code, sizeof(patch_code) - 1)); + OK(uc_ctl_remove_cache(uc, code_start, code_start + sizeof(patch_code) - 1)); + // zero out x0 + r_x0 = 0x0; + OK(uc_reg_write(uc, UC_ARM64_REG_X0, &r_x0)); + OK(uc_emu_start(uc, code_start, -1, 0, 1)); + // check value + OK(uc_reg_read(uc, UC_ARM64_REG_X0, &r_x0)); + TEST_CHECK(r_x0 != 0x1); + TEST_CHECK(r_x0 == 0x7ff); + + OK(uc_close(uc)); +} + +TEST_LIST = { + {"test_arm64_until", test_arm64_until}, + {"test_arm64_code_patching", test_arm64_code_patching}, + {"test_arm64_code_patching_count", test_arm64_code_patching_count}, + {NULL, NULL} +}; diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 2e38392e..cb413132 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -372,6 +372,62 @@ static void test_riscv64_fp_move_to_int(void) uc_close(uc); } +static void test_riscv64_code_patching() { + uc_engine *uc; + char code[] = "\x93\x82\x12\x00"; // addi t0, t0, 0x1 + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1); + // Zero out t0 and t1 + uint64_t r_t0 = 0x0; + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + // emulate the instruction + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + // check value + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + TEST_CHECK(r_t0 == 0x1); + // patch instruction + char patch_code[] = "\x93\x82\xf2\x7f"; // addi t0, t0, 0x7FF + OK(uc_mem_write(uc, code_start, patch_code, sizeof(patch_code) - 1)); + // zero out t0 + r_t0 = 0x0; + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(patch_code) -1, 0, 0)); + // check value + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + TEST_CHECK(r_t0 != 0x1); + TEST_CHECK(r_t0 == 0x7ff); + + OK(uc_close(uc)); +} + +// Need to flush the cache before running the emulation after patching +static void test_riscv64_code_patching_count() { + uc_engine *uc; + char code[] = "\x93\x82\x12\x00"; // addi t0, t0, 0x1 + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1); + // Zero out t0 and t1 + uint64_t r_t0 = 0x0; + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + // emulate the instruction + OK(uc_emu_start(uc, code_start, -1, 0, 1)); + // check value + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + TEST_CHECK(r_t0 == 0x1); + // patch instruction + char patch_code[] = "\x93\x82\xf2\x7f"; // addi t0, t0, 0x7FF + OK(uc_mem_write(uc, code_start, patch_code, sizeof(patch_code) - 1)); + OK(uc_ctl_remove_cache(uc, code_start, code_start + sizeof(patch_code) - 1)); + // zero out t0 + r_t0 = 0x0; + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_emu_start(uc, code_start, -1, 0, 1)); + // check value + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + TEST_CHECK(r_t0 != 0x1); + TEST_CHECK(r_t0 == 0x7ff); + + OK(uc_close(uc)); +} + static void test_riscv64_ecall_cb(uc_engine *uc, uint32_t intno, void *data) { uc_emu_stop(uc); @@ -492,4 +548,6 @@ TEST_LIST = {{"test_riscv32_nop", test_riscv32_nop}, {"test_riscv32_mmio_map", test_riscv32_mmio_map}, {"test_riscv64_mmio_map", test_riscv64_mmio_map}, {"test_riscv32_map", test_riscv32_map}, + {"test_riscv64_code_patching", test_riscv64_code_patching}, + {"test_riscv64_code_patching_count", test_riscv64_code_patching_count}, {NULL, NULL}};