This commit is contained in:
2026-02-26 16:59:30 +08:00
commit 3339111ff2
31 changed files with 4635 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
diff --git a/qemu/tcg/ffi.inc.c b/qemu/tcg/ffi.inc.c
index f0300a76..68ea4ebc 100644
--- a/qemu/tcg/ffi.inc.c
+++ b/qemu/tcg/ffi.inc.c
@@ -19,6 +19,7 @@ static int debug_info(TCGHelperInfo *info) {
printf("sizemask: 0x%x\n", info->sizemask);
printf("n_args: %d\n", info->n_args);
printf("t0: %lu\n", (uintptr_t)info->func);
+ return 0;
}
static uint64_t do_op_call(tcg_target_ulong *regs, tcg_target_ulong t0) {
@@ -32,20 +33,50 @@ static uint64_t do_op_call(tcg_target_ulong *regs, tcg_target_ulong t0) {
// Manual ABI interventions (wasm32 requires very specific conventions for uint64_t)
#if TCG_TARGET_REG_BITS == 32
- if (info->flags & dh_callflag_void && info->sizemask == 0x10 && info->n_args == 4) {
- ((void (*)(uint32_t, uint64_t, uint32_t, uint32_t))t0)(tci_read_reg(regs, TCG_REG_R0), tci_read_reg_ext(regs, TCG_REG_R1), tci_read_reg(regs, TCG_REG_R3), tci_read_reg(regs, TCG_REG_R4));
+ if (info->name && strcmp(info->name, "uc_tracecode") == 0) {
+ uint64_t trace_addr = tci_read_reg_ext(regs, TCG_REG_R3);
+ // printf("ffi wasm32 fastpath: uc_tracecode r0=%u r1=%u r2=%lu addr=0x%llx\n",
+ // (unsigned)tci_read_reg(regs, TCG_REG_R0),
+ // (unsigned)tci_read_reg(regs, TCG_REG_R1),
+ // (unsigned long)tci_read_reg(regs, TCG_REG_R2),
+ // (unsigned long long)trace_addr);
+ ((void (*)(uint32_t, uint32_t, uintptr_t, uint64_t))t0)(
+ tci_read_reg(regs, TCG_REG_R0),
+ tci_read_reg(regs, TCG_REG_R1),
+ (uintptr_t)tci_read_reg(regs, TCG_REG_R2),
+ trace_addr
+ );
+ return 0;
+ }
+
+ if (info->flags & dh_callflag_void && info->sizemask == 0x10 && info->n_args == 4) {
+ ((void (*)(uint32_t, uint32_t, uint64_t, uint32_t))t0)(
+ tci_read_reg(regs, TCG_REG_R0),
+ tci_read_reg(regs, TCG_REG_R1),
+ tci_read_reg_ext(regs, TCG_REG_R2),
+ tci_read_reg(regs, TCG_REG_R4)
+ );
return 0;
} else if (info->sizemask == 0x255 && info->n_args == 4) {
return ((uint64_t (*)(uint64_t, uint64_t, uint64_t, uint32_t))t0)(tci_read_reg_ext(regs, TCG_REG_R0), tci_read_reg_ext(regs, TCG_REG_R2), tci_read_reg_ext(regs, TCG_REG_R4), tci_read_reg(regs, TCG_REG_R7));
} else if (info->sizemask == 4 && info->n_args == 3) {
return ((uint32_t (*)(uint64_t, uint32_t, uint32_t))t0)(tci_read_reg_ext(regs, TCG_REG_R0), tci_read_reg(regs, TCG_REG_R2), tci_read_reg(regs, TCG_REG_R3));
} else if ((info->sizemask == 0x15 || info->sizemask == 0x3f) && info->n_args == 2) {
- return ((uint64_t (*)(uint64_t, uint64_t))t0)(tci_read_reg_ext(regs, TCG_REG_R0), tci_read_reg(regs, TCG_REG_R2));
+ return ((uint64_t (*)(uint64_t, uint64_t))t0)(tci_read_reg_ext(regs, TCG_REG_R0), tci_read_reg_ext(regs, TCG_REG_R2));
} else if (info->sizemask == 0x40 && info->n_args == 3) {
((void (*)(uintptr_t, uintptr_t, uint64_t))t0)(tci_read_reg(regs, TCG_REG_R0), tci_read_reg(regs, TCG_REG_R1), tci_read_reg_ext(regs, TCG_REG_R2));
return 0;
} else if (info->sizemask == 0x15 && info->n_args == 3) {
return ((uint64_t (*)(uint64_t, uint64_t, uint32_t))t0)(tci_read_reg_ext(regs, TCG_REG_R0), tci_read_reg_ext(regs, TCG_REG_R2), tci_read_reg(regs, TCG_REG_R4));
+ } else if (info->sizemask == 0x4 && info->n_args == 1) {
+ // helper with arg shape (i64) -> i32, e.g., neon_narrow_u16, neon_narrow_high_u8, iwmmxt_setpsr_nz
+ return ((uint32_t (*)(uint64_t))t0)(tci_read_reg_ext(regs, TCG_REG_R0));
+ } else if (info->sizemask == 0x4 && info->n_args == 2) {
+ // helper with arg shape (env, i64) -> i32, e.g., neon_narrow_sat_u8 (env is ptr)
+ return ((uint32_t (*)(uintptr_t, uint64_t))t0)(
+ tci_read_reg(regs, TCG_REG_R0),
+ tci_read_reg_ext(regs, TCG_REG_R1)
+ );
}
for (int i = 1; i < 15; i++) {

191
script/patches/ffi.rs.diff Normal file
View File

@@ -0,0 +1,191 @@
diff --git a/bindings/rust/src/ffi.rs b/bindings/rust/src/ffi.rs
index 7f7a205b..d812e8cd 100644
--- a/bindings/rust/src/ffi.rs
+++ b/bindings/rust/src/ffi.rs
@@ -121,9 +121,15 @@ pub unsafe extern "C" fn mmio_read_callback_proxy<D, F>(
where
F: FnMut(&mut crate::Unicorn<D>, u64, usize) -> u64,
{
+ if user_data.is_null() {
+ return 0;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return 0;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc, offset, size)
@@ -138,9 +144,15 @@ pub unsafe extern "C" fn mmio_write_callback_proxy<D, F>(
) where
F: FnMut(&mut crate::Unicorn<D>, u64, usize, u64),
{
+ if user_data.is_null() {
+ return;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc, offset, size, value);
@@ -154,9 +166,15 @@ pub unsafe extern "C" fn code_hook_proxy<D, F>(
) where
F: FnMut(&mut crate::Unicorn<D>, u64, u32),
{
+ if user_data.is_null() {
+ return;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc, address, size);
@@ -170,9 +188,15 @@ pub unsafe extern "C" fn block_hook_proxy<D, F>(
) where
F: FnMut(&mut crate::Unicorn<D>, u64, u32),
{
+ if user_data.is_null() {
+ return;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc, address, size);
@@ -189,9 +213,15 @@ pub unsafe extern "C" fn mem_hook_proxy<D, F>(
where
F: FnMut(&mut crate::Unicorn<D>, MemType, u64, usize, i64) -> bool,
{
+ if user_data.is_null() {
+ return false;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return false;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc, mem_type, address, size as usize, value)
@@ -204,9 +234,15 @@ pub unsafe extern "C" fn intr_hook_proxy<D, F>(
) where
F: FnMut(&mut crate::Unicorn<D>, u32),
{
+ if user_data.is_null() {
+ return;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc, value);
@@ -221,9 +257,15 @@ pub unsafe extern "C" fn insn_in_hook_proxy<D, F>(
where
F: FnMut(&mut crate::Unicorn<D>, u32, usize) -> u32,
{
+ if user_data.is_null() {
+ return 0;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return 0;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc, port, size)
@@ -236,9 +278,15 @@ pub unsafe extern "C" fn insn_invalid_hook_proxy<D, F>(
where
F: FnMut(&mut crate::Unicorn<D>) -> bool,
{
+ if user_data.is_null() {
+ return false;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return false;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc)
@@ -253,9 +301,15 @@ pub unsafe extern "C" fn insn_out_hook_proxy<D, F>(
) where
F: FnMut(&mut crate::Unicorn<D>, u32, usize, u32),
{
+ if user_data.is_null() {
+ return;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc, port, size, value);
@@ -265,9 +319,15 @@ pub unsafe extern "C" fn insn_sys_hook_proxy<D, F>(uc: uc_handle, user_data: *mu
where
F: FnMut(&mut crate::Unicorn<D>),
{
+ if user_data.is_null() {
+ return;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
(user_data.callback)(&mut user_data_uc);
@@ -283,9 +343,15 @@ pub unsafe extern "C" fn tlb_lookup_hook_proxy<D, F>(
where
F: FnMut(&mut crate::Unicorn<D>, u64, MemType) -> Option<TlbEntry>,
{
+ if user_data.is_null() {
+ return false;
+ }
let user_data = &mut *user_data;
+ let Some(inner) = user_data.uc.upgrade() else {
+ return false;
+ };
let mut user_data_uc = Unicorn {
- inner: user_data.uc.upgrade().unwrap(),
+ inner,
};
debug_assert_eq!(uc, user_data_uc.get_handle());
let r = (user_data.callback)(&mut user_data_uc, vaddr, mem_type);

View File

@@ -0,0 +1,16 @@
diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c
index 0524fefd..9bc1fd39 100644
--- a/qemu/accel/tcg/translate-all.c
+++ b/qemu/accel/tcg/translate-all.c
@@ -862,6 +862,11 @@ static inline void *alloc_code_gen_buffer(struct uc_struct *uc)
return buf;
}
+
+void free_code_gen_buffer(struct uc_struct *uc)
+{
+ (void)uc;
+}
#elif defined(_WIN32)
#define COMMIT_COUNT (1024) // Commit 4MB per exception
#define CLOSURE_SIZE (4096)