diff --git a/remill/Arch/Runtime/HyperCall.h b/remill/Arch/Runtime/HyperCall.h index ec5d91b5b..b4b945395 100644 --- a/remill/Arch/Runtime/HyperCall.h +++ b/remill/Arch/Runtime/HyperCall.h @@ -87,8 +87,9 @@ class AsyncHyperCall { kX86SysEnter, kX86SysExit, - // Far jumps: CS should be updated. + // Far jumps/calls: CS should be updated. kX86JmpFar, + kX86CallFar, kAArch64SupervisorCall, diff --git a/remill/Arch/X86/Semantics/CALL_RET.cpp b/remill/Arch/X86/Semantics/CALL_RET.cpp index 6d3c03363..c613097e6 100644 --- a/remill/Arch/X86/Semantics/CALL_RET.cpp +++ b/remill/Arch/X86/Semantics/CALL_RET.cpp @@ -27,6 +27,24 @@ DEF_SEM(CALL, T target_pc, PC return_pc) { return memory; } +template +DEF_SEM(CALL_FAR_PTR, S1 target_pc, S2 target_seg, PC return_pc) { + HYPER_CALL = AsyncHyperCall::kX86CallFar; + + addr_t next_sp = USub(REG_XSP, ADDRESS_SIZE_BYTES * 2); + + // stack update + WriteZExt(WritePtr(next_sp + ADDRESS_SIZE_BYTES), Read(REG_CS.flat)); + Write(WritePtr(next_sp _IF_32BIT(REG_SS_BASE)), Read(return_pc)); + + // register update + Write(REG_XSP, Read(next_sp)); + WriteZExt(REG_PC, Read(target_pc)); + Write(REG_CS.flat, Read(target_seg)); + + return memory; +} + DEF_SEM(RET_IMM, I16 bytes) { Write(REG_PC, Read(ReadPtr(REG_XSP _IF_32BIT(REG_SS_BASE)))); Write(REG_XSP, @@ -53,6 +71,8 @@ IF_32BIT( DEF_ISEL(CALL_NEAR_GPRv_16) = CALL; ) IF_32BIT( DEF_ISEL(CALL_NEAR_GPRv_32) = CALL; ) IF_64BIT( DEF_ISEL(CALL_NEAR_GPRv_64) = CALL; ) +IF_32BIT( DEF_ISEL(CALL_FAR_PTRp_IMMw_32) = CALL_FAR_PTR; ) + /* 352 CALL_FAR CALL_FAR_MEMp2 CALL BASE I86 ATTRIBUTES: FAR_XFER FIXED_BASE1 NOTSX SCALABLE STACKPUSH1 353 CALL_FAR CALL_FAR_PTRp_IMMw CALL BASE I86 ATTRIBUTES: FAR_XFER FIXED_BASE0 NOTSX SCALABLE STACKPUSH0