From 3ea7857be3bba21a1c41dc3f5629f36cc9747946 Mon Sep 17 00:00:00 2001 From: mio Date: Thu, 20 Oct 2022 21:57:28 +0200 Subject: [PATCH] Exit early when invalid read happens In this way, the target register won't be overwritten --- qemu/accel/tcg/cputlb.c | 11 +++++++++++ tests/unit/test_arm64.c | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/qemu/accel/tcg/cputlb.c b/qemu/accel/tcg/cputlb.c index 9305b06c..04c892a2 100644 --- a/qemu/accel/tcg/cputlb.c +++ b/qemu/accel/tcg/cputlb.c @@ -1484,6 +1484,11 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, if (mr == NULL) { uc->invalid_error = UC_ERR_MAP; cpu_exit(uc->cpu); + // XXX(@lazymio): We have to exit early so that the target register won't be overwritten + // because qemu might generate tcg code like: + // qemu_ld_i64 x0,x1,leq,8 sync: 0 dead: 0 1 + // where we don't have a change to recover x0 value + cpu_loop_exit(uc->cpu); return 0; } } else { @@ -1491,6 +1496,8 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uc->invalid_error = error_code; // printf("***** Invalid fetch (unmapped memory) at " TARGET_FMT_lx "\n", addr); cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); return 0; } } @@ -1533,6 +1540,8 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uc->invalid_error = UC_ERR_READ_PROT; // printf("***** Invalid memory read (non-readable) at " TARGET_FMT_lx "\n", addr); cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); return 0; } } @@ -1561,6 +1570,8 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi, uc->invalid_error = UC_ERR_FETCH_PROT; // printf("***** Invalid fetch (non-executable) at " TARGET_FMT_lx "\n", addr); cpu_exit(uc->cpu); + // See comments above + cpu_loop_exit(uc->cpu); return 0; } } diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 789be967..52bd95ca 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -366,7 +366,7 @@ static void test_arm64_block_invalid_mem_read_write_sync(void) OK(uc_reg_read(uc, UC_ARM64_REG_X1, &r_x1)); TEST_CHECK(r_pc == code_start + 8); - // TEST_CHECK(r_x0 == 1); // Unfortunately this can't be guarantee-ed + TEST_CHECK(r_x0 == 1); TEST_CHECK(r_x1 == 2); OK(uc_close(uc));