From 2933d1683bdaae7ab55e4340c9a12b3e03b85d1b Mon Sep 17 00:00:00 2001 From: flobernd Date: Thu, 30 Oct 2014 16:36:25 +0100 Subject: [PATCH] Improved the intel instruction formatter Some minor bugfixes --- Examples/PerformanceTest/Main.cpp | 5 +- VerteronDisassemblerEngine/VXDisassembler.h | 2 + .../VXDisassemblerUtils.cpp | 78 ++++ .../VXDisassemblerUtils.h | 53 +++ .../VXInstructionDecoder.cpp | 74 ++-- .../VXInstructionFormatter.cpp | 351 ++++++++++++------ .../VXInstructionFormatter.h | 48 ++- VerteronDisassemblerEngine/VXOpcodeTable.cpp | 146 ++++---- VerteronDisassemblerEngine/VXOpcodeTable.h | 46 +-- .../VerteronDisassemblerEngine.vcxproj | 2 + ...VerteronDisassemblerEngine.vcxproj.filters | 2 + 11 files changed, 561 insertions(+), 246 deletions(-) create mode 100644 VerteronDisassemblerEngine/VXDisassemblerUtils.cpp create mode 100644 VerteronDisassemblerEngine/VXDisassemblerUtils.h diff --git a/Examples/PerformanceTest/Main.cpp b/Examples/PerformanceTest/Main.cpp index bb1f9e6..648b182 100644 --- a/Examples/PerformanceTest/Main.cpp +++ b/Examples/PerformanceTest/Main.cpp @@ -48,7 +48,7 @@ void testDecodingAndFormatting(uintptr_t baseAddress, PIMAGE_NT_HEADERS ntHeader reinterpret_cast( reinterpret_cast(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; } diff --git a/VerteronDisassemblerEngine/VXDisassembler.h b/VerteronDisassemblerEngine/VXDisassembler.h index 76dc526..7720a6c 100644 --- a/VerteronDisassemblerEngine/VXDisassembler.h +++ b/VerteronDisassemblerEngine/VXDisassembler.h @@ -31,6 +31,8 @@ **************************************************************************************************/ #pragma once +#include "VXDisassemblerTypes.h" #include "VXInstructionDecoder.h" #include "VXInstructionFormatter.h" #include "VXSymbolResolver.h" +#include "VXDisassemblerUtils.h" diff --git a/VerteronDisassemblerEngine/VXDisassemblerUtils.cpp b/VerteronDisassemblerEngine/VXDisassemblerUtils.cpp new file mode 100644 index 0000000..31ee21b --- /dev/null +++ b/VerteronDisassemblerEngine/VXDisassemblerUtils.cpp @@ -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; +} + +} + +} diff --git a/VerteronDisassemblerEngine/VXDisassemblerUtils.h b/VerteronDisassemblerEngine/VXDisassemblerUtils.h new file mode 100644 index 0000000..b2c788d --- /dev/null +++ b/VerteronDisassemblerEngine/VXDisassemblerUtils.h @@ -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 +#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); + +} + +} diff --git a/VerteronDisassemblerEngine/VXInstructionDecoder.cpp b/VerteronDisassemblerEngine/VXInstructionDecoder.cpp index 16c3552..c950f39 100644 --- a/VerteronDisassemblerEngine/VXInstructionDecoder.cpp +++ b/VerteronDisassemblerEngine/VXInstructionDecoder.cpp @@ -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) diff --git a/VerteronDisassemblerEngine/VXInstructionFormatter.cpp b/VerteronDisassemblerEngine/VXInstructionFormatter.cpp index aca7cc8..1fdf80c 100644 --- a/VerteronDisassemblerEngine/VXInstructionFormatter.cpp +++ b/VerteronDisassemblerEngine/VXInstructionFormatter.cpp @@ -30,7 +30,9 @@ **************************************************************************************************/ #include "VXInstructionFormatter.h" +#include "VXDisassemblerUtils.h" #include +#include 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(operand.lval.sbyte); + } else + { + assert(operand.size == 32); + value = static_cast(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 diff --git a/VerteronDisassemblerEngine/VXInstructionFormatter.h b/VerteronDisassemblerEngine/VXInstructionFormatter.h index 14e8eed..149d419 100644 --- a/VerteronDisassemblerEngine/VXInstructionFormatter.h +++ b/VerteronDisassemblerEngine/VXInstructionFormatter.h @@ -50,6 +50,7 @@ private: static const char *m_registerStrings[]; VXBaseSymbolResolver *m_symbolResolver; std::vector 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. diff --git a/VerteronDisassemblerEngine/VXOpcodeTable.cpp b/VerteronDisassemblerEngine/VXOpcodeTable.cpp index d8ee13f..9ad8ebc 100644 --- a/VerteronDisassemblerEngine/VXOpcodeTable.cpp +++ b/VerteronDisassemblerEngine/VXOpcodeTable.cpp @@ -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", diff --git a/VerteronDisassemblerEngine/VXOpcodeTable.h b/VerteronDisassemblerEngine/VXOpcodeTable.h index 38137b3..ea95715 100644 --- a/VerteronDisassemblerEngine/VXOpcodeTable.h +++ b/VerteronDisassemblerEngine/VXOpcodeTable.h @@ -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((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(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(static_cast(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((static_cast(operandSize) >> 4) & 0x0F); } diff --git a/VerteronDisassemblerEngine/VerteronDisassemblerEngine.vcxproj b/VerteronDisassemblerEngine/VerteronDisassemblerEngine.vcxproj index b8545bc..6af81a9 100644 --- a/VerteronDisassemblerEngine/VerteronDisassemblerEngine.vcxproj +++ b/VerteronDisassemblerEngine/VerteronDisassemblerEngine.vcxproj @@ -20,6 +20,7 @@ + @@ -27,6 +28,7 @@ + diff --git a/VerteronDisassemblerEngine/VerteronDisassemblerEngine.vcxproj.filters b/VerteronDisassemblerEngine/VerteronDisassemblerEngine.vcxproj.filters index 1d64032..57ea373 100644 --- a/VerteronDisassemblerEngine/VerteronDisassemblerEngine.vcxproj.filters +++ b/VerteronDisassemblerEngine/VerteronDisassemblerEngine.vcxproj.filters @@ -7,11 +7,13 @@ + + \ No newline at end of file