commit
7420dec402
|
@ -80,7 +80,7 @@
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<Optimization>MaxSpeed</Optimization>
|
<Optimization>MaxSpeed</Optimization>
|
||||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||||
<AdditionalIncludeDirectories>..\..\src\Common;..\..\import\OpenXDK\include;..\..\import\zydis\Zydis;..\..\import\glew-2.0.0\include;..\..\src;..\..\src\Common\Win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\import\OpenXDK\include;..\..\import\distorm\include;..\..\import\glew-2.0.0\include;..\..\src;..\..\src\Common;..\..\src\Common\Win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CXBXKRNL_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CXBXKRNL_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<StringPooling>true</StringPooling>
|
<StringPooling>true</StringPooling>
|
||||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||||
|
@ -103,7 +103,7 @@
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
<LargeAddressAware>false</LargeAddressAware>
|
<LargeAddressAware>false</LargeAddressAware>
|
||||||
<AdditionalLibraryDirectories>..\..\import\zydis\Build\$(Configuration)\;..\..\import\glew-2.0.0\lib\Release\Win32\</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\import\distorm\lib\Win32\;..\..\import\glew-2.0.0\lib\Release\Win32\</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
<Bscmake>
|
<Bscmake>
|
||||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
@ -140,7 +140,7 @@
|
||||||
</Midl>
|
</Midl>
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<AdditionalIncludeDirectories>..\..\src\Common;..\..\import\OpenXDK\include;..\..\import\zydis\Zydis;..\..\import\glew-2.0.0\include;..\..\src;..\..\src\Common\Win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>..\..\import\OpenXDK\include;..\..\import\distorm\include;..\..\import\glew-2.0.0\include;..\..\src;..\..\src\Common;..\..\src\Common\Win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CXBXKRNL_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CXBXKRNL_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<MinimalRebuild>true</MinimalRebuild>
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||||
|
@ -155,7 +155,7 @@
|
||||||
<AdditionalIncludeDirectories>Include\Win32\CxbxKrnl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>Include\Win32\CxbxKrnl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>Shlwapi.lib;Zydis.lib;legacy_stdio_definitions.lib;dxerr8.lib;xinput.lib;ws2_32.lib;dsound.lib;winmm.lib;ddraw.lib;d3dx8.lib;d3d8.lib;dinput8.lib;dxguid.lib;odbc32.lib;odbccp32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Shlwapi.lib;legacy_stdio_definitions.lib;dxerr8.lib;xinput.lib;ws2_32.lib;dsound.lib;winmm.lib;ddraw.lib;d3dx8.lib;d3d8.lib;dinput8.lib;dxguid.lib;odbc32.lib;odbccp32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
<IgnoreSpecificDefaultLibraries>libci.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
<IgnoreSpecificDefaultLibraries>libci.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
@ -167,7 +167,7 @@
|
||||||
<TargetMachine>MachineX86</TargetMachine>
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
<LargeAddressAware>false</LargeAddressAware>
|
<LargeAddressAware>false</LargeAddressAware>
|
||||||
<AdditionalLibraryDirectories>..\..\import\zydis\Build\$(Configuration)\;..\..\import\glew-2.0.0\lib\Release\Win32\</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\import\distorm\lib\Win32\;..\..\import\glew-2.0.0\lib\Release\Win32\</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
<Bscmake>
|
<Bscmake>
|
||||||
<SuppressStartupBanner>true</SuppressStartupBanner>
|
<SuppressStartupBanner>true</SuppressStartupBanner>
|
||||||
|
|
|
@ -0,0 +1,482 @@
|
||||||
|
/* diStorm 3.3.3 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
distorm.h
|
||||||
|
|
||||||
|
diStorm3 - Powerful disassembler for X86/AMD64
|
||||||
|
http://ragestorm.net/distorm/
|
||||||
|
distorm at gmail dot com
|
||||||
|
Copyright (C) 2003-2016 Gil Dabah
|
||||||
|
This library is licensed under the BSD license. See the file COPYING.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DISTORM_H
|
||||||
|
#define DISTORM_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 64 bit offsets support:
|
||||||
|
* If the diStorm library you use was compiled with 64 bits offsets,
|
||||||
|
* make sure you compile your own code with the following macro set:
|
||||||
|
* SUPPORT_64BIT_OFFSET
|
||||||
|
* Otherwise comment it out, or you will get a linker error of an unresolved symbol...
|
||||||
|
* Turned on by default!
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC))
|
||||||
|
/* Define this macro for outer projects by default. */
|
||||||
|
#define SUPPORT_64BIT_OFFSET
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* TINYC has a problem with some 64bits library functions, so ignore 64 bit offsets. */
|
||||||
|
#ifdef __TINYC__
|
||||||
|
#undef SUPPORT_64BIT_OFFSET
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* If your compiler doesn't support stdint.h, define your own 64 bits type. */
|
||||||
|
#ifdef SUPPORT_64BIT_OFFSET
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define OFFSET_INTEGER unsigned __int64
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#define OFFSET_INTEGER uint64_t
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
/* 32 bit offsets are used. */
|
||||||
|
#define OFFSET_INTEGER unsigned long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* Since MSVC isn't shipped with stdint.h, we will have our own: */
|
||||||
|
typedef signed __int64 int64_t;
|
||||||
|
typedef unsigned __int64 uint64_t;
|
||||||
|
typedef signed __int32 int32_t;
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
typedef signed __int16 int16_t;
|
||||||
|
typedef unsigned __int16 uint16_t;
|
||||||
|
typedef signed __int8 int8_t;
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Support C++ compilers */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* *** Helper Macros *** */
|
||||||
|
|
||||||
|
/* Get the ISC of the instruction, used with the definitions below. */
|
||||||
|
#define META_GET_ISC(meta) (((meta) >> 3) & 0x1f)
|
||||||
|
#define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 3))
|
||||||
|
/* Get the flow control flags of the instruction, see 'features for decompose' below. */
|
||||||
|
#define META_GET_FC(meta) ((meta) & 0x7)
|
||||||
|
|
||||||
|
/* Get the target address of a branching instruction. O_PC operand type. */
|
||||||
|
#define INSTRUCTION_GET_TARGET(di) ((_OffsetType)(((di)->addr + (di)->imm.addr + (di)->size)))
|
||||||
|
/* Get the target address of a RIP-relative memory indirection. */
|
||||||
|
#define INSTRUCTION_GET_RIP_TARGET(di) ((_OffsetType)(((di)->addr + (di)->disp + (di)->size)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Operand Size or Adderss size are stored inside the flags:
|
||||||
|
* 00 - 16 bits
|
||||||
|
* 01 - 32 bits
|
||||||
|
* 10 - 64 bits
|
||||||
|
* 11 - reserved
|
||||||
|
*
|
||||||
|
* If you call these set-macros more than once, you will have to clean the bits before doing so.
|
||||||
|
*/
|
||||||
|
#define FLAG_SET_OPSIZE(di, size) ((di->flags) |= (((size) & 3) << 8))
|
||||||
|
#define FLAG_SET_ADDRSIZE(di, size) ((di->flags) |= (((size) & 3) << 10))
|
||||||
|
#define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3)
|
||||||
|
#define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3)
|
||||||
|
/* To get the LOCK/REPNZ/REP prefixes. */
|
||||||
|
#define FLAG_GET_PREFIX(flags) ((flags) & 7)
|
||||||
|
/* Indicates whether the instruction is privileged. */
|
||||||
|
#define FLAG_GET_PRIVILEGED(flags) (((flags) & FLAG_PRIVILEGED_INSTRUCTION) != 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macros to extract segment registers from 'segment':
|
||||||
|
*/
|
||||||
|
#define SEGMENT_DEFAULT 0x80
|
||||||
|
#define SEGMENT_SET(di, seg) ((di->segment) |= seg)
|
||||||
|
#define SEGMENT_GET(segment) (((segment) == R_NONE) ? R_NONE : ((segment) & 0x7f))
|
||||||
|
#define SEGMENT_IS_DEFAULT(segment) (((segment) & SEGMENT_DEFAULT) == SEGMENT_DEFAULT)
|
||||||
|
|
||||||
|
|
||||||
|
/* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */
|
||||||
|
typedef enum { Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 } _DecodeType;
|
||||||
|
|
||||||
|
typedef OFFSET_INTEGER _OffsetType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
_OffsetType codeOffset, nextOffset; /* nextOffset is OUT only. */
|
||||||
|
const uint8_t* code;
|
||||||
|
int codeLen; /* Using signed integer makes it easier to detect an underflow. */
|
||||||
|
_DecodeType dt;
|
||||||
|
unsigned int features;
|
||||||
|
} _CodeInfo;
|
||||||
|
|
||||||
|
typedef enum { O_NONE, O_REG, O_IMM, O_IMM1, O_IMM2, O_DISP, O_SMEM, O_MEM, O_PC, O_PTR } _OperandType;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
/* Used by O_IMM: */
|
||||||
|
int8_t sbyte;
|
||||||
|
uint8_t byte;
|
||||||
|
int16_t sword;
|
||||||
|
uint16_t word;
|
||||||
|
int32_t sdword;
|
||||||
|
uint32_t dword;
|
||||||
|
int64_t sqword; /* All immediates are SIGN-EXTENDED to 64 bits! */
|
||||||
|
uint64_t qword;
|
||||||
|
|
||||||
|
/* Used by O_PC: (Use GET_TARGET_ADDR).*/
|
||||||
|
_OffsetType addr; /* It's a relative offset as for now. */
|
||||||
|
|
||||||
|
/* Used by O_PTR: */
|
||||||
|
struct {
|
||||||
|
uint16_t seg;
|
||||||
|
/* Can be 16 or 32 bits, size is in ops[n].size. */
|
||||||
|
uint32_t off;
|
||||||
|
} ptr;
|
||||||
|
|
||||||
|
/* Used by O_IMM1 (i1) and O_IMM2 (i2). ENTER instruction only. */
|
||||||
|
struct {
|
||||||
|
uint32_t i1;
|
||||||
|
uint32_t i2;
|
||||||
|
} ex;
|
||||||
|
} _Value;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* Type of operand:
|
||||||
|
O_NONE: operand is to be ignored.
|
||||||
|
O_REG: index holds global register index.
|
||||||
|
O_IMM: instruction.imm.
|
||||||
|
O_IMM1: instruction.imm.ex.i1.
|
||||||
|
O_IMM2: instruction.imm.ex.i2.
|
||||||
|
O_DISP: memory dereference with displacement only, instruction.disp.
|
||||||
|
O_SMEM: simple memory dereference with optional displacement (a single register memory dereference).
|
||||||
|
O_MEM: complex memory dereference (optional fields: s/i/b/disp).
|
||||||
|
O_PC: the relative address of a branch instruction (instruction.imm.addr).
|
||||||
|
O_PTR: the absolute target address of a far branch instruction (instruction.imm.ptr.seg/off).
|
||||||
|
*/
|
||||||
|
uint8_t type; /* _OperandType */
|
||||||
|
|
||||||
|
/* Index of:
|
||||||
|
O_REG: holds global register index
|
||||||
|
O_SMEM: holds the 'base' register. E.G: [ECX], [EBX+0x1234] are both in operand.index.
|
||||||
|
O_MEM: holds the 'index' register. E.G: [EAX*4] is in operand.index.
|
||||||
|
*/
|
||||||
|
uint8_t index;
|
||||||
|
|
||||||
|
/* Size in bits of:
|
||||||
|
O_REG: register
|
||||||
|
O_IMM: instruction.imm
|
||||||
|
O_IMM1: instruction.imm.ex.i1
|
||||||
|
O_IMM2: instruction.imm.ex.i2
|
||||||
|
O_DISP: instruction.disp
|
||||||
|
O_SMEM: size of indirection.
|
||||||
|
O_MEM: size of indirection.
|
||||||
|
O_PC: size of the relative offset
|
||||||
|
O_PTR: size of instruction.imm.ptr.off (16 or 32)
|
||||||
|
*/
|
||||||
|
uint16_t size;
|
||||||
|
} _Operand;
|
||||||
|
|
||||||
|
#define OPCODE_ID_NONE 0
|
||||||
|
/* Instruction could not be disassembled. */
|
||||||
|
#define FLAG_NOT_DECODABLE ((uint16_t)-1)
|
||||||
|
/* The instruction locks memory access. */
|
||||||
|
#define FLAG_LOCK (1 << 0)
|
||||||
|
/* The instruction is prefixed with a REPNZ. */
|
||||||
|
#define FLAG_REPNZ (1 << 1)
|
||||||
|
/* The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. */
|
||||||
|
#define FLAG_REP (1 << 2)
|
||||||
|
/* Indicates there is a hint taken for Jcc instructions only. */
|
||||||
|
#define FLAG_HINT_TAKEN (1 << 3)
|
||||||
|
/* Indicates there is a hint non-taken for Jcc instructions only. */
|
||||||
|
#define FLAG_HINT_NOT_TAKEN (1 << 4)
|
||||||
|
/* The Imm value is signed extended (E.G in 64 bit decoding mode, a 32 bit imm is usually sign extended into 64 bit imm). */
|
||||||
|
#define FLAG_IMM_SIGNED (1 << 5)
|
||||||
|
/* The destination operand is writable. */
|
||||||
|
#define FLAG_DST_WR (1 << 6)
|
||||||
|
/* The instruction uses RIP-relative indirection. */
|
||||||
|
#define FLAG_RIP_RELATIVE (1 << 7)
|
||||||
|
|
||||||
|
/* See flag FLAG_GET_XXX macros above. */
|
||||||
|
|
||||||
|
/* The instruction is privileged and can only be used from Ring0. */
|
||||||
|
#define FLAG_PRIVILEGED_INSTRUCTION (1 << 15)
|
||||||
|
|
||||||
|
/* No register was defined. */
|
||||||
|
#define R_NONE ((uint8_t)-1)
|
||||||
|
|
||||||
|
#define REGS64_BASE 0
|
||||||
|
#define REGS32_BASE 16
|
||||||
|
#define REGS16_BASE 32
|
||||||
|
#define REGS8_BASE 48
|
||||||
|
#define REGS8_REX_BASE 64
|
||||||
|
#define SREGS_BASE 68
|
||||||
|
#define FPUREGS_BASE 75
|
||||||
|
#define MMXREGS_BASE 83
|
||||||
|
#define SSEREGS_BASE 91
|
||||||
|
#define AVXREGS_BASE 107
|
||||||
|
#define CREGS_BASE 123
|
||||||
|
#define DREGS_BASE 132
|
||||||
|
|
||||||
|
#define OPERANDS_NO (4)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* Used by ops[n].type == O_IMM/O_IMM1&O_IMM2/O_PTR/O_PC. Its size is ops[n].size. */
|
||||||
|
_Value imm;
|
||||||
|
/* Used by ops[n].type == O_SMEM/O_MEM/O_DISP. Its size is dispSize. */
|
||||||
|
uint64_t disp;
|
||||||
|
/* Virtual address of first byte of instruction. */
|
||||||
|
_OffsetType addr;
|
||||||
|
/* General flags of instruction, holds prefixes and more, if FLAG_NOT_DECODABLE, instruction is invalid. */
|
||||||
|
uint16_t flags;
|
||||||
|
/* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */
|
||||||
|
uint16_t unusedPrefixesMask;
|
||||||
|
/* Mask of registers that were used in the operands, only used for quick look up, in order to know *some* operand uses that register class. */
|
||||||
|
uint32_t usedRegistersMask;
|
||||||
|
/* ID of opcode in the global opcode table. Use for mnemonic look up. */
|
||||||
|
uint16_t opcode;
|
||||||
|
/* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */
|
||||||
|
_Operand ops[OPERANDS_NO];
|
||||||
|
/* Size of the whole instruction in bytes. */
|
||||||
|
uint8_t size;
|
||||||
|
/* Segment information of memory indirection, default segment, or overriden one, can be -1. Use SEGMENT macros. */
|
||||||
|
uint8_t segment;
|
||||||
|
/* Used by ops[n].type == O_MEM. Base global register index (might be R_NONE), scale size (2/4/8), ignored for 0 or 1. */
|
||||||
|
uint8_t base, scale;
|
||||||
|
uint8_t dispSize;
|
||||||
|
/* Meta defines the instruction set class, and the flow control flags. Use META macros. */
|
||||||
|
uint8_t meta;
|
||||||
|
/* The CPU flags that the instruction operates upon. */
|
||||||
|
uint16_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask;
|
||||||
|
} _DInst;
|
||||||
|
|
||||||
|
#ifndef DISTORM_LIGHT
|
||||||
|
|
||||||
|
/* Static size of strings. Do not change this value. Keep Python wrapper in sync. */
|
||||||
|
#define MAX_TEXT_SIZE (48)
|
||||||
|
typedef struct {
|
||||||
|
unsigned int length;
|
||||||
|
unsigned char p[MAX_TEXT_SIZE]; /* p is a null terminated string. */
|
||||||
|
} _WString;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Old decoded instruction structure in text format.
|
||||||
|
* Used only for backward compatibility with diStorm64.
|
||||||
|
* This structure holds all information the disassembler generates per instruction.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
_WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */
|
||||||
|
_WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */
|
||||||
|
_WString instructionHex; /* Hex dump - little endian, including prefixes. */
|
||||||
|
unsigned int size; /* Size of decoded instruction in bytes. */
|
||||||
|
_OffsetType offset; /* Start offset of the decoded instruction. */
|
||||||
|
} _DecodedInst;
|
||||||
|
|
||||||
|
#endif /* DISTORM_LIGHT */
|
||||||
|
|
||||||
|
/* Register masks for quick look up, each mask indicates one of a register-class that is being used in some operand. */
|
||||||
|
#define RM_AX 1 /* AL, AH, AX, EAX, RAX */
|
||||||
|
#define RM_CX 2 /* CL, CH, CX, ECX, RCX */
|
||||||
|
#define RM_DX 4 /* DL, DH, DX, EDX, RDX */
|
||||||
|
#define RM_BX 8 /* BL, BH, BX, EBX, RBX */
|
||||||
|
#define RM_SP 0x10 /* SPL, SP, ESP, RSP */
|
||||||
|
#define RM_BP 0x20 /* BPL, BP, EBP, RBP */
|
||||||
|
#define RM_SI 0x40 /* SIL, SI, ESI, RSI */
|
||||||
|
#define RM_DI 0x80 /* DIL, DI, EDI, RDI */
|
||||||
|
#define RM_FPU 0x100 /* ST(0) - ST(7) */
|
||||||
|
#define RM_MMX 0x200 /* MM0 - MM7 */
|
||||||
|
#define RM_SSE 0x400 /* XMM0 - XMM15 */
|
||||||
|
#define RM_AVX 0x800 /* YMM0 - YMM15 */
|
||||||
|
#define RM_CR 0x1000 /* CR0, CR2, CR3, CR4, CR8 */
|
||||||
|
#define RM_DR 0x2000 /* DR0, DR1, DR2, DR3, DR6, DR7 */
|
||||||
|
#define RM_R8 0x4000 /* R8B, R8W, R8D, R8 */
|
||||||
|
#define RM_R9 0x8000 /* R9B, R9W, R9D, R9 */
|
||||||
|
#define RM_R10 0x10000 /* R10B, R10W, R10D, R10 */
|
||||||
|
#define RM_R11 0x20000 /* R11B, R11W, R11D, R11 */
|
||||||
|
#define RM_R12 0x40000 /* R12B, R12W, R12D, R12 */
|
||||||
|
#define RM_R13 0x80000 /* R13B, R13W, R13D, R13 */
|
||||||
|
#define RM_R14 0x100000 /* R14B, R14W, R14D, R14 */
|
||||||
|
#define RM_R15 0x200000 /* R15B, R15W, R15D, R15 */
|
||||||
|
|
||||||
|
/* RIP should be checked using the 'flags' field and FLAG_RIP_RELATIVE.
|
||||||
|
* Segments should be checked using the segment macros.
|
||||||
|
* For now R8 - R15 are not supported and non general purpose registers map into same RM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* CPU flags that instructions modify, test or undefine (are EFLAGS compatible!). */
|
||||||
|
#define D_CF 1 /* Carry */
|
||||||
|
#define D_PF 4 /* Parity */
|
||||||
|
#define D_AF 0x10 /* Auxiliary */
|
||||||
|
#define D_ZF 0x40 /* Zero */
|
||||||
|
#define D_SF 0x80 /* Sign */
|
||||||
|
#define D_IF 0x200 /* Interrupt */
|
||||||
|
#define D_DF 0x400 /* Direction */
|
||||||
|
#define D_OF 0x800 /* Overflow */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instructions Set classes:
|
||||||
|
* if you want a better understanding of the available classes, look at disOps project, file: x86sets.py.
|
||||||
|
*/
|
||||||
|
/* Indicates the instruction belongs to the General Integer set. */
|
||||||
|
#define ISC_INTEGER 1
|
||||||
|
/* Indicates the instruction belongs to the 387 FPU set. */
|
||||||
|
#define ISC_FPU 2
|
||||||
|
/* Indicates the instruction belongs to the P6 set. */
|
||||||
|
#define ISC_P6 3
|
||||||
|
/* Indicates the instruction belongs to the MMX set. */
|
||||||
|
#define ISC_MMX 4
|
||||||
|
/* Indicates the instruction belongs to the SSE set. */
|
||||||
|
#define ISC_SSE 5
|
||||||
|
/* Indicates the instruction belongs to the SSE2 set. */
|
||||||
|
#define ISC_SSE2 6
|
||||||
|
/* Indicates the instruction belongs to the SSE3 set. */
|
||||||
|
#define ISC_SSE3 7
|
||||||
|
/* Indicates the instruction belongs to the SSSE3 set. */
|
||||||
|
#define ISC_SSSE3 8
|
||||||
|
/* Indicates the instruction belongs to the SSE4.1 set. */
|
||||||
|
#define ISC_SSE4_1 9
|
||||||
|
/* Indicates the instruction belongs to the SSE4.2 set. */
|
||||||
|
#define ISC_SSE4_2 10
|
||||||
|
/* Indicates the instruction belongs to the AMD's SSE4.A set. */
|
||||||
|
#define ISC_SSE4_A 11
|
||||||
|
/* Indicates the instruction belongs to the 3DNow! set. */
|
||||||
|
#define ISC_3DNOW 12
|
||||||
|
/* Indicates the instruction belongs to the 3DNow! Extensions set. */
|
||||||
|
#define ISC_3DNOWEXT 13
|
||||||
|
/* Indicates the instruction belongs to the VMX (Intel) set. */
|
||||||
|
#define ISC_VMX 14
|
||||||
|
/* Indicates the instruction belongs to the SVM (AMD) set. */
|
||||||
|
#define ISC_SVM 15
|
||||||
|
/* Indicates the instruction belongs to the AVX (Intel) set. */
|
||||||
|
#define ISC_AVX 16
|
||||||
|
/* Indicates the instruction belongs to the FMA (Intel) set. */
|
||||||
|
#define ISC_FMA 17
|
||||||
|
/* Indicates the instruction belongs to the AES/AVX (Intel) set. */
|
||||||
|
#define ISC_AES 18
|
||||||
|
/* Indicates the instruction belongs to the CLMUL (Intel) set. */
|
||||||
|
#define ISC_CLMUL 19
|
||||||
|
|
||||||
|
/* Features for decompose: */
|
||||||
|
#define DF_NONE 0
|
||||||
|
/* The decoder will limit addresses to a maximum of 16 bits. */
|
||||||
|
#define DF_MAXIMUM_ADDR16 1
|
||||||
|
/* The decoder will limit addresses to a maximum of 32 bits. */
|
||||||
|
#define DF_MAXIMUM_ADDR32 2
|
||||||
|
/* The decoder will return only flow control instructions (and filter the others internally). */
|
||||||
|
#define DF_RETURN_FC_ONLY 4
|
||||||
|
/* The decoder will stop and return to the caller when the instruction 'CALL' (near and far) was decoded. */
|
||||||
|
#define DF_STOP_ON_CALL 8
|
||||||
|
/* The decoder will stop and return to the caller when the instruction 'RET' (near and far) was decoded. */
|
||||||
|
#define DF_STOP_ON_RET 0x10
|
||||||
|
/* The decoder will stop and return to the caller when the instruction system-call/ret was decoded. */
|
||||||
|
#define DF_STOP_ON_SYS 0x20
|
||||||
|
/* The decoder will stop and return to the caller when any of the branch 'JMP', (near and far) instructions were decoded. */
|
||||||
|
#define DF_STOP_ON_UNC_BRANCH 0x40
|
||||||
|
/* The decoder will stop and return to the caller when any of the conditional branch instruction were decoded. */
|
||||||
|
#define DF_STOP_ON_CND_BRANCH 0x80
|
||||||
|
/* The decoder will stop and return to the caller when the instruction 'INT' (INT, INT1, INTO, INT 3) was decoded. */
|
||||||
|
#define DF_STOP_ON_INT 0x100
|
||||||
|
/* The decoder will stop and return to the caller when any of the 'CMOVxx' instruction was decoded. */
|
||||||
|
#define DF_STOP_ON_CMOV 0x200
|
||||||
|
/* The decoder will stop and return to the caller when any flow control instruction was decoded. */
|
||||||
|
#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV)
|
||||||
|
|
||||||
|
/* Indicates the instruction is not a flow-control instruction. */
|
||||||
|
#define FC_NONE 0
|
||||||
|
/* Indicates the instruction is one of: CALL, CALL FAR. */
|
||||||
|
#define FC_CALL 1
|
||||||
|
/* Indicates the instruction is one of: RET, IRET, RETF. */
|
||||||
|
#define FC_RET 2
|
||||||
|
/* Indicates the instruction is one of: SYSCALL, SYSRET, SYSENTER, SYSEXIT. */
|
||||||
|
#define FC_SYS 3
|
||||||
|
/* Indicates the instruction is one of: JMP, JMP FAR. */
|
||||||
|
#define FC_UNC_BRANCH 4
|
||||||
|
/*
|
||||||
|
* Indicates the instruction is one of:
|
||||||
|
* JCXZ, JO, JNO, JB, JAE, JZ, JNZ, JBE, JA, JS, JNS, JP, JNP, JL, JGE, JLE, JG, LOOP, LOOPZ, LOOPNZ.
|
||||||
|
*/
|
||||||
|
#define FC_CND_BRANCH 5
|
||||||
|
/* Indiciates the instruction is one of: INT, INT1, INT 3, INTO, UD2. */
|
||||||
|
#define FC_INT 6
|
||||||
|
/* Indicates the instruction is one of: CMOVxx. */
|
||||||
|
#define FC_CMOV 7
|
||||||
|
|
||||||
|
/* Return code of the decoding function. */
|
||||||
|
typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR, DECRES_FILTERED } _DecodeResult;
|
||||||
|
|
||||||
|
/* Define the following interface functions only for outer projects. */
|
||||||
|
#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC))
|
||||||
|
|
||||||
|
/* distorm_decode
|
||||||
|
* Input:
|
||||||
|
* offset - Origin of the given code (virtual address that is), NOT an offset in code.
|
||||||
|
* code - Pointer to the code buffer to be disassembled.
|
||||||
|
* length - Amount of bytes that should be decoded from the code buffer.
|
||||||
|
* dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits).
|
||||||
|
* result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions.
|
||||||
|
* maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound.
|
||||||
|
* usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array.
|
||||||
|
* Output: usedInstructionsCount will hold the number of entries used in the result array
|
||||||
|
* and the result array itself will be filled with the disassembled instructions.
|
||||||
|
* Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...),
|
||||||
|
* DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount!
|
||||||
|
* Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the
|
||||||
|
* array you passed, this function will try to use as much entries as possible!
|
||||||
|
* Notes: 1)The minimal size of maxInstructions is 15.
|
||||||
|
* 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* distorm_decompose
|
||||||
|
* See more documentation online at the GitHub project's wiki.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifdef SUPPORT_64BIT_OFFSET
|
||||||
|
|
||||||
|
_DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount);
|
||||||
|
#define distorm_decompose distorm_decompose64
|
||||||
|
|
||||||
|
#ifndef DISTORM_LIGHT
|
||||||
|
/* If distorm-light is defined, we won't export these text-formatting functionality. */
|
||||||
|
_DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount);
|
||||||
|
void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result);
|
||||||
|
#define distorm_decode distorm_decode64
|
||||||
|
#define distorm_format distorm_format64
|
||||||
|
#endif /*DISTORM_LIGHT*/
|
||||||
|
|
||||||
|
#else /*SUPPORT_64BIT_OFFSET*/
|
||||||
|
|
||||||
|
_DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount);
|
||||||
|
#define distorm_decompose distorm_decompose32
|
||||||
|
|
||||||
|
#ifndef DISTORM_LIGHT
|
||||||
|
/* If distorm-light is defined, we won't export these text-formatting functionality. */
|
||||||
|
_DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount);
|
||||||
|
void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result);
|
||||||
|
#define distorm_decode distorm_decode32
|
||||||
|
#define distorm_format distorm_format32
|
||||||
|
#endif /*DISTORM_LIGHT*/
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* distorm_version
|
||||||
|
* Input:
|
||||||
|
* none
|
||||||
|
*
|
||||||
|
* Output: unsigned int - version of compiled library.
|
||||||
|
*/
|
||||||
|
unsigned int distorm_version();
|
||||||
|
|
||||||
|
#endif /* DISTORM_STATIC */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* End Of Extern */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* DISTORM_H */
|
|
@ -0,0 +1,301 @@
|
||||||
|
/*
|
||||||
|
mnemonics.h
|
||||||
|
|
||||||
|
diStorm3 - Powerful disassembler for X86/AMD64
|
||||||
|
http://ragestorm.net/distorm/
|
||||||
|
distorm at gmail dot com
|
||||||
|
Copyright (C) 2003-2016 Gil Dabah
|
||||||
|
This library is licensed under the BSD license. See the file COPYING.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MNEMONICS_H
|
||||||
|
#define MNEMONICS_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DISTORM_LIGHT
|
||||||
|
|
||||||
|
typedef struct WMnemonic {
|
||||||
|
unsigned char length;
|
||||||
|
unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */
|
||||||
|
} _WMnemonic;
|
||||||
|
|
||||||
|
typedef struct WRegister {
|
||||||
|
unsigned int length;
|
||||||
|
unsigned char p[6]; /* p is a null terminated string. */
|
||||||
|
} _WRegister;
|
||||||
|
|
||||||
|
extern const unsigned char _MNEMONICS[];
|
||||||
|
extern const _WRegister _REGISTERS[];
|
||||||
|
|
||||||
|
#endif /* DISTORM_LIGHT */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* End Of Extern */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p
|
||||||
|
#define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
I_UNDEFINED = 0, I_AAA = 66, I_AAD = 389, I_AAM = 384, I_AAS = 76, I_ADC = 31, I_ADD = 11, I_ADDPD = 3132,
|
||||||
|
I_ADDPS = 3125, I_ADDSD = 3146, I_ADDSS = 3139, I_ADDSUBPD = 6416, I_ADDSUBPS = 6426,
|
||||||
|
I_AESDEC = 9231, I_AESDECLAST = 9248, I_AESENC = 9189, I_AESENCLAST = 9206,
|
||||||
|
I_AESIMC = 9172, I_AESKEYGENASSIST = 9817, I_AND = 41, I_ANDNPD = 3043, I_ANDNPS = 3035,
|
||||||
|
I_ANDPD = 3012, I_ANDPS = 3005, I_ARPL = 111, I_BLENDPD = 9394, I_BLENDPS = 9375,
|
||||||
|
I_BLENDVPD = 7641, I_BLENDVPS = 7631, I_BOUND = 104, I_BSF = 4368, I_BSR = 4380,
|
||||||
|
I_BSWAP = 960, I_BT = 872, I_BTC = 934, I_BTR = 912, I_BTS = 887, I_CALL = 456,
|
||||||
|
I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250, I_CDQE = 239, I_CLC = 492, I_CLD = 512,
|
||||||
|
I_CLFLUSH = 4351, I_CLGI = 1855, I_CLI = 502, I_CLTS = 541, I_CMC = 487, I_CMOVA = 694,
|
||||||
|
I_CMOVAE = 663, I_CMOVB = 656, I_CMOVBE = 686, I_CMOVG = 754, I_CMOVGE = 738,
|
||||||
|
I_CMOVL = 731, I_CMOVLE = 746, I_CMOVNO = 648, I_CMOVNP = 723, I_CMOVNS = 708,
|
||||||
|
I_CMOVNZ = 678, I_CMOVO = 641, I_CMOVP = 716, I_CMOVS = 701, I_CMOVZ = 671,
|
||||||
|
I_CMP = 71, I_CMPEQPD = 4471, I_CMPEQPS = 4392, I_CMPEQSD = 4629, I_CMPEQSS = 4550,
|
||||||
|
I_CMPLEPD = 4489, I_CMPLEPS = 4410, I_CMPLESD = 4647, I_CMPLESS = 4568, I_CMPLTPD = 4480,
|
||||||
|
I_CMPLTPS = 4401, I_CMPLTSD = 4638, I_CMPLTSS = 4559, I_CMPNEQPD = 4510, I_CMPNEQPS = 4431,
|
||||||
|
I_CMPNEQSD = 4668, I_CMPNEQSS = 4589, I_CMPNLEPD = 4530, I_CMPNLEPS = 4451,
|
||||||
|
I_CMPNLESD = 4688, I_CMPNLESS = 4609, I_CMPNLTPD = 4520, I_CMPNLTPS = 4441,
|
||||||
|
I_CMPNLTSD = 4678, I_CMPNLTSS = 4599, I_CMPORDPD = 4540, I_CMPORDPS = 4461,
|
||||||
|
I_CMPORDSD = 4698, I_CMPORDSS = 4619, I_CMPS = 301, I_CMPUNORDPD = 4498, I_CMPUNORDPS = 4419,
|
||||||
|
I_CMPUNORDSD = 4656, I_CMPUNORDSS = 4577, I_CMPXCHG = 898, I_CMPXCHG16B = 6395,
|
||||||
|
I_CMPXCHG8B = 6384, I_COMISD = 2801, I_COMISS = 2793, I_CPUID = 865, I_CQO = 255,
|
||||||
|
I_CRC32 = 9280, I_CVTDQ2PD = 6809, I_CVTDQ2PS = 3329, I_CVTPD2DQ = 6819, I_CVTPD2PI = 2703,
|
||||||
|
I_CVTPD2PS = 3255, I_CVTPH2PS = 4183, I_CVTPI2PD = 2517, I_CVTPI2PS = 2507,
|
||||||
|
I_CVTPS2DQ = 3339, I_CVTPS2PD = 3245, I_CVTPS2PH = 4193, I_CVTPS2PI = 2693,
|
||||||
|
I_CVTSD2SI = 2723, I_CVTSD2SS = 3275, I_CVTSI2SD = 2537, I_CVTSI2SS = 2527,
|
||||||
|
I_CVTSS2SD = 3265, I_CVTSS2SI = 2713, I_CVTTPD2DQ = 6798, I_CVTTPD2PI = 2636,
|
||||||
|
I_CVTTPS2DQ = 3349, I_CVTTPS2PI = 2625, I_CVTTSD2SI = 2658, I_CVTTSS2SI = 2647,
|
||||||
|
I_CWD = 245, I_CWDE = 233, I_DAA = 46, I_DAS = 56, I_DEC = 86, I_DIV = 1646,
|
||||||
|
I_DIVPD = 3521, I_DIVPS = 3514, I_DIVSD = 3535, I_DIVSS = 3528, I_DPPD = 9637,
|
||||||
|
I_DPPS = 9624, I_EMMS = 4122, I_ENTER = 340, I_EXTRACTPS = 9502, I_EXTRQ = 4158,
|
||||||
|
I_F2XM1 = 1192, I_FABS = 1123, I_FADD = 1023, I_FADDP = 1549, I_FBLD = 1601,
|
||||||
|
I_FBSTP = 1607, I_FCHS = 1117, I_FCLEX = 7311, I_FCMOVB = 1376, I_FCMOVBE = 1392,
|
||||||
|
I_FCMOVE = 1384, I_FCMOVNB = 1445, I_FCMOVNBE = 1463, I_FCMOVNE = 1454, I_FCMOVNU = 1473,
|
||||||
|
I_FCMOVU = 1401, I_FCOM = 1035, I_FCOMI = 1512, I_FCOMIP = 1623, I_FCOMP = 1041,
|
||||||
|
I_FCOMPP = 1563, I_FCOS = 1311, I_FDECSTP = 1238, I_FDIV = 1061, I_FDIVP = 1594,
|
||||||
|
I_FDIVR = 1067, I_FDIVRP = 1586, I_FEDISI = 1488, I_FEMMS = 574, I_FENI = 1482,
|
||||||
|
I_FFREE = 1527, I_FIADD = 1317, I_FICOM = 1331, I_FICOMP = 1338, I_FIDIV = 1361,
|
||||||
|
I_FIDIVR = 1368, I_FILD = 1418, I_FIMUL = 1324, I_FINCSTP = 1247, I_FINIT = 7326,
|
||||||
|
I_FIST = 1432, I_FISTP = 1438, I_FISTTP = 1424, I_FISUB = 1346, I_FISUBR = 1353,
|
||||||
|
I_FLD = 1074, I_FLD1 = 1141, I_FLDCW = 1098, I_FLDENV = 1090, I_FLDL2E = 1155,
|
||||||
|
I_FLDL2T = 1147, I_FLDLG2 = 1170, I_FLDLN2 = 1178, I_FLDPI = 1163, I_FLDZ = 1186,
|
||||||
|
I_FMUL = 1029, I_FMULP = 1556, I_FNCLEX = 7303, I_FNINIT = 7318, I_FNOP = 1111,
|
||||||
|
I_FNSAVE = 7333, I_FNSTCW = 7288, I_FNSTENV = 7271, I_FNSTSW = 7348, I_FPATAN = 1213,
|
||||||
|
I_FPREM = 1256, I_FPREM1 = 1230, I_FPTAN = 1206, I_FRNDINT = 1288, I_FRSTOR = 1519,
|
||||||
|
I_FSAVE = 7341, I_FSCALE = 1297, I_FSETPM = 1496, I_FSIN = 1305, I_FSINCOS = 1279,
|
||||||
|
I_FSQRT = 1272, I_FST = 1079, I_FSTCW = 7296, I_FSTENV = 7280, I_FSTP = 1084,
|
||||||
|
I_FSTSW = 7356, I_FSUB = 1048, I_FSUBP = 1579, I_FSUBR = 1054, I_FSUBRP = 1571,
|
||||||
|
I_FTST = 1129, I_FUCOM = 1534, I_FUCOMI = 1504, I_FUCOMIP = 1614, I_FUCOMP = 1541,
|
||||||
|
I_FUCOMPP = 1409, I_FXAM = 1135, I_FXCH = 1105, I_FXRSTOR = 9914, I_FXRSTOR64 = 9923,
|
||||||
|
I_FXSAVE = 9886, I_FXSAVE64 = 9894, I_FXTRACT = 1221, I_FYL2X = 1199, I_FYL2XP1 = 1263,
|
||||||
|
I_GETSEC = 633, I_HADDPD = 4203, I_HADDPS = 4211, I_HLT = 482, I_HSUBPD = 4237,
|
||||||
|
I_HSUBPS = 4245, I_IDIV = 1651, I_IMUL = 117, I_IN = 447, I_INC = 81, I_INS = 123,
|
||||||
|
I_INSERTPS = 9569, I_INSERTQ = 4165, I_INT = 367, I_INT_3 = 360, I_INT1 = 476,
|
||||||
|
I_INTO = 372, I_INVD = 555, I_INVEPT = 8306, I_INVLPG = 1727, I_INVLPGA = 1869,
|
||||||
|
I_INVPCID = 8323, I_INVVPID = 8314, I_IRET = 378, I_JA = 166, I_JAE = 147,
|
||||||
|
I_JB = 143, I_JBE = 161, I_JCXZ = 427, I_JECXZ = 433, I_JG = 202, I_JGE = 192,
|
||||||
|
I_JL = 188, I_JLE = 197, I_JMP = 462, I_JMP_FAR = 467, I_JNO = 138, I_JNP = 183,
|
||||||
|
I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, I_JRCXZ = 440, I_JS = 170,
|
||||||
|
I_JZ = 152, I_LAHF = 289, I_LAR = 522, I_LDDQU = 7016, I_LDMXCSR = 9944, I_LDS = 335,
|
||||||
|
I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4287, I_LFS = 917, I_LGDT = 1703,
|
||||||
|
I_LGS = 922, I_LIDT = 1709, I_LLDT = 1668, I_LMSW = 1721, I_LODS = 313, I_LOOP = 421,
|
||||||
|
I_LOOPNZ = 406, I_LOOPZ = 414, I_LSL = 527, I_LSS = 907, I_LTR = 1674, I_LZCNT = 4385,
|
||||||
|
I_MASKMOVDQU = 7141, I_MASKMOVQ = 7131, I_MAXPD = 3581, I_MAXPS = 3574, I_MAXSD = 3595,
|
||||||
|
I_MAXSS = 3588, I_MFENCE = 4313, I_MINPD = 3461, I_MINPS = 3454, I_MINSD = 3475,
|
||||||
|
I_MINSS = 3468, I_MONITOR = 1771, I_MOV = 218, I_MOVAPD = 2481, I_MOVAPS = 2473,
|
||||||
|
I_MOVBE = 9273, I_MOVD = 3942, I_MOVDDUP = 2208, I_MOVDQ2Q = 6544, I_MOVDQA = 3968,
|
||||||
|
I_MOVDQU = 3976, I_MOVHLPS = 2173, I_MOVHPD = 2367, I_MOVHPS = 2359, I_MOVLHPS = 2350,
|
||||||
|
I_MOVLPD = 2190, I_MOVLPS = 2182, I_MOVMSKPD = 2837, I_MOVMSKPS = 2827, I_MOVNTDQ = 6871,
|
||||||
|
I_MOVNTDQA = 7917, I_MOVNTI = 952, I_MOVNTPD = 2578, I_MOVNTPS = 2569, I_MOVNTQ = 6863,
|
||||||
|
I_MOVNTSD = 2596, I_MOVNTSS = 2587, I_MOVQ = 3948, I_MOVQ2DQ = 6535, I_MOVS = 295,
|
||||||
|
I_MOVSD = 2132, I_MOVSHDUP = 2375, I_MOVSLDUP = 2198, I_MOVSS = 2125, I_MOVSX = 939,
|
||||||
|
I_MOVSXD = 10027, I_MOVUPD = 2117, I_MOVUPS = 2109, I_MOVZX = 927, I_MPSADBW = 9650,
|
||||||
|
I_MUL = 1641, I_MULPD = 3192, I_MULPS = 3185, I_MULSD = 3206, I_MULSS = 3199,
|
||||||
|
I_MWAIT = 1780, I_NEG = 1636, I_NOP = 581, I_NOT = 1631, I_OR = 27, I_ORPD = 3075,
|
||||||
|
I_ORPS = 3069, I_OUT = 451, I_OUTS = 128, I_PABSB = 7710, I_PABSD = 7740, I_PABSW = 7725,
|
||||||
|
I_PACKSSDW = 3871, I_PACKSSWB = 3703, I_PACKUSDW = 7938, I_PACKUSWB = 3781,
|
||||||
|
I_PADDB = 7226, I_PADDD = 7256, I_PADDQ = 6503, I_PADDSB = 6952, I_PADDSW = 6969,
|
||||||
|
I_PADDUSB = 6642, I_PADDUSW = 6661, I_PADDW = 7241, I_PALIGNR = 9432, I_PAND = 6629,
|
||||||
|
I_PANDN = 6687, I_PAUSE = 10035, I_PAVGB = 6702, I_PAVGUSB = 2100, I_PAVGW = 6747,
|
||||||
|
I_PBLENDVB = 7621, I_PBLENDW = 9413, I_PCLMULQDQ = 9669, I_PCMPEQB = 4065,
|
||||||
|
I_PCMPEQD = 4103, I_PCMPEQQ = 7898, I_PCMPEQW = 4084, I_PCMPESTRI = 9748,
|
||||||
|
I_PCMPESTRM = 9725, I_PCMPGTB = 3724, I_PCMPGTD = 3762, I_PCMPGTQ = 8109,
|
||||||
|
I_PCMPGTW = 3743, I_PCMPISTRI = 9794, I_PCMPISTRM = 9771, I_PEXTRB = 9451,
|
||||||
|
I_PEXTRD = 9468, I_PEXTRQ = 9476, I_PEXTRW = 6333, I_PF2ID = 1936, I_PF2IW = 1929,
|
||||||
|
I_PFACC = 2050, I_PFADD = 1999, I_PFCMPEQ = 2057, I_PFCMPGE = 1960, I_PFCMPGT = 2006,
|
||||||
|
I_PFMAX = 2015, I_PFMIN = 1969, I_PFMUL = 2066, I_PFNACC = 1943, I_PFPNACC = 1951,
|
||||||
|
I_PFRCP = 1976, I_PFRCPIT1 = 2022, I_PFRCPIT2 = 2073, I_PFRSQIT1 = 2032, I_PFRSQRT = 1983,
|
||||||
|
I_PFSUB = 1992, I_PFSUBR = 2042, I_PHADDD = 7397, I_PHADDSW = 7414, I_PHADDW = 7380,
|
||||||
|
I_PHMINPOSUW = 8281, I_PHSUBD = 7473, I_PHSUBSW = 7490, I_PHSUBW = 7456, I_PI2FD = 1922,
|
||||||
|
I_PI2FW = 1915, I_PINSRB = 9552, I_PINSRD = 9590, I_PINSRQ = 9598, I_PINSRW = 6316,
|
||||||
|
I_PMADDUBSW = 7433, I_PMADDWD = 7095, I_PMAXSB = 8196, I_PMAXSD = 8213, I_PMAXSW = 6986,
|
||||||
|
I_PMAXUB = 6670, I_PMAXUD = 8247, I_PMAXUW = 8230, I_PMINSB = 8128, I_PMINSD = 8145,
|
||||||
|
I_PMINSW = 6924, I_PMINUB = 6612, I_PMINUD = 8179, I_PMINUW = 8162, I_PMOVMSKB = 6553,
|
||||||
|
I_PMOVSXBD = 7776, I_PMOVSXBQ = 7797, I_PMOVSXBW = 7755, I_PMOVSXDQ = 7860,
|
||||||
|
I_PMOVSXWD = 7818, I_PMOVSXWQ = 7839, I_PMOVZXBD = 8004, I_PMOVZXBQ = 8025,
|
||||||
|
I_PMOVZXBW = 7983, I_PMOVZXDQ = 8088, I_PMOVZXWD = 8046, I_PMOVZXWQ = 8067,
|
||||||
|
I_PMULDQ = 7881, I_PMULHRSW = 7560, I_PMULHRW = 2083, I_PMULHUW = 6762, I_PMULHW = 6781,
|
||||||
|
I_PMULLD = 8264, I_PMULLW = 6518, I_PMULUDQ = 7076, I_POP = 22, I_POPA = 98,
|
||||||
|
I_POPCNT = 4360, I_POPF = 277, I_POR = 6941, I_PREFETCH = 1894, I_PREFETCHNTA = 2424,
|
||||||
|
I_PREFETCHT0 = 2437, I_PREFETCHT1 = 2449, I_PREFETCHT2 = 2461, I_PREFETCHW = 1904,
|
||||||
|
I_PSADBW = 7114, I_PSHUFB = 7363, I_PSHUFD = 4010, I_PSHUFHW = 4018, I_PSHUFLW = 4027,
|
||||||
|
I_PSHUFW = 4002, I_PSIGNB = 7509, I_PSIGND = 7543, I_PSIGNW = 7526, I_PSLLD = 7046,
|
||||||
|
I_PSLLDQ = 9869, I_PSLLQ = 7061, I_PSLLW = 7031, I_PSRAD = 6732, I_PSRAW = 6717,
|
||||||
|
I_PSRLD = 6473, I_PSRLDQ = 9852, I_PSRLQ = 6488, I_PSRLW = 6458, I_PSUBB = 7166,
|
||||||
|
I_PSUBD = 7196, I_PSUBQ = 7211, I_PSUBSB = 6890, I_PSUBSW = 6907, I_PSUBUSB = 6574,
|
||||||
|
I_PSUBUSW = 6593, I_PSUBW = 7181, I_PSWAPD = 2092, I_PTEST = 7651, I_PUNPCKHBW = 3802,
|
||||||
|
I_PUNPCKHDQ = 3848, I_PUNPCKHQDQ = 3917, I_PUNPCKHWD = 3825, I_PUNPCKLBW = 3634,
|
||||||
|
I_PUNPCKLDQ = 3680, I_PUNPCKLQDQ = 3892, I_PUNPCKLWD = 3657, I_PUSH = 16,
|
||||||
|
I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 7003, I_RCL = 977, I_RCPPS = 2975, I_RCPSS = 2982,
|
||||||
|
I_RCR = 982, I_RDFSBASE = 9904, I_RDGSBASE = 9934, I_RDMSR = 600, I_RDPMC = 607,
|
||||||
|
I_RDRAND = 10048, I_RDTSC = 593, I_RDTSCP = 1886, I_RET = 325, I_RETF = 354,
|
||||||
|
I_ROL = 967, I_ROR = 972, I_ROUNDPD = 9318, I_ROUNDPS = 9299, I_ROUNDSD = 9356,
|
||||||
|
I_ROUNDSS = 9337, I_RSM = 882, I_RSQRTPS = 2937, I_RSQRTSS = 2946, I_SAHF = 283,
|
||||||
|
I_SAL = 997, I_SALC = 394, I_SAR = 1002, I_SBB = 36, I_SCAS = 319, I_SETA = 807,
|
||||||
|
I_SETAE = 780, I_SETB = 774, I_SETBE = 800, I_SETG = 859, I_SETGE = 845, I_SETL = 839,
|
||||||
|
I_SETLE = 852, I_SETNO = 767, I_SETNP = 832, I_SETNS = 819, I_SETNZ = 793,
|
||||||
|
I_SETO = 761, I_SETP = 826, I_SETS = 813, I_SETZ = 787, I_SFENCE = 4343, I_SGDT = 1691,
|
||||||
|
I_SHL = 987, I_SHLD = 876, I_SHR = 992, I_SHRD = 892, I_SHUFPD = 6358, I_SHUFPS = 6350,
|
||||||
|
I_SIDT = 1697, I_SKINIT = 1861, I_SLDT = 1657, I_SMSW = 1715, I_SQRTPD = 2877,
|
||||||
|
I_SQRTPS = 2869, I_SQRTSD = 2893, I_SQRTSS = 2885, I_STC = 497, I_STD = 517,
|
||||||
|
I_STGI = 1849, I_STI = 507, I_STMXCSR = 9973, I_STOS = 307, I_STR = 1663, I_SUB = 51,
|
||||||
|
I_SUBPD = 3401, I_SUBPS = 3394, I_SUBSD = 3415, I_SUBSS = 3408, I_SWAPGS = 1878,
|
||||||
|
I_SYSCALL = 532, I_SYSENTER = 614, I_SYSEXIT = 624, I_SYSRET = 547, I_TEST = 206,
|
||||||
|
I_TZCNT = 4373, I_UCOMISD = 2764, I_UCOMISS = 2755, I_UD2 = 569, I_UNPCKHPD = 2318,
|
||||||
|
I_UNPCKHPS = 2308, I_UNPCKLPD = 2276, I_UNPCKLPS = 2266, I_VADDPD = 3161,
|
||||||
|
I_VADDPS = 3153, I_VADDSD = 3177, I_VADDSS = 3169, I_VADDSUBPD = 6436, I_VADDSUBPS = 6447,
|
||||||
|
I_VAESDEC = 9239, I_VAESDECLAST = 9260, I_VAESENC = 9197, I_VAESENCLAST = 9218,
|
||||||
|
I_VAESIMC = 9180, I_VAESKEYGENASSIST = 9834, I_VANDNPD = 3060, I_VANDNPS = 3051,
|
||||||
|
I_VANDPD = 3027, I_VANDPS = 3019, I_VBLENDPD = 9403, I_VBLENDPS = 9384, I_VBLENDVPD = 9703,
|
||||||
|
I_VBLENDVPS = 9692, I_VBROADCASTF128 = 7694, I_VBROADCASTSD = 7680, I_VBROADCASTSS = 7666,
|
||||||
|
I_VCMPEQPD = 5110, I_VCMPEQPS = 4708, I_VCMPEQSD = 5914, I_VCMPEQSS = 5512,
|
||||||
|
I_VCMPEQ_OSPD = 5291, I_VCMPEQ_OSPS = 4889, I_VCMPEQ_OSSD = 6095, I_VCMPEQ_OSSS = 5693,
|
||||||
|
I_VCMPEQ_UQPD = 5197, I_VCMPEQ_UQPS = 4795, I_VCMPEQ_UQSD = 6001, I_VCMPEQ_UQSS = 5599,
|
||||||
|
I_VCMPEQ_USPD = 5400, I_VCMPEQ_USPS = 4998, I_VCMPEQ_USSD = 6204, I_VCMPEQ_USSS = 5802,
|
||||||
|
I_VCMPFALSEPD = 5232, I_VCMPFALSEPS = 4830, I_VCMPFALSESD = 6036, I_VCMPFALSESS = 5634,
|
||||||
|
I_VCMPFALSE_OSPD = 5441, I_VCMPFALSE_OSPS = 5039, I_VCMPFALSE_OSSD = 6245,
|
||||||
|
I_VCMPFALSE_OSSS = 5843, I_VCMPGEPD = 5259, I_VCMPGEPS = 4857, I_VCMPGESD = 6063,
|
||||||
|
I_VCMPGESS = 5661, I_VCMPGE_OQPD = 5471, I_VCMPGE_OQPS = 5069, I_VCMPGE_OQSD = 6275,
|
||||||
|
I_VCMPGE_OQSS = 5873, I_VCMPGTPD = 5269, I_VCMPGTPS = 4867, I_VCMPGTSD = 6073,
|
||||||
|
I_VCMPGTSS = 5671, I_VCMPGT_OQPD = 5484, I_VCMPGT_OQPS = 5082, I_VCMPGT_OQSD = 6288,
|
||||||
|
I_VCMPGT_OQSS = 5886, I_VCMPLEPD = 5130, I_VCMPLEPS = 4728, I_VCMPLESD = 5934,
|
||||||
|
I_VCMPLESS = 5532, I_VCMPLE_OQPD = 5317, I_VCMPLE_OQPS = 4915, I_VCMPLE_OQSD = 6121,
|
||||||
|
I_VCMPLE_OQSS = 5719, I_VCMPLTPD = 5120, I_VCMPLTPS = 4718, I_VCMPLTSD = 5924,
|
||||||
|
I_VCMPLTSS = 5522, I_VCMPLT_OQPD = 5304, I_VCMPLT_OQPS = 4902, I_VCMPLT_OQSD = 6108,
|
||||||
|
I_VCMPLT_OQSS = 5706, I_VCMPNEQPD = 5153, I_VCMPNEQPS = 4751, I_VCMPNEQSD = 5957,
|
||||||
|
I_VCMPNEQSS = 5555, I_VCMPNEQ_OQPD = 5245, I_VCMPNEQ_OQPS = 4843, I_VCMPNEQ_OQSD = 6049,
|
||||||
|
I_VCMPNEQ_OQSS = 5647, I_VCMPNEQ_OSPD = 5457, I_VCMPNEQ_OSPS = 5055, I_VCMPNEQ_OSSD = 6261,
|
||||||
|
I_VCMPNEQ_OSSS = 5859, I_VCMPNEQ_USPD = 5345, I_VCMPNEQ_USPS = 4943, I_VCMPNEQ_USSD = 6149,
|
||||||
|
I_VCMPNEQ_USSS = 5747, I_VCMPNGEPD = 5210, I_VCMPNGEPS = 4808, I_VCMPNGESD = 6014,
|
||||||
|
I_VCMPNGESS = 5612, I_VCMPNGE_UQPD = 5413, I_VCMPNGE_UQPS = 5011, I_VCMPNGE_UQSD = 6217,
|
||||||
|
I_VCMPNGE_UQSS = 5815, I_VCMPNGTPD = 5221, I_VCMPNGTPS = 4819, I_VCMPNGTSD = 6025,
|
||||||
|
I_VCMPNGTSS = 5623, I_VCMPNGT_UQPD = 5427, I_VCMPNGT_UQPS = 5025, I_VCMPNGT_UQSD = 6231,
|
||||||
|
I_VCMPNGT_UQSS = 5829, I_VCMPNLEPD = 5175, I_VCMPNLEPS = 4773, I_VCMPNLESD = 5979,
|
||||||
|
I_VCMPNLESS = 5577, I_VCMPNLE_UQPD = 5373, I_VCMPNLE_UQPS = 4971, I_VCMPNLE_UQSD = 6177,
|
||||||
|
I_VCMPNLE_UQSS = 5775, I_VCMPNLTPD = 5164, I_VCMPNLTPS = 4762, I_VCMPNLTSD = 5968,
|
||||||
|
I_VCMPNLTSS = 5566, I_VCMPNLT_UQPD = 5359, I_VCMPNLT_UQPS = 4957, I_VCMPNLT_UQSD = 6163,
|
||||||
|
I_VCMPNLT_UQSS = 5761, I_VCMPORDPD = 5186, I_VCMPORDPS = 4784, I_VCMPORDSD = 5990,
|
||||||
|
I_VCMPORDSS = 5588, I_VCMPORD_SPD = 5387, I_VCMPORD_SPS = 4985, I_VCMPORD_SSD = 6191,
|
||||||
|
I_VCMPORD_SSS = 5789, I_VCMPTRUEPD = 5279, I_VCMPTRUEPS = 4877, I_VCMPTRUESD = 6083,
|
||||||
|
I_VCMPTRUESS = 5681, I_VCMPTRUE_USPD = 5497, I_VCMPTRUE_USPS = 5095, I_VCMPTRUE_USSD = 6301,
|
||||||
|
I_VCMPTRUE_USSS = 5899, I_VCMPUNORDPD = 5140, I_VCMPUNORDPS = 4738, I_VCMPUNORDSD = 5944,
|
||||||
|
I_VCMPUNORDSS = 5542, I_VCMPUNORD_SPD = 5330, I_VCMPUNORD_SPS = 4928, I_VCMPUNORD_SSD = 6134,
|
||||||
|
I_VCMPUNORD_SSS = 5732, I_VCOMISD = 2818, I_VCOMISS = 2809, I_VCVTDQ2PD = 6841,
|
||||||
|
I_VCVTDQ2PS = 3360, I_VCVTPD2DQ = 6852, I_VCVTPD2PS = 3296, I_VCVTPS2DQ = 3371,
|
||||||
|
I_VCVTPS2PD = 3285, I_VCVTSD2SI = 2744, I_VCVTSD2SS = 3318, I_VCVTSI2SD = 2558,
|
||||||
|
I_VCVTSI2SS = 2547, I_VCVTSS2SD = 3307, I_VCVTSS2SI = 2733, I_VCVTTPD2DQ = 6829,
|
||||||
|
I_VCVTTPS2DQ = 3382, I_VCVTTSD2SI = 2681, I_VCVTTSS2SI = 2669, I_VDIVPD = 3550,
|
||||||
|
I_VDIVPS = 3542, I_VDIVSD = 3566, I_VDIVSS = 3558, I_VDPPD = 9643, I_VDPPS = 9630,
|
||||||
|
I_VERR = 1679, I_VERW = 1685, I_VEXTRACTF128 = 9538, I_VEXTRACTPS = 9513,
|
||||||
|
I_VFMADD132PD = 8409, I_VFMADD132PS = 8396, I_VFMADD132SD = 8435, I_VFMADD132SS = 8422,
|
||||||
|
I_VFMADD213PD = 8689, I_VFMADD213PS = 8676, I_VFMADD213SD = 8715, I_VFMADD213SS = 8702,
|
||||||
|
I_VFMADD231PD = 8969, I_VFMADD231PS = 8956, I_VFMADD231SD = 8995, I_VFMADD231SS = 8982,
|
||||||
|
I_VFMADDSUB132PD = 8348, I_VFMADDSUB132PS = 8332, I_VFMADDSUB213PD = 8628,
|
||||||
|
I_VFMADDSUB213PS = 8612, I_VFMADDSUB231PD = 8908, I_VFMADDSUB231PS = 8892,
|
||||||
|
I_VFMSUB132PD = 8461, I_VFMSUB132PS = 8448, I_VFMSUB132SD = 8487, I_VFMSUB132SS = 8474,
|
||||||
|
I_VFMSUB213PD = 8741, I_VFMSUB213PS = 8728, I_VFMSUB213SD = 8767, I_VFMSUB213SS = 8754,
|
||||||
|
I_VFMSUB231PD = 9021, I_VFMSUB231PS = 9008, I_VFMSUB231SD = 9047, I_VFMSUB231SS = 9034,
|
||||||
|
I_VFMSUBADD132PD = 8380, I_VFMSUBADD132PS = 8364, I_VFMSUBADD213PD = 8660,
|
||||||
|
I_VFMSUBADD213PS = 8644, I_VFMSUBADD231PD = 8940, I_VFMSUBADD231PS = 8924,
|
||||||
|
I_VFNMADD132PD = 8514, I_VFNMADD132PS = 8500, I_VFNMADD132SD = 8542, I_VFNMADD132SS = 8528,
|
||||||
|
I_VFNMADD213PD = 8794, I_VFNMADD213PS = 8780, I_VFNMADD213SD = 8822, I_VFNMADD213SS = 8808,
|
||||||
|
I_VFNMADD231PD = 9074, I_VFNMADD231PS = 9060, I_VFNMADD231SD = 9102, I_VFNMADD231SS = 9088,
|
||||||
|
I_VFNMSUB132PD = 8570, I_VFNMSUB132PS = 8556, I_VFNMSUB132SD = 8598, I_VFNMSUB132SS = 8584,
|
||||||
|
I_VFNMSUB213PD = 8850, I_VFNMSUB213PS = 8836, I_VFNMSUB213SD = 8878, I_VFNMSUB213SS = 8864,
|
||||||
|
I_VFNMSUB231PD = 9130, I_VFNMSUB231PS = 9116, I_VFNMSUB231SD = 9158, I_VFNMSUB231SS = 9144,
|
||||||
|
I_VHADDPD = 4219, I_VHADDPS = 4228, I_VHSUBPD = 4253, I_VHSUBPS = 4262, I_VINSERTF128 = 9525,
|
||||||
|
I_VINSERTPS = 9579, I_VLDDQU = 7023, I_VLDMXCSR = 9963, I_VMASKMOVDQU = 7153,
|
||||||
|
I_VMASKMOVPD = 7971, I_VMASKMOVPS = 7959, I_VMAXPD = 3610, I_VMAXPS = 3602,
|
||||||
|
I_VMAXSD = 3626, I_VMAXSS = 3618, I_VMCALL = 1735, I_VMCLEAR = 10011, I_VMFUNC = 1803,
|
||||||
|
I_VMINPD = 3490, I_VMINPS = 3482, I_VMINSD = 3506, I_VMINSS = 3498, I_VMLAUNCH = 1743,
|
||||||
|
I_VMLOAD = 1833, I_VMMCALL = 1824, I_VMOVAPD = 2498, I_VMOVAPS = 2489, I_VMOVD = 3954,
|
||||||
|
I_VMOVDDUP = 2256, I_VMOVDQA = 3984, I_VMOVDQU = 3993, I_VMOVHLPS = 2217,
|
||||||
|
I_VMOVHPD = 2404, I_VMOVHPS = 2395, I_VMOVLHPS = 2385, I_VMOVLPD = 2236, I_VMOVLPS = 2227,
|
||||||
|
I_VMOVMSKPD = 2858, I_VMOVMSKPS = 2847, I_VMOVNTDQ = 6880, I_VMOVNTDQA = 7927,
|
||||||
|
I_VMOVNTPD = 2615, I_VMOVNTPS = 2605, I_VMOVQ = 3961, I_VMOVSD = 2165, I_VMOVSHDUP = 2413,
|
||||||
|
I_VMOVSLDUP = 2245, I_VMOVSS = 2157, I_VMOVUPD = 2148, I_VMOVUPS = 2139, I_VMPSADBW = 9659,
|
||||||
|
I_VMPTRLD = 10002, I_VMPTRST = 6407, I_VMREAD = 4150, I_VMRESUME = 1753, I_VMRUN = 1817,
|
||||||
|
I_VMSAVE = 1841, I_VMULPD = 3221, I_VMULPS = 3213, I_VMULSD = 3237, I_VMULSS = 3229,
|
||||||
|
I_VMWRITE = 4174, I_VMXOFF = 1763, I_VMXON = 10020, I_VORPD = 3088, I_VORPS = 3081,
|
||||||
|
I_VPABSB = 7717, I_VPABSD = 7747, I_VPABSW = 7732, I_VPACKSSDW = 3881, I_VPACKSSWB = 3713,
|
||||||
|
I_VPACKUSDW = 7948, I_VPACKUSWB = 3791, I_VPADDB = 7233, I_VPADDD = 7263,
|
||||||
|
I_VPADDQ = 6510, I_VPADDSB = 6960, I_VPADDSW = 6977, I_VPADDUSW = 6651, I_VPADDW = 7248,
|
||||||
|
I_VPALIGNR = 9441, I_VPAND = 6635, I_VPANDN = 6694, I_VPAVGB = 6709, I_VPAVGW = 6754,
|
||||||
|
I_VPBLENDVB = 9714, I_VPBLENDW = 9422, I_VPCLMULQDQ = 9680, I_VPCMPEQB = 4074,
|
||||||
|
I_VPCMPEQD = 4112, I_VPCMPEQQ = 7907, I_VPCMPEQW = 4093, I_VPCMPESTRI = 9759,
|
||||||
|
I_VPCMPESTRM = 9736, I_VPCMPGTB = 3733, I_VPCMPGTD = 3771, I_VPCMPGTQ = 8118,
|
||||||
|
I_VPCMPGTW = 3752, I_VPCMPISTRI = 9805, I_VPCMPISTRM = 9782, I_VPERM2F128 = 9287,
|
||||||
|
I_VPERMILPD = 7592, I_VPERMILPS = 7581, I_VPEXTRB = 9459, I_VPEXTRD = 9484,
|
||||||
|
I_VPEXTRQ = 9493, I_VPEXTRW = 6341, I_VPHADDD = 7405, I_VPHADDSW = 7423, I_VPHADDW = 7388,
|
||||||
|
I_VPHMINPOSUW = 8293, I_VPHSUBD = 7481, I_VPHSUBSW = 7499, I_VPHSUBW = 7464,
|
||||||
|
I_VPINSRB = 9560, I_VPINSRD = 9606, I_VPINSRQ = 9615, I_VPINSRW = 6324, I_VPMADDUBSW = 7444,
|
||||||
|
I_VPMADDWD = 7104, I_VPMAXSB = 8204, I_VPMAXSD = 8221, I_VPMAXSW = 6994, I_VPMAXUB = 6678,
|
||||||
|
I_VPMAXUD = 8255, I_VPMAXUW = 8238, I_VPMINSB = 8136, I_VPMINSD = 8153, I_VPMINSW = 6932,
|
||||||
|
I_VPMINUB = 6620, I_VPMINUD = 8187, I_VPMINUW = 8170, I_VPMOVMSKB = 6563,
|
||||||
|
I_VPMOVSXBD = 7786, I_VPMOVSXBQ = 7807, I_VPMOVSXBW = 7765, I_VPMOVSXDQ = 7870,
|
||||||
|
I_VPMOVSXWD = 7828, I_VPMOVSXWQ = 7849, I_VPMOVZXBD = 8014, I_VPMOVZXBQ = 8035,
|
||||||
|
I_VPMOVZXBW = 7993, I_VPMOVZXDQ = 8098, I_VPMOVZXWD = 8056, I_VPMOVZXWQ = 8077,
|
||||||
|
I_VPMULDQ = 7889, I_VPMULHRSW = 7570, I_VPMULHUW = 6771, I_VPMULHW = 6789,
|
||||||
|
I_VPMULLD = 8272, I_VPMULLW = 6526, I_VPMULUDQ = 7085, I_VPOR = 6946, I_VPSADBW = 7122,
|
||||||
|
I_VPSHUFB = 7371, I_VPSHUFD = 4036, I_VPSHUFHW = 4045, I_VPSHUFLW = 4055,
|
||||||
|
I_VPSIGNB = 7517, I_VPSIGND = 7551, I_VPSIGNW = 7534, I_VPSLLD = 7053, I_VPSLLDQ = 9877,
|
||||||
|
I_VPSLLQ = 7068, I_VPSLLW = 7038, I_VPSRAD = 6739, I_VPSRAW = 6724, I_VPSRLD = 6480,
|
||||||
|
I_VPSRLDQ = 9860, I_VPSRLQ = 6495, I_VPSRLW = 6465, I_VPSUBB = 7173, I_VPSUBD = 7203,
|
||||||
|
I_VPSUBQ = 7218, I_VPSUBSB = 6898, I_VPSUBSW = 6915, I_VPSUBUSB = 6583, I_VPSUBUSW = 6602,
|
||||||
|
I_VPSUBW = 7188, I_VPTEST = 7658, I_VPUNPCKHBW = 3813, I_VPUNPCKHDQ = 3859,
|
||||||
|
I_VPUNPCKHQDQ = 3929, I_VPUNPCKHWD = 3836, I_VPUNPCKLBW = 3645, I_VPUNPCKLDQ = 3691,
|
||||||
|
I_VPUNPCKLQDQ = 3904, I_VPUNPCKLWD = 3668, I_VPXOR = 7009, I_VRCPPS = 2989,
|
||||||
|
I_VRCPSS = 2997, I_VROUNDPD = 9327, I_VROUNDPS = 9308, I_VROUNDSD = 9365,
|
||||||
|
I_VROUNDSS = 9346, I_VRSQRTPS = 2955, I_VRSQRTSS = 2965, I_VSHUFPD = 6375,
|
||||||
|
I_VSHUFPS = 6366, I_VSQRTPD = 2910, I_VSQRTPS = 2901, I_VSQRTSD = 2928, I_VSQRTSS = 2919,
|
||||||
|
I_VSTMXCSR = 9992, I_VSUBPD = 3430, I_VSUBPS = 3422, I_VSUBSD = 3446, I_VSUBSS = 3438,
|
||||||
|
I_VTESTPD = 7612, I_VTESTPS = 7603, I_VUCOMISD = 2783, I_VUCOMISS = 2773,
|
||||||
|
I_VUNPCKHPD = 2339, I_VUNPCKHPS = 2328, I_VUNPCKLPD = 2297, I_VUNPCKLPS = 2286,
|
||||||
|
I_VXORPD = 3117, I_VXORPS = 3109, I_VZEROALL = 4140, I_VZEROUPPER = 4128,
|
||||||
|
I_WAIT = 10042, I_WBINVD = 561, I_WRFSBASE = 9953, I_WRGSBASE = 9982, I_WRMSR = 586,
|
||||||
|
I_XABORT = 1007, I_XADD = 946, I_XBEGIN = 1015, I_XCHG = 212, I_XEND = 1811,
|
||||||
|
I_XGETBV = 1787, I_XLAT = 400, I_XOR = 61, I_XORPD = 3102, I_XORPS = 3095,
|
||||||
|
I_XRSTOR = 4295, I_XRSTOR64 = 4303, I_XSAVE = 4271, I_XSAVE64 = 4278, I_XSAVEOPT = 4321,
|
||||||
|
I_XSAVEOPT64 = 4331, I_XSETBV = 1795, I__3DNOW = 10056
|
||||||
|
} _InstructionType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15,
|
||||||
|
R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D,
|
||||||
|
R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W,
|
||||||
|
R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B,
|
||||||
|
R_SPL, R_BPL, R_SIL, R_DIL,
|
||||||
|
R_ES, R_CS, R_SS, R_DS, R_FS, R_GS,
|
||||||
|
R_RIP,
|
||||||
|
R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7,
|
||||||
|
R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7,
|
||||||
|
R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15,
|
||||||
|
R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15,
|
||||||
|
R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8,
|
||||||
|
R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7
|
||||||
|
} _RegisterType;
|
||||||
|
|
||||||
|
#endif /* MNEMONICS_H */
|
Binary file not shown.
|
@ -1,183 +0,0 @@
|
||||||
## Ignore Visual Studio temporary files, build results, and
|
|
||||||
## files generated by popular Visual Studio add-ons.
|
|
||||||
|
|
||||||
# User-specific files
|
|
||||||
*.suo
|
|
||||||
*.user
|
|
||||||
*.sln.docstates
|
|
||||||
|
|
||||||
# Build results
|
|
||||||
[Dd]ebug/
|
|
||||||
[Dd]ebugPublic/
|
|
||||||
[Rr]elease/
|
|
||||||
[Rr]eleases/
|
|
||||||
x64/
|
|
||||||
x86/
|
|
||||||
build/
|
|
||||||
bld/
|
|
||||||
[Bb]in/
|
|
||||||
[Oo]bj/
|
|
||||||
|
|
||||||
# Roslyn cache directories
|
|
||||||
*.ide/
|
|
||||||
|
|
||||||
# MSTest test Results
|
|
||||||
[Tt]est[Rr]esult*/
|
|
||||||
[Bb]uild[Ll]og.*
|
|
||||||
|
|
||||||
#NUNIT
|
|
||||||
*.VisualState.xml
|
|
||||||
TestResult.xml
|
|
||||||
|
|
||||||
# Build Results of an ATL Project
|
|
||||||
[Dd]ebugPS/
|
|
||||||
[Rr]eleasePS/
|
|
||||||
dlldata.c
|
|
||||||
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*_i.h
|
|
||||||
*.ilk
|
|
||||||
*.meta
|
|
||||||
*.obj
|
|
||||||
*.pch
|
|
||||||
*.pdb
|
|
||||||
*.pgc
|
|
||||||
*.pgd
|
|
||||||
*.rsp
|
|
||||||
*.sbr
|
|
||||||
*.tlb
|
|
||||||
*.tli
|
|
||||||
*.tlh
|
|
||||||
*.tmp
|
|
||||||
*.tmp_proj
|
|
||||||
*.log
|
|
||||||
*.vspscc
|
|
||||||
*.vssscc
|
|
||||||
.builds
|
|
||||||
*.pidb
|
|
||||||
*.svclog
|
|
||||||
*.scc
|
|
||||||
|
|
||||||
# Chutzpah Test files
|
|
||||||
_Chutzpah*
|
|
||||||
|
|
||||||
# Visual C++ cache files
|
|
||||||
ipch/
|
|
||||||
*.aps
|
|
||||||
*.ncb
|
|
||||||
*.opensdf
|
|
||||||
*.sdf
|
|
||||||
*.cachefile
|
|
||||||
|
|
||||||
# Visual Studio profiler
|
|
||||||
*.psess
|
|
||||||
*.vsp
|
|
||||||
*.vspx
|
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
|
||||||
$tf/
|
|
||||||
|
|
||||||
# Guidance Automation Toolkit
|
|
||||||
*.gpState
|
|
||||||
|
|
||||||
# ReSharper is a .NET coding add-in
|
|
||||||
_ReSharper*/
|
|
||||||
*.[Rr]e[Ss]harper
|
|
||||||
*.DotSettings.user
|
|
||||||
|
|
||||||
# JustCode is a .NET coding addin-in
|
|
||||||
.JustCode
|
|
||||||
|
|
||||||
# TeamCity is a build add-in
|
|
||||||
_TeamCity*
|
|
||||||
|
|
||||||
# DotCover is a Code Coverage Tool
|
|
||||||
*.dotCover
|
|
||||||
|
|
||||||
# NCrunch
|
|
||||||
_NCrunch_*
|
|
||||||
.*crunch*.local.xml
|
|
||||||
|
|
||||||
# MightyMoose
|
|
||||||
*.mm.*
|
|
||||||
AutoTest.Net/
|
|
||||||
|
|
||||||
# Web workbench (sass)
|
|
||||||
.sass-cache/
|
|
||||||
|
|
||||||
# Installshield output folder
|
|
||||||
[Ee]xpress/
|
|
||||||
|
|
||||||
# DocProject is a documentation generator add-in
|
|
||||||
DocProject/buildhelp/
|
|
||||||
DocProject/Help/*.HxT
|
|
||||||
DocProject/Help/*.HxC
|
|
||||||
DocProject/Help/*.hhc
|
|
||||||
DocProject/Help/*.hhk
|
|
||||||
DocProject/Help/*.hhp
|
|
||||||
DocProject/Help/Html2
|
|
||||||
DocProject/Help/html
|
|
||||||
|
|
||||||
# Click-Once directory
|
|
||||||
publish/
|
|
||||||
|
|
||||||
# Publish Web Output
|
|
||||||
*.[Pp]ublish.xml
|
|
||||||
*.azurePubxml
|
|
||||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
|
||||||
# but database connection strings (with potential passwords) will be unencrypted
|
|
||||||
*.pubxml
|
|
||||||
*.publishproj
|
|
||||||
|
|
||||||
# NuGet Packages
|
|
||||||
*.nupkg
|
|
||||||
# The packages folder can be ignored because of Package Restore
|
|
||||||
**/packages/*
|
|
||||||
# except build/, which is used as an MSBuild target.
|
|
||||||
!**/packages/build/
|
|
||||||
# If using the old MSBuild-Integrated Package Restore, uncomment this:
|
|
||||||
#!**/packages/repositories.config
|
|
||||||
|
|
||||||
# Windows Azure Build Output
|
|
||||||
csx/
|
|
||||||
*.build.csdef
|
|
||||||
|
|
||||||
# Windows Store app package directory
|
|
||||||
AppPackages/
|
|
||||||
|
|
||||||
# Others
|
|
||||||
sql/
|
|
||||||
*.Cache
|
|
||||||
ClientBin/
|
|
||||||
[Ss]tyle[Cc]op.*
|
|
||||||
~$*
|
|
||||||
*~
|
|
||||||
*.dbmdl
|
|
||||||
*.dbproj.schemaview
|
|
||||||
*.pfx
|
|
||||||
*.publishsettings
|
|
||||||
node_modules/
|
|
||||||
|
|
||||||
# RIA/Silverlight projects
|
|
||||||
Generated_Code/
|
|
||||||
|
|
||||||
# Backup & report files from converting an old project file
|
|
||||||
# to a newer Visual Studio version. Backup files are not needed,
|
|
||||||
# because we have git ;-)
|
|
||||||
_UpgradeReport_Files/
|
|
||||||
Backup*/
|
|
||||||
UpgradeLog*.XML
|
|
||||||
UpgradeLog*.htm
|
|
||||||
|
|
||||||
# SQL Server files
|
|
||||||
*.mdf
|
|
||||||
*.ldf
|
|
||||||
|
|
||||||
# Business Intelligence projects
|
|
||||||
*.rdl.data
|
|
||||||
*.bim.layout
|
|
||||||
*.bim_*.settings
|
|
||||||
|
|
||||||
# Microsoft Fakes
|
|
||||||
FakesAssemblies/
|
|
|
@ -1,29 +0,0 @@
|
||||||
language: cpp
|
|
||||||
compiler: clang
|
|
||||||
|
|
||||||
script: make
|
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# Install clang 3.6
|
|
||||||
- echo "yes" | sudo add-apt-repository 'deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu precise main'
|
|
||||||
- echo "yes" | sudo add-apt-repository 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.6 main'
|
|
||||||
- wget --no-check-certificate -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -;
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-get install -qq --allow-unauthenticated llvm-3.6 llvm-3.6-dev clang-3.6 libstdc++-4.8-dev lib32stdc++6
|
|
||||||
- export CXX="clang++-3.6" CC="clang-3.6"
|
|
||||||
# Install cmake 3.2
|
|
||||||
- wget --no-check-certificate https://www.cmake.org/files/v3.2/cmake-3.2.2-Linux-i386.sh
|
|
||||||
- chmod a+x cmake-3.2.2-Linux-i386.sh
|
|
||||||
- sudo ./cmake-3.2.2-Linux-i386.sh --skip-license --prefix=/usr
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- mkdir build
|
|
||||||
- cd build
|
|
||||||
- cmake ..
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,96 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
|
||||||
include(GenerateExportHeader)
|
|
||||||
|
|
||||||
project(Zydis)
|
|
||||||
|
|
||||||
option(BUILD_SHARED_LIBS "Build shared libraries rather than static ones" FALSE)
|
|
||||||
option(FORCE_SHARED_CRT
|
|
||||||
"Forces shared linkage against the CRT even when building a static library"
|
|
||||||
FALSE)
|
|
||||||
option(BUILD_EXAMPLES "Build examples" TRUE)
|
|
||||||
option(BUILD_C_BINDINGS "Build C bindings" TRUE)
|
|
||||||
|
|
||||||
if (NOT CONFIGURED_ONCE)
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
|
|
||||||
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|
||||||
set(compiler_specific "-Werror")
|
|
||||||
set(compiler_specific_cxx "-std=c++14")
|
|
||||||
elseif (MSVC)
|
|
||||||
set(compiler_specific "/WX /W4 /D_CRT_SECURE_NO_WARNINGS /GR-")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${compiler_specific} ${compiler_specific_cxx}"
|
|
||||||
CACHE STRING "Flags used by the compiler during all build types." FORCE)
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_specific}"
|
|
||||||
CACHE STRING "Flags used by the compiler during all build types." FORCE)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# CMake always orders MSVC to build with a shared CRT. Hack CMake variables in order
|
|
||||||
# to generate with a statically linked CRT when we build as a static library.
|
|
||||||
if (MSVC AND NOT FORCE_SHARED_CRT)
|
|
||||||
set(manipulated_vars
|
|
||||||
CMAKE_CXX_FLAGS_DEBUG
|
|
||||||
CMAKE_CXX_FLAGS_MINSIZEREL
|
|
||||||
CMAKE_CXX_FLAGS_RELEASE
|
|
||||||
CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
|
||||||
CMAKE_C_FLAGS_DEBUG
|
|
||||||
CMAKE_C_FLAGS_MINSIZEREL
|
|
||||||
CMAKE_C_FLAGS_RELEASE
|
|
||||||
CMAKE_C_FLAGS_RELWITHDEBINFO)
|
|
||||||
foreach (cur_var ${manipulated_vars})
|
|
||||||
string(REPLACE "/MD" "/MT" ${cur_var} "${${cur_var}}")
|
|
||||||
endforeach ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Library
|
|
||||||
set(headers
|
|
||||||
"Zydis/Zydis.hpp"
|
|
||||||
"Zydis/ZydisInstructionDecoder.hpp"
|
|
||||||
"Zydis/ZydisInstructionFormatter.hpp"
|
|
||||||
"Zydis/ZydisOpcodeTable.hpp"
|
|
||||||
"Zydis/ZydisSymbolResolver.hpp"
|
|
||||||
"Zydis/ZydisTypes.hpp"
|
|
||||||
"Zydis/ZydisUtils.hpp")
|
|
||||||
set(sources
|
|
||||||
"Zydis/ZydisInstructionDecoder.cpp"
|
|
||||||
"Zydis/ZydisInstructionFormatter.cpp"
|
|
||||||
"Zydis/ZydisOpcodeTable.cpp"
|
|
||||||
"Zydis/ZydisSymbolResolver.cpp"
|
|
||||||
"Zydis/ZydisUtils.cpp")
|
|
||||||
|
|
||||||
if (BUILD_SHARED_LIBS AND WIN32)
|
|
||||||
set(sources ${sources}
|
|
||||||
"Zydis/VersionInfo.rc")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BUILD_C_BINDINGS)
|
|
||||||
set(headers ${headers}
|
|
||||||
"Zydis/ZydisAPI.h")
|
|
||||||
set(sources ${sources}
|
|
||||||
"Zydis/ZydisAPI.cpp")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_library("Zydis" ${headers} ${sources})
|
|
||||||
set_target_properties("Zydis" PROPERTIES COMPILE_DEFINITIONS "Zydis_EXPORTS")
|
|
||||||
generate_export_header(
|
|
||||||
"Zydis"
|
|
||||||
BASE_NAME "ZYDIS"
|
|
||||||
EXPORT_FILE_NAME "ZydisExportConfig.h")
|
|
||||||
include_directories(${PROJECT_BINARY_DIR})
|
|
||||||
|
|
||||||
# Examples
|
|
||||||
if (BUILD_EXAMPLES)
|
|
||||||
include_directories("Zydis")
|
|
||||||
|
|
||||||
add_executable("SimpleDemo_CPP" "Examples/CPP/SimpleDemo/SimpleDemo.cpp")
|
|
||||||
target_link_libraries("SimpleDemo_CPP" "Zydis")
|
|
||||||
add_executable("CustomDataSource_CPP" "Examples/CPP/CustomDataSource/CustomDataSource.cpp")
|
|
||||||
target_link_libraries("CustomDataSource_CPP" "Zydis")
|
|
||||||
|
|
||||||
if (BUILD_C_BINDINGS)
|
|
||||||
add_executable("SimpleDemo_C" "Examples/C/SimpleDemo/SimpleDemo.c")
|
|
||||||
target_link_libraries("SimpleDemo_C" "Zydis")
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(CONFIGURED_ONCE TRUE CACHE INTERNAL "CMake has configured at least once.")
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,201 +0,0 @@
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
#include <ZydisAPI.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
void PrintZydisError()
|
|
||||||
{
|
|
||||||
puts("Zydis error: ");
|
|
||||||
switch (ZydisGetLastError())
|
|
||||||
{
|
|
||||||
case ZYDIS_ERROR_SUCCESS:
|
|
||||||
puts("success");
|
|
||||||
break;
|
|
||||||
case ZYDIS_ERROR_UNKNOWN:
|
|
||||||
puts("unknown error");
|
|
||||||
break;
|
|
||||||
case ZYDIS_ERROR_NOT_ENOUGH_MEMORY:
|
|
||||||
puts("not enough memory");
|
|
||||||
break;
|
|
||||||
case ZYDIS_ERROR_INVALID_PARAMETER:
|
|
||||||
puts("invalid parameter");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
uint8_t data32[] =
|
|
||||||
{
|
|
||||||
0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x6A, 0xFE, 0x68, 0xD8, 0x18, 0x09, 0x77, 0x68, 0x85, 0xD2,
|
|
||||||
0x09, 0x77, 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x50, 0x83, 0xEC, 0x14, 0x53, 0x56, 0x57,
|
|
||||||
0xA1, 0x68, 0xEE, 0x13, 0x77, 0x31, 0x45, 0xF8, 0x33, 0xC5, 0x50, 0x8D, 0x45, 0xF0, 0x64,
|
|
||||||
0xA3, 0x00, 0x00, 0x00, 0x00, 0x89, 0x65, 0xE8, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x8B, 0x5D, 0x08, 0xF6, 0xC3, 0x04, 0x0F, 0x85, 0x57, 0x74, 0x00, 0x00, 0x53, 0x6A, 0x00,
|
|
||||||
0xFF, 0x35, 0xA0, 0xE3, 0x13, 0x77, 0xFF, 0x15, 0x00, 0x10, 0x14, 0x77, 0x85, 0xC0, 0x0F,
|
|
||||||
0x84, 0xC6, 0x48, 0x04, 0x00, 0xC7, 0x45, 0x08, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xFC,
|
|
||||||
0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0xC0, 0x8B, 0x4D, 0xF0, 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x59, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC2, 0x04, 0x00
|
|
||||||
};
|
|
||||||
uint8_t data64[] =
|
|
||||||
{
|
|
||||||
0x48, 0x89, 0x5C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x89, 0x4C, 0x24, 0x08, 0x57,
|
|
||||||
0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x40, 0x4C, 0x8B, 0xF2,
|
|
||||||
0x8B, 0xD9, 0x48, 0xC7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00, 0x33, 0xF6, 0x48, 0x89,
|
|
||||||
0x74, 0x24, 0x30, 0x45, 0x33, 0xFF, 0xF7, 0xC1, 0x8D, 0xF0, 0xFF, 0xFF, 0x0F, 0x85, 0xAA,
|
|
||||||
0x53, 0x08, 0x00, 0xF6, 0xC1, 0x40, 0x8B, 0xFE, 0x41, 0xBD, 0x08, 0x00, 0x00, 0x00, 0x41,
|
|
||||||
0x0F, 0x45, 0xFD, 0xF6, 0xC1, 0x02, 0x48, 0x8B, 0x0D, 0x10, 0xD4, 0x0E, 0x00, 0x0F, 0x85,
|
|
||||||
0x40, 0xE1, 0x01, 0x00, 0x8B, 0x15, 0x4C, 0xD5, 0x0E, 0x00, 0x81, 0xC2, 0x00, 0x00, 0x14,
|
|
||||||
0x00, 0x0B, 0xD7, 0x4D, 0x8B, 0xC6, 0xFF, 0x15, 0x3B, 0x2F, 0x10, 0x00, 0x48, 0x8B, 0xD8,
|
|
||||||
0x48, 0x85, 0xC0, 0x0F, 0x84, 0x93, 0x78, 0x0A, 0x00, 0x48, 0x8B, 0xC3, 0x48, 0x8B, 0x5C,
|
|
||||||
0x24, 0x78, 0x48, 0x8B, 0xB4, 0x24, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x40, 0x41,
|
|
||||||
0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x5F, 0xC3
|
|
||||||
};
|
|
||||||
|
|
||||||
ZydisInstructionInfo info;
|
|
||||||
ZydisInstructionDecoderContext* decoder = NULL;
|
|
||||||
ZydisInstructionFormatterContext* formatter = NULL;
|
|
||||||
ZydisInputContext* input32 = NULL;
|
|
||||||
ZydisInputContext* input64 = NULL;
|
|
||||||
|
|
||||||
// Create decoder and formatter instances
|
|
||||||
decoder = ZydisCreateInstructionDecoder();
|
|
||||||
if (!decoder)
|
|
||||||
{
|
|
||||||
goto ZydisError;
|
|
||||||
}
|
|
||||||
formatter = ZydisCreateIntelInstructionFormatter();
|
|
||||||
if (!formatter)
|
|
||||||
{
|
|
||||||
goto FreeZydisDecoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create memory data sources
|
|
||||||
input32 = ZydisCreateMemoryInput(&data32[0], sizeof(data32));
|
|
||||||
if (!input32)
|
|
||||||
{
|
|
||||||
goto FreeZydisFormatter;
|
|
||||||
}
|
|
||||||
input64 = ZydisCreateMemoryInput(&data64[0], sizeof(data64));
|
|
||||||
if (!input64)
|
|
||||||
{
|
|
||||||
goto FreeZydisInput32;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set decoder properties
|
|
||||||
ZydisSetDisassemblerMode(decoder, ZYDIS_DM_M32BIT);
|
|
||||||
ZydisSetDataSource(decoder, input32);
|
|
||||||
ZydisSetInstructionPointer(decoder, 0x77091852);
|
|
||||||
|
|
||||||
// Decode and format all instructions
|
|
||||||
puts("32 bit test ...\n\n");
|
|
||||||
while (ZydisDecodeInstruction(decoder, &info))
|
|
||||||
{
|
|
||||||
printf("%08X ", (uint32_t)(info.instrAddress & 0xFFFFFFFF));
|
|
||||||
if (info.flags & ZYDIS_IF_ERROR_MASK)
|
|
||||||
{
|
|
||||||
printf("db %02X\n", info.data[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char* instructionText;
|
|
||||||
if (!ZydisFormatInstruction(formatter, &info, &instructionText))
|
|
||||||
{
|
|
||||||
goto FreeZydisInput64;
|
|
||||||
}
|
|
||||||
printf("%s\n", instructionText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if an error occured in ZydisDecodeInstruction or the end of the input was reached.
|
|
||||||
if (ZydisGetLastError() != ZYDIS_ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
goto FreeZydisInput64;
|
|
||||||
}
|
|
||||||
|
|
||||||
puts("\n");
|
|
||||||
|
|
||||||
// Set decoder properties
|
|
||||||
ZydisSetDisassemblerMode(decoder, ZYDIS_DM_M64BIT);
|
|
||||||
ZydisSetDataSource(decoder, input64);
|
|
||||||
ZydisSetInstructionPointer(decoder, 0x00007FFA39A81930ull);
|
|
||||||
|
|
||||||
// Decode and format all instructions
|
|
||||||
puts("64 bit test ...\n\n");
|
|
||||||
while (ZydisDecodeInstruction(decoder, &info))
|
|
||||||
{
|
|
||||||
printf("%016"PRIX64" ", info.instrAddress);
|
|
||||||
if (info.flags & ZYDIS_IF_ERROR_MASK)
|
|
||||||
{
|
|
||||||
printf("db %02X", info.data[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char* instructionText;
|
|
||||||
if (!ZydisFormatInstruction(formatter, &info, &instructionText))
|
|
||||||
{
|
|
||||||
goto FreeZydisInput64;
|
|
||||||
}
|
|
||||||
printf("%s\n", instructionText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if an error occured in ZydisDecodeInstruction or the end of the input was reached.
|
|
||||||
if (ZydisGetLastError() != ZYDIS_ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
goto FreeZydisInput64;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup code
|
|
||||||
FreeZydisInput64:
|
|
||||||
ZydisFreeInput(input64);
|
|
||||||
FreeZydisInput32:
|
|
||||||
ZydisFreeInput(input32);
|
|
||||||
FreeZydisFormatter:
|
|
||||||
ZydisFreeInstructionFormatter(formatter);
|
|
||||||
FreeZydisDecoder:
|
|
||||||
ZydisFreeInstructionDecoder(decoder);
|
|
||||||
ZydisError:
|
|
||||||
|
|
||||||
if (ZydisGetLastError() != ZYDIS_ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
PrintZydisError();
|
|
||||||
getchar();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
getchar();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,171 +0,0 @@
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <Zydis.hpp>
|
|
||||||
|
|
||||||
class ZydisStdinInput : public Zydis::BaseInput
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::vector<uint8_t> m_buffer;
|
|
||||||
uint32_t m_position = 0;
|
|
||||||
uint64_t m_globalPosition = 0;
|
|
||||||
private:
|
|
||||||
void gatherInput();
|
|
||||||
protected:
|
|
||||||
uint8_t internalInputPeek() override;
|
|
||||||
uint8_t internalInputNext() override;
|
|
||||||
public:
|
|
||||||
bool isEndOfInput() const override;
|
|
||||||
uint64_t getPosition() const override;
|
|
||||||
bool setPosition(uint64_t position) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
void ZydisStdinInput::gatherInput()
|
|
||||||
{
|
|
||||||
if (m_position != m_buffer.size())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::vector<uint8_t> buffer;
|
|
||||||
bool valid;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
valid = true;
|
|
||||||
buffer.clear();
|
|
||||||
std::string input;
|
|
||||||
std::getline(std::cin, input);
|
|
||||||
if (input.empty())
|
|
||||||
{
|
|
||||||
valid = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::istringstream ss(input);
|
|
||||||
uint32_t x;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ss >> std::hex >> x;
|
|
||||||
if (ss.fail())
|
|
||||||
{
|
|
||||||
std::cout << std::endl << "# Error: Invalid hex input." << std::endl << std::endl;
|
|
||||||
ss.ignore();
|
|
||||||
valid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (buffer.size() == buffer.capacity())
|
|
||||||
{
|
|
||||||
buffer.reserve(buffer.capacity() + 512);
|
|
||||||
}
|
|
||||||
if (x > 255)
|
|
||||||
{
|
|
||||||
std::cout << std::endl << "# Warning: 0x"
|
|
||||||
<< std::hex << std::setw(8) << std::setfill('0') << std::uppercase << x
|
|
||||||
<< " converted to uint8_t. Possible data loss." << std::endl << std::endl;
|
|
||||||
}
|
|
||||||
buffer.resize(buffer.size() + 1);
|
|
||||||
buffer[buffer.size() - 1] = static_cast<uint8_t>(x);
|
|
||||||
} while (!ss.eof());
|
|
||||||
} while (!valid);
|
|
||||||
m_buffer = buffer;
|
|
||||||
m_position = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ZydisStdinInput::internalInputPeek()
|
|
||||||
{
|
|
||||||
gatherInput();
|
|
||||||
return m_buffer[m_position];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ZydisStdinInput::internalInputNext()
|
|
||||||
{
|
|
||||||
gatherInput();
|
|
||||||
m_globalPosition++;
|
|
||||||
return m_buffer[m_position++];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisStdinInput::isEndOfInput() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t ZydisStdinInput::getPosition() const
|
|
||||||
{
|
|
||||||
return m_globalPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisStdinInput::setPosition(uint64_t position)
|
|
||||||
{
|
|
||||||
if (position > m_globalPosition)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int64_t delta = m_globalPosition - position;
|
|
||||||
if (delta > m_position)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_position = m_position - static_cast<int32_t>(delta);
|
|
||||||
m_globalPosition = position;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
Zydis::InstructionInfo info;
|
|
||||||
Zydis::InstructionDecoder decoder;
|
|
||||||
Zydis::IntelInstructionFormatter formatter;
|
|
||||||
ZydisStdinInput input;
|
|
||||||
|
|
||||||
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
|
|
||||||
decoder.setDataSource(&input);
|
|
||||||
decoder.setInstructionPointer(0x00000000);
|
|
||||||
|
|
||||||
while (decoder.decodeInstruction(info))
|
|
||||||
{
|
|
||||||
std::cout << std::hex << std::setw(8) << std::setfill('0') << std::uppercase
|
|
||||||
<< info.instrAddress << " ";
|
|
||||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
|
||||||
{
|
|
||||||
std::cout << "db " << std::setw(2) << static_cast<int>(info.data[0]) << std::endl;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <Zydis.hpp>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
uint8_t data32[] =
|
|
||||||
{
|
|
||||||
0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x6A, 0xFE, 0x68, 0xD8, 0x18, 0x09, 0x77, 0x68, 0x85, 0xD2,
|
|
||||||
0x09, 0x77, 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x50, 0x83, 0xEC, 0x14, 0x53, 0x56, 0x57,
|
|
||||||
0xA1, 0x68, 0xEE, 0x13, 0x77, 0x31, 0x45, 0xF8, 0x33, 0xC5, 0x50, 0x8D, 0x45, 0xF0, 0x64,
|
|
||||||
0xA3, 0x00, 0x00, 0x00, 0x00, 0x89, 0x65, 0xE8, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x8B, 0x5D, 0x08, 0xF6, 0xC3, 0x04, 0x0F, 0x85, 0x57, 0x74, 0x00, 0x00, 0x53, 0x6A, 0x00,
|
|
||||||
0xFF, 0x35, 0xA0, 0xE3, 0x13, 0x77, 0xFF, 0x15, 0x00, 0x10, 0x14, 0x77, 0x85, 0xC0, 0x0F,
|
|
||||||
0x84, 0xC6, 0x48, 0x04, 0x00, 0xC7, 0x45, 0x08, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xFC,
|
|
||||||
0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0xC0, 0x8B, 0x4D, 0xF0, 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x59, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC2, 0x04, 0x00
|
|
||||||
};
|
|
||||||
uint8_t data64[] =
|
|
||||||
{
|
|
||||||
0x48, 0x89, 0x5C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x89, 0x4C, 0x24, 0x08, 0x57,
|
|
||||||
0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x40, 0x4C, 0x8B, 0xF2,
|
|
||||||
0x8B, 0xD9, 0x48, 0xC7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00, 0x33, 0xF6, 0x48, 0x89,
|
|
||||||
0x74, 0x24, 0x30, 0x45, 0x33, 0xFF, 0xF7, 0xC1, 0x8D, 0xF0, 0xFF, 0xFF, 0x0F, 0x85, 0xAA,
|
|
||||||
0x53, 0x08, 0x00, 0xF6, 0xC1, 0x40, 0x8B, 0xFE, 0x41, 0xBD, 0x08, 0x00, 0x00, 0x00, 0x41,
|
|
||||||
0x0F, 0x45, 0xFD, 0xF6, 0xC1, 0x02, 0x48, 0x8B, 0x0D, 0x10, 0xD4, 0x0E, 0x00, 0x0F, 0x85,
|
|
||||||
0x40, 0xE1, 0x01, 0x00, 0x8B, 0x15, 0x4C, 0xD5, 0x0E, 0x00, 0x81, 0xC2, 0x00, 0x00, 0x14,
|
|
||||||
0x00, 0x0B, 0xD7, 0x4D, 0x8B, 0xC6, 0xFF, 0x15, 0x3B, 0x2F, 0x10, 0x00, 0x48, 0x8B, 0xD8,
|
|
||||||
0x48, 0x85, 0xC0, 0x0F, 0x84, 0x93, 0x78, 0x0A, 0x00, 0x48, 0x8B, 0xC3, 0x48, 0x8B, 0x5C,
|
|
||||||
0x24, 0x78, 0x48, 0x8B, 0xB4, 0x24, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x40, 0x41,
|
|
||||||
0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x5F, 0xC3
|
|
||||||
};
|
|
||||||
|
|
||||||
Zydis::InstructionInfo info;
|
|
||||||
Zydis::InstructionDecoder decoder;
|
|
||||||
Zydis::IntelInstructionFormatter formatter;
|
|
||||||
Zydis::MemoryInput input32(&data32[0], sizeof(data32));
|
|
||||||
Zydis::MemoryInput input64(&data64[0], sizeof(data64));
|
|
||||||
|
|
||||||
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
|
|
||||||
decoder.setDataSource(&input32);
|
|
||||||
decoder.setInstructionPointer(0x77091852);
|
|
||||||
std::cout << "32 bit test ..." << std::endl << std::endl;
|
|
||||||
while (decoder.decodeInstruction(info))
|
|
||||||
{
|
|
||||||
std::cout << std::hex << std::setw(8) << std::setfill('0') << std::uppercase
|
|
||||||
<< info.instrAddress << " ";
|
|
||||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
|
||||||
{
|
|
||||||
std::cout << "db " << std::setw(2) << static_cast<int>(info.data[0]) << std::endl;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M64BIT);
|
|
||||||
decoder.setDataSource(&input64);
|
|
||||||
decoder.setInstructionPointer(0x00007FFA39A81930ull);
|
|
||||||
std::cout << "64 bit test ..." << std::endl << std::endl;
|
|
||||||
while (decoder.decodeInstruction(info))
|
|
||||||
{
|
|
||||||
std::cout << std::hex << std::setw(16) << std::setfill('0') << std::uppercase
|
|
||||||
<< info.instrAddress << " ";
|
|
||||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
|
||||||
{
|
|
||||||
std::cout << "db " << std::setw(2) << static_cast<int>(info.data[0]) << std::endl;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cin.get();
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Florian Bernd
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
/**************************************************************************************************
|
|
||||||
|
|
||||||
Verteron Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications :
|
|
||||||
|
|
||||||
Last change : 29. October 2014
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
**************************************************************************************************/
|
|
||||||
#include <tchar.h>
|
|
||||||
#include "PugiXML/pugixml.hpp"
|
|
||||||
#include "VXDisassemblerTypes.h"
|
|
||||||
|
|
||||||
int _tmain(int argc, _TCHAR* argv[])
|
|
||||||
{
|
|
||||||
// TODO:
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{EFA075B8-AFB9-4E06-99AD-BD58F50A9500}</ProjectGuid>
|
|
||||||
<Keyword>Win32Proj</Keyword>
|
|
||||||
<RootNamespace>OptableGenerator</RootNamespace>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v120</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v120</PlatformToolset>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v120</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v120</PlatformToolset>
|
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<IncludePath>..\VerteronDisassemblerEngine\;$(IncludePath)</IncludePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
<IncludePath>..\VerteronDisassemblerEngine\;$(IncludePath)</IncludePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<IncludePath>..\VerteronDisassemblerEngine\;$(IncludePath)</IncludePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
<IncludePath>..\VerteronDisassemblerEngine\;$(IncludePath)</IncludePath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PrecompiledHeader>
|
|
||||||
</PrecompiledHeader>
|
|
||||||
<Optimization>MaxSpeed</Optimization>
|
|
||||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
|
||||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<SubSystem>Console</SubSystem>
|
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="Main.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\VerteronDisassemblerEngine\VerteronDisassemblerEngine.vcxproj">
|
|
||||||
<Project>{f5c6f0a7-f75d-42bd-a8ab-a2d1d5f67099}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
|
@ -1,72 +0,0 @@
|
||||||
/**
|
|
||||||
* pugixml parser - version 1.4
|
|
||||||
* --------------------------------------------------------
|
|
||||||
* Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
|
||||||
* Report bugs and download new versions at http://pugixml.org/
|
|
||||||
*
|
|
||||||
* This library is distributed under the MIT License. See notice at the end
|
|
||||||
* of this file.
|
|
||||||
*
|
|
||||||
* This work is based on the pugxml parser, which is:
|
|
||||||
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HEADER_PUGICONFIG_HPP
|
|
||||||
#define HEADER_PUGICONFIG_HPP
|
|
||||||
|
|
||||||
// Uncomment this to enable wchar_t mode
|
|
||||||
// #define PUGIXML_WCHAR_MODE
|
|
||||||
|
|
||||||
// Uncomment this to disable XPath
|
|
||||||
// #define PUGIXML_NO_XPATH
|
|
||||||
|
|
||||||
// Uncomment this to disable STL
|
|
||||||
// #define PUGIXML_NO_STL
|
|
||||||
|
|
||||||
// Uncomment this to disable exceptions
|
|
||||||
// #define PUGIXML_NO_EXCEPTIONS
|
|
||||||
|
|
||||||
// Set this to control attributes for public classes/functions, i.e.:
|
|
||||||
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
|
|
||||||
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
|
|
||||||
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
|
|
||||||
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
|
|
||||||
|
|
||||||
// Tune these constants to adjust memory-related behavior
|
|
||||||
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
|
|
||||||
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
|
|
||||||
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
|
|
||||||
|
|
||||||
// Uncomment this to switch to header-only version
|
|
||||||
// #define PUGIXML_HEADER_ONLY
|
|
||||||
// #include "pugixml.cpp"
|
|
||||||
|
|
||||||
// Uncomment this to enable long long support
|
|
||||||
// #define PUGIXML_HAS_LONG_LONG
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright (c) 2006-2014 Arseny Kapoulkine
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person
|
|
||||||
* obtaining a copy of this software and associated documentation
|
|
||||||
* files (the "Software"), to deal in the Software without
|
|
||||||
* restriction, including without limitation the rights to use,
|
|
||||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following
|
|
||||||
* conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,90 +0,0 @@
|
||||||
Zyan Disassembler Engine (Zydis) [](https://travis-ci.org/zyantific/zyan-disassembler-engine)
|
|
||||||
================================
|
|
||||||
|
|
||||||
Fast and lightweight x86/x86-64 disassembler library.
|
|
||||||
|
|
||||||
## Features ##
|
|
||||||
|
|
||||||
- Supports all x86 and x86-64 (AMD64) General purpose and System instructions.
|
|
||||||
- Supported ISA extensions:
|
|
||||||
- MMX, FPU (x87), AMD 3DNow
|
|
||||||
- SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES,
|
|
||||||
- AMD-V, INTEL-VMX, SMX
|
|
||||||
- Optimized for high performance
|
|
||||||
- Very small overhead compared to other common disassembler libraries (about 60KiB)
|
|
||||||
- Abstract formatter and symbol-resolver classes for custom syntax implementations.
|
|
||||||
- Intel syntax is implemented by default
|
|
||||||
- Complete doxygen documentation
|
|
||||||
|
|
||||||
## Quick Example ##
|
|
||||||
|
|
||||||
The following example program uses Zydis to disassemble a given memory buffer and prints the output to the console.
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <Zydis.hpp>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
uint8_t data[] =
|
|
||||||
{
|
|
||||||
0x51, 0x8D, 0x45, 0xFF, 0x50, 0xFF, 0x75, 0x0C, 0xFF, 0x75,
|
|
||||||
0x08, 0xFF, 0x15, 0xA0, 0xA5, 0x48, 0x76, 0x85, 0xC0, 0x0F,
|
|
||||||
0x88, 0xFC, 0xDA, 0x02, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
Zydis::MemoryInput input(&data[0], sizeof(data));
|
|
||||||
Zydis::InstructionInfo info;
|
|
||||||
Zydis::InstructionDecoder decoder;
|
|
||||||
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
|
|
||||||
decoder.setDataSource(&input);
|
|
||||||
decoder.setInstructionPointer(0x00400000);
|
|
||||||
Zydis::IntelInstructionFormatter formatter;
|
|
||||||
|
|
||||||
while (decoder.decodeInstruction(info))
|
|
||||||
{
|
|
||||||
std::cout << std::hex << std::setw(8) << std::setfill('0')
|
|
||||||
<< std::uppercase << info.instrAddress << " ";
|
|
||||||
|
|
||||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
|
||||||
{
|
|
||||||
std::cout << "db " << std::setw(2)
|
|
||||||
<< static_cast<int>(info.data[0])
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << formatter.formatInstruction(info) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Sample Output ##
|
|
||||||
|
|
||||||
The above example program generates the following output:
|
|
||||||
|
|
||||||
```
|
|
||||||
00400000 push ecx
|
|
||||||
00400001 lea eax, [ebp-01]
|
|
||||||
00400004 push eax
|
|
||||||
00400005 push dword ptr [ebp+0C]
|
|
||||||
00400008 push dword ptr [ebp+08]
|
|
||||||
0040000B call dword ptr [7648A5A0]
|
|
||||||
00400011 test eax, eax
|
|
||||||
00400013 js 0042DB15
|
|
||||||
```
|
|
||||||
|
|
||||||
## Compilation ##
|
|
||||||
|
|
||||||
Zydis builds cleanly on most platforms without any external dependencies. You can use CMake to generate project files for your favorite C++14 compiler.
|
|
||||||
|
|
||||||
## Documentation ##
|
|
||||||
|
|
||||||
[The HTML Doxygen documentation](https://www.zyantific.com/doc/zydis/index.html) is automatically built from master every 12 hours.
|
|
||||||
|
|
||||||
## License ##
|
|
||||||
|
|
||||||
Zyan Disassembler Engine is licensed under the MIT License. Dependencies are under their respective licenses.
|
|
Binary file not shown.
|
@ -1,100 +0,0 @@
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief C++ API include file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @mainpage Zyan Disassembler Engine (Zydis)
|
|
||||||
*
|
|
||||||
* Zydis is a fast and lightweight x86/x86-64 disassembler library.
|
|
||||||
*
|
|
||||||
* @section Features
|
|
||||||
* - Supports all x86 and x86-64 (AMD64) General purpose and System instructions.
|
|
||||||
* - Supported ISA extensions:
|
|
||||||
* - MMX, FPU (x87), AMD 3DNow
|
|
||||||
* - SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES,
|
|
||||||
* - AMD-V, INTEL-VMX, SMX
|
|
||||||
* - Optimized for high performance
|
|
||||||
* - Very small overhead compared to other common disassembler libraries (about 60KiB)
|
|
||||||
* - Abstract formatter and symbol-resolver classes for custom syntax implementations.
|
|
||||||
* - Intel syntax is implemented by default
|
|
||||||
* - Complete doxygen documentation
|
|
||||||
*
|
|
||||||
* @section Quick Example
|
|
||||||
* The following example program uses Zydis to disassemble a given memory buffer and prints the
|
|
||||||
* output to the console.
|
|
||||||
*
|
|
||||||
* @code
|
|
||||||
* #include <tchar.h>
|
|
||||||
* #include <iostream>
|
|
||||||
* #include <stdint.h>
|
|
||||||
* #include "Zydis.hpp"
|
|
||||||
*
|
|
||||||
* int _tmain(int argc, _TCHAR* argv[])
|
|
||||||
* {
|
|
||||||
* uint8_t data[] =
|
|
||||||
* {
|
|
||||||
* 0x90, 0xE9, 0x00, 0x00, 0x00, 0x00, 0xC3
|
|
||||||
* };
|
|
||||||
* Zydis::MemoryInput input(&data[0], sizeof(data));
|
|
||||||
* Zydis::InstructionInfo info;
|
|
||||||
* Zydis::InstructionDecoder decoder;
|
|
||||||
* decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
|
|
||||||
* decoder.setDataSource(&input);
|
|
||||||
* decoder.setInstructionPointer(0);
|
|
||||||
* Zydis::IntelInstructionFormatter formatter;
|
|
||||||
* while (decoder.decodeInstruction(info))
|
|
||||||
* {
|
|
||||||
* std::cout << formatter.formatInstruction(info) << std::endl;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* @section Compilation
|
|
||||||
* Zydis builds cleanly on most platforms without any external dependencies. You can use CMake
|
|
||||||
* to generate project files for your favorite C++14 compiler.
|
|
||||||
*
|
|
||||||
* @section License
|
|
||||||
* Zyan Disassembler Engine is licensed under the MIT License. Dependencies are under their
|
|
||||||
* respective licenses.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ZYDIS_HPP_
|
|
||||||
#define _ZYDIS_HPP_
|
|
||||||
|
|
||||||
#include "ZydisInstructionDecoder.hpp"
|
|
||||||
#include "ZydisInstructionFormatter.hpp"
|
|
||||||
#include "ZydisSymbolResolver.hpp"
|
|
||||||
#include "ZydisUtils.hpp"
|
|
||||||
|
|
||||||
#endif /*_ZYDIS_HPP_ */
|
|
|
@ -1,655 +0,0 @@
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
#include "ZydisAPI.h"
|
|
||||||
#include "ZydisInstructionDecoder.hpp"
|
|
||||||
#include "ZydisInstructionFormatter.hpp"
|
|
||||||
|
|
||||||
/* Static Checks ================================================================================ */
|
|
||||||
|
|
||||||
static_assert(
|
|
||||||
sizeof(ZydisOperandInfo) == sizeof(Zydis::OperandInfo),
|
|
||||||
"struct size mismatch");
|
|
||||||
|
|
||||||
static_assert(
|
|
||||||
sizeof(ZydisInstructionInfo) == sizeof(Zydis::InstructionInfo),
|
|
||||||
"struct size mismatch");
|
|
||||||
|
|
||||||
/* Error Handling =============================================================================== */
|
|
||||||
|
|
||||||
static uint32_t g_zydisLastError = ZYDIS_ERROR_SUCCESS;
|
|
||||||
|
|
||||||
uint32_t ZydisGetLastError()
|
|
||||||
{
|
|
||||||
return g_zydisLastError;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ZydisSetLastError(uint32_t errorCode)
|
|
||||||
{
|
|
||||||
g_zydisLastError = errorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Conversion Helper ============================================================================ */
|
|
||||||
|
|
||||||
typedef enum _ZydisClassType
|
|
||||||
{
|
|
||||||
ZYDIS_CONTEXT_INPUT = 0x00000080,
|
|
||||||
ZYDIS_CONTEXT_INPUT_CUSTOM = ZYDIS_CONTEXT_INPUT | 0x00000001,
|
|
||||||
ZYDIS_CONTEXT_INPUT_MEMORY = ZYDIS_CONTEXT_INPUT | 0x00000002,
|
|
||||||
ZYDIS_CONTEXT_INSTRUCTIONDECODER = 0x00000040,
|
|
||||||
ZYDIS_CONTEXT_INSTRUCTIONFORMATTER = 0x00000020,
|
|
||||||
ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_CUSTOM = ZYDIS_CONTEXT_INSTRUCTIONFORMATTER | 0x00000001,
|
|
||||||
ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_INTEL = ZYDIS_CONTEXT_INSTRUCTIONFORMATTER | 0x00000002,
|
|
||||||
ZYDIS_CONTEXT_SYMBOLRESOLVER = 0x00000010,
|
|
||||||
ZYDIS_CONTEXT_SYMBOLRESOLVER_CUSTOM = ZYDIS_CONTEXT_SYMBOLRESOLVER | 0x00000001,
|
|
||||||
ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT = ZYDIS_CONTEXT_SYMBOLRESOLVER | 0x00000002
|
|
||||||
} ZydisClassType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This helper class extends a zydis class with a type field. It is used by the C-bindings
|
|
||||||
* to check type correctness for input parameters.
|
|
||||||
* @param ZydisClassT The zydis class type.
|
|
||||||
*/
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
template <typename ZydisClassT>
|
|
||||||
class ZydisClassEx final
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
using FullClassT = ZydisClassEx<ZydisClassT>;
|
|
||||||
public:
|
|
||||||
uint32_t type;
|
|
||||||
uint32_t align;
|
|
||||||
std::conditional_t<std::is_abstract<ZydisClassT>::value, char, ZydisClassT> instance;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
* @param InstanceCtorArgsT The argument types for the constructor of the zydis class.
|
|
||||||
* @param classType The type of the zydis class.
|
|
||||||
* @param args... The arguments for the constructor of the zydis class.
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
typename ZydisClassTT=ZydisClassT,
|
|
||||||
std::enable_if_t<!std::is_abstract<ZydisClassTT>::value, int> = 0,
|
|
||||||
typename... InstanceCtorArgsT>
|
|
||||||
ZydisClassEx(uint32_t classType, InstanceCtorArgsT... args)
|
|
||||||
: type(classType)
|
|
||||||
, align(0)
|
|
||||||
, instance(args...) { };
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Returns the class type.
|
|
||||||
* @return The assigned class type.
|
|
||||||
*/
|
|
||||||
uint32_t getClassType() const
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @brief Returns the zydis class instance.
|
|
||||||
* @return Pointer to the zydis class instance.
|
|
||||||
*/
|
|
||||||
ZydisClassT* getInstance()
|
|
||||||
{
|
|
||||||
return reinterpret_cast<ZydisClassT*>(&instance);
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Casts the given instance to @c ZydisClassEx.
|
|
||||||
* @param instance The zydis class instance.
|
|
||||||
* @return Pointer to the @c ZydisClassEx instance.
|
|
||||||
*/
|
|
||||||
static FullClassT* fromInstance(ZydisClassT* instance)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<FullClassT*>(
|
|
||||||
reinterpret_cast<uintptr_t>(instance)
|
|
||||||
- sizeof(std::declval<FullClassT>().type)
|
|
||||||
- sizeof(std::declval<FullClassT>().align));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Creates a context by constructing a new wrapped zydis class instance.
|
|
||||||
* @param ContextClassT The context class.
|
|
||||||
* @param ZydisClassT The zydis class type.
|
|
||||||
* @param ZydisClassCtorArgsT The argument types for the constructor of the zydis class.
|
|
||||||
* @param classType The type of the zydis class.
|
|
||||||
* @param args... The arguments for the constructor of the zydis class.
|
|
||||||
*/
|
|
||||||
template <typename ContextClassT, typename ZydisClassT, typename... ZydisClassCtorArgsT>
|
|
||||||
ContextClassT* ZydisCreateContext(uint32_t classType, ZydisClassCtorArgsT... args)
|
|
||||||
{
|
|
||||||
auto instanceEx = new (std::nothrow) ZydisClassEx<ZydisClassT>(classType, args...);
|
|
||||||
if (!instanceEx)
|
|
||||||
{
|
|
||||||
ZydisSetLastError(ZYDIS_ERROR_NOT_ENOUGH_MEMORY);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
// Return the original instance as context.
|
|
||||||
return reinterpret_cast<ContextClassT*>(instanceEx->getInstance());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Retrieves the zydis class instance of the given context.
|
|
||||||
* @param ContextClassT The context class.
|
|
||||||
* @param ZydisClassT The zydis class type.
|
|
||||||
* @param expectedType The expected type of the zydis class.
|
|
||||||
*/
|
|
||||||
template <typename ContextClassT, typename ZydisClassT>
|
|
||||||
ZydisClassT* ZydisRetrieveInstance(uint32_t expectedType, const ContextClassT* context)
|
|
||||||
{
|
|
||||||
auto instanceEx = ZydisClassEx<ZydisClassT>::fromInstance(
|
|
||||||
reinterpret_cast<ZydisClassT*>(const_cast<ContextClassT*>(context)));
|
|
||||||
if ((instanceEx->getClassType() & expectedType) != expectedType)
|
|
||||||
{
|
|
||||||
ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
// The context points to the same address as the instance. We just need to cast it.
|
|
||||||
return reinterpret_cast<ZydisClassT*>(const_cast<ContextClassT*>(context));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Creates a context by constructing a new wrapped zydis instance.
|
|
||||||
* @param ContextClassT The context class.
|
|
||||||
* @param ZydisClassT The zydis class type.
|
|
||||||
* @param expectedType The expected type of the zydis class.
|
|
||||||
*/
|
|
||||||
template <typename ContextClassT, typename ZydisClassT>
|
|
||||||
bool ZydisFreeContext(uint32_t expectedType, const ContextClassT* context)
|
|
||||||
{
|
|
||||||
auto instanceEx = ZydisClassEx<ZydisClassT>::fromInstance(
|
|
||||||
reinterpret_cast<ZydisClassT*>(const_cast<ContextClassT*>(context)));
|
|
||||||
if ((instanceEx->getClassType() & expectedType) != expectedType)
|
|
||||||
{
|
|
||||||
ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
delete instanceEx;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Input ======================================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Helper class for custom input implementations.
|
|
||||||
*/
|
|
||||||
class ZydisCustomInput : public Zydis::BaseInput
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
void* m_userData;
|
|
||||||
ZydisCustomDestructorT m_cbDestructor;
|
|
||||||
ZydisCustomInputPeekT m_cbPeek;
|
|
||||||
ZydisCustomInputNextT m_cbNext;
|
|
||||||
ZydisCustomInputIsEndOfInputT m_cbIsEndOfInput;
|
|
||||||
ZydisCustomInputGetPositionT m_cbGetPosition;
|
|
||||||
ZydisCustomInputSetPositionT m_cbSetPosition;
|
|
||||||
protected:
|
|
||||||
uint8_t internalInputPeek() override
|
|
||||||
{
|
|
||||||
return m_cbPeek(m_userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t internalInputNext() override
|
|
||||||
{
|
|
||||||
return m_cbNext(m_userData);
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
ZydisCustomInput(void* userData,
|
|
||||||
ZydisCustomInputPeekT cbPeek, ZydisCustomInputNextT cbNext,
|
|
||||||
ZydisCustomInputIsEndOfInputT cbIsEndOfInput, ZydisCustomInputGetPositionT cbGetPosition,
|
|
||||||
ZydisCustomInputSetPositionT cbSetPosition, ZydisCustomDestructorT cbDestructor)
|
|
||||||
: m_userData(userData)
|
|
||||||
, m_cbDestructor(cbDestructor)
|
|
||||||
, m_cbPeek(cbPeek)
|
|
||||||
, m_cbNext(cbNext)
|
|
||||||
, m_cbIsEndOfInput(cbIsEndOfInput)
|
|
||||||
, m_cbGetPosition(cbGetPosition)
|
|
||||||
, m_cbSetPosition(cbSetPosition)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
~ZydisCustomInput() override
|
|
||||||
{
|
|
||||||
if (m_cbDestructor)
|
|
||||||
{
|
|
||||||
m_cbDestructor(m_userData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
bool isEndOfInput() const override
|
|
||||||
{
|
|
||||||
return m_cbIsEndOfInput(m_userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t getPosition() const override
|
|
||||||
{
|
|
||||||
return m_cbGetPosition(m_userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool setPosition(uint64_t position) override
|
|
||||||
{
|
|
||||||
return m_cbSetPosition(m_userData, position);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ZydisInputContext* ZydisCreateCustomInput(void* userData,
|
|
||||||
ZydisCustomInputPeekT cbPeek, ZydisCustomInputNextT cbNext,
|
|
||||||
ZydisCustomInputIsEndOfInputT cbIsEndOfInput, ZydisCustomInputGetPositionT cbGetPosition,
|
|
||||||
ZydisCustomInputSetPositionT cbSetPosition, ZydisCustomDestructorT cbDestructor)
|
|
||||||
{
|
|
||||||
if (!cbPeek || !cbNext || !cbIsEndOfInput || !cbGetPosition || !cbSetPosition)
|
|
||||||
{
|
|
||||||
ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return ZydisCreateContext<ZydisInputContext, ZydisCustomInput>(ZYDIS_CONTEXT_INPUT_CUSTOM,
|
|
||||||
userData, cbPeek, cbNext, cbIsEndOfInput, cbGetPosition, cbSetPosition, cbDestructor);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZydisInputContext* ZydisCreateMemoryInput(const void* buffer, size_t bufferLen)
|
|
||||||
{
|
|
||||||
return ZydisCreateContext<ZydisInputContext, Zydis::MemoryInput>(
|
|
||||||
ZYDIS_CONTEXT_INPUT_MEMORY, buffer, bufferLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisIsEndOfInput(const ZydisInputContext* input, bool* isEndOfInput)
|
|
||||||
{
|
|
||||||
Zydis::BaseInput* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*isEndOfInput = instance->isEndOfInput();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisGetInputPosition(const ZydisInputContext* input, uint64_t* position)
|
|
||||||
{
|
|
||||||
Zydis::BaseInput* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*position = instance->getPosition();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisSetInputPosition(const ZydisInputContext* input, uint64_t position)
|
|
||||||
{
|
|
||||||
Zydis::BaseInput* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ZydisSetLastError(ZYDIS_ERROR_SUCCESS);
|
|
||||||
return instance->setPosition(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisFreeInput(const ZydisInputContext* input)
|
|
||||||
{
|
|
||||||
return ZydisFreeContext<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* InstructionDecoder =========================================================================== */
|
|
||||||
|
|
||||||
ZydisInstructionDecoderContext* ZydisCreateInstructionDecoder()
|
|
||||||
{
|
|
||||||
return ZydisCreateContext<ZydisInstructionDecoderContext, Zydis::InstructionDecoder>(
|
|
||||||
ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
||||||
}
|
|
||||||
|
|
||||||
ZydisInstructionDecoderContext* ZydisCreateInstructionDecoderEx(
|
|
||||||
const ZydisInputContext* input, ZydisDisassemblerMode disassemblerMode,
|
|
||||||
ZydisInstructionSetVendor preferredVendor, uint64_t instructionPointer)
|
|
||||||
{
|
|
||||||
Zydis::BaseInput* object =
|
|
||||||
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
|
|
||||||
if (!object)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return ZydisCreateContext<ZydisInstructionDecoderContext, Zydis::InstructionDecoder>(
|
|
||||||
ZYDIS_CONTEXT_INSTRUCTIONDECODER, object,
|
|
||||||
static_cast<Zydis::DisassemblerMode>(disassemblerMode),
|
|
||||||
static_cast<Zydis::InstructionSetVendor>(preferredVendor), instructionPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisDecodeInstruction(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
ZydisInstructionInfo* info)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ZydisSetLastError(ZYDIS_ERROR_SUCCESS);
|
|
||||||
return instance->decodeInstruction(*reinterpret_cast<Zydis::InstructionInfo*>(info));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisGetDataSource(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
ZydisInputContext** input)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*input = reinterpret_cast<ZydisInputContext*>(instance->getDataSource());
|
|
||||||
if (!input)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisSetDataSource(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
ZydisInputContext* input)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Zydis::BaseInput* object =
|
|
||||||
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
|
|
||||||
if (!object)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
instance->setDataSource(object);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisGetDisassemblerMode(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
ZydisDisassemblerMode* disassemblerMode)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*disassemblerMode = static_cast<ZydisDisassemblerMode>(instance->getDisassemblerMode());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisSetDisassemblerMode(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
ZydisDisassemblerMode disassemblerMode)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
instance->setDisassemblerMode(static_cast<Zydis::DisassemblerMode>(disassemblerMode));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisGetPreferredVendor(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
ZydisInstructionSetVendor* preferredVendor)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*preferredVendor = static_cast<ZydisInstructionSetVendor>(instance->getPreferredVendor());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisSetPreferredVendor(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
ZydisInstructionSetVendor preferredVendor)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
instance->setPreferredVendor(static_cast<Zydis::InstructionSetVendor>(preferredVendor));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisGetInstructionPointer(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
uint64_t* instructionPointer)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*instructionPointer = instance->getInstructionPointer();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisSetInstructionPointer(const ZydisInstructionDecoderContext* decoder,
|
|
||||||
uint64_t instructionPointer)
|
|
||||||
{
|
|
||||||
Zydis::InstructionDecoder* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
|
|
||||||
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
instance->setInstructionPointer(instructionPointer);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisFreeInstructionDecoder(const ZydisInstructionDecoderContext* decoder)
|
|
||||||
{
|
|
||||||
return ZydisFreeContext<ZydisInstructionDecoderContext, Zydis::InstructionDecoder>(
|
|
||||||
ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* InstructionFormatter ========================================================================= */
|
|
||||||
|
|
||||||
ZydisInstructionFormatterContext* ZydisCreateCustomInstructionFormatter(/* TODO */)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZydisInstructionFormatterContext* ZydisCreateIntelInstructionFormatter()
|
|
||||||
{
|
|
||||||
return ZydisCreateContext<ZydisInstructionFormatterContext,
|
|
||||||
Zydis::IntelInstructionFormatter>(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_INTEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisFormatInstruction(const ZydisInstructionFormatterContext* formatter,
|
|
||||||
const ZydisInstructionInfo* info, const char** instructionText)
|
|
||||||
{
|
|
||||||
Zydis::BaseInstructionFormatter* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionFormatterContext,
|
|
||||||
Zydis::BaseInstructionFormatter>(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*instructionText =
|
|
||||||
instance->formatInstruction(*reinterpret_cast<const Zydis::InstructionInfo*>(info));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisGetSymbolResolver(const ZydisInstructionFormatterContext* formatter,
|
|
||||||
ZydisSymbolResolverContext** resolver)
|
|
||||||
{
|
|
||||||
Zydis::BaseInstructionFormatter* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionFormatterContext,
|
|
||||||
Zydis::BaseInstructionFormatter>(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*resolver = reinterpret_cast<ZydisSymbolResolverContext*>(instance->getSymbolResolver());
|
|
||||||
if (!resolver)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisSetSymbolResolver(const ZydisInstructionFormatterContext* formatter,
|
|
||||||
ZydisSymbolResolverContext* resolver)
|
|
||||||
{
|
|
||||||
Zydis::BaseInstructionFormatter* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisInstructionFormatterContext,
|
|
||||||
Zydis::BaseInstructionFormatter>(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Zydis::BaseSymbolResolver* object =
|
|
||||||
ZydisRetrieveInstance<ZydisSymbolResolverContext,
|
|
||||||
Zydis::BaseSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver);
|
|
||||||
if (!object)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
instance->setSymbolResolver(object);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisFreeInstructionFormatter(const ZydisInstructionFormatterContext* formatter)
|
|
||||||
{
|
|
||||||
return ZydisFreeContext<ZydisInstructionFormatterContext, Zydis::BaseInstructionFormatter>(
|
|
||||||
ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SymbolResolver =============================================================================== */
|
|
||||||
|
|
||||||
ZydisSymbolResolverContext* ZydisCreateCustomSymbolResolver(/*TODO*/)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZydisSymbolResolverContext* ZydisCreateExactSymbolResolver()
|
|
||||||
{
|
|
||||||
return ZydisCreateContext<ZydisSymbolResolverContext, Zydis::ExactSymbolResolver>(
|
|
||||||
ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisResolveSymbol(const ZydisSymbolResolverContext* resolver,
|
|
||||||
const ZydisInstructionInfo* info, uint64_t address, const char** symbol, uint64_t* offset)
|
|
||||||
{
|
|
||||||
Zydis::BaseSymbolResolver* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisSymbolResolverContext,
|
|
||||||
Zydis::BaseSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*symbol = instance->resolveSymbol(*reinterpret_cast<const Zydis::InstructionInfo*>(info),
|
|
||||||
address, *offset);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisExactSymbolResolverContainsSymbol(
|
|
||||||
const ZydisSymbolResolverContext* resolver, uint64_t address, bool* containsSymbol)
|
|
||||||
{
|
|
||||||
Zydis::ExactSymbolResolver* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisSymbolResolverContext,
|
|
||||||
Zydis::ExactSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*containsSymbol = instance->containsSymbol(address);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisExactSymbolResolverSetSymbol(const ZydisSymbolResolverContext* resolver,
|
|
||||||
uint64_t address, const char* name)
|
|
||||||
{
|
|
||||||
Zydis::ExactSymbolResolver* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisSymbolResolverContext,
|
|
||||||
Zydis::ExactSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
instance->setSymbol(address, name);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisExactSymbolResolverRemoveSymbol(const ZydisSymbolResolverContext* resolver,
|
|
||||||
uint64_t address)
|
|
||||||
{
|
|
||||||
Zydis::ExactSymbolResolver* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisSymbolResolverContext,
|
|
||||||
Zydis::ExactSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
instance->removeSymbol(address);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisExactSymbolResolverClear(const ZydisSymbolResolverContext* resolver)
|
|
||||||
{
|
|
||||||
Zydis::ExactSymbolResolver* instance =
|
|
||||||
ZydisRetrieveInstance<ZydisSymbolResolverContext,
|
|
||||||
Zydis::ExactSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver);
|
|
||||||
if (!instance)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
instance->clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ZydisFreeSymbolResolver(const ZydisSymbolResolverContext* resolver)
|
|
||||||
{
|
|
||||||
return ZydisFreeContext<ZydisSymbolResolverContext, Zydis::BaseSymbolResolver>(
|
|
||||||
ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================================== */
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,728 +0,0 @@
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Instruction decoder classes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ZYDIS_INSTRUCTIONDECODER_HPP_
|
|
||||||
#define _ZYDIS_INSTRUCTIONDECODER_HPP_
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
#include <istream>
|
|
||||||
#include "ZydisTypes.hpp"
|
|
||||||
|
|
||||||
namespace Zydis
|
|
||||||
{
|
|
||||||
|
|
||||||
/* BaseInput ==================================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The base class for all data-source implementations.
|
|
||||||
*/
|
|
||||||
class BaseInput
|
|
||||||
{
|
|
||||||
friend class InstructionDecoder;
|
|
||||||
private:
|
|
||||||
uint8_t m_currentInput;
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte from the data source. This method does NOT increase the
|
|
||||||
* current input position or the @c length field of the @c info parameter.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @return The current input byte. If the result is zero, you should always check the
|
|
||||||
* @c flags field of the @c info parameter for error flags.
|
|
||||||
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
|
|
||||||
*/
|
|
||||||
uint8_t inputPeek(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte from the data source. This method increases the current
|
|
||||||
* input position and the @c length field of the @c info parameter.
|
|
||||||
* This method also appends the new byte to to @c data field of the @c info
|
|
||||||
* parameter.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @return The current input byte. If the result is zero, you should always check the
|
|
||||||
* @c flags field of the @c info parameter for error flags.
|
|
||||||
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
|
|
||||||
*/
|
|
||||||
uint8_t inputNext(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte(s) from the data source. This method increases the current
|
|
||||||
* input position and the @c length field of the @c info parameter.
|
|
||||||
* This method also appends the new byte(s) to to @c data field of the @c info
|
|
||||||
* parameter.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @return The current input data. If the result is zero, you should always check the
|
|
||||||
* @c flags field of the @c info parameter for error flags.
|
|
||||||
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
T inputNext(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Returns the current input byte. The current input byte is set everytime the
|
|
||||||
* @c inputPeek or @c inputNext method is called.
|
|
||||||
* @return The current input byte.
|
|
||||||
*/
|
|
||||||
uint8_t inputCurrent() const;
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Override this method in your custom data source implementations.
|
|
||||||
* Reads the next byte from the data source. This method increases the current
|
|
||||||
* input position by one.
|
|
||||||
* @return The current input byte.
|
|
||||||
*/
|
|
||||||
virtual uint8_t internalInputPeek() = 0;
|
|
||||||
/**
|
|
||||||
* @brief Override this method in your custom data source implementations.
|
|
||||||
* Reads the next byte from the data source. This method does NOT increase the
|
|
||||||
* current input position.
|
|
||||||
* @return The current input byte.
|
|
||||||
*/
|
|
||||||
virtual uint8_t internalInputNext() = 0;
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Default constructor.
|
|
||||||
*/
|
|
||||||
BaseInput() { };
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Destructor.
|
|
||||||
*/
|
|
||||||
virtual ~BaseInput() { };
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Override this method in your custom data source implementations.
|
|
||||||
* Signals, if the end of the data source is reached.
|
|
||||||
* @return True if end of input, false if not.
|
|
||||||
*/
|
|
||||||
virtual bool isEndOfInput() const = 0;
|
|
||||||
/**
|
|
||||||
* @brief Override this method in your custom data source implementations.
|
|
||||||
* Returns the current input position.
|
|
||||||
* @return The current input position.
|
|
||||||
*/
|
|
||||||
virtual uint64_t getPosition() const = 0;
|
|
||||||
/**
|
|
||||||
* @brief Override this method in your custom data source implementations.
|
|
||||||
* Sets a new input position.
|
|
||||||
* @param position The new input position.
|
|
||||||
* @return Returns false, if the new position exceeds the maximum input length.
|
|
||||||
*/
|
|
||||||
virtual bool setPosition(uint64_t position) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uint8_t BaseInput::inputPeek(InstructionInfo& info)
|
|
||||||
{
|
|
||||||
if (info.length == 15)
|
|
||||||
{
|
|
||||||
info.flags |= IF_ERROR_LENGTH;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (isEndOfInput())
|
|
||||||
{
|
|
||||||
info.flags |= IF_ERROR_END_OF_INPUT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
m_currentInput = internalInputPeek();
|
|
||||||
return m_currentInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t BaseInput::inputNext(InstructionInfo& info)
|
|
||||||
{
|
|
||||||
if (info.length == 15)
|
|
||||||
{
|
|
||||||
info.flags |= IF_ERROR_LENGTH;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (isEndOfInput())
|
|
||||||
{
|
|
||||||
info.flags |= IF_ERROR_END_OF_INPUT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
m_currentInput = internalInputNext();
|
|
||||||
info.data[info.length] = m_currentInput;
|
|
||||||
info.length++;
|
|
||||||
return m_currentInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T BaseInput::inputNext(InstructionInfo& info)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value, "integral type required");
|
|
||||||
T result = 0;
|
|
||||||
for (unsigned i = 0; i < (sizeof(T) / sizeof(uint8_t)); ++i)
|
|
||||||
{
|
|
||||||
T b = inputNext(info);
|
|
||||||
if (!b && (info.flags & IF_ERROR_MASK))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
result |= (b << (i * 8));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t BaseInput::inputCurrent() const
|
|
||||||
{
|
|
||||||
return m_currentInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MemoryInput ================================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A memory-buffer based data source for the @c InstructionDecoder class.
|
|
||||||
*/
|
|
||||||
class MemoryInput : public BaseInput
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const void* m_inputBuffer;
|
|
||||||
uint64_t m_inputBufferLen;
|
|
||||||
uint64_t m_inputBufferPos;
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte from the data source. This method increases the current
|
|
||||||
* input position by one.
|
|
||||||
* @return The current input byte.
|
|
||||||
*/
|
|
||||||
uint8_t internalInputPeek() override;
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte from the data source. This method does NOT increase the
|
|
||||||
* current input position.
|
|
||||||
* @return The current input byte.
|
|
||||||
*/
|
|
||||||
uint8_t internalInputNext() override;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor.
|
|
||||||
* @param buffer The input buffer.
|
|
||||||
* @param bufferLen The length of the input buffer.
|
|
||||||
*/
|
|
||||||
MemoryInput(const void* buffer, size_t bufferLen)
|
|
||||||
: m_inputBuffer(buffer)
|
|
||||||
, m_inputBufferLen(bufferLen)
|
|
||||||
, m_inputBufferPos(0) { };
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Signals, if the end of the data source is reached.
|
|
||||||
* @return True if end of input, false if not.
|
|
||||||
*/
|
|
||||||
bool isEndOfInput() const override;
|
|
||||||
/**
|
|
||||||
* @brief Returns the current input position.
|
|
||||||
* @return The current input position.
|
|
||||||
*/
|
|
||||||
uint64_t getPosition() const override;
|
|
||||||
/**
|
|
||||||
* @brief Sets a new input position.
|
|
||||||
* @param position The new input position.
|
|
||||||
* @return Returns false, if the new position exceeds the maximum input length.
|
|
||||||
*/
|
|
||||||
bool setPosition(uint64_t position) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uint8_t MemoryInput::internalInputPeek()
|
|
||||||
{
|
|
||||||
return *(static_cast<const uint8_t*>(m_inputBuffer) + m_inputBufferPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t MemoryInput::internalInputNext()
|
|
||||||
{
|
|
||||||
++m_inputBufferPos;
|
|
||||||
return *(static_cast<const uint8_t*>(m_inputBuffer) + m_inputBufferPos - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool MemoryInput::isEndOfInput() const
|
|
||||||
{
|
|
||||||
return (m_inputBufferPos >= m_inputBufferLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t MemoryInput::getPosition() const
|
|
||||||
{
|
|
||||||
return m_inputBufferPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool MemoryInput::setPosition(uint64_t position)
|
|
||||||
{
|
|
||||||
m_inputBufferPos = position;
|
|
||||||
return isEndOfInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* StreamInput ================================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A stream based data source for the @c InstructionDecoder class.
|
|
||||||
*/
|
|
||||||
class StreamInput : public BaseInput
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::istream* m_inputStream;
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte from the data source. This method increases the current
|
|
||||||
* input position by one.
|
|
||||||
* @return The current input byte.
|
|
||||||
*/
|
|
||||||
uint8_t internalInputPeek() override;
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte from the data source. This method does NOT increase the
|
|
||||||
* current input position.
|
|
||||||
* @return The current input byte.
|
|
||||||
*/
|
|
||||||
uint8_t internalInputNext() override;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor.
|
|
||||||
* @param stream The input stream.
|
|
||||||
*/
|
|
||||||
explicit StreamInput(std::istream* stream)
|
|
||||||
: m_inputStream(stream) { };
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Signals, if the end of the data source is reached.
|
|
||||||
* @return True if end of input, false if not.
|
|
||||||
*/
|
|
||||||
bool isEndOfInput() const override;
|
|
||||||
/**
|
|
||||||
* @brief Returns the current input position.
|
|
||||||
* @return The current input position.
|
|
||||||
*/
|
|
||||||
uint64_t getPosition() const override;
|
|
||||||
/**
|
|
||||||
* @brief Sets a new input position.
|
|
||||||
* @param position The new input position.
|
|
||||||
* @return Returns false, if the new position exceeds the maximum input length.
|
|
||||||
*/
|
|
||||||
bool setPosition(uint64_t position) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uint8_t StreamInput::internalInputPeek()
|
|
||||||
{
|
|
||||||
if (!m_inputStream)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return static_cast<uint8_t>(m_inputStream->peek());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t StreamInput::internalInputNext()
|
|
||||||
{
|
|
||||||
if (!m_inputStream)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return static_cast<uint8_t>(m_inputStream->get());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool StreamInput::isEndOfInput() const
|
|
||||||
{
|
|
||||||
if (!m_inputStream)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// We use good() instead of eof() to make sure the decoding will fail, if an stream internal
|
|
||||||
// error occured.
|
|
||||||
return !m_inputStream->good();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t StreamInput::getPosition() const
|
|
||||||
{
|
|
||||||
if (!m_inputStream)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_inputStream->tellg();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool StreamInput::setPosition(uint64_t position)
|
|
||||||
{
|
|
||||||
if (!m_inputStream)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_inputStream->seekg(position);
|
|
||||||
return isEndOfInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enums ======================================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Values that represent a disassembler mode.
|
|
||||||
*/
|
|
||||||
enum class DisassemblerMode : uint8_t
|
|
||||||
{
|
|
||||||
M16BIT,
|
|
||||||
M32BIT,
|
|
||||||
M64BIT
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Values that represent an instruction-set vendor.
|
|
||||||
*/
|
|
||||||
enum class InstructionSetVendor : uint8_t
|
|
||||||
{
|
|
||||||
ANY,
|
|
||||||
INTEL,
|
|
||||||
AMD
|
|
||||||
};
|
|
||||||
|
|
||||||
/* InstructionDecoder =========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The @c InstructionDecoder class decodes x86/x86-64 assembly instructions from a
|
|
||||||
* given data source.
|
|
||||||
*/
|
|
||||||
class InstructionDecoder
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
enum class RegisterClass : uint8_t
|
|
||||||
{
|
|
||||||
GENERAL_PURPOSE,
|
|
||||||
MMX,
|
|
||||||
CONTROL,
|
|
||||||
DEBUG,
|
|
||||||
SEGMENT,
|
|
||||||
XMM
|
|
||||||
};
|
|
||||||
private:
|
|
||||||
BaseInput* m_input;
|
|
||||||
DisassemblerMode m_disassemblerMode;
|
|
||||||
InstructionSetVendor m_preferredVendor;
|
|
||||||
uint64_t m_instructionPointer;
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte from the data source. This method does NOT increase the
|
|
||||||
* current input position or the @c length field of the @c info parameter.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @return The current input byte. If the result is zero, you should always check the
|
|
||||||
* @c flags field of the @c info parameter for error flags.
|
|
||||||
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
|
|
||||||
*/
|
|
||||||
uint8_t inputPeek(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte from the data source. This method increases the current
|
|
||||||
* input position and the @c length field of the @info parameter.
|
|
||||||
* This method also appends the new byte to to @c data field of the @c info
|
|
||||||
* parameter.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @return The current input byte. If the result is zero, you should always check the
|
|
||||||
* @c flags field of the @c info parameter for error flags.
|
|
||||||
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
|
|
||||||
*/
|
|
||||||
uint8_t inputNext(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Reads the next byte(s) from the data source. This method increases the current
|
|
||||||
* input position and the @c length field of the @info parameter.
|
|
||||||
* This method also appends the new byte(s) to to @c data field of the @c info
|
|
||||||
* parameter.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @return The current input data. If the result is zero, you should always check the
|
|
||||||
* @c flags field of the @c info parameter for error flags.
|
|
||||||
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
T inputNext(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Returns the current input byte. The current input byte is set everytime the
|
|
||||||
* @c inputPeek or @c inputNext method is called.
|
|
||||||
* @return The current input byte.
|
|
||||||
*/
|
|
||||||
uint8_t inputCurrent() const;
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Decodes a register operand.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operand The @c OperandInfo struct that receives the decoded data.
|
|
||||||
* @param registerClass The register class to use.
|
|
||||||
* @param registerId The register id.
|
|
||||||
* @param operandSize The defined size of the operand.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeRegisterOperand(InstructionInfo& info, OperandInfo& operand,
|
|
||||||
RegisterClass registerClass, uint8_t registerId, DefinedOperandSize operandSize) const;
|
|
||||||
/**
|
|
||||||
* @brief Decodes a register/memory operand.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operand The @c OperandInfo struct that receives the decoded data.
|
|
||||||
* @param registerClass The register class to use.
|
|
||||||
* @param operandSize The defined size of the operand.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeRegisterMemoryOperand(InstructionInfo& info, OperandInfo& operand,
|
|
||||||
RegisterClass registerClass, DefinedOperandSize operandSize);
|
|
||||||
/**
|
|
||||||
* @brief Decodes an immediate operand.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operand The @c OperandInfo struct that receives the decoded data.
|
|
||||||
* @param operandSize The defined size of the operand.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeImmediate(InstructionInfo& info, OperandInfo& operand,
|
|
||||||
DefinedOperandSize operandSize);
|
|
||||||
/**
|
|
||||||
* @brief Decodes a displacement operand.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operand The @c OperandInfo struct that receives the decoded data.
|
|
||||||
* @param size The size of the displacement data.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeDisplacement(InstructionInfo& info, OperandInfo& operand, uint8_t size);
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Decodes the modrm field of the instruction. This method reads an additional
|
|
||||||
* input byte.
|
|
||||||
* @param The @c InstructionInfo struct that receives the decoded data.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeModrm(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Decodes the sib field of the instruction. This method reads an additional
|
|
||||||
* input byte.
|
|
||||||
* @param info The @c InstructionInfo struct that receives the decoded data.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeSIB(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Decodes vex prefix of the instruction. This method takes the current input byte
|
|
||||||
* to determine the vex prefix type and reads one or two additional input bytes
|
|
||||||
* on demand.
|
|
||||||
* @param info The @c InstructionInfo struct that receives the decoded data.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeVex(InstructionInfo& info);
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Returns the effective operand size.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operandSize The defined operand size.
|
|
||||||
* @return The effective operand size.
|
|
||||||
*/
|
|
||||||
uint16_t getEffectiveOperandSize(const InstructionInfo& info,
|
|
||||||
DefinedOperandSize operandSize) const;
|
|
||||||
/**
|
|
||||||
* @brief Decodes all instruction operands.
|
|
||||||
* @param info The @c InstructionInfo struct that receives the decoded data.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeOperands(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Decodes the specified instruction operand.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operand The @c OperandInfo struct that receives the decoded data.
|
|
||||||
* @param operandType The defined type of the operand.
|
|
||||||
* @param operandSize The defined size of the operand.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeOperand(InstructionInfo& info, OperandInfo& operand,
|
|
||||||
DefinedOperandType operandType, DefinedOperandSize operandSize);
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Resolves the effective operand and address mode of the instruction.
|
|
||||||
* This method requires a non-null value in the @c instrDefinition field of the
|
|
||||||
* @c info struct.
|
|
||||||
* @param info The @c InstructionInfo struct that receives the effective operand and
|
|
||||||
* address mode.
|
|
||||||
*/
|
|
||||||
void resolveOperandAndAddressMode(InstructionInfo& info) const;
|
|
||||||
/**
|
|
||||||
* @brief Calculates the effective REX/VEX.w, r, x, b, l values.
|
|
||||||
* This method requires a non-null value in the @c instrDefinition field of the
|
|
||||||
* @c info struct.
|
|
||||||
* @param info The @c InstructionInfo struct that receives the effective operand and
|
|
||||||
* address mode.
|
|
||||||
*/
|
|
||||||
void calculateEffectiveRexVexValues(InstructionInfo& info) const;
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Collects and decodes optional instruction prefixes.
|
|
||||||
* @param info The @c InstructionInfo struct that receives the decoded data.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodePrefixes(InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Collects and decodes the instruction opcodes using the opcode tree.
|
|
||||||
* @param info The @c InstructionInfo struct that receives the decoded data.
|
|
||||||
* @return True if it succeeds, false if it fails.
|
|
||||||
*/
|
|
||||||
bool decodeOpcode(InstructionInfo& info);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Default constructor.
|
|
||||||
*/
|
|
||||||
InstructionDecoder();
|
|
||||||
/**
|
|
||||||
* @brief Constructor.
|
|
||||||
* @param input A reference to the input data source.
|
|
||||||
* @param disassemblerMode The disasasembler mode.
|
|
||||||
* @param preferredVendor The preferred instruction-set vendor.
|
|
||||||
* @param instructionPointer The initial instruction pointer.
|
|
||||||
*/
|
|
||||||
explicit InstructionDecoder(BaseInput* input,
|
|
||||||
DisassemblerMode disassemblerMode = DisassemblerMode::M32BIT,
|
|
||||||
InstructionSetVendor preferredVendor = InstructionSetVendor::ANY,
|
|
||||||
uint64_t instructionPointer = 0);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Decodes the next instruction from the input data source.
|
|
||||||
* @param info The @c InstructionInfo struct that receives the information about the
|
|
||||||
* decoded instruction.
|
|
||||||
* @return This method returns false, if the current position has exceeded the maximum input
|
|
||||||
* length.
|
|
||||||
* In all other cases (valid and invalid instructions) the return value is true.
|
|
||||||
*/
|
|
||||||
bool decodeInstruction(InstructionInfo& info);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Returns a pointer to the current data source.
|
|
||||||
* @return A pointer to the current data source.
|
|
||||||
*/
|
|
||||||
BaseInput* getDataSource() const;
|
|
||||||
/**
|
|
||||||
* @brief Sets a new data source.
|
|
||||||
* @param input A reference to the new input data source.
|
|
||||||
*/
|
|
||||||
void setDataSource(BaseInput* input);
|
|
||||||
/**
|
|
||||||
* @brief Returns the current disassembler mode.
|
|
||||||
* @return The current disassembler mode.
|
|
||||||
*/
|
|
||||||
DisassemblerMode getDisassemblerMode() const;
|
|
||||||
/**
|
|
||||||
* @brief Sets the current disassembler mode.
|
|
||||||
* @param disassemblerMode The new disassembler mode.
|
|
||||||
*/
|
|
||||||
void setDisassemblerMode(DisassemblerMode disassemblerMode);
|
|
||||||
/**
|
|
||||||
* @brief Returns the preferred instruction-set vendor.
|
|
||||||
* @return The preferred instruction-set vendor.
|
|
||||||
*/
|
|
||||||
InstructionSetVendor getPreferredVendor() const;
|
|
||||||
/**
|
|
||||||
* @brief Sets the preferred instruction-set vendor.
|
|
||||||
* @param preferredVendor The new preferred instruction-set vendor.
|
|
||||||
*/
|
|
||||||
void setPreferredVendor(InstructionSetVendor preferredVendor);
|
|
||||||
/**
|
|
||||||
* @brief Returns the current instruction pointer.
|
|
||||||
* @return The current instruction pointer.
|
|
||||||
*/
|
|
||||||
uint64_t getInstructionPointer() const;
|
|
||||||
/**
|
|
||||||
* @brief Sets a new instruction pointer.
|
|
||||||
* @param instructionPointer The new instruction pointer.
|
|
||||||
*/
|
|
||||||
void setInstructionPointer(uint64_t instructionPointer);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uint8_t InstructionDecoder::inputPeek(InstructionInfo& info)
|
|
||||||
{
|
|
||||||
if (!m_input)
|
|
||||||
{
|
|
||||||
info.flags |= IF_ERROR_END_OF_INPUT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_input->inputPeek(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t InstructionDecoder::inputNext(InstructionInfo& info)
|
|
||||||
{
|
|
||||||
if (!m_input)
|
|
||||||
{
|
|
||||||
info.flags |= IF_ERROR_END_OF_INPUT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_input->inputNext(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline T InstructionDecoder::inputNext(InstructionInfo& info)
|
|
||||||
{
|
|
||||||
if (!m_input)
|
|
||||||
{
|
|
||||||
info.flags |= IF_ERROR_END_OF_INPUT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_input->inputNext<T>(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint8_t InstructionDecoder::inputCurrent() const
|
|
||||||
{
|
|
||||||
if (!m_input)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return m_input->inputCurrent();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BaseInput *InstructionDecoder::getDataSource() const
|
|
||||||
{
|
|
||||||
return m_input;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InstructionDecoder::setDataSource(BaseInput* input)
|
|
||||||
{
|
|
||||||
m_input = input;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline DisassemblerMode InstructionDecoder::getDisassemblerMode() const
|
|
||||||
{
|
|
||||||
return m_disassemblerMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InstructionDecoder::setDisassemblerMode(DisassemblerMode disassemblerMode)
|
|
||||||
{
|
|
||||||
m_disassemblerMode = disassemblerMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline InstructionSetVendor InstructionDecoder::getPreferredVendor() const
|
|
||||||
{
|
|
||||||
return m_preferredVendor;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InstructionDecoder::setPreferredVendor(InstructionSetVendor preferredVendor)
|
|
||||||
{
|
|
||||||
m_preferredVendor = preferredVendor;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t InstructionDecoder::getInstructionPointer() const
|
|
||||||
{
|
|
||||||
return m_instructionPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void InstructionDecoder::setInstructionPointer(uint64_t instructionPointer)
|
|
||||||
{
|
|
||||||
m_instructionPointer = instructionPointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================================== */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ZYDIS_INSTRUCTIONDECODER_HPP_ */
|
|
|
@ -1,604 +0,0 @@
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
#include "ZydisInstructionFormatter.hpp"
|
|
||||||
#include "ZydisUtils.hpp"
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <cctype>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace Zydis
|
|
||||||
{
|
|
||||||
|
|
||||||
/* BaseInstructionFormatter ================================================================ */
|
|
||||||
|
|
||||||
const char* BaseInstructionFormatter::m_registerStrings[] =
|
|
||||||
{
|
|
||||||
/* 8 bit general purpose registers */
|
|
||||||
"al", "cl", "dl", "bl",
|
|
||||||
"ah", "ch", "dh", "bh",
|
|
||||||
"spl", "bpl", "sil", "dil",
|
|
||||||
"r8b", "r9b", "r10b", "r11b",
|
|
||||||
"r12b", "r13b", "r14b", "r15b",
|
|
||||||
/* 16 bit general purpose registers */
|
|
||||||
"ax", "cx", "dx", "bx",
|
|
||||||
"sp", "bp", "si", "di",
|
|
||||||
"r8w", "r9w", "r10w", "r11w",
|
|
||||||
"r12w", "r13w", "r14w", "r15w",
|
|
||||||
/* 32 bit general purpose registers */
|
|
||||||
"eax", "ecx", "edx", "ebx",
|
|
||||||
"esp", "ebp", "esi", "edi",
|
|
||||||
"r8d", "r9d", "r10d", "r11d",
|
|
||||||
"r12d", "r13d", "r14d", "r15d",
|
|
||||||
/* 64 bit general purpose registers */
|
|
||||||
"rax", "rcx", "rdx", "rbx",
|
|
||||||
"rsp", "rbp", "rsi", "rdi",
|
|
||||||
"r8", "r9", "r10", "r11",
|
|
||||||
"r12", "r13", "r14", "r15",
|
|
||||||
/* segment registers */
|
|
||||||
"es", "cs", "ss",
|
|
||||||
"ds", "fs", "gs",
|
|
||||||
/* control registers */
|
|
||||||
"cr0", "cr1", "cr2", "cr3",
|
|
||||||
"cr4", "cr5", "cr6", "cr7",
|
|
||||||
"cr8", "cr9", "cr10", "cr11",
|
|
||||||
"cr12", "cr13", "cr14", "cr15",
|
|
||||||
/* debug registers */
|
|
||||||
"dr0", "dr1", "dr2", "dr3",
|
|
||||||
"dr4", "dr5", "dr6", "dr7",
|
|
||||||
"dr8", "dr9", "dr10", "dr11",
|
|
||||||
"dr12", "dr13", "dr14", "dr15",
|
|
||||||
/* mmx registers */
|
|
||||||
"mm0", "mm1", "mm2", "mm3",
|
|
||||||
"mm4", "mm5", "mm6", "mm7",
|
|
||||||
/* x87 registers */
|
|
||||||
"st0", "st1", "st2", "st3",
|
|
||||||
"st4", "st5", "st6", "st7",
|
|
||||||
/* extended multimedia registers */
|
|
||||||
"xmm0", "xmm1", "xmm2", "xmm3",
|
|
||||||
"xmm4", "xmm5", "xmm6", "xmm7",
|
|
||||||
"xmm8", "xmm9", "xmm10", "xmm11",
|
|
||||||
"xmm12", "xmm13", "xmm14", "xmm15",
|
|
||||||
/* 256 bit multimedia registers */
|
|
||||||
"ymm0", "ymm1", "ymm2", "ymm3",
|
|
||||||
"ymm4", "ymm5", "ymm6", "ymm7",
|
|
||||||
"ymm8", "ymm9", "ymm10", "ymm11",
|
|
||||||
"ymm12", "ymm13", "ymm14", "ymm15",
|
|
||||||
/* instruction pointer register */
|
|
||||||
"rip"
|
|
||||||
};
|
|
||||||
|
|
||||||
void BaseInstructionFormatter::internalFormatInstruction(const InstructionInfo& /*info*/)
|
|
||||||
{
|
|
||||||
// Nothing to do here
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseInstructionFormatter::BaseInstructionFormatter()
|
|
||||||
: m_symbolResolver(nullptr)
|
|
||||||
, m_outputStringLen(0)
|
|
||||||
, m_outputUppercase(false)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseInstructionFormatter::BaseInstructionFormatter(
|
|
||||||
BaseSymbolResolver *symbolResolver)
|
|
||||||
: m_symbolResolver(symbolResolver)
|
|
||||||
, m_outputStringLen(0)
|
|
||||||
, m_outputUppercase(false)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* BaseInstructionFormatter::formatInstruction(const InstructionInfo& info)
|
|
||||||
{
|
|
||||||
// Clears the internal string buffer
|
|
||||||
outputClear();
|
|
||||||
// Calls the virtual format method that actually formats the instruction
|
|
||||||
internalFormatInstruction(info);
|
|
||||||
if (m_outputBuffer.size() == 0)
|
|
||||||
{
|
|
||||||
// The basic instruction formatter only returns the instruction menmonic.
|
|
||||||
return Internal::GetInstructionMnemonicString(info.mnemonic);
|
|
||||||
}
|
|
||||||
// Return the formatted instruction string
|
|
||||||
return outputString();
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseInstructionFormatter::~BaseInstructionFormatter()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseInstructionFormatter::outputClear()
|
|
||||||
{
|
|
||||||
m_outputStringLen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *BaseInstructionFormatter::outputString()
|
|
||||||
{
|
|
||||||
return& m_outputBuffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseInstructionFormatter::outputAppend(char const* text)
|
|
||||||
{
|
|
||||||
// Get the string length including the null-terminator char
|
|
||||||
size_t strLen = strlen(text) + 1;
|
|
||||||
// Get the buffer size
|
|
||||||
size_t bufLen = m_outputBuffer.size();
|
|
||||||
// Decrease the offset by one, to exclude already existing null-terminator chars in the
|
|
||||||
// output buffer
|
|
||||||
size_t offset = (m_outputStringLen) ? m_outputStringLen - 1 : 0;
|
|
||||||
// Resize capacity of the output buffer on demand and add some extra space to improve the
|
|
||||||
// performance
|
|
||||||
if (bufLen <= (m_outputStringLen + strLen))
|
|
||||||
{
|
|
||||||
m_outputBuffer.resize(bufLen + strLen + 512);
|
|
||||||
}
|
|
||||||
// Write the text to the output buffer
|
|
||||||
memcpy(&m_outputBuffer[offset], text, strLen);
|
|
||||||
// Increase the string length
|
|
||||||
m_outputStringLen = offset + strLen;
|
|
||||||
// Convert to uppercase
|
|
||||||
if (m_outputUppercase)
|
|
||||||
{
|
|
||||||
for (size_t i = offset; i < m_outputStringLen - 1; ++i)
|
|
||||||
{
|
|
||||||
m_outputBuffer[i] = static_cast<char>(toupper(m_outputBuffer[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseInstructionFormatter::outputAppendFormatted(char const* format, ...)
|
|
||||||
{
|
|
||||||
va_list arguments;
|
|
||||||
va_start(arguments, format);
|
|
||||||
// Get the buffer size
|
|
||||||
size_t bufLen = m_outputBuffer.size();
|
|
||||||
// Decrease the offset by one, to exclude already existing null-terminator chars in the
|
|
||||||
// output buffer
|
|
||||||
size_t offset = (m_outputStringLen) ? m_outputStringLen - 1 : 0;
|
|
||||||
// Resize the output buffer on demand and add some extra space to improve the performance
|
|
||||||
if ((bufLen - m_outputStringLen) < 256)
|
|
||||||
{
|
|
||||||
bufLen = bufLen + 512;
|
|
||||||
m_outputBuffer.resize(bufLen);
|
|
||||||
}
|
|
||||||
int strLen = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
// If the formatted text did not fit in the output buffer, resize it, and try again
|
|
||||||
if (strLen < 0)
|
|
||||||
{
|
|
||||||
m_outputBuffer.resize(bufLen + 512);
|
|
||||||
return outputAppendFormatted(format, arguments);
|
|
||||||
}
|
|
||||||
// Write the formatted text to the output buffer
|
|
||||||
assert((bufLen - offset) > 0);
|
|
||||||
strLen = std::vsnprintf(&m_outputBuffer[offset], bufLen - offset, format, arguments);
|
|
||||||
} while (strLen < 0);
|
|
||||||
// Increase the string length
|
|
||||||
m_outputStringLen = offset + strLen + 1;
|
|
||||||
// Convert to uppercase
|
|
||||||
if (m_outputUppercase)
|
|
||||||
{
|
|
||||||
for (size_t i = offset; i < m_outputStringLen - 1; ++i)
|
|
||||||
{
|
|
||||||
m_outputBuffer[i] = static_cast<char>(toupper(m_outputBuffer[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
va_end(arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseInstructionFormatter::outputAppendAddress(const InstructionInfo& info,
|
|
||||||
uint64_t address, bool resolveSymbols)
|
|
||||||
{
|
|
||||||
uint64_t offset = 0;
|
|
||||||
const char *name = nullptr;
|
|
||||||
if (resolveSymbols)
|
|
||||||
{
|
|
||||||
name = resolveSymbol(info, address, offset);
|
|
||||||
}
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
if (offset)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%s+%.2llX", name, offset);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
outputAppend(name);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
if (info.flags & IF_DISASSEMBLER_MODE_16)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%.4X", address);
|
|
||||||
} else if (info.flags & IF_DISASSEMBLER_MODE_32)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%.8lX", address);
|
|
||||||
} else if (info.flags & IF_DISASSEMBLER_MODE_64)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%.16llX", address);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseInstructionFormatter::outputAppendImmediate(const InstructionInfo& info,
|
|
||||||
const OperandInfo& operand, bool resolveSymbols)
|
|
||||||
{
|
|
||||||
assert(operand.type == OperandType::IMMEDIATE);
|
|
||||||
uint64_t value = 0;
|
|
||||||
if (operand.signed_lval&& (operand.size != info.operand_mode))
|
|
||||||
{
|
|
||||||
if (operand.size == 8)
|
|
||||||
{
|
|
||||||
value = static_cast<int64_t>(operand.lval.sbyte);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
assert(operand.size == 32);
|
|
||||||
value = static_cast<int64_t>(operand.lval.sdword);
|
|
||||||
}
|
|
||||||
if (info.operand_mode < 64)
|
|
||||||
{
|
|
||||||
value = value& ((1ull << info.operand_mode) - 1ull);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
switch (operand.size)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
value = operand.lval.ubyte;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
value = operand.lval.uword;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
value = operand.lval.udword;
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
value = operand.lval.uqword;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uint64_t offset = 0;
|
|
||||||
const char* name = nullptr;
|
|
||||||
if (resolveSymbols)
|
|
||||||
{
|
|
||||||
name = resolveSymbol(info, value, offset);
|
|
||||||
}
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
if (offset)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%s+%.2llX", name, offset);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
outputAppend(name);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%.2llX", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseInstructionFormatter::outputAppendDisplacement(const OperandInfo& operand)
|
|
||||||
{
|
|
||||||
assert(operand.offset > 0);
|
|
||||||
if ((operand.base == Register::NONE) && (operand.index == Register::NONE))
|
|
||||||
{
|
|
||||||
// Assume the displacement value is unsigned
|
|
||||||
assert(operand.scale == 0);
|
|
||||||
assert(operand.offset != 8);
|
|
||||||
uint64_t value = 0;
|
|
||||||
switch (operand.offset)
|
|
||||||
{
|
|
||||||
case 16:
|
|
||||||
value = operand.lval.uword;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
value = operand.lval.udword;
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
value = operand.lval.uqword;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
outputAppendFormatted("%.2llX", value);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
// The displacement value might be negative
|
|
||||||
assert(operand.offset != 64);
|
|
||||||
int64_t value = 0;
|
|
||||||
switch (operand.offset)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
value = operand.lval.sbyte;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
value = operand.lval.sword;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
value = operand.lval.sdword;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
if (value < 0)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("-%.2lX", -value);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%s%.2lX", (operand.base != Register::NONE ||
|
|
||||||
operand.index != Register::NONE) ? "+" : "", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IntelInstructionFormatter =============================================================== */
|
|
||||||
|
|
||||||
void IntelInstructionFormatter::outputAppendOperandCast(const OperandInfo& operand)
|
|
||||||
{
|
|
||||||
switch(operand.size)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
outputAppend("byte ptr " );
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
outputAppend("word ptr " );
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
outputAppend("dword ptr ");
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
outputAppend("qword ptr ");
|
|
||||||
break;
|
|
||||||
case 80:
|
|
||||||
outputAppend("tword ptr ");
|
|
||||||
break;
|
|
||||||
case 128:
|
|
||||||
outputAppend("oword ptr ");
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
outputAppend("yword ptr ");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IntelInstructionFormatter::formatOperand(const InstructionInfo& info,
|
|
||||||
const OperandInfo& operand)
|
|
||||||
{
|
|
||||||
switch (operand.type)
|
|
||||||
{
|
|
||||||
case OperandType::REGISTER:
|
|
||||||
outputAppend(registerToString(operand.base));
|
|
||||||
break;
|
|
||||||
case OperandType::MEMORY:
|
|
||||||
if (info.flags & IF_PREFIX_SEGMENT)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%s:", registerToString(info.segment));
|
|
||||||
}
|
|
||||||
outputAppend("[");
|
|
||||||
if (operand.base == Register::RIP)
|
|
||||||
{
|
|
||||||
// TODO: Add option
|
|
||||||
outputAppendAddress(info, CalcAbsoluteTarget(info, operand), true);
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
if (operand.base != Register::NONE)
|
|
||||||
{
|
|
||||||
outputAppend(registerToString(operand.base));
|
|
||||||
}
|
|
||||||
if (operand.index != Register::NONE)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("%s%s", operand.base != Register::NONE ? "+" : "",
|
|
||||||
registerToString(operand.index));
|
|
||||||
if (operand.scale)
|
|
||||||
{
|
|
||||||
outputAppendFormatted("*%d", operand.scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (operand.offset)
|
|
||||||
{
|
|
||||||
outputAppendDisplacement(operand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outputAppend("]");
|
|
||||||
break;
|
|
||||||
case OperandType::POINTER:
|
|
||||||
// TODO: resolve symbols
|
|
||||||
switch (operand.size)
|
|
||||||
{
|
|
||||||
case 32:
|
|
||||||
outputAppendFormatted("word %.4X:%.4X", operand.lval.ptr.seg,
|
|
||||||
operand.lval.ptr.off& 0xFFFF);
|
|
||||||
break;
|
|
||||||
case 48:
|
|
||||||
outputAppendFormatted("dword %.4X:%.8lX", operand.lval.ptr.seg, operand.lval.ptr.off);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OperandType::IMMEDIATE:
|
|
||||||
{
|
|
||||||
outputAppendImmediate(info, operand, true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OperandType::REL_IMMEDIATE:
|
|
||||||
{
|
|
||||||
if (operand.size == 8)
|
|
||||||
{
|
|
||||||
outputAppend("short ");
|
|
||||||
}
|
|
||||||
outputAppendAddress(info, CalcAbsoluteTarget(info, operand), true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OperandType::CONSTANT:
|
|
||||||
outputAppendFormatted("%.2X", operand.lval.udword);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IntelInstructionFormatter::internalFormatInstruction(const InstructionInfo& info)
|
|
||||||
{
|
|
||||||
// Append string prefixes
|
|
||||||
if (info.flags & IF_PREFIX_LOCK)
|
|
||||||
{
|
|
||||||
outputAppend("lock ");
|
|
||||||
}
|
|
||||||
if (info.flags & IF_PREFIX_REP)
|
|
||||||
{
|
|
||||||
outputAppend("rep ");
|
|
||||||
} else if (info.flags & IF_PREFIX_REPNE)
|
|
||||||
{
|
|
||||||
outputAppend("repne ");
|
|
||||||
}
|
|
||||||
// Append the instruction mnemonic
|
|
||||||
outputAppend(Internal::GetInstructionMnemonicString(info.mnemonic));
|
|
||||||
// Append the first operand
|
|
||||||
if (info.operand[0].type != OperandType::NONE)
|
|
||||||
{
|
|
||||||
outputAppend(" ");
|
|
||||||
bool cast = false;
|
|
||||||
if (info.operand[0].type == OperandType::MEMORY)
|
|
||||||
{
|
|
||||||
if (info.operand[1].type == OperandType::IMMEDIATE ||
|
|
||||||
info.operand[1].type == OperandType::CONSTANT ||
|
|
||||||
info.operand[1].type == OperandType::NONE ||
|
|
||||||
(info.operand[0].size != info.operand[1].size))
|
|
||||||
{
|
|
||||||
cast = true;
|
|
||||||
} else if (info.operand[1].type == OperandType::REGISTER &&
|
|
||||||
info.operand[1].base == Register::CL)
|
|
||||||
{
|
|
||||||
switch (info.mnemonic)
|
|
||||||
{
|
|
||||||
case InstructionMnemonic::RCL:
|
|
||||||
case InstructionMnemonic::ROL:
|
|
||||||
case InstructionMnemonic::ROR:
|
|
||||||
case InstructionMnemonic::RCR:
|
|
||||||
case InstructionMnemonic::SHL:
|
|
||||||
case InstructionMnemonic::SHR:
|
|
||||||
case InstructionMnemonic::SAR:
|
|
||||||
cast = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cast)
|
|
||||||
{
|
|
||||||
outputAppendOperandCast(info.operand[0]);
|
|
||||||
}
|
|
||||||
formatOperand(info, info.operand[0]);
|
|
||||||
}
|
|
||||||
// Append the second operand
|
|
||||||
if (info.operand[1].type != OperandType::NONE)
|
|
||||||
{
|
|
||||||
outputAppend(", ");
|
|
||||||
bool cast = false;
|
|
||||||
if (info.operand[1].type == OperandType::MEMORY &&
|
|
||||||
info.operand[0].size != info.operand[1].size &&
|
|
||||||
((info.operand[0].type != OperandType::REGISTER) ||
|
|
||||||
((info.operand[0].base != Register::ES) &&
|
|
||||||
(info.operand[0].base != Register::CS) &&
|
|
||||||
(info.operand[0].base != Register::SS) &&
|
|
||||||
(info.operand[0].base != Register::DS) &&
|
|
||||||
(info.operand[0].base != Register::FS) &&
|
|
||||||
(info.operand[0].base != Register::GS))))
|
|
||||||
{
|
|
||||||
cast = true;
|
|
||||||
}
|
|
||||||
if (cast)
|
|
||||||
{
|
|
||||||
outputAppendOperandCast(info.operand[1]);
|
|
||||||
}
|
|
||||||
formatOperand(info, info.operand[1]);
|
|
||||||
}
|
|
||||||
// Append the third operand
|
|
||||||
if (info.operand[2].type != OperandType::NONE)
|
|
||||||
{
|
|
||||||
outputAppend(", ");
|
|
||||||
bool cast = false;
|
|
||||||
if (info.operand[2].type == OperandType::MEMORY &&
|
|
||||||
(info.operand[2].size != info.operand[1].size))
|
|
||||||
{
|
|
||||||
cast = true;
|
|
||||||
}
|
|
||||||
if (cast)
|
|
||||||
{
|
|
||||||
outputAppendOperandCast(info.operand[2]);
|
|
||||||
}
|
|
||||||
formatOperand(info, info.operand[2]);
|
|
||||||
}
|
|
||||||
// Append the fourth operand
|
|
||||||
if (info.operand[3].type != OperandType::NONE)
|
|
||||||
{
|
|
||||||
outputAppend(", ");
|
|
||||||
formatOperand(info, info.operand[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IntelInstructionFormatter::IntelInstructionFormatter()
|
|
||||||
: BaseInstructionFormatter()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
IntelInstructionFormatter::IntelInstructionFormatter(
|
|
||||||
BaseSymbolResolver *symbolResolver)
|
|
||||||
: BaseInstructionFormatter(symbolResolver)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
IntelInstructionFormatter::~IntelInstructionFormatter()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================================== */
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,250 +0,0 @@
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Instruction formatting classes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ZYDIS_INSTRUCTIONFORMATTER_HPP_
|
|
||||||
#define _ZYDIS_INSTRUCTIONFORMATTER_HPP_
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include "ZydisTypes.hpp"
|
|
||||||
#include "ZydisSymbolResolver.hpp"
|
|
||||||
|
|
||||||
namespace Zydis
|
|
||||||
{
|
|
||||||
|
|
||||||
/* BaseInstructionFormatter ===================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Base class for all instruction formatter implementations.
|
|
||||||
*/
|
|
||||||
class BaseInstructionFormatter
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static const char* m_registerStrings[];
|
|
||||||
BaseSymbolResolver* m_symbolResolver;
|
|
||||||
std::vector<char> m_outputBuffer;
|
|
||||||
size_t m_outputStringLen;
|
|
||||||
bool m_outputUppercase;
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Clears the output string buffer.
|
|
||||||
*/
|
|
||||||
void outputClear();
|
|
||||||
/**
|
|
||||||
* @brief Returns the content of the output string buffer.
|
|
||||||
* @return Pointer to the content of the ouput string buffer.
|
|
||||||
*/
|
|
||||||
const char* outputString();
|
|
||||||
/**
|
|
||||||
* @brief Appends text to the ouput string buffer.
|
|
||||||
* @param text The text.
|
|
||||||
*/
|
|
||||||
void outputAppend(const char* text);
|
|
||||||
/**
|
|
||||||
* @brief Appends formatted text to the output string buffer.
|
|
||||||
* @param format The format string.
|
|
||||||
*/
|
|
||||||
void outputAppendFormatted(const char* format, ...);
|
|
||||||
/**
|
|
||||||
* @brief Changes automatic conversion of characters to uppercase.
|
|
||||||
* @param uppercase Set true to enable automatic uppercase conversion.
|
|
||||||
*/
|
|
||||||
void outputSetUppercase(bool uppercase);
|
|
||||||
/**
|
|
||||||
* @brief Appends a formatted address to the output string buffer.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param address The address.
|
|
||||||
* @param resolveSymbols If this parameter is true, the method will try to display a
|
|
||||||
* smybol name instead of the numeric value.
|
|
||||||
*/
|
|
||||||
void outputAppendAddress(const InstructionInfo& info, uint64_t address,
|
|
||||||
bool resolveSymbols = true);
|
|
||||||
/**
|
|
||||||
* @brief Appends a formatted immediate value to the output string buffer.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operand The immediate operand.
|
|
||||||
* @param resolveSymbols If this parameter is true, the method will try to display a
|
|
||||||
* smybol name instead of the numeric value.
|
|
||||||
*/
|
|
||||||
void outputAppendImmediate(const InstructionInfo& info, const OperandInfo& operand,
|
|
||||||
bool resolveSymbols = false);
|
|
||||||
/**
|
|
||||||
* @brief Appends a formatted memory displacement value to the output string buffer.
|
|
||||||
* @param operand The memory operand.
|
|
||||||
*/
|
|
||||||
void outputAppendDisplacement(const OperandInfo& operand);
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Returns the string representation of a given register.
|
|
||||||
* @param reg The register.
|
|
||||||
* @return The string representation of the given register.
|
|
||||||
*/
|
|
||||||
const char *registerToString(Register reg) const;
|
|
||||||
/**
|
|
||||||
* @brief Resolves a symbol.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param address The address.
|
|
||||||
* @param offset Reference to an unsigned 64 bit integer that receives an offset
|
|
||||||
* relative to the base address of the symbol.
|
|
||||||
* @return The name of the symbol, if the symbol was found, @c NULL if not.
|
|
||||||
*/
|
|
||||||
const char* resolveSymbol(const InstructionInfo& info, uint64_t address,
|
|
||||||
uint64_t& offset) const;
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Override this method to implement a custom disassembly syntax. Use the
|
|
||||||
* @c outputAppend and @c outputAppendFormatted methods to fill the internal
|
|
||||||
* string buffer.
|
|
||||||
* @param info The instruction info.
|
|
||||||
*/
|
|
||||||
virtual void internalFormatInstruction(const InstructionInfo& info);
|
|
||||||
/**
|
|
||||||
* @brief Default constructor.
|
|
||||||
*/
|
|
||||||
BaseInstructionFormatter();
|
|
||||||
/**
|
|
||||||
* @brief Constructor.
|
|
||||||
* @param symbolResolver Pointer to a symbol resolver instance or @c NULL, if no smybol
|
|
||||||
* resolver should be used.
|
|
||||||
*/
|
|
||||||
explicit BaseInstructionFormatter(BaseSymbolResolver* symbolResolver);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Destructor.
|
|
||||||
*/
|
|
||||||
virtual ~BaseInstructionFormatter();
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Formats a decoded instruction.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @return Pointer to the formatted instruction string.
|
|
||||||
*/
|
|
||||||
const char* formatInstruction(const InstructionInfo& info);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Returns a pointer to the current symbol resolver.
|
|
||||||
* @return Pointer to the current symbol resolver or @c NULL, if no symbol resolver is used.
|
|
||||||
*/
|
|
||||||
BaseSymbolResolver* getSymbolResolver() const;
|
|
||||||
/**
|
|
||||||
* @brief Sets a new symbol resolver.
|
|
||||||
* @param symbolResolver Pointer to a symbol resolver instance or @c NULL, if no smybol
|
|
||||||
* resolver should be used.
|
|
||||||
*/
|
|
||||||
void setSymbolResolver(BaseSymbolResolver* symbolResolver);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void BaseInstructionFormatter::outputSetUppercase(bool uppercase)
|
|
||||||
{
|
|
||||||
m_outputUppercase = uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char const* BaseInstructionFormatter::registerToString(Register reg) const
|
|
||||||
{
|
|
||||||
if (reg == Register::NONE)
|
|
||||||
{
|
|
||||||
return "error";
|
|
||||||
}
|
|
||||||
return m_registerStrings[static_cast<uint16_t>(reg) - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
inline char const* BaseInstructionFormatter::resolveSymbol(const InstructionInfo& info,
|
|
||||||
uint64_t address, uint64_t& offset) const
|
|
||||||
{
|
|
||||||
if (m_symbolResolver)
|
|
||||||
{
|
|
||||||
return m_symbolResolver->resolveSymbol(info, address, offset);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline BaseSymbolResolver* BaseInstructionFormatter::getSymbolResolver() const
|
|
||||||
{
|
|
||||||
return m_symbolResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void BaseInstructionFormatter::setSymbolResolver(
|
|
||||||
BaseSymbolResolver* symbolResolver)
|
|
||||||
{
|
|
||||||
m_symbolResolver = symbolResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IntelInstructionFormatter ==================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Intel syntax instruction formatter.
|
|
||||||
*/
|
|
||||||
class IntelInstructionFormatter : public BaseInstructionFormatter
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Appends an operand cast to the output string buffer.
|
|
||||||
* @param operand The operand.
|
|
||||||
*/
|
|
||||||
void outputAppendOperandCast(const OperandInfo& operand);
|
|
||||||
/**
|
|
||||||
* @brief Formats the specified operand and appends the resulting string to the output
|
|
||||||
* buffer.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operand The operand.
|
|
||||||
*/
|
|
||||||
void formatOperand(const InstructionInfo& info, const OperandInfo& operand);
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Fills the internal string buffer with an intel style formatted instruction string.
|
|
||||||
* @param info The instruction info.
|
|
||||||
*/
|
|
||||||
void internalFormatInstruction(const InstructionInfo& info) override;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Default constructor.
|
|
||||||
*/
|
|
||||||
IntelInstructionFormatter();
|
|
||||||
/**
|
|
||||||
* @brief Constructor.
|
|
||||||
* @param symbolResolver Pointer to a symbol resolver instance or @c NULL, if no smybol
|
|
||||||
* resolver should be used.
|
|
||||||
*/
|
|
||||||
explicit IntelInstructionFormatter(BaseSymbolResolver* symbolResolver);
|
|
||||||
/**
|
|
||||||
* @brief Destructor.
|
|
||||||
*/
|
|
||||||
~IntelInstructionFormatter() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ============================================================================================== */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ZYDIS_INSTRUCTIONFORMATTER_HPP_ */
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,93 +0,0 @@
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
#include "ZydisSymbolResolver.hpp"
|
|
||||||
|
|
||||||
namespace Zydis
|
|
||||||
{
|
|
||||||
|
|
||||||
/* BaseSymbolResolver ====================================================================== */
|
|
||||||
|
|
||||||
BaseSymbolResolver::~BaseSymbolResolver()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* BaseSymbolResolver::resolveSymbol(const InstructionInfo& /*info*/,
|
|
||||||
uint64_t /*address*/, uint64_t& /*offset*/)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ExactSymbolResolver ===================================================================== */
|
|
||||||
|
|
||||||
ExactSymbolResolver::~ExactSymbolResolver()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* ExactSymbolResolver::resolveSymbol(const InstructionInfo& /*info*/,
|
|
||||||
uint64_t address, uint64_t& offset)
|
|
||||||
{
|
|
||||||
std::unordered_map<uint64_t, std::string>::const_iterator iterator = m_symbolMap.find(address);
|
|
||||||
if (iterator != m_symbolMap.cend())
|
|
||||||
{
|
|
||||||
offset = 0;
|
|
||||||
return iterator->second.c_str();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ExactSymbolResolver::containsSymbol(uint64_t address) const
|
|
||||||
{
|
|
||||||
std::unordered_map<uint64_t, std::string>::const_iterator iterator = m_symbolMap.find(address);
|
|
||||||
return (iterator != m_symbolMap.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExactSymbolResolver::setSymbol(uint64_t address, const char *name)
|
|
||||||
{
|
|
||||||
m_symbolMap[address].assign(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExactSymbolResolver::removeSymbol(uint64_t address)
|
|
||||||
{
|
|
||||||
m_symbolMap.erase(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExactSymbolResolver::clear()
|
|
||||||
{
|
|
||||||
m_symbolMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================================================== */
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Classes for symbol resolving in the disassembly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ZYDIS_SYMBOLRESOLVER_HPP_
|
|
||||||
#define _ZYDIS_SYMBOLRESOLVER_HPP_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "ZydisTypes.hpp"
|
|
||||||
|
|
||||||
namespace Zydis
|
|
||||||
{
|
|
||||||
|
|
||||||
/* BaseSymbolResolver =========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Base class for all symbol resolver implementations.
|
|
||||||
*/
|
|
||||||
class BaseSymbolResolver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Destructor.
|
|
||||||
*/
|
|
||||||
virtual ~BaseSymbolResolver();
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Resolves a symbol.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param address The address.
|
|
||||||
* @param offset Reference to an unsigned 64 bit integer that receives an offset
|
|
||||||
* relative to the base address of the symbol.
|
|
||||||
* @return The name of the symbol, if the symbol was found, @c NULL if not.
|
|
||||||
*/
|
|
||||||
virtual const char* resolveSymbol(const InstructionInfo& info, uint64_t address,
|
|
||||||
uint64_t& offset);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ExactSymbolResolver ========================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Simple symbol resolver that only matches exact addresses.
|
|
||||||
*/
|
|
||||||
class ExactSymbolResolver : public BaseSymbolResolver
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::unordered_map<uint64_t, std::string> m_symbolMap;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Destructor.
|
|
||||||
*/
|
|
||||||
~ExactSymbolResolver() override;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Resolves a symbol.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param address The address.
|
|
||||||
* @param offset Reference to an unsigned 64 bit integer that receives an offset
|
|
||||||
* relative to the base address of the symbol.
|
|
||||||
* @return The name of the symbol, if the symbol was found, @c NULL if not.
|
|
||||||
*/
|
|
||||||
const char* resolveSymbol(const InstructionInfo& info, uint64_t address,
|
|
||||||
uint64_t& offset) override;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Query if the given address is a known symbol.
|
|
||||||
* @param address The address.
|
|
||||||
* @return True if the address is known, false if not.
|
|
||||||
*/
|
|
||||||
bool containsSymbol(uint64_t address) const;
|
|
||||||
/**
|
|
||||||
* @brief Adds or changes a symbol.
|
|
||||||
* @param address The address.
|
|
||||||
* @param name The symbol name.
|
|
||||||
*/
|
|
||||||
void setSymbol(uint64_t address, const char* name);
|
|
||||||
/**
|
|
||||||
* @brief Removes the symbol described by address. This will invalidate all char pointers
|
|
||||||
* to the specific symbol name.
|
|
||||||
* @param address The address.
|
|
||||||
*/
|
|
||||||
void removeSymbol(uint64_t address);
|
|
||||||
/**
|
|
||||||
* @brief Clears the symbol tree.
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ============================================================================================== */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ZYDIS_SYMBOLRESOLVER_HPP_ */
|
|
|
@ -1,543 +0,0 @@
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _ZYDIS_TYPES_HPP_
|
|
||||||
#define _ZYDIS_TYPES_HPP_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "ZydisOpcodeTable.hpp"
|
|
||||||
|
|
||||||
namespace Zydis
|
|
||||||
{
|
|
||||||
|
|
||||||
/* InstructionFlags ============================================================================= */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Values that represent additional flags of a decoded instruction.
|
|
||||||
*/
|
|
||||||
enum InstructionFlags : uint32_t
|
|
||||||
{
|
|
||||||
IF_NONE = 0x00000000,
|
|
||||||
/**
|
|
||||||
* @brief The instruction was decoded in 16 bit disassembler mode.
|
|
||||||
*/
|
|
||||||
IF_DISASSEMBLER_MODE_16 = 0x00000001,
|
|
||||||
/**
|
|
||||||
* @brief The instruction was decoded in 32 bit disassembler mode.
|
|
||||||
*/
|
|
||||||
IF_DISASSEMBLER_MODE_32 = 0x00000002,
|
|
||||||
/**
|
|
||||||
* @brief The instruction was decoded in 64 bit disassembler mode.
|
|
||||||
*/
|
|
||||||
IF_DISASSEMBLER_MODE_64 = 0x00000004,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has a segment prefix (0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65).
|
|
||||||
*/
|
|
||||||
IF_PREFIX_SEGMENT = 0x00000008,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has a lock prefix (0xF0).
|
|
||||||
*/
|
|
||||||
IF_PREFIX_LOCK = 0x00000010,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has a repne prefix (0xF2).
|
|
||||||
*/
|
|
||||||
IF_PREFIX_REPNE = 0x00000020,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has a rep prefix (0xF3).
|
|
||||||
*/
|
|
||||||
IF_PREFIX_REP = 0x00000040,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has an operand size prefix (0x66).
|
|
||||||
*/
|
|
||||||
IF_PREFIX_OPERAND_SIZE = 0x00000080,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has an address size prefix (0x67).
|
|
||||||
*/
|
|
||||||
IF_PREFIX_ADDRESS_SIZE = 0x00000100,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has a rex prefix (0x40 - 0x4F).
|
|
||||||
*/
|
|
||||||
IF_PREFIX_REX = 0x00000200,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has a vex prefix (0xC4 or 0xC5).
|
|
||||||
*/
|
|
||||||
IF_PREFIX_VEX = 0x00000400,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has a modrm byte.
|
|
||||||
*/
|
|
||||||
IF_MODRM = 0x00000800,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has a sib byte.
|
|
||||||
*/
|
|
||||||
IF_SIB = 0x00001000,
|
|
||||||
/**
|
|
||||||
* @brief The instruction has an operand with a relative address.
|
|
||||||
*/
|
|
||||||
IF_RELATIVE = 0x00002000,
|
|
||||||
/**
|
|
||||||
* @brief An error occured while decoding the instruction.
|
|
||||||
*/
|
|
||||||
IF_ERROR_MASK = 0xFFF00000,
|
|
||||||
/**
|
|
||||||
* @brief End of input reached while decoding the instruction.
|
|
||||||
*/
|
|
||||||
IF_ERROR_END_OF_INPUT = 0x00100000,
|
|
||||||
/**
|
|
||||||
* @brief The instruction length has exceeded the maximum of 15 bytes.
|
|
||||||
*/
|
|
||||||
IF_ERROR_LENGTH = 0x00200000,
|
|
||||||
/**
|
|
||||||
* @brief The instruction is invalid.
|
|
||||||
*/
|
|
||||||
IF_ERROR_INVALID = 0x00400000,
|
|
||||||
/**
|
|
||||||
* @brief The instruction is invalid in 64 bit mode.
|
|
||||||
*/
|
|
||||||
IF_ERROR_INVALID_64 = 0x00800000,
|
|
||||||
/**
|
|
||||||
* @brief An error occured while decoding the instruction operands.
|
|
||||||
*/
|
|
||||||
IF_ERROR_OPERAND = 0x01000000
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Register ===================================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Values that represent a cpu register.
|
|
||||||
*/
|
|
||||||
enum class Register : uint16_t
|
|
||||||
{
|
|
||||||
NONE,
|
|
||||||
/* 8 bit general purpose registers */
|
|
||||||
AL, CL, DL, BL,
|
|
||||||
AH, CH, DH, BH,
|
|
||||||
SPL, BPL, SIL, DIL,
|
|
||||||
R8B, R9B, R10B, R11B,
|
|
||||||
R12B, R13B, R14B, R15B,
|
|
||||||
/* 16 bit general purpose registers */
|
|
||||||
AX, CX, DX, BX,
|
|
||||||
SP, BP, SI, DI,
|
|
||||||
R8W, R9W, R10W, R11W,
|
|
||||||
R12W, R13W, R14W, R15W,
|
|
||||||
/* 32 bit general purpose registers */
|
|
||||||
EAX, ECX, EDX, EBX,
|
|
||||||
ESP, EBP, ESI, EDI,
|
|
||||||
R8D, R9D, R10D, R11D,
|
|
||||||
R12D, R13D, R14D, R15D,
|
|
||||||
/* 64 bit general purpose registers */
|
|
||||||
RAX, RCX, RDX, RBX,
|
|
||||||
RSP, RBP, RSI, RDI,
|
|
||||||
R8, R9, R10, R11,
|
|
||||||
R12, R13, R14, R15,
|
|
||||||
/* segment registers */
|
|
||||||
ES, CS, SS,
|
|
||||||
DS, FS, GS,
|
|
||||||
/* control registers */
|
|
||||||
CR0, CR1, CR2, CR3,
|
|
||||||
CR4, CR5, CR6, CR7,
|
|
||||||
CR8, CR9, CR10, CR11,
|
|
||||||
CR12, CR13, CR14, CR15,
|
|
||||||
/* debug registers */
|
|
||||||
DR0, DR1, DR2, DR3,
|
|
||||||
DR4, DR5, DR6, DR7,
|
|
||||||
DR8, DR9, DR10, DR11,
|
|
||||||
DR12, DR13, DR14, DR15,
|
|
||||||
/* mmx registers */
|
|
||||||
MM0, MM1, MM2, MM3,
|
|
||||||
MM4, MM5, MM6, MM7,
|
|
||||||
/* x87 registers */
|
|
||||||
ST0, ST1, ST2, ST3,
|
|
||||||
ST4, ST5, ST6, ST7,
|
|
||||||
/* extended multimedia registers */
|
|
||||||
XMM0, XMM1, XMM2, XMM3,
|
|
||||||
XMM4, XMM5, XMM6, XMM7,
|
|
||||||
XMM8, XMM9, XMM10, XMM11,
|
|
||||||
XMM12, XMM13, XMM14, XMM15,
|
|
||||||
/* 256 bit multimedia registers */
|
|
||||||
YMM0, YMM1, YMM2, YMM3,
|
|
||||||
YMM4, YMM5, YMM6, YMM7,
|
|
||||||
YMM8, YMM9, YMM10, YMM11,
|
|
||||||
YMM12, YMM13, YMM14, YMM15,
|
|
||||||
/* instruction pointer register */
|
|
||||||
RIP
|
|
||||||
};
|
|
||||||
|
|
||||||
/* OperandType ================================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Values that represent the type of a decoded operand.
|
|
||||||
*/
|
|
||||||
enum class OperandType : uint8_t
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief The operand is not used.
|
|
||||||
*/
|
|
||||||
NONE,
|
|
||||||
/**
|
|
||||||
* @brief The operand is a register operand.
|
|
||||||
*/
|
|
||||||
REGISTER,
|
|
||||||
/**
|
|
||||||
* @brief The operand is a memory operand.
|
|
||||||
*/
|
|
||||||
MEMORY,
|
|
||||||
/**
|
|
||||||
* @brief The operand is a pointer operand.
|
|
||||||
*/
|
|
||||||
POINTER,
|
|
||||||
/**
|
|
||||||
* @brief The operand is an immediate operand.
|
|
||||||
*/
|
|
||||||
IMMEDIATE,
|
|
||||||
/**
|
|
||||||
* @brief The operand is a relative immediate operand.
|
|
||||||
*/
|
|
||||||
REL_IMMEDIATE,
|
|
||||||
/**
|
|
||||||
* @brief The operand is a constant value.
|
|
||||||
*/
|
|
||||||
CONSTANT
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ZydisOperandAccessMode ============================================================================ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Values that represent the operand access mode.
|
|
||||||
*/
|
|
||||||
enum class OperandAccessMode : uint8_t
|
|
||||||
{
|
|
||||||
NA,
|
|
||||||
/**
|
|
||||||
* @brief The operand is accessed in read-only mode.
|
|
||||||
*/
|
|
||||||
READ,
|
|
||||||
/**
|
|
||||||
* @brief The operand is accessed in write mode.
|
|
||||||
*/
|
|
||||||
WRITE,
|
|
||||||
/**
|
|
||||||
* @brief The operand is accessed in read-write mode.
|
|
||||||
*/
|
|
||||||
READWRITE
|
|
||||||
};
|
|
||||||
|
|
||||||
/* OperandInfo ================================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This struct holds information about a decoded operand.
|
|
||||||
*/
|
|
||||||
struct OperandInfo
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief The type of the operand.
|
|
||||||
*/
|
|
||||||
OperandType type;
|
|
||||||
/**
|
|
||||||
* @brief The size of the operand.
|
|
||||||
*/
|
|
||||||
uint16_t size;
|
|
||||||
/**
|
|
||||||
* @brief The operand access mode.
|
|
||||||
*/
|
|
||||||
OperandAccessMode access_mode;
|
|
||||||
/**
|
|
||||||
* @brief The base register.
|
|
||||||
*/
|
|
||||||
Register base;
|
|
||||||
/**
|
|
||||||
* @brief The index register.
|
|
||||||
*/
|
|
||||||
Register index;
|
|
||||||
/**
|
|
||||||
* @brief The scale factor.
|
|
||||||
*/
|
|
||||||
uint8_t scale;
|
|
||||||
/**
|
|
||||||
* @brief The lvalue offset. If the @c offset is zero and the operand @c type is not
|
|
||||||
* @c CONSTANT, no lvalue is present.
|
|
||||||
*/
|
|
||||||
uint8_t offset;
|
|
||||||
/**
|
|
||||||
* @brief Signals, if the lval is signed.
|
|
||||||
*/
|
|
||||||
bool signed_lval;
|
|
||||||
/**
|
|
||||||
* @brief The lvalue.
|
|
||||||
*/
|
|
||||||
union {
|
|
||||||
int8_t sbyte;
|
|
||||||
uint8_t ubyte;
|
|
||||||
int16_t sword;
|
|
||||||
uint16_t uword;
|
|
||||||
int32_t sdword;
|
|
||||||
uint32_t udword;
|
|
||||||
int64_t sqword;
|
|
||||||
uint64_t uqword;
|
|
||||||
struct {
|
|
||||||
uint16_t seg;
|
|
||||||
uint32_t off;
|
|
||||||
} ptr;
|
|
||||||
} lval;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* InstructionInfo ============================================================================== */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This struct holds information about a decoded instruction.
|
|
||||||
*/
|
|
||||||
struct InstructionInfo
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief The instruction flags.
|
|
||||||
*/
|
|
||||||
uint32_t flags;
|
|
||||||
/**
|
|
||||||
* @brief The instruction mnemonic.
|
|
||||||
*/
|
|
||||||
InstructionMnemonic mnemonic;
|
|
||||||
/**
|
|
||||||
* @brief The total length of the instruction.
|
|
||||||
*/
|
|
||||||
uint8_t length;
|
|
||||||
/**
|
|
||||||
* @brief Contains all bytes of the instruction.
|
|
||||||
*/
|
|
||||||
uint8_t data[15];
|
|
||||||
/**
|
|
||||||
* @brief The length of the instruction opcodes.
|
|
||||||
*/
|
|
||||||
uint8_t opcode_length;
|
|
||||||
/**
|
|
||||||
* @brief The instruction opcodes.
|
|
||||||
*/
|
|
||||||
uint8_t opcode[3];
|
|
||||||
/**
|
|
||||||
* @brief The operand mode.
|
|
||||||
*/
|
|
||||||
uint8_t operand_mode;
|
|
||||||
/**
|
|
||||||
* @brief The address mode.
|
|
||||||
*/
|
|
||||||
uint8_t address_mode;
|
|
||||||
/**
|
|
||||||
* @brief The decoded operands.
|
|
||||||
*/
|
|
||||||
OperandInfo operand[4];
|
|
||||||
/**
|
|
||||||
* @brief The segment register. This value will default to @c NONE, if no segment register
|
|
||||||
* prefix is present.
|
|
||||||
*/
|
|
||||||
Register segment;
|
|
||||||
/**
|
|
||||||
* @brief The rex prefix byte.
|
|
||||||
*/
|
|
||||||
uint8_t rex;
|
|
||||||
/**
|
|
||||||
* @brief When 1, a 64-bit operand size is used. Otherwise, when 0, the default operand size
|
|
||||||
* is used.
|
|
||||||
*/
|
|
||||||
uint8_t rex_w;
|
|
||||||
/**
|
|
||||||
* @brief This 1-bit value is an extension to the MODRM.reg field.
|
|
||||||
*/
|
|
||||||
uint8_t rex_r;
|
|
||||||
/**
|
|
||||||
* @brief This 1-bit value is an extension to the SIB.index field.
|
|
||||||
*/
|
|
||||||
uint8_t rex_x;
|
|
||||||
/**
|
|
||||||
* @brief This 1-bit value is an extension to the MODRM.rm field or the SIB.base field.
|
|
||||||
*/
|
|
||||||
uint8_t rex_b;
|
|
||||||
/**
|
|
||||||
* @brief The modrm byte.
|
|
||||||
*/
|
|
||||||
uint8_t modrm;
|
|
||||||
/**
|
|
||||||
* @brief The modrm modus bits. When this field is b11, then register-direct addressing mode
|
|
||||||
* is used; otherwise register-indirect addressing mode is used.
|
|
||||||
*/
|
|
||||||
uint8_t modrm_mod;
|
|
||||||
/**
|
|
||||||
* @brief The modrm register bits. The REX.R, VEX.~R or XOP.~R field can extend this field
|
|
||||||
* with 1 most-significant bit to 4 bits total.
|
|
||||||
*/
|
|
||||||
uint8_t modrm_reg;
|
|
||||||
/**
|
|
||||||
* @brief The extended modrm register bits. If the instruction definition does not have the
|
|
||||||
* @c IDF_ACCEPTS_REXR flag set, this value defaults to the normal @c modrm_reg
|
|
||||||
* field.
|
|
||||||
*/
|
|
||||||
uint8_t modrm_reg_ext;
|
|
||||||
/**
|
|
||||||
* @brief The modrm register/memory bits. Specifies a direct or indirect register operand,
|
|
||||||
* optionally with a displacement. The REX.B, VEX.~B or XOP.~B field can extend this
|
|
||||||
* field with 1 most-significant bit to 4 bits total.
|
|
||||||
*/
|
|
||||||
uint8_t modrm_rm;
|
|
||||||
/**
|
|
||||||
* @brief The extended modrm register/memory bits. If the instruction definition does not
|
|
||||||
* have the @c IDF_ACCEPTS_REXB flag set, this value defaults to the normal
|
|
||||||
* @c modrm_rm field.
|
|
||||||
*/
|
|
||||||
uint8_t modrm_rm_ext;
|
|
||||||
/**
|
|
||||||
* @brief The sib byte.
|
|
||||||
*/
|
|
||||||
uint8_t sib;
|
|
||||||
/**
|
|
||||||
* @brief This field indicates the scaling factor of SIB.index.
|
|
||||||
*/
|
|
||||||
uint8_t sib_scale;
|
|
||||||
/**
|
|
||||||
* @brief The index register to use. The REX.X, VEX.~X or XOP.~X field can extend this field
|
|
||||||
* with 1 most-significant bit to 4 bits total.
|
|
||||||
*/
|
|
||||||
uint8_t sib_index;
|
|
||||||
/**
|
|
||||||
* @brief The extended index register. If the instruction definition does not have the
|
|
||||||
* @c IDF_ACCEPTS_REXX flag set, this value defaults to the normal @c sib_index
|
|
||||||
* field.
|
|
||||||
*/
|
|
||||||
uint8_t sib_index_ext;
|
|
||||||
/**
|
|
||||||
* @brief The base register to use. The REX.B, VEX.~B or XOP.~B field can extend this field
|
|
||||||
* with 1 most-significant bit to 4 bits total.
|
|
||||||
*/
|
|
||||||
uint8_t sib_base;
|
|
||||||
/**
|
|
||||||
* @brief The extended base register. If the instruction definition does not have the
|
|
||||||
* @c IDF_ACCEPTS_REXB flag set, this value defaults to the normal @c sib_index
|
|
||||||
* field.
|
|
||||||
*/
|
|
||||||
uint8_t sib_base_ext;
|
|
||||||
/**
|
|
||||||
* @brief The primary vex prefix byte.
|
|
||||||
*/
|
|
||||||
uint8_t vex_op;
|
|
||||||
/**
|
|
||||||
* @brief The second vex prefix byte.
|
|
||||||
*/
|
|
||||||
uint8_t vex_b1;
|
|
||||||
/**
|
|
||||||
* @brief The third vex prefix byte.
|
|
||||||
*/
|
|
||||||
uint8_t vex_b2;
|
|
||||||
/**
|
|
||||||
* @brief This 1-bit value is an 'inverted' extension to the MODRM.reg field. The inverse of
|
|
||||||
* REX.R.
|
|
||||||
*/
|
|
||||||
uint8_t vex_r;
|
|
||||||
/**
|
|
||||||
* @brief This 1-bit value is an 'inverted' extension to the SIB.index field. The inverse of
|
|
||||||
* REX.X.
|
|
||||||
*/
|
|
||||||
uint8_t vex_x;
|
|
||||||
/**
|
|
||||||
* @brief This 1-bit value is an 'inverted' extension to the MODRM.rm field or the SIB.base
|
|
||||||
* field. The inverse of REX.B.
|
|
||||||
*/
|
|
||||||
uint8_t vex_b;
|
|
||||||
/**
|
|
||||||
* @brief Specifies the opcode map to use.
|
|
||||||
* 00 = 0x0F
|
|
||||||
* 01 = 0x0F 0x38
|
|
||||||
* 02 = 0x0F 0x3A
|
|
||||||
*/
|
|
||||||
uint8_t vex_m_mmmm;
|
|
||||||
/**
|
|
||||||
* @brief For integer instructions: when 1, a 64-bit operand size is used; otherwise,
|
|
||||||
* when 0, the default operand size is used (equivalent with REX.W). For non-integer
|
|
||||||
* instructions, this bit is a general opcode extension bit.
|
|
||||||
*/
|
|
||||||
uint8_t vex_w;
|
|
||||||
/**
|
|
||||||
* @brief An additional operand for the instruction. The value of the XMM or YMM register
|
|
||||||
* is 'inverted'.
|
|
||||||
*/
|
|
||||||
uint8_t vex_vvvv;
|
|
||||||
/**
|
|
||||||
* @brief When 0, a 128-bit vector lengh is used. Otherwise, when 1, a 256-bit vector length
|
|
||||||
* is used.
|
|
||||||
*/
|
|
||||||
uint8_t vex_l;
|
|
||||||
/**
|
|
||||||
* @brief Specifies an implied mandatory prefix for the opcode.
|
|
||||||
* 00 = none
|
|
||||||
* 01 = 0x66
|
|
||||||
* 10 = 0xF3
|
|
||||||
* 11 = 0xF2
|
|
||||||
*/
|
|
||||||
uint8_t vex_pp;
|
|
||||||
/**
|
|
||||||
* @brief The effectively used REX/VEX.w value. If the instruction definition does not have
|
|
||||||
* the @c IDF_ACCEPTS_REXW flag set, this value defaults to zero.
|
|
||||||
*/
|
|
||||||
uint8_t eff_rexvex_w;
|
|
||||||
/**
|
|
||||||
* @brief The effectively used REX/VEX.r value. If the instruction definition does not have
|
|
||||||
* the @c IDF_ACCEPTS_REXR flag set, this value defaults to zero.
|
|
||||||
*/
|
|
||||||
uint8_t eff_rexvex_r;
|
|
||||||
/**
|
|
||||||
* @brief The effectively used REX/VEX.x value. If the instruction definition does not have
|
|
||||||
* the @c IDF_ACCEPTS_REXX flag set, this value defaults to zero.
|
|
||||||
*/
|
|
||||||
uint8_t eff_rexvex_x;
|
|
||||||
/**
|
|
||||||
* @brief The effectively used REX/VEX.b value. If the instruction definition does not have
|
|
||||||
* the @c IDF_ACCEPTS_REXB flag set, this value defaults to zero.
|
|
||||||
*/
|
|
||||||
uint8_t eff_rexvex_b;
|
|
||||||
/**
|
|
||||||
* @brief The effectively used VEX.l value. If the instruction definition does not have
|
|
||||||
* the @c IDF_ACCEPTS_VEXL flag set, this value defaults to zero.
|
|
||||||
*/
|
|
||||||
uint8_t eff_vex_l;
|
|
||||||
/**
|
|
||||||
* @brief The instruction definition.
|
|
||||||
*/
|
|
||||||
const InstructionDefinition* instrDefinition;
|
|
||||||
/**
|
|
||||||
* @brief The instruction address points to the current instruction (relative to the
|
|
||||||
* initial instruction pointer).
|
|
||||||
*/
|
|
||||||
uint64_t instrAddress;
|
|
||||||
/**
|
|
||||||
* @brief The instruction pointer points to the address of the next instruction (relative
|
|
||||||
* to the initial instruction pointer).
|
|
||||||
* This field is used to properly format relative instructions.
|
|
||||||
*/
|
|
||||||
uint64_t instrPointer;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ZYDIS_TYPES_HPP_ */
|
|
|
@ -1,75 +0,0 @@
|
||||||
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
||||||
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
#include "ZydisUtils.hpp"
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
namespace Zydis
|
|
||||||
{
|
|
||||||
|
|
||||||
uint64_t CalcAbsoluteTarget(const InstructionInfo& info, const OperandInfo& operand)
|
|
||||||
{
|
|
||||||
assert((operand.type == OperandType::REL_IMMEDIATE) ||
|
|
||||||
((operand.type == OperandType::MEMORY) && (operand.base == Register::RIP)));
|
|
||||||
|
|
||||||
uint64_t truncMask = 0xFFFFFFFFFFFFFFFFull;
|
|
||||||
if (!(info.flags & IF_DISASSEMBLER_MODE_64))
|
|
||||||
{
|
|
||||||
truncMask >>= (64 - info.operand_mode);
|
|
||||||
}
|
|
||||||
uint16_t size = operand.size;
|
|
||||||
if ((operand.type == OperandType::MEMORY) && (operand.base == Register::RIP))
|
|
||||||
{
|
|
||||||
size = operand.offset;
|
|
||||||
}
|
|
||||||
switch (size)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
return (info.instrPointer + operand.lval.sbyte) & truncMask;
|
|
||||||
case 16:
|
|
||||||
{
|
|
||||||
uint32_t delta = operand.lval.sword & truncMask;
|
|
||||||
if ((info.instrPointer + delta) > 0xFFFF)
|
|
||||||
{
|
|
||||||
return (info.instrPointer& 0xF0000) + ((info.instrPointer + delta) & 0xFFFF);
|
|
||||||
}
|
|
||||||
return info.instrPointer + delta;
|
|
||||||
}
|
|
||||||
case 32:
|
|
||||||
return (info.instrPointer + operand.lval.sdword) & truncMask;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/***************************************************************************************************
|
|
||||||
|
|
||||||
Zyan Disassembler Engine
|
|
||||||
Version 1.0
|
|
||||||
|
|
||||||
Remarks : Freeware, Copyright must be included
|
|
||||||
|
|
||||||
Original Author : Florian Bernd
|
|
||||||
Modifications : Joel Höner
|
|
||||||
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
|
|
||||||
***************************************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* @brief Utility functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _ZYDIS_UTILS_HPP_
|
|
||||||
#define _ZYDIS_UTILS_HPP_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "ZydisTypes.hpp"
|
|
||||||
|
|
||||||
namespace Zydis
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculates the absolute target address of a relative instruction operand.
|
|
||||||
* @param info The instruction info.
|
|
||||||
* @param operand The operand.
|
|
||||||
* @return The absolute target address.
|
|
||||||
*/
|
|
||||||
uint64_t CalcAbsoluteTarget(const InstructionInfo& info, const OperandInfo& operand);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ZYDIS_UTILS_HPP_ */
|
|
|
@ -45,6 +45,7 @@ namespace xboxkrnl
|
||||||
|
|
||||||
#include "CxbxKrnl.h"
|
#include "CxbxKrnl.h"
|
||||||
#include "Emu.h"
|
#include "Emu.h"
|
||||||
|
#include "EmuX86.h"
|
||||||
#include "EmuFile.h"
|
#include "EmuFile.h"
|
||||||
#include "EmuFS.h"
|
#include "EmuFS.h"
|
||||||
#include "EmuShared.h"
|
#include "EmuShared.h"
|
||||||
|
@ -381,12 +382,20 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
|
||||||
{
|
{
|
||||||
if (AllocConsole())
|
if (AllocConsole())
|
||||||
{
|
{
|
||||||
|
HANDLE StdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
// Maximise the console scroll buffer height :
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO coninfo;
|
||||||
|
GetConsoleScreenBufferInfo(StdHandle, &coninfo);
|
||||||
|
coninfo.dwSize.Y = SHRT_MAX - 1; // = 32767-1 = 32766 = maximum value that works
|
||||||
|
SetConsoleScreenBufferSize(StdHandle, coninfo.dwSize);
|
||||||
|
|
||||||
freopen("CONOUT$", "wt", stdout);
|
freopen("CONOUT$", "wt", stdout);
|
||||||
freopen("CONIN$", "rt", stdin);
|
freopen("CONIN$", "rt", stdin);
|
||||||
|
|
||||||
SetConsoleTitle("Cxbx-Reloaded : Kernel Debug Console");
|
SetConsoleTitle("Cxbx-Reloaded : Kernel Debug Console");
|
||||||
|
|
||||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
|
SetConsoleTextAttribute(StdHandle, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
|
||||||
|
|
||||||
printf("EmuMain (0x%X): Cxbx-Reloaded Version %s\n", GetCurrentThreadId(), _CXBX_VERSION);
|
printf("EmuMain (0x%X): Cxbx-Reloaded Version %s\n", GetCurrentThreadId(), _CXBX_VERSION);
|
||||||
printf("EmuMain (0x%X): Debug Console Allocated (DM_CONSOLE).\n", GetCurrentThreadId());
|
printf("EmuMain (0x%X): Debug Console Allocated (DM_CONSOLE).\n", GetCurrentThreadId());
|
||||||
|
@ -616,6 +625,7 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
|
||||||
EmuGenerateFS(pTLS, pTLSData);
|
EmuGenerateFS(pTLS, pTLSData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EmuX86_Init();
|
||||||
|
|
||||||
DbgPrintf("EmuMain (0x%X): Initial thread starting.\n", GetCurrentThreadId());
|
DbgPrintf("EmuMain (0x%X): Initial thread starting.\n", GetCurrentThreadId());
|
||||||
|
|
||||||
|
|
|
@ -145,126 +145,125 @@ extern "C" CXBXKRNL_API void NTAPI EmuWarning(const char *szWarningMessage, ...)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void EmuExceptionPrintDebugInformation(LPEXCEPTION_POINTERS e, bool IsBreakpointException)
|
||||||
|
{
|
||||||
|
// print debug information
|
||||||
|
{
|
||||||
|
if (IsBreakpointException)
|
||||||
|
printf("EmuMain (0x%X): Recieved Breakpoint Exception (int 3)\n", GetCurrentThreadId());
|
||||||
|
else
|
||||||
|
printf("EmuMain (0x%X): Recieved Exception (Code := 0x%.08X)\n", GetCurrentThreadId(), e->ExceptionRecord->ExceptionCode);
|
||||||
|
|
||||||
|
printf("\n"
|
||||||
|
" EIP := 0x%.08X EFL := 0x%.08X\n"
|
||||||
|
" EAX := 0x%.08X EBX := 0x%.08X ECX := 0x%.08X EDX := 0x%.08X\n"
|
||||||
|
" ESI := 0x%.08X EDI := 0x%.08X ESP := 0x%.08X EBP := 0x%.08X\n"
|
||||||
|
" CR2 := 0x%.08X\n"
|
||||||
|
"\n",
|
||||||
|
e->ContextRecord->Eip, e->ContextRecord->EFlags,
|
||||||
|
e->ContextRecord->Eax, e->ContextRecord->Ebx, e->ContextRecord->Ecx, e->ContextRecord->Edx,
|
||||||
|
e->ContextRecord->Esi, e->ContextRecord->Edi, e->ContextRecord->Esp, e->ContextRecord->Ebp,
|
||||||
|
e->ContextRecord->Dr2);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
CONTEXT Context = *(e->ContextRecord);
|
||||||
|
EmuPrintStackTrace(&Context);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuExceptionExitProcess()
|
||||||
|
{
|
||||||
|
printf("EmuMain (0x%X): Aborting Emulation\n", GetCurrentThreadId());
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
if (CxbxKrnl_hEmuParent != NULL)
|
||||||
|
SendMessage(CxbxKrnl_hEmuParent, WM_PARENTNOTIFY, WM_DESTROY, 0);
|
||||||
|
|
||||||
|
ExitProcess(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuExceptionBreakpointAsk(LPEXCEPTION_POINTERS e)
|
||||||
|
{
|
||||||
|
EmuExceptionPrintDebugInformation(e, /*IsBreakpointException=*/true);
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
sprintf(buffer,
|
||||||
|
"Recieved Breakpoint Exception (int 3) @ EIP := 0x%.08X\n"
|
||||||
|
"\n"
|
||||||
|
" Press Abort to terminate emulation.\n"
|
||||||
|
" Press Retry to debug.\n"
|
||||||
|
" Press Ignore to continue emulation.",
|
||||||
|
e->ContextRecord->Eip);
|
||||||
|
|
||||||
|
int ret = MessageBox(g_hEmuWindow, buffer, "Cxbx-Reloaded", MB_ICONSTOP | MB_ABORTRETRYIGNORE);
|
||||||
|
if (ret == IDABORT)
|
||||||
|
{
|
||||||
|
EmuExceptionExitProcess();
|
||||||
|
}
|
||||||
|
else if (ret == IDIGNORE)
|
||||||
|
{
|
||||||
|
printf("EmuMain (0x%X): Ignored Breakpoint Exception\n", GetCurrentThreadId());
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
e->ContextRecord->Eip += 1; // TODO : Skip actual instruction size bytes
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuExceptionNonBreakpointUnhandledShow(LPEXCEPTION_POINTERS e)
|
||||||
|
{
|
||||||
|
EmuExceptionPrintDebugInformation(e, /*IsBreakpointException=*/false);
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
sprintf(buffer,
|
||||||
|
"Recieved Exception Code 0x%.08X @ EIP := 0x%.08X\n"
|
||||||
|
"\n"
|
||||||
|
" Press \"OK\" to terminate emulation.\n"
|
||||||
|
" Press \"Cancel\" to debug.",
|
||||||
|
e->ExceptionRecord->ExceptionCode, e->ContextRecord->Eip);
|
||||||
|
|
||||||
|
if (MessageBox(g_hEmuWindow, buffer, "Cxbx-Reloaded", MB_ICONSTOP | MB_OKCANCEL) == IDOK)
|
||||||
|
{
|
||||||
|
EmuExceptionExitProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// exception handler
|
// exception handler
|
||||||
extern int EmuException(LPEXCEPTION_POINTERS e)
|
extern int EmuException(LPEXCEPTION_POINTERS e)
|
||||||
{
|
{
|
||||||
g_bEmuException = true;
|
g_bEmuException = true;
|
||||||
|
if (e->ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
|
||||||
|
{
|
||||||
|
// notify user
|
||||||
|
if (EmuExceptionBreakpointAsk(e))
|
||||||
|
{
|
||||||
|
// We're allowed to continue :
|
||||||
|
g_bEmuException = false;
|
||||||
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Pass the exception to our X86 implementation, to try and execute the failing instruction
|
||||||
|
if (EmuX86_DecodeException(e))
|
||||||
|
{
|
||||||
|
// We're allowed to continue :
|
||||||
|
g_bEmuException = false;
|
||||||
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
|
}
|
||||||
|
|
||||||
// notify user
|
// notify user
|
||||||
{
|
EmuExceptionNonBreakpointUnhandledShow(e);
|
||||||
char buffer[256];
|
}
|
||||||
|
|
||||||
if(e->ExceptionRecord->ExceptionCode == 0x80000003)
|
|
||||||
{
|
|
||||||
// print debug information
|
|
||||||
{
|
|
||||||
printf("EmuMain (0x%X): Recieved Breakpoint Exception (int 3)\n", GetCurrentThreadId());
|
|
||||||
|
|
||||||
printf("\n"
|
|
||||||
" EIP := 0x%.08X EFL := 0x%.08X\n"
|
|
||||||
" EAX := 0x%.08X EBX := 0x%.08X ECX := 0x%.08X EDX := 0x%.08X\n"
|
|
||||||
" ESI := 0x%.08X EDI := 0x%.08X ESP := 0x%.08X EBP := 0x%.08X\n"
|
|
||||||
" CR2 := 0x%.08X\n"
|
|
||||||
"\n",
|
|
||||||
e->ContextRecord->Eip, e->ContextRecord->EFlags,
|
|
||||||
e->ContextRecord->Eax, e->ContextRecord->Ebx, e->ContextRecord->Ecx, e->ContextRecord->Edx,
|
|
||||||
e->ContextRecord->Esi, e->ContextRecord->Edi, e->ContextRecord->Esp, e->ContextRecord->Ebp,
|
|
||||||
e->ContextRecord->Dr2);
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
CONTEXT Context = *(e->ContextRecord);
|
|
||||||
EmuPrintStackTrace(&Context);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
sprintf(buffer,
|
|
||||||
"Recieved Breakpoint Exception (int 3) @ EIP := 0x%.08X\n"
|
|
||||||
"\n"
|
|
||||||
" Press Abort to terminate emulation.\n"
|
|
||||||
" Press Retry to debug.\n"
|
|
||||||
" Press Ignore to continue emulation.",
|
|
||||||
e->ContextRecord->Eip);
|
|
||||||
|
|
||||||
e->ContextRecord->Eip += 1;
|
|
||||||
|
|
||||||
int ret = MessageBox(g_hEmuWindow, buffer, "Cxbx-Reloaded", MB_ICONSTOP | MB_ABORTRETRYIGNORE);
|
|
||||||
|
|
||||||
if(ret == IDABORT)
|
|
||||||
{
|
|
||||||
printf("EmuMain (0x%X): Aborting Emulation\n", GetCurrentThreadId());
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
if(CxbxKrnl_hEmuParent != NULL)
|
|
||||||
SendMessage(CxbxKrnl_hEmuParent, WM_PARENTNOTIFY, WM_DESTROY, 0);
|
|
||||||
|
|
||||||
ExitProcess(1);
|
|
||||||
}
|
|
||||||
else if(ret == IDIGNORE)
|
|
||||||
{
|
|
||||||
printf("EmuMain (0x%X): Ignored Breakpoint Exception\n", GetCurrentThreadId());
|
|
||||||
|
|
||||||
g_bEmuException = false;
|
|
||||||
|
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Pass the exception to our X86 implementation, to try and execute the failing instruction
|
|
||||||
if (EmuX86_DecodeException(e))
|
|
||||||
{
|
|
||||||
g_bEmuException = false;
|
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// print debug information
|
|
||||||
{
|
|
||||||
printf("EmuMain (0x%X): Recieved Exception (Code := 0x%.08X)\n", GetCurrentThreadId(), e->ExceptionRecord->ExceptionCode);
|
|
||||||
|
|
||||||
printf("\n"
|
|
||||||
" EIP := 0x%.08X EFL := 0x%.08X\n"
|
|
||||||
" EAX := 0x%.08X EBX := 0x%.08X ECX := 0x%.08X EDX := 0x%.08X\n"
|
|
||||||
" ESI := 0x%.08X EDI := 0x%.08X ESP := 0x%.08X EBP := 0x%.08X\n"
|
|
||||||
" CR2 := 0x%.08X\n"
|
|
||||||
"\n",
|
|
||||||
e->ContextRecord->Eip, e->ContextRecord->EFlags,
|
|
||||||
e->ContextRecord->Eax, e->ContextRecord->Ebx, e->ContextRecord->Ecx, e->ContextRecord->Edx,
|
|
||||||
e->ContextRecord->Esi, e->ContextRecord->Edi, e->ContextRecord->Esp, e->ContextRecord->Ebp,
|
|
||||||
e->ContextRecord->Dr2);
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
CONTEXT Context = *(e->ContextRecord);
|
|
||||||
EmuPrintStackTrace(&Context);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
sprintf(buffer,
|
|
||||||
"Recieved Exception Code 0x%.08X @ EIP := 0x%.08X\n"
|
|
||||||
"\n"
|
|
||||||
" Press \"OK\" to terminate emulation.\n"
|
|
||||||
" Press \"Cancel\" to debug.",
|
|
||||||
e->ExceptionRecord->ExceptionCode, e->ContextRecord->Eip);
|
|
||||||
|
|
||||||
if(MessageBox(g_hEmuWindow, buffer, "Cxbx-Reloaded", MB_ICONSTOP | MB_OKCANCEL) == IDOK)
|
|
||||||
{
|
|
||||||
printf("EmuMain (0x%X): Aborting Emulation\n", GetCurrentThreadId());
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
if(CxbxKrnl_hEmuParent != NULL)
|
|
||||||
SendMessage(CxbxKrnl_hEmuParent, WM_PARENTNOTIFY, WM_DESTROY, 0);
|
|
||||||
|
|
||||||
ExitProcess(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_bEmuException = false;
|
|
||||||
|
|
||||||
|
// Unhandled exception :
|
||||||
|
g_bEmuException = false;
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,8 @@
|
||||||
# pragma comment(lib, "glew32.lib")
|
# pragma comment(lib, "glew32.lib")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <Zydis.hpp>
|
#include <distorm.h> // For uint32_t
|
||||||
|
#include <string> // For std::string
|
||||||
|
|
||||||
#include "CxbxKrnl.h"
|
#include "CxbxKrnl.h"
|
||||||
#include "Emu.h"
|
#include "Emu.h"
|
||||||
|
|
|
@ -36,7 +36,14 @@
|
||||||
#define _CXBXKRNL_INTERNAL
|
#define _CXBXKRNL_INTERNAL
|
||||||
#define _XBOXKRNL_DEFEXTRN_
|
#define _XBOXKRNL_DEFEXTRN_
|
||||||
|
|
||||||
#include <Zydis.hpp>
|
// Link the library into our project.
|
||||||
|
#pragma comment(lib, "distorm.lib")
|
||||||
|
|
||||||
|
// Cxbx uses dynamic linking of distorm, which by default chooses for 64 bits offsets :
|
||||||
|
#define SUPPORT_64BIT_OFFSET
|
||||||
|
|
||||||
|
#include "distorm.h"
|
||||||
|
#include "mnemonics.h"
|
||||||
|
|
||||||
#include "CxbxKrnl.h"
|
#include "CxbxKrnl.h"
|
||||||
#include "Emu.h"
|
#include "Emu.h"
|
||||||
|
@ -92,9 +99,9 @@ uint16_t EmuX86_Read16(uint32_t addr)
|
||||||
EmuWarning("EmuX86_Read16(0x%08X) Forwarding to EmuX86_Read32...", addr);
|
EmuWarning("EmuX86_Read16(0x%08X) Forwarding to EmuX86_Read32...", addr);
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
if (addr & 2)
|
if (addr & 2)
|
||||||
value = (uint16_t)EmuX86_Read32(addr - 2);
|
value = (uint16_t)(EmuX86_Read32(addr - 2) >> 16);
|
||||||
else
|
else
|
||||||
value = (uint16_t)(EmuX86_Read32(addr) >> 16);
|
value = (uint16_t)EmuX86_Read32(addr);
|
||||||
|
|
||||||
EmuWarning("EmuX86_Read16(0x%08X) = 0x%04X", addr, value);
|
EmuWarning("EmuX86_Read16(0x%08X) = 0x%04X", addr, value);
|
||||||
return value;
|
return value;
|
||||||
|
@ -105,9 +112,9 @@ uint8_t EmuX86_Read8(uint32_t addr)
|
||||||
EmuWarning("EmuX86_Read8(0x%08X) Forwarding to EmuX86_Read16...", addr);
|
EmuWarning("EmuX86_Read8(0x%08X) Forwarding to EmuX86_Read16...", addr);
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
if (addr & 1)
|
if (addr & 1)
|
||||||
value = (uint8_t)EmuX86_Read16(addr - 1);
|
value = (uint8_t)(EmuX86_Read16(addr - 1) >> 8);
|
||||||
else
|
else
|
||||||
value = (uint8_t)(EmuX86_Read16(addr) >> 8);
|
value = (uint8_t)EmuX86_Read16(addr);
|
||||||
|
|
||||||
EmuWarning("EmuX86_Read8(0x%08X) = 0x%02X", addr, value);
|
EmuWarning("EmuX86_Read8(0x%08X) = 0x%02X", addr, value);
|
||||||
return value;
|
return value;
|
||||||
|
@ -133,165 +140,433 @@ void EmuX86_Write8(uint32_t addr, uint8_t value)
|
||||||
EmuWarning("EmuX86_Write8(0x%08X, 0x%02X) [Unknown address]", addr, value);
|
EmuWarning("EmuX86_Write8(0x%08X, 0x%02X) [Unknown address]", addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline DWORD* EmuX86_GetRegisterPointer(LPEXCEPTION_POINTERS e, Zydis::Register reg)
|
int ContextRecordOffsetByRegisterType[/*_RegisterType*/R_DR7 + 1] = { 0 };
|
||||||
|
|
||||||
|
// Populate ContextRecordOffsetByRegisterType for each distorm::_RegisterType
|
||||||
|
// supported by the Xbox1's Coppermine Pentium III.
|
||||||
|
// Based on https://maximumcrack.wordpress.com/2011/08/07/fpu-mmx-xmm-and-bbq/
|
||||||
|
void EmuX86_InitContextRecordOffsetByRegisterType()
|
||||||
{
|
{
|
||||||
switch (reg) {
|
/* R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15,*/
|
||||||
case Zydis::Register::AL: case Zydis::Register::AH: case Zydis::Register::AX: case Zydis::Register::EAX:
|
ContextRecordOffsetByRegisterType[R_EAX] = offsetof(CONTEXT, Eax);
|
||||||
return &e->ContextRecord->Eax;
|
ContextRecordOffsetByRegisterType[R_ECX] = offsetof(CONTEXT, Ecx);
|
||||||
case Zydis::Register::BL: case Zydis::Register::BH: case Zydis::Register::BX: case Zydis::Register::EBX:
|
ContextRecordOffsetByRegisterType[R_EDX] = offsetof(CONTEXT, Edx);
|
||||||
return &e->ContextRecord->Ebx;
|
ContextRecordOffsetByRegisterType[R_EBX] = offsetof(CONTEXT, Ebx);
|
||||||
case Zydis::Register::CL: case Zydis::Register::CH: case Zydis::Register::CX: case Zydis::Register::ECX:
|
ContextRecordOffsetByRegisterType[R_ESP] = offsetof(CONTEXT, Esp);
|
||||||
return &e->ContextRecord->Ecx;
|
ContextRecordOffsetByRegisterType[R_EBP] = offsetof(CONTEXT, Ebp);
|
||||||
case Zydis::Register::DL: case Zydis::Register::DH: case Zydis::Register::DX: case Zydis::Register::EDX:
|
ContextRecordOffsetByRegisterType[R_ESI] = offsetof(CONTEXT, Esi);
|
||||||
return &e->ContextRecord->Edx;
|
ContextRecordOffsetByRegisterType[R_EDI] = offsetof(CONTEXT, Edi);
|
||||||
case Zydis::Register::EDI:
|
/* R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D,*/
|
||||||
return &e->ContextRecord->Edi;
|
ContextRecordOffsetByRegisterType[R_AX] = offsetof(CONTEXT, Eax);
|
||||||
case Zydis::Register::ESI:
|
ContextRecordOffsetByRegisterType[R_CX] = offsetof(CONTEXT, Ecx);
|
||||||
return &e->ContextRecord->Esi;
|
ContextRecordOffsetByRegisterType[R_DX] = offsetof(CONTEXT, Edx);
|
||||||
case Zydis::Register::EBP:
|
ContextRecordOffsetByRegisterType[R_BX] = offsetof(CONTEXT, Ebx);
|
||||||
return &e->ContextRecord->Ebp;
|
ContextRecordOffsetByRegisterType[R_SP] = offsetof(CONTEXT, Esp); // ??
|
||||||
}
|
ContextRecordOffsetByRegisterType[R_BP] = offsetof(CONTEXT, Ebp); // ??
|
||||||
|
ContextRecordOffsetByRegisterType[R_SI] = offsetof(CONTEXT, Esi); // ??
|
||||||
|
ContextRecordOffsetByRegisterType[R_DI] = offsetof(CONTEXT, Edi); // ??
|
||||||
|
/* R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, */
|
||||||
|
ContextRecordOffsetByRegisterType[R_AL] = offsetof(CONTEXT, Eax);
|
||||||
|
ContextRecordOffsetByRegisterType[R_CL] = offsetof(CONTEXT, Ecx);
|
||||||
|
ContextRecordOffsetByRegisterType[R_DL] = offsetof(CONTEXT, Edx);
|
||||||
|
ContextRecordOffsetByRegisterType[R_BL] = offsetof(CONTEXT, Ebx);
|
||||||
|
ContextRecordOffsetByRegisterType[R_AH] = offsetof(CONTEXT, Eax) + 1;
|
||||||
|
ContextRecordOffsetByRegisterType[R_CH] = offsetof(CONTEXT, Ecx) + 1;
|
||||||
|
ContextRecordOffsetByRegisterType[R_DH] = offsetof(CONTEXT, Edx) + 1;
|
||||||
|
ContextRecordOffsetByRegisterType[R_BH] = offsetof(CONTEXT, Ebx) + 1;
|
||||||
|
/* R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, */
|
||||||
|
ContextRecordOffsetByRegisterType[R_SPL] = offsetof(CONTEXT, Esp); // ??
|
||||||
|
ContextRecordOffsetByRegisterType[R_BPL] = offsetof(CONTEXT, Ebp); // ??
|
||||||
|
ContextRecordOffsetByRegisterType[R_SIL] = offsetof(CONTEXT, Esi); // ??
|
||||||
|
ContextRecordOffsetByRegisterType[R_DIL] = offsetof(CONTEXT, Edi); // ??
|
||||||
|
ContextRecordOffsetByRegisterType[R_ES] = offsetof(CONTEXT, SegEs);
|
||||||
|
ContextRecordOffsetByRegisterType[R_CS] = offsetof(CONTEXT, SegCs);
|
||||||
|
ContextRecordOffsetByRegisterType[R_SS] = offsetof(CONTEXT, SegSs);
|
||||||
|
ContextRecordOffsetByRegisterType[R_DS] = offsetof(CONTEXT, SegDs);
|
||||||
|
ContextRecordOffsetByRegisterType[R_FS] = offsetof(CONTEXT, SegFs);
|
||||||
|
ContextRecordOffsetByRegisterType[R_GS] = offsetof(CONTEXT, SegGs);
|
||||||
|
/* R_RIP, R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, */
|
||||||
|
ContextRecordOffsetByRegisterType[R_MM0] = offsetof(CONTEXT, ExtendedRegisters[(10 + 0) * 16]);
|
||||||
|
ContextRecordOffsetByRegisterType[R_MM1] = offsetof(CONTEXT, ExtendedRegisters[(10 + 1) * 16]);
|
||||||
|
ContextRecordOffsetByRegisterType[R_MM2] = offsetof(CONTEXT, ExtendedRegisters[(10 + 2) * 16]);
|
||||||
|
ContextRecordOffsetByRegisterType[R_MM3] = offsetof(CONTEXT, ExtendedRegisters[(10 + 3) * 16]);
|
||||||
|
ContextRecordOffsetByRegisterType[R_MM4] = offsetof(CONTEXT, ExtendedRegisters[(10 + 4) * 16]);
|
||||||
|
ContextRecordOffsetByRegisterType[R_MM5] = offsetof(CONTEXT, ExtendedRegisters[(10 + 5) * 16]);
|
||||||
|
ContextRecordOffsetByRegisterType[R_MM6] = offsetof(CONTEXT, ExtendedRegisters[(10 + 6) * 16]);
|
||||||
|
ContextRecordOffsetByRegisterType[R_MM7] = offsetof(CONTEXT, ExtendedRegisters[(10 + 7) * 16]);
|
||||||
|
/* R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, */
|
||||||
|
/* R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, */
|
||||||
|
/* R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, */
|
||||||
|
ContextRecordOffsetByRegisterType[R_DR0] = offsetof(CONTEXT, Dr0);
|
||||||
|
ContextRecordOffsetByRegisterType[R_DR1] = offsetof(CONTEXT, Dr1);
|
||||||
|
ContextRecordOffsetByRegisterType[R_DR2] = offsetof(CONTEXT, Dr2);
|
||||||
|
ContextRecordOffsetByRegisterType[R_DR3] = offsetof(CONTEXT, Dr3);
|
||||||
|
/* R_UNUSED4, R_UNUSED5, */
|
||||||
|
ContextRecordOffsetByRegisterType[R_DR6] = offsetof(CONTEXT, Dr6);
|
||||||
|
ContextRecordOffsetByRegisterType[R_DR7] = offsetof(CONTEXT, Dr7);
|
||||||
|
|
||||||
|
/* struct CONTEXT { // ! markers below, are used in the above offsetof calls
|
||||||
|
DWORD ContextFlags;
|
||||||
|
!DWORD Dr0;
|
||||||
|
!DWORD Dr1;
|
||||||
|
!DWORD Dr2;
|
||||||
|
!DWORD Dr3;
|
||||||
|
!DWORD Dr6;
|
||||||
|
!DWORD Dr7;
|
||||||
|
struct _FLOATING_SAVE_AREA {
|
||||||
|
DWORD ControlWord;
|
||||||
|
DWORD StatusWord;
|
||||||
|
DWORD TagWord;
|
||||||
|
DWORD ErrorOffset;
|
||||||
|
DWORD ErrorSelector;
|
||||||
|
DWORD DataOffset;
|
||||||
|
DWORD DataSelector;
|
||||||
|
BYTE RegisterArea[SIZE_OF_80387_REGISTERS];
|
||||||
|
DWORD Spare0;
|
||||||
|
} FLOATING_SAVE_AREA FloatSave;
|
||||||
|
!DWORD SegGs;
|
||||||
|
!DWORD SegFs;
|
||||||
|
!DWORD SegEs;
|
||||||
|
!DWORD SegDs;
|
||||||
|
!DWORD Edi;
|
||||||
|
!DWORD Esi;
|
||||||
|
!DWORD Ebx;
|
||||||
|
!DWORD Edx;
|
||||||
|
!DWORD Ecx;
|
||||||
|
!DWORD Eax;
|
||||||
|
!DWORD Ebp;
|
||||||
|
DWORD Eip;
|
||||||
|
!DWORD SegCs; // MUST BE SANITIZED
|
||||||
|
DWORD EFlags; // MUST BE SANITIZED
|
||||||
|
!DWORD Esp;
|
||||||
|
!DWORD SegSs;
|
||||||
|
!BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];*/
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void * EmuX86_GetRegisterPointer(LPEXCEPTION_POINTERS e, uint8_t reg)
|
||||||
|
{
|
||||||
|
int offset = ContextRecordOffsetByRegisterType[reg];
|
||||||
|
if (offset > 0)
|
||||||
|
return (void*)((uintptr_t)(e->ContextRecord) + offset);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool EmuX86_GetRegisterValue(uint32_t* output, LPEXCEPTION_POINTERS e, Zydis::Register reg)
|
inline uint32_t EmuX86_GetRegisterValue32(LPEXCEPTION_POINTERS e, uint8_t reg)
|
||||||
{
|
{
|
||||||
uint32_t value = 0;
|
if (reg != R_NONE)
|
||||||
if (reg != Zydis::Register::NONE)
|
|
||||||
{
|
{
|
||||||
DWORD* regptr = EmuX86_GetRegisterPointer(e, reg);
|
void* regptr = EmuX86_GetRegisterPointer(e, reg);
|
||||||
if (regptr == nullptr)
|
if (regptr != nullptr)
|
||||||
return false;
|
return *(uint32_t *)regptr;
|
||||||
|
|
||||||
value = *regptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*output = value;
|
return 0;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool EmuX86_DecodeMemoryOperand(uint32_t* output, LPEXCEPTION_POINTERS e, Zydis::OperandInfo& operand)
|
inline uint16_t EmuX86_GetRegisterValue16(LPEXCEPTION_POINTERS e, uint8_t reg)
|
||||||
{
|
{
|
||||||
uint32_t base = 0;
|
if (reg != R_NONE)
|
||||||
uint32_t index = 0;
|
{
|
||||||
if (!EmuX86_GetRegisterValue(&base, e, operand.base) || !EmuX86_GetRegisterValue(&index, e, operand.base)) {
|
void* regptr = EmuX86_GetRegisterPointer(e, reg);
|
||||||
|
if (regptr != nullptr)
|
||||||
|
return *(uint16_t *)regptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t EmuX86_GetRegisterValue8(LPEXCEPTION_POINTERS e, uint8_t reg)
|
||||||
|
{
|
||||||
|
if (reg != R_NONE)
|
||||||
|
{
|
||||||
|
void* regptr = EmuX86_GetRegisterPointer(e, reg);
|
||||||
|
if (regptr != nullptr)
|
||||||
|
return *(uint8_t *)regptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EmuX86_Distorm_O_SMEM_Addr(LPEXCEPTION_POINTERS e, _DInst& info, int operand)
|
||||||
|
{
|
||||||
|
uint32_t base = EmuX86_GetRegisterValue32(e, info.ops[operand].index);
|
||||||
|
|
||||||
|
return base + info.disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t EmuX86_Distorm_O_MEM_Addr(LPEXCEPTION_POINTERS e, _DInst& info, int operand)
|
||||||
|
{
|
||||||
|
uint32_t base = EmuX86_GetRegisterValue32(e, info.base);
|
||||||
|
|
||||||
|
uint32_t index = EmuX86_GetRegisterValue32(e, info.ops[operand].index);
|
||||||
|
|
||||||
|
if (info.scale >= 2)
|
||||||
|
return base + (index * info.scale) + info.disp;
|
||||||
|
else
|
||||||
|
return base + index + info.disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuX86_Addr_Read(uint32_t srcAddr, uint16_t size, OUT uint32_t *value)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 8:
|
||||||
|
*value = EmuX86_Read8(srcAddr);
|
||||||
|
return;
|
||||||
|
case 16:
|
||||||
|
*value = EmuX86_Read16(srcAddr);
|
||||||
|
return;
|
||||||
|
case 32:
|
||||||
|
*value = EmuX86_Read32(srcAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuX86_Addr_Write(uint32_t destAddr, uint16_t size, uint32_t value)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
case 8:
|
||||||
|
EmuX86_Write8(destAddr, value & 0xFF);
|
||||||
|
return;
|
||||||
|
case 16:
|
||||||
|
EmuX86_Write16(destAddr, value & 0xFFFF);
|
||||||
|
return;
|
||||||
|
case 32:
|
||||||
|
EmuX86_Write32(destAddr, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuX86_Operand_Read(LPEXCEPTION_POINTERS e, _DInst& info, int operand, OUT uint32_t *value)
|
||||||
|
{
|
||||||
|
switch (info.ops[operand].type) {
|
||||||
|
case O_NONE:
|
||||||
|
{
|
||||||
|
// ignore operand
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case O_REG:
|
||||||
|
{
|
||||||
|
void* regAddr = EmuX86_GetRegisterPointer(e, info.ops[operand].index);
|
||||||
|
if (regAddr == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (info.ops[operand].size) {
|
||||||
|
case 8:
|
||||||
|
*value = *((uint8_t*)regAddr);
|
||||||
|
return true;
|
||||||
|
case 16:
|
||||||
|
*value = *((uint16_t*)regAddr);
|
||||||
|
return true;
|
||||||
|
case 32:
|
||||||
|
*value = *((uint32_t*)regAddr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
case O_IMM:
|
||||||
*output = base + (index * operand.scale) + operand.lval.udword;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmuX86_ZydisReadValueFromSource(LPEXCEPTION_POINTERS e, Zydis::OperandInfo& operand, OUT uint32_t *value)
|
|
||||||
{
|
|
||||||
switch (operand.type) {
|
|
||||||
// TODO : case Zydis::OperandType::CONSTANT:
|
|
||||||
// TODO : case Zydis::OperandType::POINTER:
|
|
||||||
// TODO : case Zydis::OperandType::REL_IMMEDIATE:
|
|
||||||
case Zydis::OperandType::IMMEDIATE:
|
|
||||||
{
|
{
|
||||||
*value = operand.lval.udword;
|
switch (info.ops[operand].size) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Zydis::OperandType::REGISTER:
|
|
||||||
{
|
|
||||||
if (!EmuX86_GetRegisterValue(value, e, operand.base))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Zydis::OperandType::MEMORY:
|
|
||||||
{
|
|
||||||
uint32_t srcAddr = 0;
|
|
||||||
if (!EmuX86_DecodeMemoryOperand(&srcAddr, e, operand))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (operand.size) {
|
|
||||||
case 8:
|
case 8:
|
||||||
*value = EmuX86_Read8(srcAddr);
|
*value = info.imm.byte;
|
||||||
break;
|
return true;
|
||||||
case 16:
|
case 16:
|
||||||
*value = EmuX86_Read16(srcAddr);
|
*value = info.imm.word;
|
||||||
break;
|
return true;
|
||||||
case 32:
|
case 32:
|
||||||
*value = EmuX86_Read32(srcAddr);
|
*value = info.imm.dword;
|
||||||
break;
|
return true;
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
break;
|
return false;
|
||||||
|
}
|
||||||
|
case O_IMM1:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case O_IMM2:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case O_DISP:
|
||||||
|
{
|
||||||
|
uint32_t srcAddr = info.disp;
|
||||||
|
EmuX86_Addr_Read(srcAddr, info.ops[operand].size, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case O_SMEM:
|
||||||
|
{
|
||||||
|
uint32_t srcAddr = EmuX86_Distorm_O_SMEM_Addr(e, info, operand);
|
||||||
|
EmuX86_Addr_Read(srcAddr, info.ops[operand].size, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case O_MEM:
|
||||||
|
{
|
||||||
|
uint32_t srcAddr = EmuX86_Distorm_O_MEM_Addr(e, info, operand);
|
||||||
|
EmuX86_Addr_Read(srcAddr, info.ops[operand].size, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case O_PC:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case O_PTR:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuX86_ZydisWriteValueToDestination(LPEXCEPTION_POINTERS e, Zydis::OperandInfo& operand, uint32_t value)
|
bool EmuX86_Operand_Write(LPEXCEPTION_POINTERS e, _DInst& info, int operand, uint32_t value)
|
||||||
{
|
{
|
||||||
switch (operand.type) {
|
switch (info.ops[operand].type) {
|
||||||
case Zydis::OperandType::REGISTER:
|
case O_NONE:
|
||||||
{
|
{
|
||||||
DWORD* pDstReg = EmuX86_GetRegisterPointer(e, operand.base);
|
// ignore operand
|
||||||
if (pDstReg == nullptr)
|
return true;
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (operand.size) {
|
|
||||||
case 8:
|
|
||||||
*((uint8_t*)pDstReg + 3) = value & 0xFF;
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
*((uint16_t*)pDstReg + 2) = value & 0xFFFF;
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
*pDstReg = value;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case Zydis::OperandType::MEMORY:
|
case O_REG:
|
||||||
{
|
{
|
||||||
uint32_t destAddr = 0;
|
void* regAddr = EmuX86_GetRegisterPointer(e, info.ops[operand].index);
|
||||||
if (!EmuX86_DecodeMemoryOperand(&destAddr, e, operand))
|
if (regAddr == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (operand.size) {
|
switch (info.ops[operand].size) {
|
||||||
case 8:
|
case 8:
|
||||||
EmuX86_Write8(destAddr, value & 0xFF);
|
*((uint8_t*)regAddr) = (uint8_t)value;
|
||||||
break;
|
return true;
|
||||||
case 16:
|
case 16:
|
||||||
EmuX86_Write16(destAddr, value & 0xFFFF);
|
*((uint16_t*)regAddr) = (uint16_t)value;
|
||||||
break;
|
return true;
|
||||||
case 32:
|
case 32:
|
||||||
EmuX86_Write32(destAddr, value);
|
*((uint32_t*)regAddr) = value;
|
||||||
break;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
return false;
|
||||||
|
}
|
||||||
|
case O_IMM:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case O_IMM1:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case O_IMM2:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case O_DISP:
|
||||||
|
{
|
||||||
|
uint32_t destAddr = info.disp;
|
||||||
|
EmuX86_Addr_Write(destAddr, info.ops[operand].size, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case O_SMEM:
|
||||||
|
{
|
||||||
|
uint32_t destAddr = EmuX86_Distorm_O_SMEM_Addr(e, info, operand);
|
||||||
|
EmuX86_Addr_Write(destAddr, info.ops[operand].size, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case O_MEM:
|
||||||
|
{
|
||||||
|
uint32_t destAddr = EmuX86_Distorm_O_MEM_Addr(e, info, operand);
|
||||||
|
EmuX86_Addr_Write(destAddr, info.ops[operand].size, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case O_PC:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case O_PTR:
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuX86_Opcode_ADD(LPEXCEPTION_POINTERS e, _DInst& info)
|
||||||
|
{
|
||||||
|
// ADD reads value from source :
|
||||||
|
uint32_t value;
|
||||||
|
if (!EmuX86_Operand_Read(e, info, 1, &value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// ADD reads and writes destination :
|
||||||
|
uint32_t addr;
|
||||||
|
// TODO : Implement EmuX86_Operand_Addr, then enable the following line :
|
||||||
|
// if (!EmuX86_Operand_Addr(e, info, 0, &addr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO : Do this better
|
||||||
|
switch (info.ops[0].size) {
|
||||||
|
case 8: {
|
||||||
|
uint8_t current = EmuX86_Read8(addr);
|
||||||
|
EmuX86_Write8(addr, (uint8_t)current + value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 16: {
|
||||||
|
uint16_t current = EmuX86_Read16(addr);
|
||||||
|
EmuX86_Write16(addr, (uint16_t)current + value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 32: {
|
||||||
|
uint32_t current = EmuX86_Read32(addr);
|
||||||
|
EmuX86_Write32(addr, (uint32_t)current + value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO : update CPU flags
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuX86_MOV(LPEXCEPTION_POINTERS e, Zydis::InstructionInfo& info)
|
bool EmuX86_Opcode_MOV(LPEXCEPTION_POINTERS e, _DInst& info)
|
||||||
{
|
{
|
||||||
// TODO : Test this refactoring
|
|
||||||
|
|
||||||
// MOV reads value from source :
|
// MOV reads value from source :
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
if (!EmuX86_ZydisReadValueFromSource(e, info.operand[1], &value))
|
if (!EmuX86_Operand_Read(e, info, 1, &value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// MOV writes value to destination :
|
// MOV writes value to destination :
|
||||||
if (!EmuX86_ZydisWriteValueToDestination(e, info.operand[0], value))
|
if (!EmuX86_Operand_Write(e, info, 0, value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Note : MOV instructions never update CPU flags
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuX86_Opcode_MOVZX(LPEXCEPTION_POINTERS e, _DInst& info)
|
||||||
|
{
|
||||||
|
// MOVZX reads value from source :
|
||||||
|
uint32_t value = 0;
|
||||||
|
if (!EmuX86_Operand_Read(e, info, 1, &value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO : Implement MOVZX zero-extension!
|
||||||
|
|
||||||
|
// MOVZX writes value to destination :
|
||||||
|
if (!EmuX86_Operand_Write(e, info, 0, value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Note : MOV instructions never update CPU flags
|
// Note : MOV instructions never update CPU flags
|
||||||
|
@ -304,16 +579,16 @@ inline void EmuX86_SetFlag(LPEXCEPTION_POINTERS e, int flag, int value)
|
||||||
e->ContextRecord->EFlags ^= (-value ^ e->ContextRecord->EFlags) & (1 << flag);
|
e->ContextRecord->EFlags ^= (-value ^ e->ContextRecord->EFlags) & (1 << flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuX86_TEST(LPEXCEPTION_POINTERS e, Zydis::InstructionInfo& info)
|
bool EmuX86_Opcode_TEST(LPEXCEPTION_POINTERS e, _DInst& info)
|
||||||
{
|
{
|
||||||
// TEST reads first value :
|
// TEST reads first value :
|
||||||
uint32_t result = 0;
|
uint32_t result = 0;
|
||||||
if (!EmuX86_ZydisReadValueFromSource(e, info.operand[0], &result))
|
if (!EmuX86_Operand_Read(e, info, 0, &result))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TEST reads second value :
|
// TEST reads second value :
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
if (!EmuX86_ZydisReadValueFromSource(e, info.operand[1], &value))
|
if (!EmuX86_Operand_Read(e, info, 1, &value))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// TEST performs bitwise AND between first and second value :
|
// TEST performs bitwise AND between first and second value :
|
||||||
|
@ -337,6 +612,85 @@ bool EmuX86_TEST(LPEXCEPTION_POINTERS e, Zydis::InstructionInfo& info)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuX86_Opcode_CPUID(LPEXCEPTION_POINTERS e, _DInst& info)
|
||||||
|
{
|
||||||
|
// This CPUID emulation is based on :
|
||||||
|
// https://github.com/docbrown/vxb/wiki/Xbox-CPUID-Information
|
||||||
|
// https://github.com/docbrown/vxb/wiki/Xbox-Hardware-Information and
|
||||||
|
// http://www.sandpile.org/x86/cpuid.htm
|
||||||
|
switch (e->ContextRecord->Eax) // simpler than EmuX86_GetRegisterValue32(e, R_EAX)
|
||||||
|
{
|
||||||
|
case 0: // CPUID Function 0, return the maximum supported standard level and vendor ID string
|
||||||
|
{
|
||||||
|
// Maximum supported standard level
|
||||||
|
e->ContextRecord->Eax = 2;
|
||||||
|
// "GenuineIntel" Intel processor
|
||||||
|
e->ContextRecord->Ebx = (ULONG)'uneG';
|
||||||
|
e->ContextRecord->Edx = (ULONG)'Ieni';
|
||||||
|
e->ContextRecord->Ecx = (ULONG)'letn';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case 1: // CPUID Function 1, Return the processor type / family / model / stepping and feature flags
|
||||||
|
{
|
||||||
|
// Family 6, Model 8, Stepping 10
|
||||||
|
e->ContextRecord->Eax = 0x68a;
|
||||||
|
e->ContextRecord->Ebx = 0;
|
||||||
|
e->ContextRecord->Ecx = 0;
|
||||||
|
// Feature Flags
|
||||||
|
e->ContextRecord->Edx = 0x383F9FF; // FPU, VME, DE, PSE, TSC, MSR, PAE, MCE, CX8, SEP, MTRR, PGE, MCA, CMOV, PAT, PSE36, MMX, FXSR, SSE
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case 2: // CPUID Function 2, Return the processor configuration descriptors
|
||||||
|
{
|
||||||
|
// AL : 01 = number of times this level must be queried to obtain all configuration descriptors
|
||||||
|
// EAX nibble 1 = 01h : code TLB, 4K pages, 4 ways, 32 entries
|
||||||
|
// EAX nibble 2 = 02h : code TLB, 4M pages, fully, 2 entries
|
||||||
|
// EAX nibble 3 = 03h : data TLB, 4K pages, 4 ways, 64 entries
|
||||||
|
e->ContextRecord->Eax = 0x3020101;
|
||||||
|
// EBX and ECX nibbles = 00h : null descriptor (=unused descriptor)
|
||||||
|
e->ContextRecord->Ebx = 0;
|
||||||
|
e->ContextRecord->Ecx = 0;
|
||||||
|
// EDX nibble 0 = 41h : code and data L2 cache, 128 KB, 4 ways, 32 byte lines
|
||||||
|
// EDX nibble 1 = 08h : code L1 cache, 16 KB, 4 ways, 32 byte lines
|
||||||
|
// EDX nibble 2 = 04h : data TLB, 4M pages, 4 ways, 8 entries
|
||||||
|
// EDX nibble 3 = 0Ch : data L1 cache, 16 KB, 4 ways, 32 byte lines
|
||||||
|
e->ContextRecord->Edx = 0xC040841;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuX86_Opcode_OUT(LPEXCEPTION_POINTERS e, _DInst& info)
|
||||||
|
{
|
||||||
|
// OUT will address the first operand :
|
||||||
|
uint32_t addr;
|
||||||
|
if (!EmuX86_Operand_Read(e, info, 0, &addr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint32_t value;
|
||||||
|
if (!EmuX86_Operand_Read(e, info, 1, &value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// OUT does an I/O write on the address, using the value from the second operand :
|
||||||
|
switch (info.ops[1].size) {
|
||||||
|
case 8: {
|
||||||
|
EmuX86_IOWrite8(addr, (uint8_t)value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 16: {
|
||||||
|
EmuX86_IOWrite16(addr, (uint16_t)value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case 32: {
|
||||||
|
EmuX86_IOWrite32(addr, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
|
bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
|
||||||
{
|
{
|
||||||
// Only decode instructions within Xbox memory space
|
// Only decode instructions within Xbox memory space
|
||||||
|
@ -344,50 +698,84 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Zydis::MemoryInput input((uint8_t*)e->ContextRecord->Eip, XBOX_MEMORY_SIZE - e->ContextRecord->Eip);
|
// Decoded instruction information.
|
||||||
Zydis::InstructionInfo info;
|
_DInst info;
|
||||||
Zydis::InstructionDecoder decoder;
|
unsigned int decodedInstructionsCount = 0;
|
||||||
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
|
|
||||||
decoder.setDataSource(&input);
|
|
||||||
decoder.setInstructionPointer(e->ContextRecord->Eip);
|
|
||||||
Zydis::IntelInstructionFormatter formatter;
|
|
||||||
|
|
||||||
// Decode a single instruction
|
_CodeInfo ci;
|
||||||
decoder.decodeInstruction(info);
|
ci.code = (uint8_t*)e->ContextRecord->Eip;
|
||||||
|
ci.codeLen = 20;
|
||||||
|
ci.codeOffset = 0;
|
||||||
|
ci.dt = (_DecodeType)Decode32Bits;
|
||||||
|
ci.features = DF_NONE;
|
||||||
|
|
||||||
if (info.flags & Zydis::IF_ERROR_MASK)
|
// Checking for DECRES_SUCCESS won't work, since we're passing distorm_decompose
|
||||||
|
// a codeLen big enough to decode any instruction-length, plus distorm doesn't
|
||||||
|
// halt cleanly after reaching maxInstructions 1. So instead, just call distorm :
|
||||||
|
distorm_decompose(&ci, &info, /*maxInstructions=*/1, &decodedInstructionsCount);
|
||||||
|
// and check if it successfully decoded one instruction :
|
||||||
|
if (decodedInstructionsCount != 1)
|
||||||
{
|
{
|
||||||
EmuWarning("EmuX86: Error decoding opcode at 0x%08X\n", e->ContextRecord->Eip);
|
EmuWarning("EmuX86: Error decoding opcode at 0x%08X\n", e->ContextRecord->Eip);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (info.mnemonic)
|
switch (info.opcode) // Keep these cases alphabetically ordered
|
||||||
{
|
{
|
||||||
case Zydis::InstructionMnemonic::MOV:
|
case I_ADD:
|
||||||
if (EmuX86_MOV(e, info)) {
|
if (EmuX86_Opcode_ADD(e, info))
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto unimplemented_opcode;
|
|
||||||
case Zydis::InstructionMnemonic::TEST:
|
|
||||||
if (EmuX86_TEST(e, info)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto unimplemented_opcode;
|
|
||||||
case Zydis::InstructionMnemonic::WBINVD:
|
|
||||||
// We can safely ignore this
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
goto unimplemented_opcode;
|
||||||
|
case I_CPUID:
|
||||||
|
EmuX86_Opcode_CPUID(e, info);
|
||||||
|
break;
|
||||||
|
case I_INVD: // Flush internal caches; initiate flushing of external caches.
|
||||||
|
// We can safely ignore this
|
||||||
|
break;
|
||||||
|
case I_MOV:
|
||||||
|
if (EmuX86_Opcode_MOV(e, info))
|
||||||
|
break;
|
||||||
|
|
||||||
|
goto unimplemented_opcode;
|
||||||
|
case I_MOVZX:
|
||||||
|
if (EmuX86_Opcode_MOVZX(e, info))
|
||||||
|
break;
|
||||||
|
|
||||||
|
goto unimplemented_opcode;
|
||||||
|
case I_OUT:
|
||||||
|
if (EmuX86_Opcode_OUT(e, info))
|
||||||
|
break;
|
||||||
|
|
||||||
|
goto unimplemented_opcode;
|
||||||
|
case I_TEST:
|
||||||
|
if (EmuX86_Opcode_TEST(e, info))
|
||||||
|
break;
|
||||||
|
|
||||||
|
goto unimplemented_opcode;
|
||||||
|
case I_WBINVD: // Write back and flush internal caches; initiate writing-back and flushing of external caches.
|
||||||
|
// We can safely ignore this
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto unimplemented_opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->ContextRecord->Eip += info.length;
|
// When falling through here, the instruction was handled correctly,
|
||||||
|
// skip over the instruction and continue execution :
|
||||||
|
e->ContextRecord->Eip += info.size;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
unimplemented_opcode:
|
unimplemented_opcode:
|
||||||
EmuWarning("EmuX86: 0x%08X: %s Not Implemented\n", e->ContextRecord->Eip, formatter.formatInstruction(info));
|
EmuWarning("EmuX86: 0x%08X: Not Implemented\n", e->ContextRecord->Eip); // TODO : format decodedInstructions[0]
|
||||||
e->ContextRecord->Eip += info.length;
|
e->ContextRecord->Eip += info.size;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuX86_Init()
|
||||||
|
{
|
||||||
|
DbgPrintf("EmuX86: Initializing distorm version %d\n", distorm_version());
|
||||||
|
EmuX86_InitContextRecordOffsetByRegisterType();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#define EMUX86_EFLAG_VIP 20
|
#define EMUX86_EFLAG_VIP 20
|
||||||
#define EMUX86_EFLAG_ID 21
|
#define EMUX86_EFLAG_ID 21
|
||||||
|
|
||||||
|
void EmuX86_Init();
|
||||||
bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e);
|
bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e);
|
||||||
uint32_t EmuX86_IORead32(uint32_t addr);
|
uint32_t EmuX86_IORead32(uint32_t addr);
|
||||||
uint16_t EmuX86_IORead16(uint32_t addr);
|
uint16_t EmuX86_IORead16(uint32_t addr);
|
||||||
|
|
Loading…
Reference in New Issue