diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 8deb08daed..158eff8626 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -2732,7 +2732,60 @@ static void test_x86_lock_btc_reg(void) OK(uc_close(uc)); } +// Regression: dense x87 memory ops in one TB exhaust TCG temps on 64-bit hosts +// when TCG_MAX_TEMPS is 512. Unicorn's check_exit_request after every qemu_ld/st +// plus live x87 temps overflow temps[] into the ops queue head and SIGSEGV in +// tcg_emit_op. See PR discussion / OpenSWE1R on Apple Silicon. +static void test_x86_tcg_temp_limit_x87_block(void) +{ + uc_engine *uc; + /* + * Real-world dense x87 basic block (matrix math) extracted from a 32-bit + * Windows game binary that crashes Unicorn 2.1.4 on Apple Silicon hosts. + * Translation of this TB drives nb_temps past TCG_MAX_TEMPS==512; temps[] + * overflows into the ops queue head and tcg_emit_op SIGSEGVs. + * + * Prologue: sub esp, 0x40; mov ecx, [esp+0x44]; mov eax, [esp+0x48]; ... + */ + static const uint8_t code[] = { + 0x83, 0xec, 0x40, 0x8b, 0x4c, 0x24, 0x44, 0x8b, 0x44, 0x24, 0x48, 0xd9, 0x41, 0x10, 0xd9, 0x41, 0x20, 0xd9, 0x41, 0x30, 0xd9, 0xc2, 0xd9, 0xc2, 0xd8, 0x48, 0x08, 0xd9, 0xc9, 0xd8, 0x48, 0x04, 0xd9, 0x01, 0xd9, 0xcb, 0xd9, 0x54, 0x24, 0x30, 0xd8, 0x48, 0x0c, 0xd9, 0x00, 0xd9, 0xcb, 0xde, 0xc2, 0xd9, 0xcb, 0xd9, 0x5c, 0x24, 0x00, 0x8b, 0x51, 0x14, 0xd9, 0xc9, 0xd8, 0x4c, 0x24, 0x00, 0xd9, 0xca, 0xde, 0xc1, 0xd9, 0x41, 0x34, 0xd9, 0xca, 0xde, 0xc1, 0x89, 0x54, 0x24, 0x14, 0x8b, 0x51, 0x24, 0xd9, 0x44, 0x24, 0x14, 0x89, 0x54, 0x24, 0x24, 0x8b, 0x51, 0x18, 0xd9, 0x44, 0x24, 0x24, 0xd9, 0xca, 0xd9, 0x19, 0x89, 0x54, 0x24, 0x18, 0x8b, 0x51, 0x28, 0xd8, 0x48, 0x04, 0xd9, 0x41, 0x04, 0xd9, 0xca, 0xd8, 0x48, 0x08, 0xd9, 0xcb, 0xd9, 0x54, 0x24, 0x34, 0xd8, 0x48, 0x0c, 0xd9, 0x00, 0xd9, 0xcc, 0xde, 0xc2, 0xd9, 0xca, 0xd9, 0x5c, 0x24, 0x04, 0xd9, 0xca, 0xd8, 0x4c, 0x24, 0x04, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0x41, 0x38, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0x44, 0x24, 0x18, 0x89, 0x54, 0x24, 0x28, 0x8b, 0x51, 0x0c, 0xd9, 0x44, 0x24, 0x28, 0xd9, 0xcb, 0xd9, 0x59, 0x04, 0x89, 0x54, 0x24, 0x0c, 0x8b, 0x51, 0x1c, 0xd8, 0x48, 0x04, 0xd9, 0x41, 0x08, 0xd9, 0xcb, 0xd8, 0x48, 0x08, 0xd9, 0xca, 0xd9, 0x54, 0x24, 0x38, 0xd8, 0x48, 0x0c, 0xd9, 0x00, 0xd9, 0xcb, 0xde, 0xc2, 0xd9, 0xcb, 0xd9, 0x5c, 0x24, 0x08, 0xd9, 0xc9, 0xd8, 0x4c, 0x24, 0x08, 0xd9, 0xca, 0xde, 0xc1, 0xd9, 0xc9, 0xde, 0xc1, 0x89, 0x54, 0x24, 0x1c, 0x8b, 0x51, 0x2c, 0x89, 0x54, 0x24, 0x2c, 0x8b, 0x51, 0x3c, 0xd9, 0x59, 0x08, 0xd9, 0x44, 0x24, 0x2c, 0xd9, 0x44, 0x24, 0x1c, 0xd8, 0x48, 0x04, 0x89, 0x54, 0x24, 0x3c, 0xd9, 0x44, 0x24, 0x3c, 0xd9, 0xca, 0xd8, 0x48, 0x08, 0xd9, 0x00, 0xd9, 0xcb, 0xd8, 0x48, 0x0c, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0xca, 0xd8, 0x4c, 0x24, 0x0c, 0xd9, 0xc4, 0xd9, 0xcb, 0xde, 0xc2, 0xd9, 0x44, 0x24, 0x30, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0x44, 0x24, 0x00, 0xd9, 0xca, 0xd9, 0x59, 0x0c, 0xd9, 0xca, 0xd8, 0x48, 0x14, 0xd9, 0xc3, 0xd9, 0xcb, 0xd8, 0x48, 0x1c, 0xd9, 0x44, 0x24, 0x14, 0xd9, 0xcb, 0xd8, 0x48, 0x10, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0xcb, 0xd8, 0x48, 0x18, 0xd9, 0x44, 0x24, 0x34, 0xd9, 0xcc, 0xde, 0xc2, 0xd9, 0x44, 0x24, 0x04, 0xd9, 0x44, 0x24, 0x24, 0xd9, 0xca, 0xde, 0xc3, 0xd9, 0x44, 0x24, 0x18, 0xd9, 0xcb, 0xd9, 0x59, 0x10, 0xd9, 0xcb, 0xd8, 0x48, 0x14, 0xd9, 0x44, 0x24, 0x38, 0xd9, 0xcd, 0xd8, 0x48, 0x1c, 0xde, 0xc1, 0xd9, 0xcb, 0xd8, 0x48, 0x10, 0xd9, 0x44, 0x24, 0x08, 0xd9, 0xc9, 0xde, 0xc4, 0xd9, 0xc9, 0xd8, 0x48, 0x18, 0xd9, 0x44, 0x24, 0x28, 0xd9, 0xc9, 0xde, 0xc4, 0xd9, 0x44, 0x24, 0x1c, 0xd9, 0xcc, 0xd9, 0x59, 0x14, 0xd9, 0xca, 0xd8, 0x48, 0x14, 0xd9, 0x44, 0x24, 0x3c, 0xd9, 0xcd, 0xd8, 0x48, 0x1c, 0xde, 0xc1, 0xd9, 0xc9, 0xd8, 0x48, 0x10, 0xd9, 0x44, 0x24, 0x0c, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0xca, 0xd8, 0x48, 0x18, 0xd9, 0x44, 0x24, 0x2c, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0xc9, 0xd9, 0x59, 0x18, 0xd9, 0xca, 0xd8, 0x48, 0x14, 0xd9, 0xc4, 0xd9, 0xcc, 0xd8, 0x48, 0x1c, 0xd9, 0xc6, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0xca, 0xd8, 0x48, 0x10, 0xd9, 0x44, 0x24, 0x30, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0xcb, 0xd8, 0x48, 0x18, 0xd9, 0x44, 0x24, 0x00, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0x44, 0x24, 0x24, 0xd9, 0xca, 0xd9, 0x59, 0x1c, 0xd9, 0xcc, 0xd8, 0x48, 0x28, 0xd9, 0x44, 0x24, 0x14, 0xd9, 0xcb, 0xd8, 0x48, 0x24, 0xde, 0xc1, 0xd9, 0xcb, 0xd8, 0x48, 0x2c, 0xd9, 0x44, 0x24, 0x34, 0xd9, 0xc9, 0xde, 0xc4, 0xd9, 0xcc, 0xd8, 0x48, 0x20, 0xd9, 0x44, 0x24, 0x04, 0xd9, 0xc9, 0xde, 0xc4, 0xd9, 0xcb, 0xd9, 0x59, 0x20, 0xd8, 0x48, 0x28, 0xd9, 0xc9, 0xd8, 0x48, 0x24, 0xd9, 0xcb, 0xd8, 0x48, 0x2c, 0xd9, 0xcb, 0xde, 0xc1, 0xd9, 0xc9, 0xd8, 0x48, 0x20, 0xd9, 0xca, 0xde, 0xc1, 0xd9, 0xc9, 0xde, 0xc1, 0xd9, 0x59, 0x24, 0xd9, 0x44, 0x24, 0x18, 0xd9, 0x44, 0x24, 0x28, 0xd8, 0x48, 0x28, 0xd9, 0x44, 0x24, 0x38, 0xd9, 0xca, 0xd8, 0x48, 0x24, 0xd9, 0x44, 0x24, 0x08, 0xd9, 0xcb, 0xd8, 0x48, 0x2c, 0xd9, 0xc9, 0xde, 0xc2, 0xd9, 0xca, 0xd8, 0x48, 0x20, 0xd9, 0x44, 0x24, 0x2c, 0xd9, 0xcb, 0xde, 0xc2, 0xd9, 0x44, 0x24, 0x1c, 0xd9, 0x44, 0x24, 0x3c, 0xd9, 0xca, 0xde, 0xc3, 0xd9, 0x44, 0x24, 0x0c, 0xd9, 0xcb, 0xd9, 0x59, 0x28, 0xd9, 0xcb, 0xd8, 0x48, 0x28, 0xd9, 0xcb, 0xd8, 0x48, 0x24, 0xd9, 0xc9, 0xd8, 0x48, 0x2c, 0xd9, 0xc9, 0xde, 0xc3, 0xd9, 0xc9, 0xd8, 0x48, 0x20, 0xd9, 0x44, 0x24, 0x30, 0xd9, 0xca, 0xde, 0xc3, 0xd9, 0x44, 0x24, 0x00, 0xd9, 0xc9, 0xde, 0xc3, 0xd9, 0x44, 0x24, 0x14, 0xd9, 0xcb, 0xd9, 0x59, 0x2c, 0xd9, 0xcc, 0xd8, 0x48, 0x34, 0xd9, 0x44, 0x24, 0x34, 0xd9, 0xca, 0xd8, 0x48, 0x3c, 0xde, 0xc1, 0xd9, 0xcc, 0xd8, 0x48, 0x30, 0xd9, 0x44, 0x24, 0x04, 0xd9, 0xc9, 0xde, 0xc5, 0xd9, 0xcb, 0xd8, 0x48, 0x38, 0xd9, 0x44, 0x24, 0x24, 0xd9, 0xc9, 0xde, 0xc5, 0xd9, 0x44, 0x24, 0x18, 0xd9, 0xcd, 0xd9, 0x59, 0x30, 0xd9, 0xca, 0xd8, 0x48, 0x34, 0xd9, 0x44, 0x24, 0x38, 0xd9, 0xca, 0xd8, 0x48, 0x3c, 0xde, 0xc1, 0xd9, 0xcb, 0xd8, 0x48, 0x30, 0xd9, 0x44, 0x24, 0x08, 0xd9, 0xc9, 0xde, 0xc4, 0xd9, 0xca, 0xd8, 0x48, 0x38, 0xd9, 0x44, 0x24, 0x28, 0xd9, 0xc9, 0xde, 0xc4, 0xd9, 0x44, 0x24, 0x1c, 0xd9, 0xcc, 0xd9, 0x59, 0x34, 0xd9, 0xcc, 0xd8, 0x48, 0x34, 0xd9, 0x44, 0x24, 0x3c, 0xd9, 0xca, 0xd8, 0x48, 0x3c, 0xde, 0xc1, 0xd9, 0xca, 0xd8, 0x48, 0x30, 0xd9, 0x44, 0x24, 0x0c, 0xd9, 0xc9, 0xde, 0xc3, 0xd9, 0xcc, 0xd8, 0x48, 0x38, 0xd9, 0x44, 0x24, 0x2c, 0xd9, 0xc9, 0xde, 0xc3, 0xd9, 0xca, 0xd9, 0x59, 0x38, 0xd9, 0xca, 0xd8, 0x48, 0x34, 0xd9, 0xca, 0xd8, 0x48, 0x3c, 0xd9, 0xcb, 0xd8, 0x48, 0x30, 0xd9, 0xcb, 0xde, 0xc2, 0xd8, 0x48, 0x38, 0xd9, 0xca, 0xde, 0xc1, 0xd9, 0xc9, 0xde, 0xc1, 0xd9, 0x59, 0x3c, 0x83, 0xc4, 0x40, 0xc3, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x51, 0x8b, 0x4c, 0x24, 0x0c, 0x8b, 0x51, 0x14, 0x8b, 0x41, 0x10, 0xd9, 0x41, 0x18, 0x89, 0x54, 0x24, 0x00, 0x89, 0x44, 0x24, 0x0c, 0xd9, 0x44, 0x24, 0x00, 0xd9, 0x44, 0x24, 0x0c, 0xd8, 0x4c, 0x24, 0x0c, 0xd9, 0xc9, 0xd8, 0x4c, 0x24, 0x00, 0xd9, 0xc2, 0xd8, 0xcb, 0xd9, 0xc9, 0xde, 0xc2, 0xc3 + }; + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, (char *)code, sizeof(code)); + + /* Two float matrices for ecx/eax */ + OK(uc_mem_map(uc, 0x10000, 0x1000, UC_PROT_ALL)); + OK(uc_mem_map(uc, 0x11000, 0x1000, UC_PROT_ALL)); + float mat[32]; + for (int i = 0; i < 32; i++) { + mat[i] = 1.0f; + } + OK(uc_mem_write(uc, 0x10000, mat, sizeof(mat))); + OK(uc_mem_write(uc, 0x11000, mat, sizeof(mat))); + + /* Stack: leave room for sub esp,0x40 then [esp+0x44]/[esp+0x48] args */ + OK(uc_mem_map(uc, 0x80000, 0x2000, UC_PROT_ALL)); + uint32_t esp = 0x81000; + uint32_t arg1 = 0x10000; + uint32_t arg2 = 0x11000; + /* Before prologue: [esp]=ret, [esp+4]=arg1, [esp+8]=arg2 */ + uint32_t ret_addr = 0x9000; + OK(uc_mem_map(uc, 0x9000, 0x1000, UC_PROT_ALL)); + uint8_t hlt = 0xF4; + OK(uc_mem_write(uc, 0x9000, &hlt, 1)); + OK(uc_mem_write(uc, esp, &ret_addr, 4)); + OK(uc_mem_write(uc, esp + 4, &arg1, 4)); + OK(uc_mem_write(uc, esp + 8, &arg2, 4)); + OK(uc_reg_write(uc, UC_X86_REG_ESP, &esp)); + + uc_err err = uc_emu_start(uc, code_start, 0x9001, 0, 0); + TEST_CHECK(err == UC_ERR_OK); + + OK(uc_close(uc)); +} + TEST_LIST = { + {"test_x86_tcg_temp_limit_x87_block", test_x86_tcg_temp_limit_x87_block}, {"test_x86_in", test_x86_in}, {"test_x86_out", test_x86_out}, {"test_x86_mem_hook_all", test_x86_mem_hook_all},