Merge pull request #3 from flobernd/develop

Development branch merge
This commit is contained in:
Florian Bernd 2014-11-03 15:19:21 +01:00
commit 634f927df7
18 changed files with 393 additions and 402 deletions

View File

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

View File

@ -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[])
{ {

View File

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

View File

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

View File

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

View File

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

View File

@ -30,12 +30,10 @@
**************************************************************************************************/ **************************************************************************************************/
#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)
{ {
@ -74,5 +72,3 @@ uint64_t VDECalcAbsoluteTarget(const VXInstructionInfo &info, const VXOperandInf
} }
} }
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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[] =
} }
} }
}

View File

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

View File

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

View File

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

View File

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

View File

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