Skip to content

Commit 1a2faf6

Browse files
committed
Add Zydis x86/x86-64 disassembler support
Integrate Zydis as an optional dependency to enable x86/x86-64 guest instruction disassembly during JIT compilation. Build with -DENABLE_ZYDIS=TRUE. Use FEX_X86DISASSEMBLE=1 at runtime to output guest x86 instructions for each compiled block.
1 parent d197300 commit 1a2faf6

File tree

6 files changed

+57
-0
lines changed

6 files changed

+57
-0
lines changed

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,7 @@
4949
[submodule "External/range-v3"]
5050
path = External/range-v3
5151
url = https://github.com/ericniebler/range-v3.git
52+
[submodule "External/zydis"]
53+
shallow = true
54+
path = External/zydis
55+
url = https://github.com/zyantific/zydis.git

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ option(ENABLE_LIBCXX "Enables LLVM libc++" FALSE)
2828
option(ENABLE_CCACHE "Enables ccache for compile caching" TRUE)
2929
option(ENABLE_VIXL_SIMULATOR "Enable use of VIXL simulator for emulation (only useful for CI testing)" FALSE)
3030
option(ENABLE_VIXL_DISASSEMBLER "Enables debug disassembler output with VIXL" FALSE)
31+
option(ENABLE_ZYDIS "Enables x86/x86-64 guest disassembler output with Zydis" FALSE)
3132
option(USE_LEGACY_BINFMTMISC "Uses legacy method of setting up binfmt_misc" FALSE)
3233
option(ENABLE_FEXCORE_PROFILER "Enables use of the FEXCore timeline profiling capabilities" FALSE)
3334
set (FEXCORE_PROFILER_BACKEND "gpuvis" CACHE STRING "Set which backend to use for the FEXCore profiler (gpuvis, tracy)")
@@ -315,6 +316,12 @@ if (BUILD_TESTING OR ENABLE_VIXL_DISASSEMBLER OR ENABLE_VIXL_SIMULATOR)
315316
include_directories(SYSTEM External/vixl/src/)
316317
endif()
317318

319+
if (ENABLE_ZYDIS)
320+
set(ZYDIS_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
321+
set(ZYDIS_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
322+
add_subdirectory(External/zydis/)
323+
endif()
324+
318325
if (ENABLE_FEXCORE_PROFILER AND FEXCORE_PROFILER_BACKEND STREQUAL "TRACY")
319326
add_subdirectory(External/tracy)
320327
endif()

External/zydis

Submodule zydis added at 9bfadd6

FEXCore/Source/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ if (ENABLE_VIXL_DISASSEMBLER)
9696
list(APPEND DEFINES -DVIXL_DISASSEMBLER=1)
9797
endif()
9898

99+
if (ENABLE_ZYDIS)
100+
list(APPEND DEFINES -DZYDIS_DISASSEMBLER=1)
101+
endif()
102+
99103
if (_M_ARM_64 AND HAS_CLANG_PRESERVE_ALL)
100104
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=__attribute__((preserve_all));-DFEXCORE_HAS_PRESERVE_ALL_ATTR=1")
101105
else()
@@ -108,6 +112,10 @@ if (ENABLE_VIXL_DISASSEMBLER OR ENABLE_VIXL_SIMULATOR)
108112
list (APPEND LIBS vixl)
109113
endif()
110114

115+
if (ENABLE_ZYDIS)
116+
list (APPEND LIBS Zydis)
117+
endif()
118+
111119
if (NOT MINGW_BUILD)
112120
list (APPEND LIBS dl)
113121
else()

FEXCore/Source/Interface/Config/Config.json.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,14 @@
334334
"\tstats: Will print stats when disassembling the code"
335335
]
336336
},
337+
"X86Disassemble": {
338+
"Type": "bool",
339+
"Default": "false",
340+
"Desc": [
341+
"Enables x86/x86-64 guest disassembly output for compiled blocks.",
342+
"Requires FEX to be built with -DENABLE_ZYDIS=TRUE"
343+
]
344+
},
337345
"ForceSVEWidth": {
338346
"Type": "uint32",
339347
"Default": "0",

FEXCore/Source/Interface/Core/Core.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ desc: Glues Frontend, OpDispatcher and IR Opts & Compilation, LookupCache, Dispa
99
*/
1010

1111
#include <cstdint>
12+
#ifdef ZYDIS_DISASSEMBLER
13+
#include <Zydis/Zydis.h>
14+
#endif
1215
#include "Interface/Core/ArchHelpers/Arm64Emitter.h"
1316
#include "Interface/Core/LookupCache.h"
1417
#include "Interface/Core/CPUBackend.h"
@@ -694,6 +697,32 @@ ContextImpl::GenerateIR(FEXCore::Core::InternalThreadState* Thread, uint64_t Gue
694697
Thread->FrontendDecoder->DelayedDisownBuffer();
695698
}
696699

700+
#ifdef ZYDIS_DISASSEMBLER
701+
{
702+
FEX_CONFIG_OPT(X86Disassemble, X86DISASSEMBLE);
703+
if (X86Disassemble()) {
704+
const uint64_t StartAddr = Thread->FrontendDecoder->DecodedMinAddress;
705+
const uint64_t Length = Thread->FrontendDecoder->DecodedMaxAddress - StartAddr;
706+
const auto MachineMode = Config.Is64BitMode ? ZYDIS_MACHINE_MODE_LONG_64 : ZYDIS_MACHINE_MODE_LEGACY_32;
707+
const uint8_t* Data = reinterpret_cast<const uint8_t*>(StartAddr);
708+
ZydisDisassembledInstruction Instruction;
709+
ZyanUSize Offset = 0;
710+
711+
LogMan::Msg::IFmt("Guest x86 Begin");
712+
while (Offset < Length) {
713+
if (ZYAN_SUCCESS(ZydisDisassembleIntel(MachineMode, StartAddr + Offset, Data + Offset, Length - Offset, &Instruction))) {
714+
LogMan::Msg::IFmt("0x{:x}: {}", StartAddr + Offset, Instruction.text);
715+
Offset += Instruction.info.length;
716+
} else {
717+
LogMan::Msg::IFmt("0x{:x}: (invalid)", StartAddr + Offset);
718+
Offset++;
719+
}
720+
}
721+
LogMan::Msg::IFmt("Guest x86 End");
722+
}
723+
}
724+
#endif
725+
697726
IR::IREmitter* IREmitter = Thread->OpDispatcher.get();
698727

699728
auto ShouldDump = Thread->OpDispatcher->ShouldDumpIR();

0 commit comments

Comments
 (0)