mirror of https://github.com/x64dbg/zydis
421 lines
14 KiB
C++
421 lines
14 KiB
C++
/***************************************************************************************************
|
|
|
|
Zyan Disassembler Engine
|
|
Version 1.0
|
|
|
|
Remarks : Freeware, Copyright must be included
|
|
|
|
Original Author : Florian Bernd
|
|
Modifications : Joel Höner
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
|
|
***************************************************************************************************/
|
|
|
|
#include "ZydisAPI.h"
|
|
#include "ZydisInstructionDecoder.hpp"
|
|
#include "ZydisInstructionFormatter.hpp"
|
|
|
|
static_assert(
|
|
sizeof(ZydisOperandInfo) == sizeof(Zydis::OperandInfo),
|
|
"struct size mismatch");
|
|
|
|
static_assert(
|
|
sizeof(ZydisInstructionInfo) == sizeof(Zydis::InstructionInfo),
|
|
"struct size mismatch");
|
|
|
|
/* Error Handling =============================================================================== */
|
|
|
|
static uint32_t g_zydisLastError = ZYDIS_ERROR_SUCCESS;
|
|
|
|
uint32_t ZydisGetLastError()
|
|
{
|
|
return g_zydisLastError;
|
|
}
|
|
|
|
void ZydisSetLastError(uint32_t errorCode)
|
|
{
|
|
g_zydisLastError = errorCode;
|
|
}
|
|
|
|
/* Conversion Helper ============================================================================ */
|
|
|
|
template <typename ContextT, typename InstanceT, typename... InstanceCtorArgsT>
|
|
ContextT* ZydisCreateContextInplace(uint8_t contextType, InstanceCtorArgsT... args)
|
|
{
|
|
ContextT* context = new (std::nothrow) ContextT;
|
|
if (!context)
|
|
{
|
|
ZydisSetLastError(ZYDIS_ERROR_NOT_ENOUGH_MEMORY);
|
|
return nullptr;
|
|
}
|
|
context->type = contextType;
|
|
context->object = new (std::nothrow) InstanceT(args...);
|
|
if (!context->object)
|
|
{
|
|
delete context;
|
|
ZydisSetLastError(ZYDIS_ERROR_NOT_ENOUGH_MEMORY);
|
|
return nullptr;
|
|
}
|
|
return context;
|
|
}
|
|
|
|
template <typename ContextT, typename InstanceT>
|
|
ContextT* ZydisCreateContext(uint8_t contextType, InstanceT* instance)
|
|
{
|
|
ContextT* context = new (std::nothrow) ContextT;
|
|
if (!context)
|
|
{
|
|
ZydisSetLastError(ZYDIS_ERROR_NOT_ENOUGH_MEMORY);
|
|
return nullptr;
|
|
}
|
|
context->type = contextType;
|
|
context->object = instance;
|
|
return context;
|
|
}
|
|
|
|
template <typename ContextT, typename InstanceT>
|
|
bool ZydisFreeContext(const ContextT* context, uint8_t expectedType)
|
|
{
|
|
InstanceT* instance = ZydisCast<ContextT, InstanceT>(context, expectedType);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
delete instance;
|
|
delete context;
|
|
return true;
|
|
}
|
|
|
|
template <typename ContextT, typename InstanceT>
|
|
InstanceT* ZydisCast(const ContextT* input, uint8_t expectedType)
|
|
{
|
|
if (!input || !input->object || ((input->type & expectedType) != expectedType))
|
|
{
|
|
ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER);
|
|
return nullptr;
|
|
}
|
|
return reinterpret_cast<InstanceT*>(input->object);
|
|
}
|
|
|
|
/* Input ======================================================================================== */
|
|
|
|
ZydisInputContext* ZydisCreateCustomInput(/* TODO */)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ZydisInputContext* ZydisCreateMemoryInput(const void* buffer, size_t bufferLen)
|
|
{
|
|
return ZydisCreateContextInplace<ZydisInputContext, Zydis::MemoryInput>(
|
|
ZYDIS_CONTEXT_INPUT | ZYDIS_CONTEXT_INPUT_MEMORY, buffer, bufferLen);
|
|
}
|
|
|
|
bool ZydisIsEndOfInput(const ZydisInputContext* input, bool* isEndOfInput)
|
|
{
|
|
Zydis::BaseInput* instance =
|
|
ZydisCast<ZydisInputContext, Zydis::BaseInput>(input, ZYDIS_CONTEXT_INPUT);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
*isEndOfInput = instance->isEndOfInput();
|
|
return true;
|
|
}
|
|
|
|
bool ZydisGetInputPosition(const ZydisInputContext* input, uint64_t* position)
|
|
{
|
|
Zydis::BaseInput* instance =
|
|
ZydisCast<ZydisInputContext, Zydis::BaseInput>(input, ZYDIS_CONTEXT_INPUT);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
*position = instance->getPosition();
|
|
return true;
|
|
}
|
|
|
|
bool ZydisSetInputPosition(const ZydisInputContext* input, uint64_t position)
|
|
{
|
|
Zydis::BaseInput* instance =
|
|
ZydisCast<ZydisInputContext, Zydis::BaseInput>(input, ZYDIS_CONTEXT_INPUT);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
ZydisSetLastError(ZYDIS_ERROR_SUCCESS);
|
|
return instance->setPosition(position);
|
|
}
|
|
|
|
bool ZydisFreeInput(const ZydisInputContext* input)
|
|
{
|
|
return ZydisFreeContext<ZydisInputContext, Zydis::BaseInput>(input, ZYDIS_CONTEXT_INPUT);
|
|
}
|
|
|
|
/* InstructionDecoder =========================================================================== */
|
|
|
|
ZydisInstructionDecoderContext* ZydisCreateInstructionDecoder()
|
|
{
|
|
return ZydisCreateContextInplace<ZydisInstructionDecoderContext, Zydis::InstructionDecoder>(
|
|
ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
}
|
|
|
|
bool ZydisDecodeInstruction(const ZydisInstructionDecoderContext* decoder,
|
|
ZydisInstructionInfo* info)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
ZydisSetLastError(ZYDIS_ERROR_SUCCESS);
|
|
return instance->decodeInstruction(*reinterpret_cast<Zydis::InstructionInfo*>(info));
|
|
}
|
|
|
|
bool ZydisGetDataSource(const ZydisInstructionDecoderContext* decoder,
|
|
ZydisInputContext** input)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
*input = ZydisCreateContext<ZydisInputContext,
|
|
Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, instance->getDataSource());
|
|
if (!input)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ZydisSetDataSource(const ZydisInstructionDecoderContext* decoder,
|
|
ZydisInputContext* input)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
Zydis::BaseInput* object =
|
|
ZydisCast<ZydisInputContext, Zydis::BaseInput>(input, ZYDIS_CONTEXT_INPUT);
|
|
if (!object)
|
|
{
|
|
return false;
|
|
}
|
|
instance->setDataSource(object);
|
|
return true;
|
|
}
|
|
|
|
bool ZydisGetDisassemblerMode(const ZydisInstructionDecoderContext* decoder,
|
|
ZydisDisassemblerMode* disassemblerMode)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
*disassemblerMode = static_cast<ZydisDisassemblerMode>(instance->getDisassemblerMode());
|
|
return true;
|
|
}
|
|
|
|
bool ZydisSetDisassemblerMode(const ZydisInstructionDecoderContext* decoder,
|
|
ZydisDisassemblerMode disassemblerMode)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
instance->setDisassemblerMode(static_cast<Zydis::DisassemblerMode>(disassemblerMode));
|
|
return true;
|
|
}
|
|
|
|
bool ZydisGetPreferredVendor(const ZydisInstructionDecoderContext* decoder,
|
|
ZydisInstructionSetVendor* preferredVendor)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
*preferredVendor = static_cast<ZydisInstructionSetVendor>(instance->getPreferredVendor());
|
|
return true;
|
|
}
|
|
|
|
bool ZydisSetPreferredVendor(const ZydisInstructionDecoderContext* decoder,
|
|
ZydisInstructionSetVendor preferredVendor)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
instance->setPreferredVendor(static_cast<Zydis::InstructionSetVendor>(preferredVendor));
|
|
return true;
|
|
}
|
|
|
|
bool ZydisGetInstructionPointer(const ZydisInstructionDecoderContext* decoder,
|
|
uint64_t* instructionPointer)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
*instructionPointer = instance->getInstructionPointer();
|
|
return true;
|
|
}
|
|
|
|
bool ZydisSetInstructionPointer(const ZydisInstructionDecoderContext* decoder,
|
|
uint64_t instructionPointer)
|
|
{
|
|
Zydis::InstructionDecoder* instance =
|
|
ZydisCast<ZydisInstructionDecoderContext,
|
|
Zydis::InstructionDecoder>(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
instance->setInstructionPointer(instructionPointer);
|
|
return true;
|
|
}
|
|
|
|
bool ZydisFreeInstructionDecoder(const ZydisInstructionDecoderContext* decoder)
|
|
{
|
|
return ZydisFreeContext<
|
|
ZydisInstructionDecoderContext, Zydis::InstructionDecoder>(
|
|
decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER);
|
|
}
|
|
|
|
/* InstructionFormatter ========================================================================= */
|
|
|
|
ZydisInstructionFormatterContext* ZydisCreateCustomInstructionFormatter(/* TODO */)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
ZydisInstructionFormatterContext* ZydisCreateIntelInstructionFormatter()
|
|
{
|
|
return ZydisCreateContextInplace<ZydisInstructionFormatterContext,
|
|
Zydis::IntelInstructionFormatter>(
|
|
ZYDIS_CONTEXT_INSTRUCTIONFORMATTER | ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_INTEL);
|
|
}
|
|
|
|
bool ZydisFormatInstruction(const ZydisInstructionFormatterContext* formatter,
|
|
const ZydisInstructionInfo* info, const char** instructionText)
|
|
{
|
|
Zydis::IntelInstructionFormatter* instance =
|
|
ZydisCast<ZydisInstructionFormatterContext,
|
|
Zydis::IntelInstructionFormatter>(formatter, ZYDIS_CONTEXT_INSTRUCTIONFORMATTER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
*instructionText =
|
|
instance->formatInstruction(*reinterpret_cast<const Zydis::InstructionInfo*>(info));
|
|
return true;
|
|
}
|
|
|
|
bool ZydisGetSymbolResolver(const ZydisInstructionFormatterContext* formatter,
|
|
ZydisSymbolResolverContext** resolver)
|
|
{
|
|
Zydis::IntelInstructionFormatter* instance =
|
|
ZydisCast<ZydisInstructionFormatterContext,
|
|
Zydis::IntelInstructionFormatter>(formatter, ZYDIS_CONTEXT_INSTRUCTIONFORMATTER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
*resolver = ZydisCreateContext<ZydisSymbolResolverContext,
|
|
Zydis::BaseSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER, instance->getSymbolResolver());
|
|
if (!resolver)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ZydisSetSymbolResolver(const ZydisInstructionFormatterContext* formatter,
|
|
ZydisSymbolResolverContext* resolver)
|
|
{
|
|
Zydis::IntelInstructionFormatter* instance =
|
|
ZydisCast<ZydisInstructionFormatterContext,
|
|
Zydis::IntelInstructionFormatter>(formatter, ZYDIS_CONTEXT_INSTRUCTIONFORMATTER);
|
|
if (!instance)
|
|
{
|
|
return false;
|
|
}
|
|
Zydis::BaseSymbolResolver* object =
|
|
ZydisCast<ZydisSymbolResolverContext,
|
|
Zydis::BaseSymbolResolver>(resolver, ZYDIS_CONTEXT_SYMBOLRESOLVER);
|
|
if (!object)
|
|
{
|
|
return false;
|
|
}
|
|
instance->setSymbolResolver(object);
|
|
return true;
|
|
}
|
|
|
|
bool ZydisFreeInstructionFormatter(const ZydisInstructionFormatterContext* formatter)
|
|
{
|
|
return ZydisFreeContext<
|
|
ZydisInstructionFormatterContext, Zydis::BaseInstructionFormatter>(
|
|
formatter, ZYDIS_CONTEXT_INSTRUCTIONFORMATTER);
|
|
}
|
|
|
|
/* SymbolResolver =============================================================================== */
|
|
|
|
ZYDIS_EXPORT ZydisSymbolResolverContext* ZydisCreateCustomSymbolResolver(/*TODO*/);
|
|
|
|
ZYDIS_EXPORT ZydisSymbolResolverContext* ZydisCreateExactSymbolResolver();
|
|
|
|
ZYDIS_EXPORT bool ZydisResolveSymbol(const ZydisSymbolResolverContext* resolver,
|
|
const ZydisInstructionInfo* info, uint64_t address, const char** symbol, uint64_t* offset);
|
|
|
|
ZYDIS_EXPORT bool ZydisExactSymbolResolverContainsSymbol(
|
|
const ZydisSymbolResolverContext* resolver, uint64_t address, bool* containsSymbol);
|
|
|
|
ZYDIS_EXPORT bool ZydisExactSymbolResolverSetSymbol(const ZydisSymbolResolverContext* resolver,
|
|
uint64_t address, const char* symbol);
|
|
|
|
ZYDIS_EXPORT bool ZydisExactSymbolResolverRemoveSymbol(const ZydisSymbolResolverContext* resolver,
|
|
uint64_t address);
|
|
|
|
ZYDIS_EXPORT bool ZydisExactSymbolResolverClear(const ZydisSymbolResolverContext* resolver);
|
|
|
|
ZYDIS_EXPORT bool ZydisFreeSymbolResolver(const ZydisSymbolResolverContext* resolver);
|
|
|
|
/* ============================================================================================== */ |