Improved the intel instruction formatter

Some minor bugfixes
This commit is contained in:
flobernd 2014-10-30 16:36:25 +01:00
parent e31a9119ff
commit 2933d1683b
11 changed files with 561 additions and 246 deletions

View File

@ -48,7 +48,7 @@ void testDecodingAndFormatting(uintptr_t baseAddress, PIMAGE_NT_HEADERS ntHeader
reinterpret_cast<PIMAGE_SECTION_HEADER>(
reinterpret_cast<uintptr_t>(ntHeaders) + sizeof(IMAGE_NT_HEADERS)
+ ntHeaders->FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER));
// Decode all code sections
// Decode and format all code sections
for (unsigned int i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
{
if (sectionHeader->Characteristics & IMAGE_SCN_CNT_CODE)
@ -60,7 +60,7 @@ void testDecodingAndFormatting(uintptr_t baseAddress, PIMAGE_NT_HEADERS ntHeader
decoder.setInstructionPointer(baseAddress + sectionHeader->VirtualAddress);
while (decoder.decodeInstruction(info))
{
formatter.formatInstruction(info);
}
}
sectionHeader++;
@ -116,6 +116,5 @@ int _tmain(int argc, _TCHAR* argv[])
<< std::endl;
std::cin.get();
return 0;
}

View File

@ -31,6 +31,8 @@
**************************************************************************************************/
#pragma once
#include "VXDisassemblerTypes.h"
#include "VXInstructionDecoder.h"
#include "VXInstructionFormatter.h"
#include "VXSymbolResolver.h"
#include "VXDisassemblerUtils.h"

View File

@ -0,0 +1,78 @@
/**************************************************************************************************
Verteron Disassembler Engine
Version 1.0
Remarks : Freeware, Copyright must be included
Original Author : Florian Bernd
Modifications :
Last change : 30. 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 "VXDisassemblerUtils.h"
namespace Verteron
{
namespace Disassembler
{
uint64_t VDECalcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInfo &operand)
{
assert((operand.type == VXOperandType::REL_IMMEDIATE) ||
((operand.type == VXOperandType::MEMORY) && (operand.base == VXRegister::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 == VXOperandType::MEMORY) && (operand.base == VXRegister::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

@ -0,0 +1,53 @@
/**************************************************************************************************
Verteron Disassembler Engine
Version 1.0
Remarks : Freeware, Copyright must be included
Original Author : Florian Bernd
Modifications :
Last change : 30. 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.
**************************************************************************************************/
#pragma once
#include <stdint.h>
#include "VXDisassemblerTypes.h"
namespace Verteron
{
namespace Disassembler
{
/**
* @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 VDECalcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInfo &operand);
}
}

View File

@ -475,11 +475,11 @@ uint16_t VXInstructionDecoder::getEffectiveOperandSize(const VXInstructionInfo &
case VXDefinedOperandSize::RDQ:
return (m_disassemblerMode == VXDisassemblerMode::M64BIT) ? 64 : 32;
default:
return Internal::GetSimpleOperandSize(operandSize);
return Internal::VDEGetSimpleOperandSize(operandSize);
}
}
bool VXInstructionDecoder::decodeOperands(VXInstructionInfo& info)
bool VXInstructionDecoder::decodeOperands(VXInstructionInfo &info)
{
assert(info.instrDefinition);
// Always try to decode the first operand
@ -493,7 +493,6 @@ bool VXInstructionDecoder::decodeOperands(VXInstructionInfo& info)
{
if (info.operand[i - 1].type != VXOperandType::NONE)
{
info.operand[i].access_mode = VXOperandAccessMode::READ;
if (!decodeOperand(info, info.operand[i], info.instrDefinition->operand[i].type,
info.instrDefinition->operand[i].size))
{
@ -502,25 +501,30 @@ bool VXInstructionDecoder::decodeOperands(VXInstructionInfo& info)
}
}
// Update operand access modes
info.operand[0].access_mode = VXOperandAccessMode::READ;
if (info.operand[0].type != VXOperandType::NONE)
for (unsigned int i = 0; i < 4; ++i)
{
if (info.instrDefinition->flags & IDF_OPERAND1_WRITE)
if (info.operand[i].type != VXOperandType::NONE)
{
info.operand[0].access_mode = VXOperandAccessMode::WRITE;
} else if (info.instrDefinition->flags & IDF_OPERAND1_READWRITE)
{
info.operand[0].access_mode = VXOperandAccessMode::READWRITE;
}
}
if (info.operand[1].type != VXOperandType::NONE)
{
if (info.instrDefinition->flags & IDF_OPERAND2_WRITE)
{
info.operand[1].access_mode = VXOperandAccessMode::WRITE;
} else if (info.instrDefinition->flags & IDF_OPERAND2_READWRITE)
{
info.operand[1].access_mode = VXOperandAccessMode::READWRITE;
info.operand[i].access_mode = VXOperandAccessMode::READ;
if (i == 0)
{
if (info.instrDefinition->flags & IDF_OPERAND1_WRITE)
{
info.operand[0].access_mode = VXOperandAccessMode::WRITE;
} else if (info.instrDefinition->flags & IDF_OPERAND1_READWRITE)
{
info.operand[0].access_mode = VXOperandAccessMode::READWRITE;
}
} else if (i == 1)
{
if (info.instrDefinition->flags & IDF_OPERAND2_WRITE)
{
info.operand[1].access_mode = VXOperandAccessMode::WRITE;
} else if (info.instrDefinition->flags & IDF_OPERAND2_READWRITE)
{
info.operand[1].access_mode = VXOperandAccessMode::READWRITE;
}
}
}
}
return true;
@ -621,11 +625,11 @@ bool VXInstructionDecoder::decodeOperand(VXInstructionInfo &info, VXOperandInfo
case VXDefinedOperandType::MR:
return decodeRegisterMemoryOperand(info, operand, RegisterClass::GENERAL_PURPOSE,
info.modrm_mod == 3 ?
GetComplexOperandRegSize(operandSize) : GetComplexOperandMemSize(operandSize));
VDEGetComplexOperandRegSize(operandSize) : VDEGetComplexOperandMemSize(operandSize));
case VXDefinedOperandType::MU:
return decodeRegisterMemoryOperand(info, operand, RegisterClass::XMM,
info.modrm_mod == 3 ?
GetComplexOperandRegSize(operandSize) : GetComplexOperandMemSize(operandSize));
VDEGetComplexOperandRegSize(operandSize) : VDEGetComplexOperandMemSize(operandSize));
case VXDefinedOperandType::N:
// ModR/M byte may refer only to memory
if (info.modrm_mod != 3)
@ -903,24 +907,24 @@ bool VXInstructionDecoder::decodeOpcode(VXInstructionInfo &info)
info.opcode[0] = inputCurrent();
info.opcode_length = 1;
// Iterate through opcode tree
VXOpcodeTreeNode node = GetOpcodeTreeChild(GetOpcodeTreeRoot(), inputCurrent());
VXOpcodeTreeNode node = VDEGetOpcodeTreeChild(VDEGetOpcodeTreeRoot(), inputCurrent());
VXOpcodeTreeNodeType nodeType;
do
{
uint16_t index = 0;
nodeType = GetOpcodeNodeType(node);
nodeType = VDEGetOpcodeNodeType(node);
switch (nodeType)
{
case VXOpcodeTreeNodeType::INSTRUCTION_DEFINITION:
{
// Check for invalid instruction
if (GetOpcodeNodeValue(node) == 0)
if (VDEGetOpcodeNodeValue(node) == 0)
{
info.flags |= IF_ERROR_INVALID;
return false;
}
// Get instruction definition
const VXInstructionDefinition *instrDefinition = GetInstructionDefinition(node);
const VXInstructionDefinition *instrDefinition = VDEGetInstructionDefinition(node);
// Check for invalid 64 bit instruction
if ((m_disassemblerMode == VXDisassemblerMode::M64BIT) &&
(instrDefinition->flags & IDF_INVALID_64))
@ -991,11 +995,11 @@ bool VXInstructionDecoder::decodeOpcode(VXInstructionInfo &info)
{
index = 3; // 66
}
if (GetOpcodeTreeChild(node, index) == 0)
if (VDEGetOpcodeTreeChild(node, index) == 0)
{
index = 0;
}
if (index && (GetOpcodeTreeChild(node, index) != 0))
if (index && (VDEGetOpcodeTreeChild(node, index) != 0))
{
// Remove REP and REPNE prefix
info.flags &= ~IF_PREFIX_REP;
@ -1055,7 +1059,7 @@ bool VXInstructionDecoder::decodeOpcode(VXInstructionInfo &info)
switch (m_preferredVendor)
{
case VXInstructionSetVendor::ANY:
index = (GetOpcodeTreeChild(node, 0) != 0) ? 0 : 1;
index = (VDEGetOpcodeTreeChild(node, 0) != 0) ? 0 : 1;
break;
case VXInstructionSetVendor::INTEL:
index = 1;
@ -1071,9 +1075,9 @@ bool VXInstructionDecoder::decodeOpcode(VXInstructionInfo &info)
{
// As all 3dnow instructions got the same operands and flag definitions, we just
// decode a random instruction and determine the specific opcode later.
assert(GetOpcodeTreeChild(node, 0x0C) != 0);
assert(VDEGetOpcodeTreeChild(node, 0x0C) != 0);
const VXInstructionDefinition *instrDefinition =
GetInstructionDefinition(GetOpcodeTreeChild(node, 0x0C));
VDEGetInstructionDefinition(VDEGetOpcodeTreeChild(node, 0x0C));
// Update instruction info
info.instrDefinition = instrDefinition;
info.mnemonic = instrDefinition->mnemonic;
@ -1094,7 +1098,7 @@ bool VXInstructionDecoder::decodeOpcode(VXInstructionInfo &info)
}
// Update instruction info
instrDefinition =
GetInstructionDefinition(GetOpcodeTreeChild(node, info.opcode[2]));
VDEGetInstructionDefinition(VDEGetOpcodeTreeChild(node, info.opcode[2]));
if (!instrDefinition ||
(instrDefinition->mnemonic == VXInstructionMnemonic::INVALID))
{
@ -1179,7 +1183,7 @@ bool VXInstructionDecoder::decodeOpcode(VXInstructionInfo &info)
default:
assert(0);
}
node = GetOpcodeTreeChild(node, index);
node = VDEGetOpcodeTreeChild(node, index);
} while (nodeType != VXOpcodeTreeNodeType::INSTRUCTION_DEFINITION);
return false;
}
@ -1252,6 +1256,8 @@ bool VXInstructionDecoder::decodeInstruction(VXInstructionInfo &info)
info.mnemonic = VXInstructionMnemonic::NOP;
info.operand[0].type = VXOperandType::NONE;
info.operand[1].type = VXOperandType::NONE;
info.operand[0].access_mode = VXOperandAccessMode::NA;
info.operand[1].access_mode = VXOperandAccessMode::NA;
}
}
if ((info.mnemonic == VXInstructionMnemonic::NOP) && (info.flags & IF_PREFIX_REP))
@ -1279,7 +1285,7 @@ DecodeError:
info.length = length;
info.data[0] = firstByte;
info.instrAddress = instrAddress;
info.instrDefinition = Internal::GetInstructionDefinition(0);
info.instrDefinition = Internal::VDEGetInstructionDefinition(0);
// Return with error, if the end of the input source was reached while decoding the
// invalid instruction
if (info.flags & IF_ERROR_END_OF_INPUT)

View File

@ -30,7 +30,9 @@
**************************************************************************************************/
#include "VXInstructionFormatter.h"
#include "VXDisassemblerUtils.h"
#include <cstdarg>
#include <cctype>
namespace Verteron
{
@ -101,12 +103,14 @@ void VXBaseInstructionFormatter::internalFormatInstruction(VXInstructionInfo con
VXBaseInstructionFormatter::VXBaseInstructionFormatter()
: m_symbolResolver(nullptr)
, m_uppercase(false)
{
}
VXBaseInstructionFormatter::VXBaseInstructionFormatter(VXBaseSymbolResolver *symbolResolver)
: m_symbolResolver(symbolResolver)
, m_uppercase(false)
{
}
@ -120,7 +124,7 @@ const char* VXBaseInstructionFormatter::formatInstruction(const VXInstructionInf
if (m_outputBuffer.size() == 0)
{
// The basic instruction formatter only returns the instruction menmonic.
return Internal::GetInstructionMnemonicString(info.mnemonic);
return Internal::VDEGetInstructionMnemonicString(info.mnemonic);
}
// Return the formatted instruction string
return outputString();
@ -160,6 +164,14 @@ void VXBaseInstructionFormatter::outputAppend(char const *text)
// Append the text
m_outputBuffer.resize(offset + strLen);
memcpy(&m_outputBuffer[offset], text, strLen);
// Convert to uppercase
if (m_uppercase)
{
for (size_t i = offset; i < m_outputBuffer.size() - 1; ++i)
{
m_outputBuffer[i] = toupper(m_outputBuffer[i]);
}
}
}
void VXBaseInstructionFormatter::outputAppendFormatted(char const *format, ...)
@ -185,35 +197,27 @@ void VXBaseInstructionFormatter::outputAppendFormatted(char const *format, ...)
// Append the formatted text
m_outputBuffer.resize(offset + strLen);
vsnprintf_s(&m_outputBuffer[offset], strLen, strLen, format, arguments);
// Convert to uppercase
if (m_uppercase)
{
for (size_t i = offset; i < m_outputBuffer.size() - 1; ++i)
{
m_outputBuffer[i] = toupper(m_outputBuffer[i]);
}
}
}
va_end(arguments);
}
uint64_t VXBaseInstructionFormatter::calcAbsoluteTarget(const VXInstructionInfo &info,
const VXOperandInfo &operand) const
{
switch (operand.size)
{
case 8:
return (info.instrPointer + operand.lval.sbyte);
case 16:
return (info.instrPointer + operand.lval.sword);
case 32:
case 64:
return (info.instrPointer + operand.lval.sdword);
default:
assert(0);
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void VXIntelInstructionFormatter::outputAppendAddress(const VXInstructionInfo &info,
uint64_t address)
void VXBaseInstructionFormatter::outputAppendAddress(const VXInstructionInfo &info,
uint64_t address, bool resolveSymbols)
{
uint64_t offset = 0;
const char* name = resolveSymbol(info, address, offset);
const char* name = nullptr;
if (resolveSymbols)
{
name = resolveSymbol(info, address, offset);
}
if (name)
{
if (offset)
@ -241,6 +245,154 @@ void VXIntelInstructionFormatter::outputAppendAddress(const VXInstructionInfo &i
}
}
void VXBaseInstructionFormatter::outputAppendImmediate(const VXInstructionInfo &info,
const VXOperandInfo &operand, bool resolveSymbols)
{
assert(operand.type == VXOperandType::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 VXBaseInstructionFormatter::outputAppendDisplacement(const VXInstructionInfo &info,
const VXOperandInfo &operand)
{
assert(operand.offset > 0);
if (operand.base == VXRegister::NONE && operand.index == VXRegister::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 != VXRegister::NONE ||
operand.index != VXRegister::NONE) ? "+" : "", value);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void VXIntelInstructionFormatter::outputAppendOperandCast(const VXInstructionInfo &info,
const VXOperandInfo &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 VXIntelInstructionFormatter::formatOperand(const VXInstructionInfo &info,
const VXOperandInfo &operand)
{
@ -250,18 +402,16 @@ void VXIntelInstructionFormatter::formatOperand(const VXInstructionInfo &info,
outputAppend(registerToString(operand.base));
break;
case VXOperandType::MEMORY:
// TODO: resolve symbols for displacement only and RIP based memory operands
if (info.flags & IF_PREFIX_SEGMENT)
{
outputAppendFormatted("%s:", registerToString(info.segment));
}
outputAppend("[");
// TODO: Fix zero sized memory operands (lea eax, [rip+1] | lidt [0])
//if (operand.base == VXRegister::RIP)
//{
// // TODO: Add option
// outputAppendAddress(info, calcAbsoluteTarget(info, operand));
//} else
if (operand.base == VXRegister::RIP)
{
// TODO: Add option
outputAppendAddress(info, VDECalcAbsoluteTarget(info, operand), true);
} else
{
if (operand.base != VXRegister::NONE)
{
@ -276,58 +426,9 @@ void VXIntelInstructionFormatter::formatOperand(const VXInstructionInfo &info,
outputAppendFormatted("*%d", operand.scale);
}
}
if (operand.lval.uqword ||
(operand.base == VXRegister::NONE && operand.index == VXRegister::NONE))
if (operand.offset)
{
if (operand.base == VXRegister::NONE && operand.index == VXRegister::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 != VXRegister::NONE ||
operand.index != VXRegister::NONE) ? "+" : "", value);
}
}
outputAppendDisplacement(info, operand);
}
}
outputAppend("]");
@ -349,26 +450,7 @@ void VXIntelInstructionFormatter::formatOperand(const VXInstructionInfo &info,
break;
case VXOperandType::IMMEDIATE:
{
// TODO: resolve symbols
uint64_t value = 0;
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);
}
outputAppendFormatted("%.2llX", value);
outputAppendImmediate(info, operand, true);
}
break;
case VXOperandType::REL_IMMEDIATE:
@ -377,11 +459,11 @@ void VXIntelInstructionFormatter::formatOperand(const VXInstructionInfo &info,
{
outputAppend("short ");
}
outputAppendAddress(info, calcAbsoluteTarget(info, operand));
outputAppendAddress(info, VDECalcAbsoluteTarget(info, operand), true);
}
break;
case VXOperandType::CONSTANT:
outputAppendFormatted("%d", operand.lval.udword);
outputAppendFormatted("%.2X", operand.lval.udword);
break;
default:
assert(0);
@ -404,23 +486,82 @@ void VXIntelInstructionFormatter::internalFormatInstruction(const VXInstructionI
outputAppend("repne ");
}
// Append the instruction mnemonic
outputAppend(Internal::GetInstructionMnemonicString(info.mnemonic));
outputAppend(Internal::VDEGetInstructionMnemonicString(info.mnemonic));
// Append the first operand
if (info.operand[0].type != VXOperandType::NONE)
{
outputAppend(" ");
bool cast = false;
if (info.operand[0].type == VXOperandType::MEMORY)
{
if (info.operand[1].type == VXOperandType::IMMEDIATE ||
info.operand[1].type == VXOperandType::CONSTANT ||
info.operand[1].type == VXOperandType::NONE ||
(info.operand[0].size != info.operand[1].size))
{
cast = true;
} else if (info.operand[1].type == VXOperandType::REGISTER &&
info.operand[1].base == VXRegister::CL)
{
switch (info.mnemonic)
{
case VXInstructionMnemonic::RCL:
case VXInstructionMnemonic::ROL:
case VXInstructionMnemonic::ROR:
case VXInstructionMnemonic::RCR:
case VXInstructionMnemonic::SHL:
case VXInstructionMnemonic::SHR:
case VXInstructionMnemonic::SAR:
cast = true;
break;
default:
break;
}
}
}
if (cast)
{
outputAppendOperandCast(info, info.operand[0]);
}
formatOperand(info, info.operand[0]);
}
// Append the second operand
if (info.operand[1].type != VXOperandType::NONE)
{
outputAppend(", ");
bool cast = false;
if (info.operand[1].type == VXOperandType::MEMORY &&
info.operand[0].size != info.operand[1].size &&
((info.operand[0].type != VXOperandType::REGISTER) ||
((info.operand[0].base != VXRegister::ES) &&
(info.operand[0].base != VXRegister::CS) &&
(info.operand[0].base != VXRegister::SS) &&
(info.operand[0].base != VXRegister::DS) &&
(info.operand[0].base != VXRegister::FS) &&
(info.operand[0].base != VXRegister::GS))))
{
cast = true;
}
if (cast)
{
outputAppendOperandCast(info, info.operand[1]);
}
formatOperand(info, info.operand[1]);
}
// Append the third operand
if (info.operand[2].type != VXOperandType::NONE)
{
outputAppend(", ");
bool cast = false;
if (info.operand[2].type == VXOperandType::MEMORY &&
(info.operand[2].size != info.operand[1].size))
{
cast = true;
}
if (cast)
{
outputAppendOperandCast(info, info.operand[2]);
}
formatOperand(info, info.operand[2]);
}
// Append the fourth operand

View File

@ -50,6 +50,7 @@ private:
static const char *m_registerStrings[];
VXBaseSymbolResolver *m_symbolResolver;
std::vector<char> m_outputBuffer;
bool m_uppercase;
protected:
/**
* @brief Clears the output string buffer.
@ -70,14 +71,36 @@ protected:
* @param format The format string.
*/
void outputAppendFormatted(const char *format, ...);
protected:
/**
* @brief Calculates the absolute target address for a relative immediate operand.
* @param info The instruction info.
* @param operand The operand.
* @return The absolute target address.
* @brief Changes automatic conversion of characters to uppercase.
* @param uppercase Set true to enable automatic uppercase conversion.
*/
uint64_t calcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInfo &operand) const;
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 VXInstructionInfo &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 VXInstructionInfo &info, const VXOperandInfo &operand,
bool resolveSymbols = false);
/**
* @brief Appends a formatted memory displacement value to the output string buffer.
* @param info The instruction info.
* @param operand The memory operand.
*/
void outputAppendDisplacement(const VXInstructionInfo &info, const VXOperandInfo &operand);
protected:
/**
* @brief Returns the string representation of a given register.
* @param reg The register.
@ -138,6 +161,11 @@ public:
void setSymbolResolver(VXBaseSymbolResolver *symbolResolver);
};
inline void VXBaseInstructionFormatter::outputSetUppercase(bool uppercase)
{
m_uppercase = uppercase;
}
inline char const* VXBaseInstructionFormatter::registerToString(VXRegister reg) const
{
if (reg == VXRegister::NONE)
@ -175,8 +203,12 @@ inline void VXBaseInstructionFormatter::setSymbolResolver(VXBaseSymbolResolver *
class VXIntelInstructionFormatter : public VXBaseInstructionFormatter
{
private:
void outputAppendAddress(const VXInstructionInfo &info, uint64_t address);
private:
/**
* @brief Appends an operand cast to the output string buffer.
* @param info The instruction info.
* @param operand The operand.
*/
void outputAppendOperandCast(const VXInstructionInfo &info, const VXOperandInfo &operand);
/**
* @brief Formats the specified operand and appends the resulting string to the output
* buffer.

View File

@ -160,20 +160,20 @@ static const VXOpcodeTreeNode optreeTable[][256] =
/* 6F */ NODE(VXOpcodeTreeNodeType::OPERAND_SIZE, 0x000A),
/* 70 */ 0x02E8,
/* 71 */ 0x02E2,
/* 72 */ 0x02CC,
/* 73 */ 0x02CA,
/* 74 */ 0x02D0,
/* 72 */ 0x02CA,
/* 73 */ 0x02DE,
/* 74 */ 0x02CE,
/* 75 */ 0x02E1,
/* 76 */ 0x02CD,
/* 77 */ 0x02C8,
/* 76 */ 0x02CB,
/* 77 */ 0x02C7,
/* 78 */ 0x02ED,
/* 79 */ 0x02E6,
/* 7A */ 0x02EB,
/* 7B */ 0x02E5,
/* 7C */ 0x02D7,
/* 7D */ 0x02D5,
/* 7E */ 0x02DA,
/* 7F */ 0x02D3,
/* 7C */ 0x02D5,
/* 7D */ 0x02D3,
/* 7E */ 0x02D8,
/* 7F */ 0x02D1,
/* 80 */ NODE(VXOpcodeTreeNodeType::MODRM_REG, 0x0013),
/* 81 */ NODE(VXOpcodeTreeNodeType::MODRM_REG, 0x0014),
/* 82 */ NODE(VXOpcodeTreeNodeType::MODRM_REG, 0x0015),
@ -279,9 +279,9 @@ static const VXOpcodeTreeNode optreeTable[][256] =
/* E6 */ 0x039D,
/* E7 */ 0x039E,
/* E8 */ 0x004E,
/* E9 */ 0x02DD,
/* E9 */ 0x02DB,
/* EA */ NODE(VXOpcodeTreeNodeType::MODE, 0x002B),
/* EB */ 0x02DE,
/* EB */ 0x02DD,
/* EC */ 0x02A7,
/* ED */ 0x02A8,
/* EE */ 0x039B,
@ -3224,8 +3224,8 @@ static const VXOpcodeTreeNode optreeModrmReg[][8] =
/* 01 */ 0x00A5,
/* 02 */ NODE(VXOpcodeTreeNodeType::MODE, 0x002C),
/* 03 */ 0x004C,
/* 04 */ 0x02DC,
/* 05 */ 0x02DB,
/* 04 */ 0x02D9,
/* 05 */ 0x02DA,
/* 06 */ 0x04B8,
/* 07 */ INVALID,
},
@ -4535,12 +4535,6 @@ static const VXOpcodeTreeNode optreeMandatory[][4] =
/* 02 */ INVALID,
/* 03 */ INVALID,
},
{
/* 00 */ 0x02CB,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
},
{
/* 00 */ 0x02C9,
/* 01 */ INVALID,
@ -4548,7 +4542,13 @@ static const VXOpcodeTreeNode optreeMandatory[][4] =
/* 03 */ INVALID,
},
{
/* 00 */ 0x02D1,
/* 00 */ 0x02DF,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
},
{
/* 00 */ 0x02CF,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
@ -4560,13 +4560,13 @@ static const VXOpcodeTreeNode optreeMandatory[][4] =
/* 03 */ INVALID,
},
{
/* 00 */ 0x02CE,
/* 00 */ 0x02CC,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
},
{
/* 00 */ 0x02C7,
/* 00 */ 0x02C8,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
@ -4595,12 +4595,6 @@ static const VXOpcodeTreeNode optreeMandatory[][4] =
/* 02 */ INVALID,
/* 03 */ INVALID,
},
{
/* 00 */ 0x02D8,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
},
{
/* 00 */ 0x02D6,
/* 01 */ INVALID,
@ -4608,13 +4602,19 @@ static const VXOpcodeTreeNode optreeMandatory[][4] =
/* 03 */ INVALID,
},
{
/* 00 */ 0x02D9,
/* 00 */ 0x02D4,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
},
{
/* 00 */ 0x02D4,
/* 00 */ 0x02D7,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
},
{
/* 00 */ 0x02D2,
/* 01 */ INVALID,
/* 02 */ INVALID,
/* 03 */ INVALID,
@ -5828,8 +5828,8 @@ static const VXOpcodeTreeNode optreeX87[][64] =
static const VXOpcodeTreeNode optreeAddressSize[][3] =
{
{
/* 00 */ 0x02CF,
/* 01 */ 0x02D2,
/* 00 */ 0x02CD,
/* 01 */ 0x02D0,
/* 02 */ 0x02EC,
},
};
@ -6133,7 +6133,7 @@ static const VXOpcodeTreeNode optreeMode[][2] =
/* 01 */ INVALID,
},
{
/* 00 */ 0x02DF,
/* 00 */ 0x02DC,
/* 01 */ INVALID,
},
{
@ -6214,11 +6214,11 @@ static const VXOpcodeTreeNode optreeVendor[][2] =
},
{
/* 00 */ INVALID,
/* 01 */ 0x02C2,
/* 01 */ 0x02C3,
},
{
/* 00 */ INVALID,
/* 01 */ 0x02C3,
/* 01 */ 0x02C2,
},
{
/* 00 */ INVALID,
@ -7573,36 +7573,36 @@ static const VXInstructionDefinition instrDefinitions[] =
/* 2BF */ { VXInstructionMnemonic::INVEPT, { OPI_Gq, OPI_Mo, OPI_NONE, OPI_NONE }, 0 },
/* 2C0 */ { VXInstructionMnemonic::INVLPG, { OPI_M, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX | IDF_ACCEPTS_REXR | IDF_ACCEPTS_REXX | IDF_ACCEPTS_REXB },
/* 2C1 */ { VXInstructionMnemonic::INVLPGA, { OPI_NONE, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2C2 */ { VXInstructionMnemonic::INVVPID, { OPI_Gd, OPI_Mo, OPI_NONE, OPI_NONE }, 0 },
/* 2C3 */ { VXInstructionMnemonic::INVVPID, { OPI_Gq, OPI_Mo, OPI_NONE, OPI_NONE }, 0 },
/* 2C2 */ { VXInstructionMnemonic::INVVPID, { OPI_Gq, OPI_Mo, OPI_NONE, OPI_NONE }, 0 },
/* 2C3 */ { VXInstructionMnemonic::INVVPID, { OPI_Gd, OPI_Mo, OPI_NONE, OPI_NONE }, 0 },
/* 2C4 */ { VXInstructionMnemonic::IRETD, { OPI_NONE, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW },
/* 2C5 */ { VXInstructionMnemonic::IRETQ, { OPI_NONE, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW },
/* 2C6 */ { VXInstructionMnemonic::IRETW, { OPI_NONE, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW },
/* 2C7 */ { VXInstructionMnemonic::JA, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2C8 */ { VXInstructionMnemonic::JA, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2C9 */ { VXInstructionMnemonic::JAE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2CA */ { VXInstructionMnemonic::JAE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2CB */ { VXInstructionMnemonic::JB, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2CC */ { VXInstructionMnemonic::JB, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2CD */ { VXInstructionMnemonic::JBE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2CE */ { VXInstructionMnemonic::JBE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2CF */ { VXInstructionMnemonic::JCXZ, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX },
/* 2D0 */ { VXInstructionMnemonic::JE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2D1 */ { VXInstructionMnemonic::JE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D2 */ { VXInstructionMnemonic::JECXZ, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX },
/* 2D3 */ { VXInstructionMnemonic::JG, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2D4 */ { VXInstructionMnemonic::JG, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D5 */ { VXInstructionMnemonic::JGE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2D6 */ { VXInstructionMnemonic::JGE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D7 */ { VXInstructionMnemonic::JL, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2D8 */ { VXInstructionMnemonic::JL, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D9 */ { VXInstructionMnemonic::JLE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2DA */ { VXInstructionMnemonic::JLE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2DB */ { VXInstructionMnemonic::JMP, { OPI_Fv, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX | IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW | IDF_ACCEPTS_REXR | IDF_ACCEPTS_REXX | IDF_ACCEPTS_REXB },
/* 2DC */ { VXInstructionMnemonic::JMP, { OPI_Ev, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX | IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW | IDF_ACCEPTS_REXR | IDF_ACCEPTS_REXX | IDF_ACCEPTS_REXB | IDF_DEFAULT_64 },
/* 2DD */ { VXInstructionMnemonic::JMP, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW | IDF_DEFAULT_64 },
/* 2DE */ { VXInstructionMnemonic::JMP, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_DEFAULT_64 },
/* 2DF */ { VXInstructionMnemonic::JMP, { OPI_Av, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX },
/* 2C7 */ { VXInstructionMnemonic::JA, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2C8 */ { VXInstructionMnemonic::JA, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2C9 */ { VXInstructionMnemonic::JB, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2CA */ { VXInstructionMnemonic::JB, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2CB */ { VXInstructionMnemonic::JBE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2CC */ { VXInstructionMnemonic::JBE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2CD */ { VXInstructionMnemonic::JCXZ, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX },
/* 2CE */ { VXInstructionMnemonic::JE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2CF */ { VXInstructionMnemonic::JE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D0 */ { VXInstructionMnemonic::JECXZ, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX },
/* 2D1 */ { VXInstructionMnemonic::JG, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2D2 */ { VXInstructionMnemonic::JG, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D3 */ { VXInstructionMnemonic::JGE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2D4 */ { VXInstructionMnemonic::JGE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D5 */ { VXInstructionMnemonic::JL, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2D6 */ { VXInstructionMnemonic::JL, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D7 */ { VXInstructionMnemonic::JLE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2D8 */ { VXInstructionMnemonic::JLE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2D9 */ { VXInstructionMnemonic::JMP, { OPI_Ev, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX | IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW | IDF_ACCEPTS_REXR | IDF_ACCEPTS_REXX | IDF_ACCEPTS_REXB | IDF_DEFAULT_64 },
/* 2DA */ { VXInstructionMnemonic::JMP, { OPI_Fv, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_ADDRESS_SIZE_PREFIX | IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW | IDF_ACCEPTS_REXR | IDF_ACCEPTS_REXX | IDF_ACCEPTS_REXB },
/* 2DB */ { VXInstructionMnemonic::JMP, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_ACCEPTS_REXW | IDF_DEFAULT_64 },
/* 2DC */ { VXInstructionMnemonic::JMP, { OPI_Av, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX },
/* 2DD */ { VXInstructionMnemonic::JMP, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_DEFAULT_64 },
/* 2DE */ { VXInstructionMnemonic::JNB, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2DF */ { VXInstructionMnemonic::JNB, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2E0 */ { VXInstructionMnemonic::JNE, { OPI_Jz, OPI_NONE, OPI_NONE, OPI_NONE }, IDF_ACCEPTS_OPERAND_SIZE_PREFIX | IDF_DEFAULT_64 },
/* 2E1 */ { VXInstructionMnemonic::JNE, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
/* 2E2 */ { VXInstructionMnemonic::JNO, { OPI_Jb, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
@ -8992,17 +8992,17 @@ const char* instrMnemonicStrings[] =
/* 0F3 */ "iretq",
/* 0F4 */ "iretw",
/* 0F5 */ "ja",
/* 0F6 */ "jae",
/* 0F7 */ "jb",
/* 0F8 */ "jbe",
/* 0F9 */ "jcxz",
/* 0FA */ "je",
/* 0FB */ "jecxz",
/* 0FC */ "jg",
/* 0FD */ "jge",
/* 0FE */ "jl",
/* 0FF */ "jle",
/* 100 */ "jmp",
/* 0F6 */ "jb",
/* 0F7 */ "jbe",
/* 0F8 */ "jcxz",
/* 0F9 */ "je",
/* 0FA */ "jecxz",
/* 0FB */ "jg",
/* 0FC */ "jge",
/* 0FD */ "jl",
/* 0FE */ "jle",
/* 0FF */ "jmp",
/* 100 */ "jnb",
/* 101 */ "jne",
/* 102 */ "jno",
/* 103 */ "jnp",

View File

@ -291,17 +291,17 @@ enum class VXInstructionMnemonic : uint16_t
/* 0F3 */ IRETQ,
/* 0F4 */ IRETW,
/* 0F5 */ JA,
/* 0F6 */ JAE,
/* 0F7 */ JB,
/* 0F8 */ JBE,
/* 0F9 */ JCXZ,
/* 0FA */ JE,
/* 0FB */ JECXZ,
/* 0FC */ JG,
/* 0FD */ JGE,
/* 0FE */ JL,
/* 0FF */ JLE,
/* 100 */ JMP,
/* 0F6 */ JB,
/* 0F7 */ JBE,
/* 0F8 */ JCXZ,
/* 0F9 */ JE,
/* 0FA */ JECXZ,
/* 0FB */ JG,
/* 0FC */ JGE,
/* 0FD */ JL,
/* 0FE */ JLE,
/* 0FF */ JMP,
/* 100 */ JNB,
/* 101 */ JNE,
/* 102 */ JNO,
/* 103 */ JNP,
@ -1608,7 +1608,7 @@ extern const char* instrMnemonicStrings[];
* @param node The node.
* @return The type of the specified opcode tree node.
*/
inline VXOpcodeTreeNodeType GetOpcodeNodeType(VXOpcodeTreeNode node)
inline VXOpcodeTreeNodeType VDEGetOpcodeNodeType(VXOpcodeTreeNode node)
{
return static_cast<VXOpcodeTreeNodeType>((node >> 12) & 0x0F);
}
@ -1618,7 +1618,7 @@ inline VXOpcodeTreeNodeType GetOpcodeNodeType(VXOpcodeTreeNode node)
* @param node The node.
* @return The value of the specified opcode tree node.
*/
inline uint16_t GetOpcodeNodeValue(VXOpcodeTreeNode node)
inline uint16_t VDEGetOpcodeNodeValue(VXOpcodeTreeNode node)
{
return (node & 0x0FFF);
}
@ -1627,7 +1627,7 @@ inline uint16_t GetOpcodeNodeValue(VXOpcodeTreeNode node)
* @brief Returns the root node of the opcode tree.
* @return The root node of the opcode tree.
*/
inline VXOpcodeTreeNode GetOpcodeTreeRoot()
inline VXOpcodeTreeNode VDEGetOpcodeTreeRoot()
{
return 0x1000;
}
@ -1638,11 +1638,11 @@ inline VXOpcodeTreeNode GetOpcodeTreeRoot()
* @param index The index of the child node to retrieve.
* @return The specified child node.
*/
inline VXOpcodeTreeNode GetOpcodeTreeChild(VXOpcodeTreeNode parent, uint16_t index)
inline VXOpcodeTreeNode VDEGetOpcodeTreeChild(VXOpcodeTreeNode parent, uint16_t index)
{
using namespace Internal;
VXOpcodeTreeNodeType nodeType = GetOpcodeNodeType(parent);
uint16_t tableIndex = GetOpcodeNodeValue(parent);
VXOpcodeTreeNodeType nodeType = VDEGetOpcodeNodeType(parent);
uint16_t tableIndex = VDEGetOpcodeNodeValue(parent);
switch (nodeType)
{
case VXOpcodeTreeNodeType::TABLE:
@ -1698,9 +1698,9 @@ inline VXOpcodeTreeNode GetOpcodeTreeChild(VXOpcodeTreeNode parent, uint16_t ind
* @param node The instruction definition node.
* @return Pointer to the instruction definition.
*/
inline const VXInstructionDefinition* GetInstructionDefinition(VXOpcodeTreeNode node)
inline const VXInstructionDefinition* VDEGetInstructionDefinition(VXOpcodeTreeNode node)
{
assert(GetOpcodeNodeType(node) == VXOpcodeTreeNodeType::INSTRUCTION_DEFINITION);
assert(VDEGetOpcodeNodeType(node) == VXOpcodeTreeNodeType::INSTRUCTION_DEFINITION);
return &instrDefinitions[node & 0x0FFF];
}
@ -1709,7 +1709,7 @@ inline const VXInstructionDefinition* GetInstructionDefinition(VXOpcodeTreeNode
* @param mnemonic The mnemonic.
* @return The instruction mnemonic string.
*/
inline const char* GetInstructionMnemonicString(VXInstructionMnemonic mnemonic)
inline const char* VDEGetInstructionMnemonicString(VXInstructionMnemonic mnemonic)
{
return instrMnemonicStrings[static_cast<uint16_t>(mnemonic)];
}
@ -1719,7 +1719,7 @@ inline const char* GetInstructionMnemonicString(VXInstructionMnemonic mnemonic)
* @param operandSize The defined operand size.
* @return The the numeric value for the simple operand size definition.
*/
inline uint16_t GetSimpleOperandSize(VXDefinedOperandSize operandSize)
inline uint16_t VDEGetSimpleOperandSize(VXDefinedOperandSize operandSize)
{
static uint16_t operandSizes[8] =
{
@ -1736,7 +1736,7 @@ inline uint16_t GetSimpleOperandSize(VXDefinedOperandSize operandSize)
* @param operandSize The defined operand size.
* @return The memory-size part of the operand size definition.
*/
inline VXDefinedOperandSize GetComplexOperandMemSize(VXDefinedOperandSize operandSize)
inline VXDefinedOperandSize VDEGetComplexOperandMemSize(VXDefinedOperandSize operandSize)
{
return static_cast<VXDefinedOperandSize>(static_cast<uint8_t>(operandSize) & 0x0F);
}
@ -1746,7 +1746,7 @@ inline VXDefinedOperandSize GetComplexOperandMemSize(VXDefinedOperandSize operan
* @param operandSize The defined operand size.
* @return The register-size part of the operand size definition.
*/
inline VXDefinedOperandSize GetComplexOperandRegSize(VXDefinedOperandSize operandSize)
inline VXDefinedOperandSize VDEGetComplexOperandRegSize(VXDefinedOperandSize operandSize)
{
return static_cast<VXDefinedOperandSize>((static_cast<uint8_t>(operandSize) >> 4) & 0x0F);
}

View File

@ -20,6 +20,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="VXDisassembler.h" />
<ClInclude Include="VXDisassemblerUtils.h" />
<ClInclude Include="VXDisassemblerTypes.h" />
<ClInclude Include="VXInstructionDecoder.h" />
<ClInclude Include="VXInstructionFormatter.h" />
@ -27,6 +28,7 @@
<ClInclude Include="VXSymbolResolver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="VXDisassemblerUtils.cpp" />
<ClCompile Include="VXInstructionDecoder.cpp" />
<ClCompile Include="VXInstructionFormatter.cpp" />
<ClCompile Include="VXOpcodeTable.cpp" />

View File

@ -7,11 +7,13 @@
<ClInclude Include="VXInstructionFormatter.h" />
<ClInclude Include="VXOpcodeTable.h" />
<ClInclude Include="VXSymbolResolver.h" />
<ClInclude Include="VXDisassemblerUtils.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="VXInstructionDecoder.cpp" />
<ClCompile Include="VXInstructionFormatter.cpp" />
<ClCompile Include="VXOpcodeTable.cpp" />
<ClCompile Include="VXSymbolResolver.cpp" />
<ClCompile Include="VXDisassemblerUtils.cpp" />
</ItemGroup>
</Project>