From 549274f44cadc952ab6223d2f800a1965bee53af Mon Sep 17 00:00:00 2001 From: Quentin DUCASSE Date: Fri, 10 Dec 2021 15:27:54 +0100 Subject: [PATCH 1/2] Code patching tests for riscv and arm64 --- tests/unit/test_arm64.c | 62 ++++++++++++++++++++++++++++++++++++++++- tests/unit/test_riscv.c | 56 +++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 302945db..33c6ca37 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -50,4 +50,64 @@ 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)); +} + +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)); + // 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..076ea347 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -372,6 +372,60 @@ 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)); +} + +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)); + // 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 +546,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}}; From 033e79abac6f80c15c5223ef5c9cd68a92102c0e Mon Sep 17 00:00:00 2001 From: Quentin DUCASSE Date: Fri, 17 Dec 2021 14:55:08 +0100 Subject: [PATCH 2/2] Added cache flush after code patching in unit tests for arm64 and riscv --- tests/unit/test_arm64.c | 2 ++ tests/unit/test_riscv.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 33c6ca37..16089d88 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -78,6 +78,7 @@ static void test_arm64_code_patching() { 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 @@ -93,6 +94,7 @@ static void test_arm64_code_patching_count() { // 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)); diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 076ea347..cb413132 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -399,6 +399,7 @@ static void test_riscv64_code_patching() { 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 @@ -414,6 +415,7 @@ static void test_riscv64_code_patching_count() { // 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));