From 20f38ea665563aab6e838db551c3fe5980850d30 Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Wed, 3 Dec 2025 10:19:55 +0100 Subject: [PATCH 1/2] add uc_ctl_get_invalid_addr this allows to read out the address where an error happens. --- include/unicorn/unicorn.h | 5 +++++ uc.c | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index b4ffc6bc75..defbc7eb19 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -605,6 +605,9 @@ typedef enum uc_control_type { // controle if context_save/restore should work with snapshots // Write: @args = (int) UC_CTL_CONTEXT_MODE, + // read the invalid_addr after an error + // Read: @args = (uint64_t*) + UC_CTL_INVALID_ADDR, } uc_control_type; /* @@ -688,6 +691,8 @@ See sample_ctl.c for a detailed example. uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TCG_BUFFER_SIZE, 1), (size)) #define uc_ctl_context_mode(uc, mode) \ uc_ctl(uc, UC_CTL_WRITE(UC_CTL_CONTEXT_MODE, 1), (mode)) +#define uc_ctl_get_invalid_addr(uc, addr) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_INVALID_ADDR, 1), (addr)) // Opaque storage for CPU context, used with uc_context_*() struct uc_context; diff --git a/uc.c b/uc.c index 75b89a0176..ac2aed7cac 100644 --- a/uc.c +++ b/uc.c @@ -2977,6 +2977,15 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) restore_jit_state(uc); break; + case UC_CTL_INVALID_ADDR: + if (rw == UC_CTL_IO_READ) { + uint64_t *invalid_addr = va_arg(args, uint64_t *); + *invalid_addr = uc->invalid_addr; + } else { + err = UC_ERR_ARG; + } + break; + default: err = UC_ERR_ARG; break; From 04d24e3d20eb4d912fbf1daa20a39be7fba7e88a Mon Sep 17 00:00:00 2001 From: "Takacs, Philipp" Date: Thu, 4 Dec 2025 13:00:55 +0100 Subject: [PATCH 2/2] mmu hook: use a seperate error code This way the user must not track the error reason --- include/unicorn/unicorn.h | 1 + qemu/softmmu/unicorn_vtlb.c | 2 +- uc.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index defbc7eb19..ec5f332da8 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -193,6 +193,7 @@ typedef enum uc_err { UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() UC_ERR_EXCEPTION, // Unhandled CPU exception UC_ERR_OVERFLOW, // Provided buffer is not large enough: uc_reg_*2() + UC_ERR_MMU_FAULT, // The tlb_fill hook returned false (see tlb_fill hook) } uc_err; /* diff --git a/qemu/softmmu/unicorn_vtlb.c b/qemu/softmmu/unicorn_vtlb.c index 25c684064f..6e15cc143b 100644 --- a/qemu/softmmu/unicorn_vtlb.c +++ b/qemu/softmmu/unicorn_vtlb.c @@ -9,7 +9,7 @@ static void raise_mmu_exception(CPUState *cs, target_ulong address, int rw, uintptr_t retaddr) { - cs->uc->invalid_error = UC_ERR_EXCEPTION; + cs->uc->invalid_error = UC_ERR_MMU_FAULT; cs->uc->invalid_addr = address; cpu_exit(cs->uc->cpu); cpu_loop_exit_restore(cs, retaddr); diff --git a/uc.c b/uc.c index ac2aed7cac..0d873dcf5b 100644 --- a/uc.c +++ b/uc.c @@ -191,6 +191,8 @@ const char *uc_strerror(uc_err code) return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; case UC_ERR_OVERFLOW: return "Provided buffer is too small (UC_ERR_OVERFLOW)"; + case UC_ERR_MMU_FAULT: + return "The tlb_fill hook returned false (UC_ERR_MMU_FAULT)"; } }