mirror of https://github.com/x64dbg/zydis
commit
634f927df7
|
@ -30,91 +30,9 @@
|
||||||
|
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include "VXDisassembler.h"
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
using namespace Verteron;
|
|
||||||
using namespace Disassembler;
|
|
||||||
|
|
||||||
void testDecodingAndFormatting(uintptr_t baseAddress, PIMAGE_NT_HEADERS ntHeaders)
|
|
||||||
{
|
|
||||||
VXInstructionInfo info;
|
|
||||||
VXInstructionDecoder decoder;
|
|
||||||
VXIntelInstructionFormatter formatter;
|
|
||||||
decoder.setDisassemblerMode(VXDisassemblerMode::M64BIT);
|
|
||||||
PIMAGE_SECTION_HEADER sectionHeader =
|
|
||||||
reinterpret_cast<PIMAGE_SECTION_HEADER>(
|
|
||||||
reinterpret_cast<uintptr_t>(ntHeaders) + sizeof(IMAGE_NT_HEADERS)
|
|
||||||
+ ntHeaders->FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER));
|
|
||||||
// Decode and format all code sections
|
|
||||||
for (unsigned int i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
|
|
||||||
{
|
|
||||||
if (sectionHeader->Characteristics & IMAGE_SCN_CNT_CODE)
|
|
||||||
{
|
|
||||||
std::cout << sectionHeader->SizeOfRawData / 1024 << " KiB" << std::endl;
|
|
||||||
VXMemoryDataSource input(reinterpret_cast<const void*>(
|
|
||||||
baseAddress + sectionHeader->VirtualAddress), sectionHeader->SizeOfRawData);
|
|
||||||
decoder.setDataSource(&input);
|
|
||||||
decoder.setInstructionPointer(baseAddress + sectionHeader->VirtualAddress);
|
|
||||||
while (decoder.decodeInstruction(info))
|
|
||||||
{
|
|
||||||
formatter.formatInstruction(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sectionHeader++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int _tmain(int argc, _TCHAR* argv[])
|
int _tmain(int argc, _TCHAR* argv[])
|
||||||
{
|
{
|
||||||
|
// TODO:
|
||||||
// Find kernel32.dll in memory
|
|
||||||
void *ntdllBase = GetModuleHandle(L"kernel32.dll");
|
|
||||||
PIMAGE_DOS_HEADER dosHeader = static_cast<PIMAGE_DOS_HEADER>(ntdllBase);
|
|
||||||
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
|
||||||
{
|
|
||||||
std::cout << "Error: kernel32.dll is corrupted.";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
PIMAGE_NT_HEADERS ntHeaders =
|
|
||||||
reinterpret_cast<PIMAGE_NT_HEADERS>(
|
|
||||||
reinterpret_cast<uintptr_t>(dosHeader) + dosHeader->e_lfanew);
|
|
||||||
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
{
|
|
||||||
std::cout << "Error: kernel32.dll is corrupted.";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
double pcFrequency = 0.0;
|
|
||||||
uint64_t pcStart = 0;
|
|
||||||
LARGE_INTEGER li;
|
|
||||||
|
|
||||||
// Start the performance counter
|
|
||||||
if (!QueryPerformanceFrequency(&li))
|
|
||||||
{
|
|
||||||
std::cout << "Error: QueryPerformanceFrequency failed.";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
pcFrequency = static_cast<double>(li.QuadPart) / 1000.0;
|
|
||||||
if (!QueryPerformanceCounter(&li))
|
|
||||||
{
|
|
||||||
std::cout << "Error: QueryPerformanceCounter failed.";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
pcStart = li.QuadPart;
|
|
||||||
// Perform decoding test
|
|
||||||
testDecodingAndFormatting(reinterpret_cast<uintptr_t>(ntdllBase), ntHeaders);
|
|
||||||
// Stop the performance counter
|
|
||||||
if (!QueryPerformanceCounter(&li))
|
|
||||||
{
|
|
||||||
std::cout << "Error: QueryPerformanceCounter failed.";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
std::cout << "Time: " << static_cast<double>(li.QuadPart - pcStart) / pcFrequency
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
std::cin.get();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
#include "VXDisassembler.h"
|
#include "VXDisassembler.h"
|
||||||
|
|
||||||
using namespace Verteron;
|
using namespace Verteron;
|
||||||
using namespace Disassembler;
|
|
||||||
|
|
||||||
int _tmain(int argc, _TCHAR* argv[])
|
int _tmain(int argc, _TCHAR* argv[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,9 +30,163 @@
|
||||||
|
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <string>
|
||||||
|
#include "VXDisassembler.h"
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
using namespace Verteron;
|
||||||
|
|
||||||
int _tmain(int argc, _TCHAR* argv[])
|
int _tmain(int argc, _TCHAR* argv[])
|
||||||
{
|
{
|
||||||
// TODO:
|
// Find module base in memory
|
||||||
|
void *moduleBase = GetModuleHandle(L"kernel32.dll");
|
||||||
|
uintptr_t baseAddress = reinterpret_cast<uintptr_t>(moduleBase);
|
||||||
|
// Parse PE headers
|
||||||
|
PIMAGE_DOS_HEADER dosHeader = static_cast<PIMAGE_DOS_HEADER>(moduleBase);
|
||||||
|
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
PIMAGE_NT_HEADERS ntHeaders =
|
||||||
|
reinterpret_cast<PIMAGE_NT_HEADERS>(baseAddress + dosHeader->e_lfanew);
|
||||||
|
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Initialize disassembler
|
||||||
|
VXInstructionInfo info;
|
||||||
|
VXInstructionDecoder decoder;
|
||||||
|
VXExactSymbolResolver resolver;
|
||||||
|
VXIntelInstructionFormatter formatter;
|
||||||
|
#ifdef _M_X64
|
||||||
|
decoder.setDisassemblerMode(VXDisassemblerMode::M64BIT);
|
||||||
|
#else
|
||||||
|
decoder.setDisassemblerMode(VXDisassemblerMode::M32BIT);
|
||||||
|
#endif
|
||||||
|
formatter.setSymbolResolver(&resolver);
|
||||||
|
// Initialize output stream
|
||||||
|
std::ofstream out;
|
||||||
|
out.open(".\\output.txt");
|
||||||
|
// Find all call and jump targets
|
||||||
|
uint64_t subCount = 0;
|
||||||
|
uint64_t locCount = 0;
|
||||||
|
PIMAGE_SECTION_HEADER sectionHeader =
|
||||||
|
reinterpret_cast<PIMAGE_SECTION_HEADER>(
|
||||||
|
reinterpret_cast<uintptr_t>(ntHeaders) + sizeof(IMAGE_NT_HEADERS)
|
||||||
|
+ ntHeaders->FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER));
|
||||||
|
for (unsigned int i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
|
||||||
|
{
|
||||||
|
if (sectionHeader->Characteristics & IMAGE_SCN_CNT_CODE)
|
||||||
|
{
|
||||||
|
VXMemoryDataSource input(reinterpret_cast<const void*>(
|
||||||
|
baseAddress + sectionHeader->VirtualAddress), sectionHeader->SizeOfRawData);
|
||||||
|
decoder.setDataSource(&input);
|
||||||
|
decoder.setInstructionPointer(baseAddress + sectionHeader->VirtualAddress);
|
||||||
|
while (decoder.decodeInstruction(info))
|
||||||
|
{
|
||||||
|
// Skip invalid and non-relative instructions
|
||||||
|
if ((info.flags & IF_ERROR_MASK) || !(info.flags & IF_RELATIVE))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (info.mnemonic)
|
||||||
|
{
|
||||||
|
case VXInstructionMnemonic::CALL:
|
||||||
|
resolver.setSymbol(VDECalcAbsoluteTarget(info, info.operand[0]),
|
||||||
|
std::string("sub_" + std::to_string(subCount)).c_str());
|
||||||
|
subCount++;
|
||||||
|
break;
|
||||||
|
case VXInstructionMnemonic::JMP:
|
||||||
|
case VXInstructionMnemonic::JO:
|
||||||
|
case VXInstructionMnemonic::JNO:
|
||||||
|
case VXInstructionMnemonic::JB:
|
||||||
|
case VXInstructionMnemonic::JNB:
|
||||||
|
case VXInstructionMnemonic::JE:
|
||||||
|
case VXInstructionMnemonic::JNE:
|
||||||
|
case VXInstructionMnemonic::JBE:
|
||||||
|
case VXInstructionMnemonic::JA:
|
||||||
|
case VXInstructionMnemonic::JS:
|
||||||
|
case VXInstructionMnemonic::JNS:
|
||||||
|
case VXInstructionMnemonic::JP:
|
||||||
|
case VXInstructionMnemonic::JNP:
|
||||||
|
case VXInstructionMnemonic::JL:
|
||||||
|
case VXInstructionMnemonic::JGE:
|
||||||
|
case VXInstructionMnemonic::JLE:
|
||||||
|
case VXInstructionMnemonic::JG:
|
||||||
|
case VXInstructionMnemonic::JCXZ:
|
||||||
|
case VXInstructionMnemonic::JECXZ:
|
||||||
|
case VXInstructionMnemonic::JRCXZ:
|
||||||
|
resolver.setSymbol(VDECalcAbsoluteTarget(info, info.operand[0]),
|
||||||
|
std::string("loc_" + std::to_string(locCount)).c_str());
|
||||||
|
locCount++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sectionHeader++;
|
||||||
|
}
|
||||||
|
// Add entry point symbol
|
||||||
|
resolver.setSymbol(baseAddress + ntHeaders->OptionalHeader.AddressOfEntryPoint, "EntryPoint");
|
||||||
|
// Add exported symbols
|
||||||
|
if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress > 0)
|
||||||
|
{
|
||||||
|
PIMAGE_EXPORT_DIRECTORY exports =
|
||||||
|
reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(reinterpret_cast<LPBYTE>(baseAddress) +
|
||||||
|
ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||||
|
PDWORD address =
|
||||||
|
reinterpret_cast<PDWORD>(reinterpret_cast<LPBYTE>(baseAddress) +
|
||||||
|
exports->AddressOfFunctions);
|
||||||
|
PDWORD name =
|
||||||
|
reinterpret_cast<PDWORD>(reinterpret_cast<LPBYTE>(baseAddress) +
|
||||||
|
exports->AddressOfNames);
|
||||||
|
PWORD ordinal =
|
||||||
|
reinterpret_cast<PWORD>(reinterpret_cast<LPBYTE>(baseAddress) +
|
||||||
|
exports->AddressOfNameOrdinals);
|
||||||
|
for(unsigned int i = 0; i < exports->NumberOfNames; ++i)
|
||||||
|
{
|
||||||
|
resolver.setSymbol(baseAddress + address[ordinal[i]],
|
||||||
|
reinterpret_cast<char*>(baseAddress) + name[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Disassemble
|
||||||
|
sectionHeader =
|
||||||
|
reinterpret_cast<PIMAGE_SECTION_HEADER>(
|
||||||
|
reinterpret_cast<uintptr_t>(ntHeaders) + sizeof(IMAGE_NT_HEADERS)
|
||||||
|
+ ntHeaders->FileHeader.SizeOfOptionalHeader - sizeof(IMAGE_OPTIONAL_HEADER));
|
||||||
|
for (unsigned int i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
|
||||||
|
{
|
||||||
|
if (sectionHeader->Characteristics & IMAGE_SCN_CNT_CODE)
|
||||||
|
{
|
||||||
|
VXMemoryDataSource input(reinterpret_cast<const void*>(
|
||||||
|
baseAddress + sectionHeader->VirtualAddress), sectionHeader->SizeOfRawData);
|
||||||
|
decoder.setDataSource(&input);
|
||||||
|
decoder.setInstructionPointer(baseAddress + sectionHeader->VirtualAddress);
|
||||||
|
while (decoder.decodeInstruction(info))
|
||||||
|
{
|
||||||
|
uint64_t offset;
|
||||||
|
const char *symbol = resolver.resolveSymbol(info, info.instrAddress, offset);
|
||||||
|
if (symbol)
|
||||||
|
{
|
||||||
|
out << symbol << ": " << std::endl;
|
||||||
|
}
|
||||||
|
out << " " << std::hex << std::setw(16) << std::setfill('0')
|
||||||
|
<< info.instrAddress << " ";
|
||||||
|
if (info.flags & IF_ERROR_MASK)
|
||||||
|
{
|
||||||
|
out << "db " << std::hex << std::setw(2) << std::setfill('0')
|
||||||
|
<< static_cast<int>(info.data[0]) << std::endl;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
out << formatter.formatInstruction(info) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sectionHeader++;
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
36
README.md
36
README.md
|
@ -11,13 +11,43 @@ Fast and lightweight x86/x86-64 disassembler library.
|
||||||
- SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES,
|
- SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES,
|
||||||
- AMD-V, INTEL-VMX, SMX
|
- AMD-V, INTEL-VMX, SMX
|
||||||
- Optimized for high performance
|
- Optimized for high performance
|
||||||
- Decoding and formatting of 50MiB takes about 1 second on a Intel Core i7 3930k @ 3.2GHz CPU
|
- Very small overhead compared to other common disassembler libraries (about 60KiB)
|
||||||
- Very small overhead compared to other common disassembler libraries
|
|
||||||
- Only 44.00 KiB (64 bit: 47.00 KiB) for the decoder and 62.00 KiB (64 bit: 69.50 KiB) with the optional formatting functionality
|
|
||||||
- Abstract formatter and symbol-resolver classes for custom syntax implementations.
|
- Abstract formatter and symbol-resolver classes for custom syntax implementations.
|
||||||
- Intel syntax is implemented by default
|
- Intel syntax is implemented by default
|
||||||
- Complete doxygen documentation
|
- Complete doxygen documentation
|
||||||
|
|
||||||
|
## Quick Example ##
|
||||||
|
|
||||||
|
The following example program uses VDE to disassemble a given memory buffer and prints the output to the console.
|
||||||
|
|
||||||
|
```C++
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "VXDisassembler.h"
|
||||||
|
|
||||||
|
using namespace Verteron;
|
||||||
|
|
||||||
|
int _tmain(int argc, _TCHAR* argv[])
|
||||||
|
{
|
||||||
|
uint8_t data[] =
|
||||||
|
{
|
||||||
|
0x90, 0xE9, 0x00, 0x00, 0x00, 0x00, 0xC3
|
||||||
|
};
|
||||||
|
VXMemoryDataSource input(&data[0], sizeof(data));
|
||||||
|
VXInstructionInfo info;
|
||||||
|
VXInstructionDecoder decoder;
|
||||||
|
decoder.setDisassemblerMode(VXDisassemblerMode::M32BIT);
|
||||||
|
decoder.setDataSource(&input);
|
||||||
|
decoder.setInstructionPointer(0);
|
||||||
|
VXIntelInstructionFormatter formatter;
|
||||||
|
while (decoder.decodeInstruction(info))
|
||||||
|
{
|
||||||
|
std::cout << formatter.formatInstruction(info) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Compilation ##
|
## Compilation ##
|
||||||
|
|
||||||
- While VDE supports other compilers in theory, compilation has not been tested with any compiler other than MSVC12 (Visual Studio 2013)
|
- While VDE supports other compilers in theory, compilation has not been tested with any compiler other than MSVC12 (Visual Studio 2013)
|
||||||
|
|
|
@ -34,5 +34,4 @@
|
||||||
#include "VXDisassemblerTypes.h"
|
#include "VXDisassemblerTypes.h"
|
||||||
#include "VXInstructionDecoder.h"
|
#include "VXInstructionDecoder.h"
|
||||||
#include "VXInstructionFormatter.h"
|
#include "VXInstructionFormatter.h"
|
||||||
#include "VXSymbolResolver.h"
|
|
||||||
#include "VXDisassemblerUtils.h"
|
#include "VXDisassemblerUtils.h"
|
||||||
|
|
|
@ -37,9 +37,6 @@
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Values that represent additional flags of a decoded instruction.
|
* @brief Values that represent additional flags of a decoded instruction.
|
||||||
*/
|
*/
|
||||||
|
@ -530,5 +527,3 @@ struct VXInstructionInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,13 +30,11 @@
|
||||||
|
|
||||||
**************************************************************************************************/
|
**************************************************************************************************/
|
||||||
#include "VXDisassemblerUtils.h"
|
#include "VXDisassemblerUtils.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
uint64_t VDECalcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInfo &operand)
|
uint64_t VDECalcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInfo &operand)
|
||||||
{
|
{
|
||||||
assert((operand.type == VXOperandType::REL_IMMEDIATE) ||
|
assert((operand.type == VXOperandType::REL_IMMEDIATE) ||
|
||||||
|
@ -74,5 +72,3 @@ uint64_t VDECalcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInf
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,9 +37,6 @@
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calculates the absolute target address of a relative instruction operand.
|
* @brief Calculates the absolute target address of a relative instruction operand.
|
||||||
* @param info The instruction info.
|
* @param info The instruction info.
|
||||||
|
@ -49,5 +46,3 @@ namespace Disassembler
|
||||||
uint64_t VDECalcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInfo &operand);
|
uint64_t VDECalcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInfo &operand);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -35,9 +35,6 @@
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
bool VXInstructionDecoder::decodeRegisterOperand(VXInstructionInfo &info, VXOperandInfo &operand,
|
bool VXInstructionDecoder::decodeRegisterOperand(VXInstructionInfo &info, VXOperandInfo &operand,
|
||||||
RegisterClass registerClass, uint8_t registerId, VXDefinedOperandSize operandSize) const
|
RegisterClass registerClass, uint8_t registerId, VXDefinedOperandSize operandSize) const
|
||||||
{
|
{
|
||||||
|
@ -1304,5 +1301,3 @@ DecodeError:
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -38,9 +38,6 @@
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,7 +192,7 @@ inline uint8_t VXBaseDataSource::inputCurrent() const
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implements a memory buffer based data source.
|
* @brief A memory-buffer based data source for the @c VXInstructionDecoder class.
|
||||||
*/
|
*/
|
||||||
class VXMemoryDataSource : public VXBaseDataSource
|
class VXMemoryDataSource : public VXBaseDataSource
|
||||||
{
|
{
|
||||||
|
@ -275,7 +272,7 @@ inline bool VXMemoryDataSource::setPosition(uint64_t position)
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implements a stream based data source.
|
* @brief A stream based data source for the @c VXInstructionDecoder class.
|
||||||
*/
|
*/
|
||||||
class VXStreamDataSource : public VXBaseDataSource
|
class VXStreamDataSource : public VXBaseDataSource
|
||||||
{
|
{
|
||||||
|
@ -719,5 +716,3 @@ inline void VXInstructionDecoder::setInstructionPointer(uint64_t instructionPoin
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,9 +37,21 @@
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
VXBaseSymbolResolver::~VXBaseSymbolResolver()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* VXBaseSymbolResolver::resolveSymbol(const VXInstructionInfo &info, uint64_t address,
|
||||||
|
uint64_t &offset)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const char* VXBaseInstructionFormatter::m_registerStrings[] =
|
const char* VXBaseInstructionFormatter::m_registerStrings[] =
|
||||||
{
|
{
|
||||||
/* 8 bit general purpose registers */
|
/* 8 bit general purpose registers */
|
||||||
|
@ -96,21 +108,23 @@ const char* VXBaseInstructionFormatter::m_registerStrings[] =
|
||||||
"rip"
|
"rip"
|
||||||
};
|
};
|
||||||
|
|
||||||
void VXBaseInstructionFormatter::internalFormatInstruction(VXInstructionInfo const& info)
|
void VXBaseInstructionFormatter::internalFormatInstruction(const VXInstructionInfo &info)
|
||||||
{
|
{
|
||||||
// Nothing to do here
|
// Nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
VXBaseInstructionFormatter::VXBaseInstructionFormatter()
|
VXBaseInstructionFormatter::VXBaseInstructionFormatter()
|
||||||
: m_symbolResolver(nullptr)
|
: m_symbolResolver(nullptr)
|
||||||
, m_uppercase(false)
|
, m_outputStringLen(0)
|
||||||
|
, m_outputUppercase(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VXBaseInstructionFormatter::VXBaseInstructionFormatter(VXBaseSymbolResolver *symbolResolver)
|
VXBaseInstructionFormatter::VXBaseInstructionFormatter(VXBaseSymbolResolver *symbolResolver)
|
||||||
: m_symbolResolver(symbolResolver)
|
: m_symbolResolver(symbolResolver)
|
||||||
, m_uppercase(false)
|
, m_outputStringLen(0)
|
||||||
|
, m_outputUppercase(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -137,7 +151,7 @@ VXBaseInstructionFormatter::~VXBaseInstructionFormatter()
|
||||||
|
|
||||||
void VXBaseInstructionFormatter::outputClear()
|
void VXBaseInstructionFormatter::outputClear()
|
||||||
{
|
{
|
||||||
m_outputBuffer.clear();
|
m_outputStringLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* VXBaseInstructionFormatter::outputString()
|
char const* VXBaseInstructionFormatter::outputString()
|
||||||
|
@ -145,65 +159,72 @@ char const* VXBaseInstructionFormatter::outputString()
|
||||||
return &m_outputBuffer[0];
|
return &m_outputBuffer[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void VXBaseInstructionFormatter::outputAppend(char const *text)
|
void VXBaseInstructionFormatter::outputAppend(char const *text)
|
||||||
{
|
{
|
||||||
// Get the string length including the null-terminator char
|
// Get the string length including the null-terminator char
|
||||||
size_t strLen = strlen(text) + 1;
|
size_t strLen = strlen(text) + 1;
|
||||||
// Get the buffer capacity and size
|
// Get the buffer size
|
||||||
size_t bufCap = m_outputBuffer.capacity();
|
|
||||||
size_t bufLen = m_outputBuffer.size();
|
size_t bufLen = m_outputBuffer.size();
|
||||||
// Decrease the offset by one, to exclude already existing null-terminator chars in the
|
// Decrease the offset by one, to exclude already existing null-terminator chars in the
|
||||||
// output buffer
|
// output buffer
|
||||||
size_t offset = (bufLen) ? bufLen - 1 : 0;
|
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
|
// Resize capacity of the output buffer on demand and add some extra space to improve the
|
||||||
// performance
|
// performance
|
||||||
if (bufCap <= (bufLen + strLen))
|
if (bufLen <= (m_outputStringLen + strLen))
|
||||||
{
|
{
|
||||||
m_outputBuffer.reserve(bufCap + strLen + 256);
|
m_outputBuffer.resize(bufLen + strLen + 512);
|
||||||
}
|
}
|
||||||
// Append the text
|
// Write the text to the output buffer
|
||||||
m_outputBuffer.resize(offset + strLen);
|
|
||||||
memcpy(&m_outputBuffer[offset], text, strLen);
|
memcpy(&m_outputBuffer[offset], text, strLen);
|
||||||
|
// Increase the string length
|
||||||
|
m_outputStringLen = offset + strLen;
|
||||||
// Convert to uppercase
|
// Convert to uppercase
|
||||||
if (m_uppercase)
|
if (m_outputUppercase)
|
||||||
{
|
{
|
||||||
for (size_t i = offset; i < m_outputBuffer.size() - 1; ++i)
|
for (size_t i = offset; i < m_outputStringLen - 1; ++i)
|
||||||
{
|
{
|
||||||
m_outputBuffer[i] = toupper(m_outputBuffer[i]);
|
m_outputBuffer[i] = toupper(m_outputBuffer[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VXBaseInstructionFormatter::outputAppendFormatted(char const *format, ...)
|
void VXBaseInstructionFormatter::outputAppendFormatted(char const *format, ...)
|
||||||
{
|
{
|
||||||
va_list arguments;
|
va_list arguments;
|
||||||
va_start(arguments, format);
|
va_start(arguments, format);
|
||||||
// Get the string length including the null-terminator char
|
// Get the buffer size
|
||||||
size_t strLen = _vscprintf(format, arguments) + 1;
|
|
||||||
// Get the buffer capacity and size
|
|
||||||
size_t bufCap = m_outputBuffer.capacity();
|
|
||||||
size_t bufLen = m_outputBuffer.size();
|
size_t bufLen = m_outputBuffer.size();
|
||||||
// Decrease the offset by one, to exclude already existing null-terminator chars in the
|
// Decrease the offset by one, to exclude already existing null-terminator chars in the
|
||||||
// output buffer
|
// output buffer
|
||||||
size_t offset = (bufLen) ? bufLen - 1 : 0;
|
size_t offset = (m_outputStringLen) ? m_outputStringLen - 1 : 0;
|
||||||
if (strLen > 1)
|
// Resize the output buffer on demand and add some extra space to improve the performance
|
||||||
|
if ((bufLen - m_outputStringLen) < 256)
|
||||||
{
|
{
|
||||||
// Resize capacity of the output buffer on demand and add some extra space to improve the
|
bufLen = bufLen + 512;
|
||||||
// performance
|
m_outputBuffer.resize(bufLen);
|
||||||
if (bufCap < (bufLen + strLen))
|
}
|
||||||
|
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.reserve(bufCap + strLen + 256);
|
m_outputBuffer.resize(bufLen + 512);
|
||||||
|
return outputAppendFormatted(format, arguments);
|
||||||
}
|
}
|
||||||
// Append the formatted text
|
// Write the formatted text to the output buffer
|
||||||
m_outputBuffer.resize(offset + strLen);
|
assert((bufLen - offset) > 0);
|
||||||
vsnprintf_s(&m_outputBuffer[offset], strLen, strLen, format, arguments);
|
strLen =
|
||||||
// Convert to uppercase
|
vsnprintf_s(&m_outputBuffer[offset], bufLen - offset, _TRUNCATE, format, arguments);
|
||||||
if (m_uppercase)
|
} 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)
|
||||||
{
|
{
|
||||||
for (size_t i = offset; i < m_outputBuffer.size() - 1; ++i)
|
m_outputBuffer[i] = toupper(m_outputBuffer[i]);
|
||||||
{
|
|
||||||
m_outputBuffer[i] = toupper(m_outputBuffer[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
va_end(arguments);
|
va_end(arguments);
|
||||||
|
@ -309,7 +330,7 @@ void VXBaseInstructionFormatter::outputAppendDisplacement(const VXInstructionInf
|
||||||
const VXOperandInfo &operand)
|
const VXOperandInfo &operand)
|
||||||
{
|
{
|
||||||
assert(operand.offset > 0);
|
assert(operand.offset > 0);
|
||||||
if (operand.base == VXRegister::NONE && operand.index == VXRegister::NONE)
|
if ((operand.base == VXRegister::NONE) && (operand.index == VXRegister::NONE))
|
||||||
{
|
{
|
||||||
// Assume the displacement value is unsigned
|
// Assume the displacement value is unsigned
|
||||||
assert(operand.scale == 0);
|
assert(operand.scale == 0);
|
||||||
|
@ -589,6 +610,46 @@ VXIntelInstructionFormatter::~VXIntelInstructionFormatter()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
VXExactSymbolResolver::~VXExactSymbolResolver()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* VXExactSymbolResolver::resolveSymbol(const VXInstructionInfo &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.end())
|
||||||
|
{
|
||||||
|
offset = 0;
|
||||||
|
return iterator->second.c_str();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VXExactSymbolResolver::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 VXExactSymbolResolver::setSymbol(uint64_t address, const char* name)
|
||||||
|
{
|
||||||
|
m_symbolMap[address].assign(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VXExactSymbolResolver::removeSymbol(uint64_t address)
|
||||||
|
{
|
||||||
|
m_symbolMap.erase(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VXExactSymbolResolver::clear()
|
||||||
|
{
|
||||||
|
m_symbolMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,14 +32,38 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
#include "VXDisassemblerTypes.h"
|
#include "VXDisassemblerTypes.h"
|
||||||
#include "VXSymbolResolver.h"
|
|
||||||
|
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base class for all symbol resolver implementations.
|
||||||
|
*/
|
||||||
|
class VXBaseSymbolResolver
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~VXBaseSymbolResolver();
|
||||||
|
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 VXInstructionInfo &info, uint64_t address,
|
||||||
|
uint64_t &offset);
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Base class for all instruction formatter implementations.
|
* @brief Base class for all instruction formatter implementations.
|
||||||
|
@ -50,7 +74,8 @@ private:
|
||||||
static const char *m_registerStrings[];
|
static const char *m_registerStrings[];
|
||||||
VXBaseSymbolResolver *m_symbolResolver;
|
VXBaseSymbolResolver *m_symbolResolver;
|
||||||
std::vector<char> m_outputBuffer;
|
std::vector<char> m_outputBuffer;
|
||||||
bool m_uppercase;
|
size_t m_outputStringLen;
|
||||||
|
bool m_outputUppercase;
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief Clears the output string buffer.
|
* @brief Clears the output string buffer.
|
||||||
|
@ -163,7 +188,7 @@ public:
|
||||||
|
|
||||||
inline void VXBaseInstructionFormatter::outputSetUppercase(bool uppercase)
|
inline void VXBaseInstructionFormatter::outputSetUppercase(bool uppercase)
|
||||||
{
|
{
|
||||||
m_uppercase = uppercase;
|
m_outputUppercase = uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char const* VXBaseInstructionFormatter::registerToString(VXRegister reg) const
|
inline char const* VXBaseInstructionFormatter::registerToString(VXRegister reg) const
|
||||||
|
@ -239,6 +264,56 @@ public:
|
||||||
~VXIntelInstructionFormatter() override;
|
~VXIntelInstructionFormatter() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Simple symbol resolver that only matches exact addresses.
|
||||||
|
*/
|
||||||
|
class VXExactSymbolResolver : public VXBaseSymbolResolver
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::unordered_map<uint64_t, std::string> m_symbolMap;
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
~VXExactSymbolResolver() 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 VXInstructionInfo &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();
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,16 +34,13 @@
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
|
|
||||||
#define INVALID 0
|
#define INVALID 0
|
||||||
#define NODE(type, n) (static_cast<VXOpcodeTreeNode>(type) << 12 | (n))
|
#define NODE(type, n) (static_cast<VXOpcodeTreeNode>(type) << 12 | (n))
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeTable[][256] =
|
const VXOpcodeTreeNode optreeTable[][256] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ 0x0015,
|
/* 00 */ 0x0015,
|
||||||
|
@ -2627,7 +2624,7 @@ static const VXOpcodeTreeNode optreeTable[][256] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeModrmMod[][2] =
|
const VXOpcodeTreeNode optreeModrmMod[][2] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ NODE(VXOpcodeTreeNodeType::MANDATORY, 0x0001),
|
/* 00 */ NODE(VXOpcodeTreeNodeType::MANDATORY, 0x0001),
|
||||||
|
@ -2747,7 +2744,7 @@ static const VXOpcodeTreeNode optreeModrmMod[][2] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeModrmReg[][8] =
|
const VXOpcodeTreeNode optreeModrmReg[][8] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ 0x0531,
|
/* 00 */ 0x0531,
|
||||||
|
@ -3231,7 +3228,7 @@ static const VXOpcodeTreeNode optreeModrmReg[][8] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeModrmRm[][8] =
|
const VXOpcodeTreeNode optreeModrmRm[][8] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ INVALID,
|
/* 00 */ INVALID,
|
||||||
|
@ -3375,7 +3372,7 @@ static const VXOpcodeTreeNode optreeModrmRm[][8] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeMandatory[][4] =
|
const VXOpcodeTreeNode optreeMandatory[][4] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ NODE(VXOpcodeTreeNodeType::MODRM_REG, 0x0000),
|
/* 00 */ NODE(VXOpcodeTreeNodeType::MODRM_REG, 0x0000),
|
||||||
|
@ -5293,7 +5290,7 @@ static const VXOpcodeTreeNode optreeMandatory[][4] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeX87[][64] =
|
const VXOpcodeTreeNode optreeX87[][64] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ 0x00BC,
|
/* 00 */ 0x00BC,
|
||||||
|
@ -5825,7 +5822,7 @@ static const VXOpcodeTreeNode optreeX87[][64] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeAddressSize[][3] =
|
const VXOpcodeTreeNode optreeAddressSize[][3] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ 0x02CD,
|
/* 00 */ 0x02CD,
|
||||||
|
@ -5834,7 +5831,7 @@ static const VXOpcodeTreeNode optreeAddressSize[][3] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeOperandSize[][3] =
|
const VXOpcodeTreeNode optreeOperandSize[][3] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ 0x03E0,
|
/* 00 */ 0x03E0,
|
||||||
|
@ -5958,7 +5955,7 @@ static const VXOpcodeTreeNode optreeOperandSize[][3] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeMode[][2] =
|
const VXOpcodeTreeNode optreeMode[][2] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ 0x04AA,
|
/* 00 */ 0x04AA,
|
||||||
|
@ -6142,7 +6139,7 @@ static const VXOpcodeTreeNode optreeMode[][2] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeVendor[][2] =
|
const VXOpcodeTreeNode optreeVendor[][2] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ INVALID,
|
/* 00 */ INVALID,
|
||||||
|
@ -6246,7 +6243,7 @@ static const VXOpcodeTreeNode optreeVendor[][2] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optree3dnow[][256] =
|
const VXOpcodeTreeNode optree3dnow[][256] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ INVALID,
|
/* 00 */ INVALID,
|
||||||
|
@ -6508,7 +6505,7 @@ static const VXOpcodeTreeNode optree3dnow[][256] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeVex[][16] =
|
const VXOpcodeTreeNode optreeVex[][16] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ NODE(VXOpcodeTreeNodeType::MODE, 0x0024),
|
/* 00 */ NODE(VXOpcodeTreeNodeType::MODE, 0x0024),
|
||||||
|
@ -6548,7 +6545,7 @@ static const VXOpcodeTreeNode optreeVex[][16] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeVexW[][2] =
|
const VXOpcodeTreeNode optreeVexW[][2] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ 0x061D,
|
/* 00 */ 0x061D,
|
||||||
|
@ -6652,7 +6649,7 @@ static const VXOpcodeTreeNode optreeVexW[][2] =
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VXOpcodeTreeNode optreeVexL[][2] =
|
const VXOpcodeTreeNode optreeVexL[][2] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
/* 00 */ 0x069C,
|
/* 00 */ 0x069C,
|
||||||
|
@ -6865,7 +6862,7 @@ static const VXOpcodeTreeNode optreeVexL[][2] =
|
||||||
#define OPI_sIb { VXDefinedOperandType::sI, VXDefinedOperandSize::B }
|
#define OPI_sIb { VXDefinedOperandType::sI, VXDefinedOperandSize::B }
|
||||||
#define OPI_sIz { VXDefinedOperandType::sI, VXDefinedOperandSize::Z }
|
#define OPI_sIz { VXDefinedOperandType::sI, VXDefinedOperandSize::Z }
|
||||||
|
|
||||||
static const VXInstructionDefinition instrDefinitions[] =
|
const VXInstructionDefinition instrDefinitions[] =
|
||||||
{
|
{
|
||||||
/* 000 */ { VXInstructionMnemonic::INVALID, { OPI_NONE, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
|
/* 000 */ { VXInstructionMnemonic::INVALID, { OPI_NONE, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
|
||||||
/* 001 */ { VXInstructionMnemonic::AAA, { OPI_NONE, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
|
/* 001 */ { VXInstructionMnemonic::AAA, { OPI_NONE, OPI_NONE, OPI_NONE, OPI_NONE }, 0 },
|
||||||
|
@ -9656,5 +9653,3 @@ const char* instrMnemonicStrings[] =
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,9 +37,6 @@
|
||||||
namespace Verteron
|
namespace Verteron
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Values that represent an instruction mnemonic.
|
* @brief Values that represent an instruction mnemonic.
|
||||||
*/
|
*/
|
||||||
|
@ -1754,5 +1751,3 @@ inline VXDefinedOperandSize VDEGetComplexOperandRegSize(VXDefinedOperandSize ope
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
/**************************************************************************************************
|
|
||||||
|
|
||||||
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 "VXSymbolResolver.h"
|
|
||||||
|
|
||||||
namespace Verteron
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
VXBaseSymbolResolver::~VXBaseSymbolResolver()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* VXBaseSymbolResolver::resolveSymbol(const VXInstructionInfo &info, uint64_t address,
|
|
||||||
uint64_t &offset)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
VXExactSymbolResolver::~VXExactSymbolResolver()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* VXExactSymbolResolver::resolveSymbol(const VXInstructionInfo &info, uint64_t address,
|
|
||||||
uint64_t &offset)
|
|
||||||
{
|
|
||||||
std::unordered_map<uint64_t, std::string>::const_iterator iterator = m_symbolMap.find(address);
|
|
||||||
return (iterator == m_symbolMap.end()) ? nullptr : iterator->second.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VXExactSymbolResolver::containsSymbol(uint64_t address) const
|
|
||||||
{
|
|
||||||
std::unordered_map<uint64_t, std::string>::const_iterator iterator = m_symbolMap.find(address);
|
|
||||||
return (iterator == m_symbolMap.end()) ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VXExactSymbolResolver::setSymbol(uint64_t address, const char* name)
|
|
||||||
{
|
|
||||||
m_symbolMap[address].assign(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VXExactSymbolResolver::removeSymbol(uint64_t address)
|
|
||||||
{
|
|
||||||
m_symbolMap.erase(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VXExactSymbolResolver::clear()
|
|
||||||
{
|
|
||||||
m_symbolMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
/**************************************************************************************************
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
**************************************************************************************************/
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include "VXDisassemblerTypes.h"
|
|
||||||
|
|
||||||
namespace Verteron
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace Disassembler
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Base class for all symbol resolver implementations.
|
|
||||||
*/
|
|
||||||
class VXBaseSymbolResolver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Destructor.
|
|
||||||
*/
|
|
||||||
virtual ~VXBaseSymbolResolver();
|
|
||||||
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 VXInstructionInfo &info, uint64_t address,
|
|
||||||
uint64_t &offset);
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Simple symbol resolver that only matches exact addresses.
|
|
||||||
*/
|
|
||||||
class VXExactSymbolResolver : public VXBaseSymbolResolver
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::unordered_map<uint64_t, std::string> m_symbolMap;
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Destructor.
|
|
||||||
*/
|
|
||||||
~VXExactSymbolResolver() 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 VXInstructionInfo &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();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -25,14 +25,12 @@
|
||||||
<ClInclude Include="VXInstructionDecoder.h" />
|
<ClInclude Include="VXInstructionDecoder.h" />
|
||||||
<ClInclude Include="VXInstructionFormatter.h" />
|
<ClInclude Include="VXInstructionFormatter.h" />
|
||||||
<ClInclude Include="VXOpcodeTable.h" />
|
<ClInclude Include="VXOpcodeTable.h" />
|
||||||
<ClInclude Include="VXSymbolResolver.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="VXDisassemblerUtils.cpp" />
|
<ClCompile Include="VXDisassemblerUtils.cpp" />
|
||||||
<ClCompile Include="VXInstructionDecoder.cpp" />
|
<ClCompile Include="VXInstructionDecoder.cpp" />
|
||||||
<ClCompile Include="VXInstructionFormatter.cpp" />
|
<ClCompile Include="VXInstructionFormatter.cpp" />
|
||||||
<ClCompile Include="VXOpcodeTable.cpp" />
|
<ClCompile Include="VXOpcodeTable.cpp" />
|
||||||
<ClCompile Include="VXSymbolResolver.cpp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{F5C6F0A7-F75D-42BD-A8AB-A2D1D5F67099}</ProjectGuid>
|
<ProjectGuid>{F5C6F0A7-F75D-42BD-A8AB-A2D1D5F67099}</ProjectGuid>
|
||||||
|
|
|
@ -3,17 +3,15 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="VXDisassembler.h" />
|
<ClInclude Include="VXDisassembler.h" />
|
||||||
<ClInclude Include="VXDisassemblerTypes.h" />
|
<ClInclude Include="VXDisassemblerTypes.h" />
|
||||||
|
<ClInclude Include="VXDisassemblerUtils.h" />
|
||||||
<ClInclude Include="VXInstructionDecoder.h" />
|
<ClInclude Include="VXInstructionDecoder.h" />
|
||||||
<ClInclude Include="VXInstructionFormatter.h" />
|
<ClInclude Include="VXInstructionFormatter.h" />
|
||||||
<ClInclude Include="VXOpcodeTable.h" />
|
<ClInclude Include="VXOpcodeTable.h" />
|
||||||
<ClInclude Include="VXSymbolResolver.h" />
|
|
||||||
<ClInclude Include="VXDisassemblerUtils.h" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="VXDisassemblerUtils.cpp" />
|
||||||
<ClCompile Include="VXInstructionDecoder.cpp" />
|
<ClCompile Include="VXInstructionDecoder.cpp" />
|
||||||
<ClCompile Include="VXInstructionFormatter.cpp" />
|
<ClCompile Include="VXInstructionFormatter.cpp" />
|
||||||
<ClCompile Include="VXOpcodeTable.cpp" />
|
<ClCompile Include="VXOpcodeTable.cpp" />
|
||||||
<ClCompile Include="VXSymbolResolver.cpp" />
|
|
||||||
<ClCompile Include="VXDisassemblerUtils.cpp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue