Merge pull request #5 from PatrickvL/distorm

Switched over to Distorm
This commit is contained in:
PatrickvL 2017-01-10 13:51:30 +01:00 committed by GitHub
commit 7420dec402
40 changed files with 1450 additions and 33439 deletions

View File

@ -80,7 +80,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<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>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@ -103,7 +103,7 @@
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<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>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
@ -140,7 +140,7 @@
</Midl>
<ClCompile>
<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>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@ -155,7 +155,7 @@
<AdditionalIncludeDirectories>Include\Win32\CxbxKrnl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<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>
<IgnoreSpecificDefaultLibraries>libci.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -167,7 +167,7 @@
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<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>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>

View File

@ -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 */

View File

@ -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.

View File

@ -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/

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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>

View File

@ -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

View File

@ -1,90 +0,0 @@
Zyan Disassembler Engine (Zydis) [![Build Status](https://travis-ci.org/zyantific/zyan-disassembler-engine.svg?branch=master)](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.

View File

@ -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_ */

View File

@ -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

View File

@ -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_ */

View File

@ -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()
{
}
/* ============================================================================================== */
}

View File

@ -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

View File

@ -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();
}
/* ============================================================================================== */
}

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;
}
}

View File

@ -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_ */

View File

@ -45,6 +45,7 @@ namespace xboxkrnl
#include "CxbxKrnl.h"
#include "Emu.h"
#include "EmuX86.h"
#include "EmuFile.h"
#include "EmuFS.h"
#include "EmuShared.h"
@ -381,12 +382,20 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
{
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("CONIN$", "rt", stdin);
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): Debug Console Allocated (DM_CONSOLE).\n", GetCurrentThreadId());
@ -616,6 +625,7 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
EmuGenerateFS(pTLS, pTLSData);
}
EmuX86_Init();
DbgPrintf("EmuMain (0x%X): Initial thread starting.\n", GetCurrentThreadId());

View File

@ -145,83 +145,13 @@ extern "C" CXBXKRNL_API void NTAPI EmuWarning(const char *szWarningMessage, ...)
}
#endif
// exception handler
extern int EmuException(LPEXCEPTION_POINTERS e)
void EmuExceptionPrintDebugInformation(LPEXCEPTION_POINTERS e, bool IsBreakpointException)
{
g_bEmuException = true;
// notify user
{
char buffer[256];
if(e->ExceptionRecord->ExceptionCode == 0x80000003)
{
// print debug information
{
if (IsBreakpointException)
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"
@ -242,7 +172,55 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
}
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"
@ -250,21 +228,42 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
" Press \"Cancel\" to debug.",
e->ExceptionRecord->ExceptionCode, e->ContextRecord->Eip);
if(MessageBox(g_hEmuWindow, buffer, "Cxbx-Reloaded", MB_ICONSTOP | MB_OKCANCEL) == IDOK)
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);
}
}
EmuExceptionExitProcess();
}
}
// exception handler
extern int EmuException(LPEXCEPTION_POINTERS e)
{
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
EmuExceptionNonBreakpointUnhandledShow(e);
}
// Unhandled exception :
g_bEmuException = false;
return EXCEPTION_CONTINUE_SEARCH;
}

View File

@ -47,7 +47,8 @@
# pragma comment(lib, "glew32.lib")
#endif
#include <Zydis.hpp>
#include <distorm.h> // For uint32_t
#include <string> // For std::string
#include "CxbxKrnl.h"
#include "Emu.h"

View File

@ -36,7 +36,14 @@
#define _CXBXKRNL_INTERNAL
#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 "Emu.h"
@ -92,9 +99,9 @@ uint16_t EmuX86_Read16(uint32_t addr)
EmuWarning("EmuX86_Read16(0x%08X) Forwarding to EmuX86_Read32...", addr);
uint16_t value;
if (addr & 2)
value = (uint16_t)EmuX86_Read32(addr - 2);
value = (uint16_t)(EmuX86_Read32(addr - 2) >> 16);
else
value = (uint16_t)(EmuX86_Read32(addr) >> 16);
value = (uint16_t)EmuX86_Read32(addr);
EmuWarning("EmuX86_Read16(0x%08X) = 0x%04X", addr, value);
return value;
@ -105,9 +112,9 @@ uint8_t EmuX86_Read8(uint32_t addr)
EmuWarning("EmuX86_Read8(0x%08X) Forwarding to EmuX86_Read16...", addr);
uint8_t value;
if (addr & 1)
value = (uint8_t)EmuX86_Read16(addr - 1);
value = (uint8_t)(EmuX86_Read16(addr - 1) >> 8);
else
value = (uint8_t)(EmuX86_Read16(addr) >> 8);
value = (uint8_t)EmuX86_Read16(addr);
EmuWarning("EmuX86_Read8(0x%08X) = 0x%02X", addr, 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);
}
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) {
case Zydis::Register::AL: case Zydis::Register::AH: case Zydis::Register::AX: case Zydis::Register::EAX:
return &e->ContextRecord->Eax;
case Zydis::Register::BL: case Zydis::Register::BH: case Zydis::Register::BX: case Zydis::Register::EBX:
return &e->ContextRecord->Ebx;
case Zydis::Register::CL: case Zydis::Register::CH: case Zydis::Register::CX: case Zydis::Register::ECX:
return &e->ContextRecord->Ecx;
case Zydis::Register::DL: case Zydis::Register::DH: case Zydis::Register::DX: case Zydis::Register::EDX:
return &e->ContextRecord->Edx;
case Zydis::Register::EDI:
return &e->ContextRecord->Edi;
case Zydis::Register::ESI:
return &e->ContextRecord->Esi;
case Zydis::Register::EBP:
return &e->ContextRecord->Ebp;
}
/* 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,*/
ContextRecordOffsetByRegisterType[R_EAX] = offsetof(CONTEXT, Eax);
ContextRecordOffsetByRegisterType[R_ECX] = offsetof(CONTEXT, Ecx);
ContextRecordOffsetByRegisterType[R_EDX] = offsetof(CONTEXT, Edx);
ContextRecordOffsetByRegisterType[R_EBX] = offsetof(CONTEXT, Ebx);
ContextRecordOffsetByRegisterType[R_ESP] = offsetof(CONTEXT, Esp);
ContextRecordOffsetByRegisterType[R_EBP] = offsetof(CONTEXT, Ebp);
ContextRecordOffsetByRegisterType[R_ESI] = offsetof(CONTEXT, Esi);
ContextRecordOffsetByRegisterType[R_EDI] = offsetof(CONTEXT, Edi);
/* R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D,*/
ContextRecordOffsetByRegisterType[R_AX] = offsetof(CONTEXT, Eax);
ContextRecordOffsetByRegisterType[R_CX] = offsetof(CONTEXT, Ecx);
ContextRecordOffsetByRegisterType[R_DX] = offsetof(CONTEXT, Edx);
ContextRecordOffsetByRegisterType[R_BX] = offsetof(CONTEXT, Ebx);
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;
}
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 != Zydis::Register::NONE)
if (reg != R_NONE)
{
DWORD* regptr = EmuX86_GetRegisterPointer(e, reg);
if (regptr == nullptr)
return false;
value = *regptr;
void* regptr = EmuX86_GetRegisterPointer(e, reg);
if (regptr != nullptr)
return *(uint32_t *)regptr;
}
*output = value;
return true;
return 0;
}
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;
uint32_t index = 0;
if (!EmuX86_GetRegisterValue(&base, e, operand.base) || !EmuX86_GetRegisterValue(&index, e, operand.base)) {
return false;
if (reg != R_NONE)
{
void* regptr = EmuX86_GetRegisterPointer(e, reg);
if (regptr != nullptr)
return *(uint16_t *)regptr;
}
*output = base + (index * operand.scale) + operand.lval.udword;
return true;
return 0;
}
bool EmuX86_ZydisReadValueFromSource(LPEXCEPTION_POINTERS e, Zydis::OperandInfo& operand, OUT uint32_t *value)
inline uint8_t EmuX86_GetRegisterValue8(LPEXCEPTION_POINTERS e, uint8_t reg)
{
switch (operand.type) {
// TODO : case Zydis::OperandType::CONSTANT:
// TODO : case Zydis::OperandType::POINTER:
// TODO : case Zydis::OperandType::REL_IMMEDIATE:
case Zydis::OperandType::IMMEDIATE:
if (reg != R_NONE)
{
*value = operand.lval.udword;
break;
void* regptr = EmuX86_GetRegisterPointer(e, reg);
if (regptr != nullptr)
return *(uint8_t *)regptr;
}
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;
return 0;
}
switch (operand.size) {
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);
break;
return;
case 16:
*value = EmuX86_Read16(srcAddr);
break;
return;
case 32:
*value = EmuX86_Read32(srcAddr);
break;
default:
return false;
}
break;
}
default:
return false;
}
return true;
}
bool EmuX86_ZydisWriteValueToDestination(LPEXCEPTION_POINTERS e, Zydis::OperandInfo& operand, uint32_t value)
void EmuX86_Addr_Write(uint32_t destAddr, uint16_t size, uint32_t value)
{
switch (operand.type) {
case Zydis::OperandType::REGISTER:
{
DWORD* pDstReg = EmuX86_GetRegisterPointer(e, operand.base);
if (pDstReg == nullptr)
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:
{
uint32_t destAddr = 0;
if (!EmuX86_DecodeMemoryOperand(&destAddr, e, operand))
return false;
switch (operand.size) {
switch (size) {
case 8:
EmuX86_Write8(destAddr, value & 0xFF);
break;
return;
case 16:
EmuX86_Write16(destAddr, value & 0xFFFF);
break;
return;
case 32:
EmuX86_Write32(destAddr, value);
break;
default:
}
}
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;
}
break;
case O_IMM:
{
switch (info.ops[operand].size) {
case 8:
*value = info.imm.byte;
return true;
case 16:
*value = info.imm.word;
return true;
case 32:
*value = info.imm.dword;
return true;
}
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:
return false;
}
return false;
}
bool EmuX86_Operand_Write(LPEXCEPTION_POINTERS e, _DInst& info, int operand, 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:
*((uint8_t*)regAddr) = (uint8_t)value;
return true;
case 16:
*((uint16_t*)regAddr) = (uint16_t)value;
return true;
case 32:
*((uint32_t*)regAddr) = value;
return true;
default:
return false;
}
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:
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;
}
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 :
uint32_t value = 0;
if (!EmuX86_ZydisReadValueFromSource(e, info.operand[1], &value))
if (!EmuX86_Operand_Read(e, info, 1, &value))
return false;
// 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;
// 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);
}
bool EmuX86_TEST(LPEXCEPTION_POINTERS e, Zydis::InstructionInfo& info)
bool EmuX86_Opcode_TEST(LPEXCEPTION_POINTERS e, _DInst& info)
{
// TEST reads first value :
uint32_t result = 0;
if (!EmuX86_ZydisReadValueFromSource(e, info.operand[0], &result))
if (!EmuX86_Operand_Read(e, info, 0, &result))
return false;
// TEST reads second value :
uint32_t value = 0;
if (!EmuX86_ZydisReadValueFromSource(e, info.operand[1], &value))
if (!EmuX86_Operand_Read(e, info, 1, &value))
return false;
// TEST performs bitwise AND between first and second value :
@ -337,6 +612,85 @@ bool EmuX86_TEST(LPEXCEPTION_POINTERS e, Zydis::InstructionInfo& info)
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)
{
// Only decode instructions within Xbox memory space
@ -344,50 +698,84 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
return false;
}
Zydis::MemoryInput input((uint8_t*)e->ContextRecord->Eip, XBOX_MEMORY_SIZE - e->ContextRecord->Eip);
Zydis::InstructionInfo info;
Zydis::InstructionDecoder decoder;
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
decoder.setDataSource(&input);
decoder.setInstructionPointer(e->ContextRecord->Eip);
Zydis::IntelInstructionFormatter formatter;
// Decoded instruction information.
_DInst info;
unsigned int decodedInstructionsCount = 0;
// Decode a single instruction
decoder.decodeInstruction(info);
_CodeInfo ci;
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);
}
else
{
switch (info.mnemonic)
switch (info.opcode) // Keep these cases alphabetically ordered
{
case Zydis::InstructionMnemonic::MOV:
if (EmuX86_MOV(e, info)) {
case I_ADD:
if (EmuX86_Opcode_ADD(e, info))
break;
}
goto unimplemented_opcode;
case Zydis::InstructionMnemonic::TEST:
if (EmuX86_TEST(e, info)) {
case I_CPUID:
EmuX86_Opcode_CPUID(e, info);
break;
}
goto unimplemented_opcode;
case Zydis::InstructionMnemonic::WBINVD:
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;
unimplemented_opcode:
EmuWarning("EmuX86: 0x%08X: %s Not Implemented\n", e->ContextRecord->Eip, formatter.formatInstruction(info));
e->ContextRecord->Eip += info.length;
return false;
EmuWarning("EmuX86: 0x%08X: Not Implemented\n", e->ContextRecord->Eip); // TODO : format decodedInstructions[0]
e->ContextRecord->Eip += info.size;
}
return false;
}
void EmuX86_Init()
{
DbgPrintf("EmuX86: Initializing distorm version %d\n", distorm_version());
EmuX86_InitContextRecordOffsetByRegisterType();
}

View File

@ -55,6 +55,7 @@
#define EMUX86_EFLAG_VIP 20
#define EMUX86_EFLAG_ID 21
void EmuX86_Init();
bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e);
uint32_t EmuX86_IORead32(uint32_t addr);
uint16_t EmuX86_IORead16(uint32_t addr);