Complete rewrite of the instruction-formatter

- Added hooking functionality to support custom instruction-formatting
- Added FormatterHooks demo that demonstrates the hooking functionality

InstructionEditor:
- Fixed issues with still non-deterministic output on code-generation
This commit is contained in:
flobernd 2016-11-26 13:08:37 +01:00
parent 03b4d69b08
commit 816bb570c7
18 changed files with 23692 additions and 22668 deletions

View File

@ -56,7 +56,6 @@ set(headers
"include/Zydis/Mnemonic.h" "include/Zydis/Mnemonic.h"
"include/Zydis/Register.h" "include/Zydis/Register.h"
"include/Zydis/Status.h" "include/Zydis/Status.h"
"include/Zydis/SymbolResolver.h"
"include/Zydis/Utils.h" "include/Zydis/Utils.h"
"include/Zydis/Zydis.h" "include/Zydis/Zydis.h"
"include/Zydis/Internal/InstructionTable.h") "include/Zydis/Internal/InstructionTable.h")
@ -97,11 +96,11 @@ endif ()
if (BUILD_EXAMPLES) if (BUILD_EXAMPLES)
include_directories("include") include_directories("include")
if (WIN32) add_executable("FormatterHooks"
add_executable("ZydisPE" "examples/ZydisPE.c") "examples/FormatterHooks.c"
target_link_libraries("ZydisPE" "Zydis") "examples/FormatHelper.h")
set_target_properties ("ZydisPE" PROPERTIES FOLDER "Examples") target_link_libraries("FormatterHooks" "Zydis")
endif () set_target_properties ("FormatterHooks" PROPERTIES FOLDER "Examples/Formatter")
endif () endif ()
# Tools # Tools

View File

@ -257,7 +257,6 @@ var
List: TList<TInstructionDefinition>; List: TList<TInstructionDefinition>;
I, J: Integer; I, J: Integer;
B: Boolean; B: Boolean;
Comparison: TComparison<TInstructionDefinition>;
begin begin
List := TList<TInstructionDefinition>.Create; List := TList<TInstructionDefinition>.Create;
try try
@ -279,12 +278,16 @@ begin
end; end;
Work(I + 1); Work(I + 1);
end; end;
Comparison := // Sort definitions with a stable algorithm to ensure deterministic output
TListHelper<TInstructionDefinition>.BubbleSort(
List, TComparer<TInstructionDefinition>.Construct(
function(const Left, Right: TInstructionDefinition): Integer function(const Left, Right: TInstructionDefinition): Integer
begin begin
Result := CompareStr(Left.Mnemonic, Right.Mnemonic); Result := CompareStr(Left.Mnemonic, Right.Mnemonic);
end; if (Result = 0) then Result := Ord(Left.Encoding) - Ord(Right.Encoding);
List.Sort(TComparer<TInstructionDefinition>.Construct(Comparison)); if (Result = 0) then Result := Ord(Left.OpcodeMap) - Ord(Right.OpcodeMap);
if (Result = 0) then Result := Ord(Left.Opcode) - Ord(Right.Opcode);
end));
SetLength(DefinitionList, List.Count); SetLength(DefinitionList, List.Count);
for I := 0 to List.Count - 1 do for I := 0 to List.Count - 1 do
begin begin

174
examples/FormatHelper.h Normal file
View File

@ -0,0 +1,174 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_FORMATHELPER_H
#define ZYDIS_FORMATHELPER_H
#include <assert.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <Zydis/Defines.h>
#include <Zydis/Status.h>
/* ============================================================================================== */
/* Format helper functions */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Enums and types */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisStringBufferAppendMode datatype.
*/
typedef uint8_t ZydisStringBufferAppendMode;
/**
* @brief Values that represent zydis string-buffer append-modes.
*/
enum ZydisStringBufferAppendModes
{
/**
* @brief Appends the string as it is.
*/
ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
/**
* @brief Converts the string to lowercase characters.
*/
ZYDIS_STRBUF_APPEND_MODE_LOWERCASE,
/**
* @brief Converts the string to uppercase characters.
*/
ZYDIS_STRBUF_APPEND_MODE_UPPERCASE
};
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Appends the @c text to the given @c buffer and increases the string-buffer pointer by
* the number of chars written.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param mode The append-mode.
* @param text The text to append.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c text.
*/
ZYDIS_INLINE ZydisStatus ZydisStringBufferAppend(char** buffer, size_t bufferLen,
ZydisStringBufferAppendMode mode, const char* text)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen != 0);
ZYDIS_ASSERT(text);
size_t strLen = strlen(text);
if (strLen >= bufferLen)
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
strncpy(*buffer, text, strLen + 1);
switch (mode)
{
case ZYDIS_STRBUF_APPEND_MODE_LOWERCASE:
for (size_t i = 0; i < strLen; ++i)
{
(*buffer[i]) = (char)tolower((*buffer)[i]);
}
break;
case ZYDIS_STRBUF_APPEND_MODE_UPPERCASE:
for (size_t i = 0; i < strLen; ++i)
{
(*buffer)[i] = (char)toupper((*buffer)[i]);
}
break;
default:
break;
}
*buffer += strLen;
return ZYDIS_STATUS_SUCCESS;
}
/**
* @brief Appends formatted text to the given @c buffer and increases the string-buffer pointer
* by the number of chars written.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param mode The append-mode.
* @param format The format string.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given text.
*/
ZYDIS_INLINE ZydisStatus ZydisStringBufferAppendFormat(char** buffer, size_t bufferLen,
ZydisStringBufferAppendMode mode, const char* format, ...)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen != 0);
ZYDIS_ASSERT(format);
va_list arglist;
va_start(arglist, format);
int w = vsnprintf(*buffer, bufferLen, format, arglist);
if ((w < 0) || ((size_t)w >= bufferLen))
{
va_end(arglist);
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
switch (mode)
{
case ZYDIS_STRBUF_APPEND_MODE_LOWERCASE:
for (size_t i = 0; i < (size_t)w; ++i)
{
(*buffer)[i] = (char)tolower((*buffer)[i]);
}
break;
case ZYDIS_STRBUF_APPEND_MODE_UPPERCASE:
for (size_t i = 0; i < (size_t)w; ++i)
{
(*buffer)[i] = (char)toupper((*buffer)[i]);
}
break;
default:
break;
}
*buffer += (size_t)w;
va_end(arglist);
return ZYDIS_STATUS_SUCCESS;
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#endif /* ZYDIS_FORMATHELPER_H */

242
examples/FormatterHooks.c Normal file
View File

@ -0,0 +1,242 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
/**
* @file
* @brief Demonstrates the hooking functionality of the @c ZydisInstructionFormatter class.
*
* This example demonstrates the hooking functionality of the @c ZydisInstructionFormatter class by
* rewriting the mnemonics of (V)CMPPS and (V)CMPPD to their corresponding alias-forms (based on
* the condition encoded in the immediate operand).
*/
#include <stdint.h>
#include <stdbool.h>
#include <Zydis/Zydis.h>
#include "FormatHelper.h"
/* ============================================================================================== */
/* Static data */
/* ============================================================================================== */
/**
* @brief Static array with the condition-code strings.
*/
static const char* conditionCodeStrings[0x20] =
{
"eq",
"lt",
"le",
"unord",
"neq",
"nlt",
"nle",
"ord",
"eq_uq",
"nge",
"ngt",
"false",
"oq",
"ge",
"gt",
"true",
"eq_os",
"lt_oq",
"le_oq",
"unord_s",
"neq_us",
"nlt_uq",
"nle_uq",
"ord_s",
"eq_us",
"nge_uq",
"ngt_uq",
"false_os",
"neq_os",
"ge_oq",
"gt_oq",
"true_us"
};
/* ============================================================================================== */
/* Hook callbacks */
/* ============================================================================================== */
ZydisFormatterFormatFunc defaultPrintMnemonic;
static ZydisStatus ZydisFormatterPrintMnemonic(ZydisInstructionFormatter* formatter,
char** buffer, size_t bufferLen, ZydisInstructionInfo* info)
{
// We use the user-data field of the instruction-info to pass data to the
// @c ZydisFormatterFormatOperandImm function.
// In this case we are using a simple ordinal value, but you could pass a pointer to a
// complex datatype as well.
info->userData = (void*)1;
// Rewrite the instruction-mnemonic for the given instructions
if ((info->operandCount == 3) && (info->operand[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))
{
uint8_t conditionCode = info->operand[2].imm.value.ubyte;
if (conditionCode < 0x08)
{
switch (info->mnemonic)
{
case ZYDIS_MNEMONIC_CMPPS:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "cmp%sps",
conditionCodeStrings[conditionCode]);
case ZYDIS_MNEMONIC_CMPPD:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "cmp%spd",
conditionCodeStrings[conditionCode]);
default:
break;
}
}
}
if ((info->operandCount == 4) && (info->operand[3].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))
{
uint8_t conditionCode = info->operand[3].imm.value.ubyte;
if (conditionCode < 0x20)
{
switch (info->mnemonic)
{
case ZYDIS_MNEMONIC_VCMPPS:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "vcmp%sps",
conditionCodeStrings[conditionCode]);
case ZYDIS_MNEMONIC_VCMPPD:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "vcmp%spd",
conditionCodeStrings[conditionCode]);
default:
break;
}
}
}
// We did not rewrite the instruction-mnemonic. Signal the @c ZydisFormatterFormatOperandImm
// function not to omit the operand
info->userData = (void*)0;
// Default mnemonic printing
return defaultPrintMnemonic(formatter, buffer, bufferLen, info);
}
/* ---------------------------------------------------------------------------------------------- */
ZydisFormatterFormatOperandFunc defaultFormatOperandImm;
static ZydisStatus ZydisFormatterFormatOperandImm(ZydisInstructionFormatter* formatter,
char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand)
{
// The @c ZydisFormatterFormatMnemonic sinals us to omit the immediate (condition-code)
// operand, because it got replaced by the alias-mnemonic
if ((int)info->userData == 1)
{
// The formatter will automatically omit the operand, if the buffer remains unchanged
// after the callback returns
return ZYDIS_STATUS_SUCCESS;
}
// Default immediate formatting
return defaultFormatOperandImm(formatter, buffer, bufferLen, info, operand);
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Helper functions */
/* ============================================================================================== */
void disassembleBuffer(uint8_t* data, size_t length, bool installHooks)
{
ZydisMemoryInput input;
ZydisInputInitMemoryInput(&input, data, length);
ZydisInstructionDecoder decoder;
ZydisDecoderInitInstructionDecoderEx(&decoder, ZYDIS_DISASSEMBLER_MODE_64BIT,
(ZydisCustomInput*)&input, ZYDIS_DECODER_FLAG_SKIP_DATA);
ZydisDecoderSetInstructionPointer(&decoder, 0x007FFFFFFF400000);
ZydisInstructionFormatter formatter;
ZydisFormatterInitInstructionFormatterEx(&formatter, ZYDIS_FORMATTER_STYLE_INTEL,
ZYDIS_FMTFLAG_FORCE_SEGMENTS | ZYDIS_FMTFLAG_FORCE_OPERANDSIZE,
ZYDIS_FORMATTER_ADDR_ABSOLUTE, ZYDIS_FORMATTER_DISP_DEFAULT, ZYDIS_FORMATTER_IMM_DEFAULT);
if (installHooks)
{
defaultPrintMnemonic = &ZydisFormatterPrintMnemonic;
ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC,
(const void**)&defaultPrintMnemonic);
defaultFormatOperandImm = &ZydisFormatterFormatOperandImm;
ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM,
(const void**)&defaultFormatOperandImm);
}
ZydisInstructionInfo info;
char buffer[256];
while (ZYDIS_SUCCESS(ZydisDecoderDecodeNextInstruction(&decoder, &info)))
{
printf("%016llX ", info.instrAddress);
if (info.instrFlags & ZYDIS_INSTRFLAG_ERROR_MASK)
{
printf(" db %02x\n", info.data[0]);
continue;
}
ZydisFormatterFormatInstruction(&formatter, &info, &buffer[0], sizeof(buffer));
printf(" %s\n", &buffer[0]);
}
}
/* ============================================================================================== */
/* Entry point */
/* ============================================================================================== */
int main()
{
uint8_t data[] =
{
// cmpps xmm1, xmm4, 0x03
0x0F, 0xC2, 0xCC, 0x03,
// vcmpord_spd xmm1, xmm2, xmm3
0xC5, 0xE9, 0xC2, 0xCB, 0x17,
// vcmpps k2 {k7}, zmm2, dword ptr ds:[rax + rbx*4 + 0x100] {1to16}, 0x0F
0x62, 0xF1, 0x6C, 0x5F, 0xC2, 0x54, 0x98, 0x40, 0x0F
};
disassembleBuffer(&data[0], sizeof(data), false);
puts("");
disassembleBuffer(&data[0], sizeof(data), true);
getchar();
return 0;
}
/* ============================================================================================== */

View File

@ -207,6 +207,8 @@ ZYDIS_EXPORT ZydisStatus ZydisDecoderGetDecoderInput(const ZydisInstructionDecod
* @param input A pointer to the new input data-source. * @param input A pointer to the new input data-source.
* *
* @return A zydis status code. * @return A zydis status code.
*
* This function flushes the internal input-buffer.
*/ */
ZYDIS_EXPORT ZydisStatus ZydisDecoderSetDecoderInput(ZydisInstructionDecoder* decoder, ZYDIS_EXPORT ZydisStatus ZydisDecoderSetDecoderInput(ZydisInstructionDecoder* decoder,
ZydisCustomInput* input); ZydisCustomInput* input);

View File

@ -31,7 +31,6 @@
#include <Zydis/Defines.h> #include <Zydis/Defines.h>
#include <Zydis/Status.h> #include <Zydis/Status.h>
#include <Zydis/InstructionInfo.h> #include <Zydis/InstructionInfo.h>
#include <Zydis/SymbolResolver.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -57,16 +56,28 @@ enum ZydisFormatterStyles
ZYDIS_FORMATTER_STYLE_INTEL ZYDIS_FORMATTER_STYLE_INTEL
}; };
/** /* ---------------------------------------------------------------------------------------------- */
* @brief Defines the @c ZydisFormatterFlags datatype.
*/
typedef uint8_t ZydisFormatterFlags;
#define ZYDIS_FORMATTER_FLAG_UPPERCASE 0x01 /**
#define ZYDIS_FORMATTER_FLAG_TAB_AFTER_MNEMONIC 0x02 * @brief Defines the @c ZydisFormatFlags datatype.
#define ZYDIS_FORMATTER_FLAG_NO_SPACE_BETWEEN_OPERANDS 0x04 */
#define ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SIZE 0x08 typedef uint32_t ZydisFormatFlags;
#define ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SEGMENT 0x10
/**
* @brief Formats the instruction in uppercase instead of lowercase.
*/
#define ZYDIS_FMTFLAG_UPPERCASE 0x00000001
/**
* @brief Forces the formatter to always print the segment register of memory-operands, instead
* of ommiting implicit DS/SS segments.
*/
#define ZYDIS_FMTFLAG_FORCE_SEGMENTS 0x00000002
/**
* @brief Forces the formatter to always print the size of memory-operands.
*/
#define ZYDIS_FMTFLAG_FORCE_OPERANDSIZE 0x00000004
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Defines the @c ZydisFormatterAddressFormat datatype. * @brief Defines the @c ZydisFormatterAddressFormat datatype.
@ -78,6 +89,9 @@ typedef uint8_t ZydisFormatterAddressFormat;
*/ */
enum ZydisFormatterAddressFormat enum ZydisFormatterAddressFormat
{ {
/**
* @brief Currently defaults to @c ZYDIS_FORMATTER_ADDR_ABSOLUTE.
*/
ZYDIS_FORMATTER_ADDR_DEFAULT, ZYDIS_FORMATTER_ADDR_DEFAULT,
/** /**
* @brief Displays absolute addresses instead of relative ones. * @brief Displays absolute addresses instead of relative ones.
@ -101,6 +115,8 @@ enum ZydisFormatterAddressFormat
ZYDIS_FORMATTER_ADDR_RELATIVE_UNSIGNED, ZYDIS_FORMATTER_ADDR_RELATIVE_UNSIGNED,
}; };
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Defines the @c ZydisFormatterDisplacementFormat datatype. * @brief Defines the @c ZydisFormatterDisplacementFormat datatype.
*/ */
@ -111,6 +127,9 @@ typedef uint8_t ZydisFormatterDisplacementFormat;
*/ */
enum ZydisFormatterDisplacementFormats enum ZydisFormatterDisplacementFormats
{ {
/**
* @brief Currently defaults to @c ZYDIS_FORMATTER_DISP_HEX_SIGNED.
*/
ZYDIS_FORMATTER_DISP_DEFAULT, ZYDIS_FORMATTER_DISP_DEFAULT,
/** /**
* @brief Formats displacements as signed hexadecimal values. * @brief Formats displacements as signed hexadecimal values.
@ -130,6 +149,8 @@ enum ZydisFormatterDisplacementFormats
ZYDIS_FORMATTER_DISP_HEX_UNSIGNED ZYDIS_FORMATTER_DISP_HEX_UNSIGNED
}; };
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Defines the @c ZydisFormatterImmediateFormat datatype. * @brief Defines the @c ZydisFormatterImmediateFormat datatype.
*/ */
@ -140,7 +161,15 @@ typedef uint8_t ZydisFormatterImmediateFormat;
*/ */
enum ZydisFormatterImmediateFormats enum ZydisFormatterImmediateFormats
{ {
/**
* @brief Currently defaults to @c ZYDIS_FORMATTER_IMM_HEX_UNSIGNED.
*/
ZYDIS_FORMATTER_IMM_DEFAULT, ZYDIS_FORMATTER_IMM_DEFAULT,
/**
* @brief Automatically chooses the most suitable formatting-mode based on the operands
* @c ZydisOperandInfo.imm.isSigned attribute.
*/
ZYDIS_FORMATTER_IMM_HEX_AUTO,
/** /**
* @brief Formats immediates as signed hexadecimal values. * @brief Formats immediates as signed hexadecimal values.
* *
@ -159,6 +188,8 @@ enum ZydisFormatterImmediateFormats
ZYDIS_FORMATTER_IMM_HEX_UNSIGNED ZYDIS_FORMATTER_IMM_HEX_UNSIGNED
}; };
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Defines the @c ZydisFormatterHookType datatype. * @brief Defines the @c ZydisFormatterHookType datatype.
*/ */
@ -170,53 +201,199 @@ typedef uint8_t ZydisFormatterHookType;
enum ZydisFormatterHookTypes enum ZydisFormatterHookTypes
{ {
/** /**
* @brief This hook is called right * @brief This function is called before the formatter starts formatting an instruction.
*/ */
ZYDIS_FORMATTER_HOOK_PRE, ZYDIS_FORMATTER_HOOK_PRE,
/**
* @brief This function is called before the formatter finished formatting an instruction.
*/
ZYDIS_FORMATTER_HOOK_POST, ZYDIS_FORMATTER_HOOK_POST,
ZYDIS_FORMATTER_HOOK_FORMAT_MNEMONIC, /**
ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND, * @brief This function refers to the main formatting function, that internally calls all
* other function except the ones that are hooked by @c ZYDIS_FORMATTER_HOOK_PRE and
* @c ZYDIS_FORMATTER_HOOK_POST.
*
* Replacing this function allows for complete custom formatting, but indirectly disables all
* other hooks except for @c ZYDIS_FORMATTER_HOOK_PRE and @c ZYDIS_FORMATTER_HOOK_POST.
*/
ZYDIS_FORMATTER_HOOK_FORMAT_INSTRUCTION,
/**
* @brief This function is called to print the instruction prefixes.
*/
ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES,
/**
* @brief This function is called to print the instruction mnemonic.
*/
ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC,
/**
* @brief This function is called to format an register operand.
*/
ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG, ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG,
/**
* @brief This function is called to format an memory operand.
*
* Replacing this function might indirectly disable some specific calls to the
* @c ZYDIS_FORMATTER_PRINT_ADDRESS function.
*/
ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_MEM, ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_MEM,
ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM, /**
* @brief This function is called to format an pointer operand.
*/
ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_PTR, ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_PTR,
ZYDIS_FORMATTER_HOOK_FORMAT_ADDRESS_ABS, /**
ZYDIS_FORMATTER_HOOK_FORMAT_ADDRESS_REL, * @brief This function is called to format an immediate operand.
ZYDIS_FORMATTER_HOOK_FORMAT_DISPLACEMENT, *
ZYDIS_FORMATTER_HOOK_FORMAT_IMMEDIATE * Replacing this function might indirectly disable some specific calls to the
* @c ZYDIS_FORMATTER_PRINT_ADDRESS function.
*/
ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM,
/**
* @brief This function is called right before formatting an memory operand to print the
* optional size-specifier.
*/
ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE,
/**
* @brief This function is called right after formatting an operand to print the optional
* avx-512 operand decorator.
*/
ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR,
/**
* @brief This function is called to print an absolute address.
*/
ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS
}; };
typedef const char* (*ZydisFormatterHookFormatMnemonicFunc)(void* context, /* ---------------------------------------------------------------------------------------------- */
const ZydisInstructionInfo* info, const ZydisOperandInfo* operand, uint64_t address,
int64_t* offset); typedef struct ZydisInstructionFormatter_ ZydisInstructionFormatter;
/**
* @brief Defines the @c ZydisFormatterNotifyFunc function pointer.
*
* @param formatter A pointer to the @c ZydisInstructionFormatter instance.
* @param info A pointer to the @c ZydisInstructionInfo struct.
*
* @return Returning a status code other than @c ZYDIS_STATUS_SUCCESS will immediately cause the
* formatting process to fail.
*
* This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRE and
* @c ZYDIS_FORMATTER_HOOK_POST hook-types.
*/
typedef ZydisStatus (*ZydisFormatterNotifyFunc)(ZydisInstructionFormatter* fornatter,
ZydisInstructionInfo* info);
/**
* @brief Defines the @c ZydisFormatterFormatFunc function pointer.
*
* @param formatter A pointer to the @c ZydisInstructionFormatter instance.
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param info A pointer to the @c ZydisInstructionInfo struct.
*
* @return Returning a status code other than @c ZYDIS_STATUS_SUCCESS will immediately cause the
* formatting process to fail.
*
* After appending text to the @c buffer you MUST increase the buffer-pointer by the size of the
* number of chars written. Not increasing the buffer-pointer will cause unexpected behavior.
*
* This function type is used for the @c ZYDIS_FORMATTER_HOOK_FORMAT_INSTRUCTION,
* @c ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES and @c ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC hook-types.
*/
typedef ZydisStatus (*ZydisFormatterFormatFunc)(ZydisInstructionFormatter* fornatter,
char** buffer, size_t bufferLen, ZydisInstructionInfo* info);
/**
* @brief Defines the @c ZydisFormatterFormatOperandFunc function pointer.
*
* @param formatter A pointer to the @c ZydisInstructionFormatter instance.
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param info A pointer to the @c ZydisInstructionInfo struct.
* @param operand A pointer to the @c ZydisOperandInfo struct.
*
* @return Returning a status code other than @c ZYDIS_STATUS_SUCCESS will immediately cause the
* formatting process to fail.
*
* After appending text to the @c buffer you MUST increase the buffer-pointer by the size of the
* number of chars written.
*
* Returning @c ZYDIS_STATUS_SUCCESS in one of the @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_X hooks
* without increasing the buffer-pointer is valid and will cause the formatter to omit the current
* operand.
*
* Returning @c ZYDIS_STATUS_SUCCESS in @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE or
* @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR without increasing the buffer-pointer is valid and
* signals that no operand-size or decorator should be printed for the current operand.
*
* Not increasing the buffer-pointer for any other hook-type will cause unexpected behavior.
*
* This function type is used for the @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG,
* @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_MEM, @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_PTR,
* @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM, @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE and
* @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR hook-types.
*/
typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(ZydisInstructionFormatter* fornatter,
char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand);
/**
* @brief Defines the @c ZydisFormatterFormatAddressFunc function pointer.
*
* @param formatter A pointer to the @c ZydisInstructionFormatter instance.
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param info A pointer to the @c ZydisInstructionInfo struct.
* @param operand A pointer to the @c ZydisOperandInfo struct.
*
* @return Returning a status code other than @c ZYDIS_STATUS_SUCCESS will immediately cause the
* formatting process to fail.
*
* After appending text to the @c buffer you MUST increase the buffer-pointer by the size of the
* number of chars written.
* Not increasing the buffer-pointer will cause unexpected behavior.
*
* This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS hook-type.
*/
typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(ZydisInstructionFormatter* fornatter,
char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand,
uint64_t address);
/** /**
* @brief Defines the @c ZydisInstructionFormatter struct. * @brief Defines the @c ZydisInstructionFormatter struct.
*/ */
typedef struct ZydisInstructionFormatter_ typedef struct ZydisInstructionFormatter_
{ {
ZydisFormatterStyle style; ZydisFormatFlags flags;
ZydisFormatterFlags flags;
ZydisFormatterAddressFormat addressFormat; ZydisFormatterAddressFormat addressFormat;
ZydisFormatterDisplacementFormat displacementFormat; ZydisFormatterDisplacementFormat displacementFormat;
ZydisFormatterImmediateFormat immediateFormat; ZydisFormatterImmediateFormat immediateFormat;
ZydisCustomSymbolResolver* symbolResolver; ZydisFormatterNotifyFunc funcPre;
ZydisFormatterNotifyFunc funcPost;
ZydisFormatterFormatFunc funcFormatInstruction;
ZydisFormatterFormatFunc funcPrintPrefixes;
ZydisFormatterFormatFunc funcPrintMnemonic;
ZydisFormatterFormatOperandFunc funcFormatOperandReg;
ZydisFormatterFormatOperandFunc funcFormatOperandMem;
ZydisFormatterFormatOperandFunc funcFormatOperandPtr;
ZydisFormatterFormatOperandFunc funcFormatOperandImm;
ZydisFormatterFormatOperandFunc funcPrintOperandSize;
ZydisFormatterFormatOperandFunc funcPrintDecorator;
ZydisFormatterFormatAddressFunc funcPrintAddress;
const char* prefixHEX;
const char* prefixOCT;
const char* delimMnemonic;
const char* delimOperands;
const char* fmtDecorator; // TODO:
} ZydisInstructionFormatter; } ZydisInstructionFormatter;
/* ============================================================================================== */ /* ============================================================================================== */
/* Exported functions */ /* Exported functions */
/* ============================================================================================== */ /* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Basic functions */
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Initializes the given @c ZydisInstructionFormatter instance. * @brief Initializes the given @c ZydisInstructionFormatter instance.
* *
* @param formatter A pointer to the instruction-formatter instance. * @param formatter A pointer to the @c ZydisInstructionFormatter instance.
* @param style The formatter style to use. * @param style The formatter style.
* *
* @return A zydis status code. * @return A zydis status code.
*/ */
@ -226,69 +403,45 @@ ZYDIS_EXPORT ZydisStatus ZydisFormatterInitInstructionFormatter(
/** /**
* @brief Initializes the given @c ZydisInstructionFormatter instance. * @brief Initializes the given @c ZydisInstructionFormatter instance.
* *
* @param formatter A pointer to the instruction-formatter instance. * @param formatter A pointer to the @c ZydisInstructionFormatter instance.
* @param style The formatter style to use. * @param style The formatter style.
* @param flags Additional formatter-flags. * @param addressFormat The address format.
* @param displacementFormat The displacement format.
* @param immmediateFormat The immediate format.
* *
* @return A zydis status code. * @return A zydis status code.
*/ */
ZYDIS_EXPORT ZydisStatus ZydisFormatterInitInstructionFormatterEx( ZYDIS_EXPORT ZydisStatus ZydisFormatterInitInstructionFormatterEx(
ZydisInstructionFormatter* formatter, ZydisFormatterStyle style, ZydisFormatterFlags flags); ZydisInstructionFormatter* formatter, ZydisFormatterStyle style, ZydisFormatFlags flags,
ZydisFormatterAddressFormat addressFormat, ZydisFormatterDisplacementFormat displacementFormat,
ZydisFormatterImmediateFormat immmediateFormat);
/** /**
* @brief Returns the symbol-resolver assigned to the given instruction-formatter instance. * @brief TODO:
* *
* @param formatter A pointer to the instruction-formatter instance. * @param formatter A pointer to the @c ZydisInstructionFormatter instance.
* @param symbolResolver A pointer to the memory that receives the current symbol-resolver * @param hook The formatter hook-type.
* pointer. * @param callback TODO: In Out
* *
* @return A zydis status code. * @return A zydis status code.
*/ */
ZYDIS_EXPORT ZydisStatus ZydisFormatterGetSymbolResolver(
const ZydisInstructionFormatter* formatter, ZydisCustomSymbolResolver** symbolResolver);
/**
* @brief Changes the symbol-resolver of the given instruction-formatter instance.
*
* @param formatter A pointer to the instruction-formatter instance.
* @param symbolResolver A pointer to the new symbol-resolver instance.
*
* @return The ZydisStatus.
*/
ZYDIS_EXPORT ZydisStatus ZydisFormatterSetSymbolResolver(
ZydisInstructionFormatter* formatter, ZydisCustomSymbolResolver* symbolResolver);
ZYDIS_EXPORT ZydisStatus ZydisFormatterSetHook(ZydisInstructionFormatter* formatter, ZYDIS_EXPORT ZydisStatus ZydisFormatterSetHook(ZydisInstructionFormatter* formatter,
ZydisFormatterHookType hook, const void* callback); ZydisFormatterHookType hook, const void** callback);
/** /**
* @brief Formats the given instruction and writes it into the output buffer. * @brief Formats the given instruction and writes it into the output buffer.
* *
* @param formatter A pointer to the instruction-formatter instance. * @param formatter A pointer to the @c ZydisInstructionFormatter instance.
* @param info A pointer to the instruction-info struct. * @param info A pointer to the @c ZydisInstructionInfo struct.
* @param buffer A pointer to the output buffer. * @param buffer A pointer to the string-buffer buffer.
* @param bufferLen The length of the output buffer. * @param bufferLen The length of the string-buffer.
* *
* @return A zydis status code. * @return A zydis status code.
*/ */
ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatInstruction( ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatInstruction(
ZydisInstructionFormatter* formatter, const ZydisInstructionInfo* info, char* buffer, ZydisInstructionFormatter* formatter, ZydisInstructionInfo* info, char* buffer,
size_t bufferLen); size_t bufferLen);
/* ---------------------------------------------------------------------------------------------- */
/* Formatting functions for custom implementations */
/* ---------------------------------------------------------------------------------------------- */
ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatOperandIntel(
const ZydisInstructionFormatter* formatter, char* buffer, size_t bufferLen, size_t* offset,
const ZydisInstructionInfo* info, const ZydisOperandInfo* operand, uint16_t typecast);
ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatOperandMemIntel(
const ZydisInstructionFormatter* formatter, char* buffer, size_t bufferLen, size_t* offset,
const ZydisInstructionInfo* info, const ZydisOperandInfo* operand, uint16_t typecast);
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */ /* ============================================================================================== */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -45,16 +45,22 @@ extern "C" {
/* Enums and types */ /* Enums and types */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
typedef struct ZydisCustomInput_ ZydisCustomInput;
/** /**
* @brief Defines the @c ZydisInputNextFunc function pointer used in the @c ZydisCustomInput * @brief Defines the @c ZydisInputNextFunc function pointer used in the @c ZydisCustomInput
* struct. * struct.
* *
* @param input The @c ZydisCustomInput instance.
* @param data A pointer to the memory that receives the input byte.
*
* @return Return @c TRUE, fi the function succeeded or @c FALSE, if the input data-source has no
* more data available
*
* This function should return the byte at the current input-position and increase the position * This function should return the byte at the current input-position and increase the position
* by one. If the input data-source has no more data available, return @c FALSE. * by one.
*/ */
typedef bool (*ZydisInputNextFunc)(void* context, uint8_t* data); typedef bool (*ZydisInputNextFunc)(ZydisCustomInput* input, uint8_t* data);
/* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Defines the zydis custom input struct. * @brief Defines the zydis custom input struct.
@ -90,11 +96,11 @@ typedef struct ZydisMemoryInput_
*/ */
ZydisCustomInput input; ZydisCustomInput input;
/** /**
* @brief A pointer to the mem buffer. * @brief A pointer to the memory buffer.
*/ */
const uint8_t* inputBuffer; const uint8_t* inputBuffer;
/** /**
* @brief The length of the mem buffer. * @brief The length of the memory buffer.
*/ */
uint64_t inputBufferLen; uint64_t inputBufferLen;
/** /**
@ -111,8 +117,8 @@ typedef struct ZydisMemoryInput_
* @brief Initializes the given @c ZydisMemoryInput instance. * @brief Initializes the given @c ZydisMemoryInput instance.
* *
* @param input A pointer to the input data-source instance. * @param input A pointer to the input data-source instance.
* @param buffer The mem buffer to use. * @param buffer The memory buffer to use.
* @param length The length of the mem buffer. * @param length The length of the memory buffer.
* *
* @return A zydis status code. * @return A zydis status code.
*/ */

View File

@ -592,6 +592,10 @@ enum ZydisAVXRoundingModes // TODO: Mirror "real" values from doc
*/ */
typedef struct ZydisOperandInfo_ typedef struct ZydisOperandInfo_
{ {
/**
* @brief The operand-id.
*/
uint8_t id;
/** /**
* @brief The type of the operand. * @brief The type of the operand.
*/ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -538,8 +538,8 @@
#define /*0219*/ ZYDIS_MNEMONIC_PMULLW 0x0219 #define /*0219*/ ZYDIS_MNEMONIC_PMULLW 0x0219
#define /*021A*/ ZYDIS_MNEMONIC_PMULUDQ 0x021A #define /*021A*/ ZYDIS_MNEMONIC_PMULUDQ 0x021A
#define /*021B*/ ZYDIS_MNEMONIC_POP 0x021B #define /*021B*/ ZYDIS_MNEMONIC_POP 0x021B
#define /*021C*/ ZYDIS_MNEMONIC_POPAL 0x021C #define /*021C*/ ZYDIS_MNEMONIC_POPA 0x021C
#define /*021D*/ ZYDIS_MNEMONIC_POPAW 0x021D #define /*021D*/ ZYDIS_MNEMONIC_POPAD 0x021D
#define /*021E*/ ZYDIS_MNEMONIC_POPCNT 0x021E #define /*021E*/ ZYDIS_MNEMONIC_POPCNT 0x021E
#define /*021F*/ ZYDIS_MNEMONIC_POPF 0x021F #define /*021F*/ ZYDIS_MNEMONIC_POPF 0x021F
#define /*0220*/ ZYDIS_MNEMONIC_POPFD 0x0220 #define /*0220*/ ZYDIS_MNEMONIC_POPFD 0x0220
@ -589,8 +589,8 @@
#define /*024C*/ ZYDIS_MNEMONIC_PUNPCKLQDQ 0x024C #define /*024C*/ ZYDIS_MNEMONIC_PUNPCKLQDQ 0x024C
#define /*024D*/ ZYDIS_MNEMONIC_PUNPCKLWD 0x024D #define /*024D*/ ZYDIS_MNEMONIC_PUNPCKLWD 0x024D
#define /*024E*/ ZYDIS_MNEMONIC_PUSH 0x024E #define /*024E*/ ZYDIS_MNEMONIC_PUSH 0x024E
#define /*024F*/ ZYDIS_MNEMONIC_PUSHAL 0x024F #define /*024F*/ ZYDIS_MNEMONIC_PUSHA 0x024F
#define /*0250*/ ZYDIS_MNEMONIC_PUSHAW 0x0250 #define /*0250*/ ZYDIS_MNEMONIC_PUSHAD 0x0250
#define /*0251*/ ZYDIS_MNEMONIC_PUSHF 0x0251 #define /*0251*/ ZYDIS_MNEMONIC_PUSHF 0x0251
#define /*0252*/ ZYDIS_MNEMONIC_PUSHFD 0x0252 #define /*0252*/ ZYDIS_MNEMONIC_PUSHFD 0x0252
#define /*0253*/ ZYDIS_MNEMONIC_PUSHFQ 0x0253 #define /*0253*/ ZYDIS_MNEMONIC_PUSHFQ 0x0253

View File

@ -538,8 +538,8 @@
/*0219*/ "pmullw", /*0219*/ "pmullw",
/*021A*/ "pmuludq", /*021A*/ "pmuludq",
/*021B*/ "pop", /*021B*/ "pop",
/*021C*/ "popal", /*021C*/ "popa",
/*021D*/ "popaw", /*021D*/ "popad",
/*021E*/ "popcnt", /*021E*/ "popcnt",
/*021F*/ "popf", /*021F*/ "popf",
/*0220*/ "popfd", /*0220*/ "popfd",
@ -589,8 +589,8 @@
/*024C*/ "punpcklqdq", /*024C*/ "punpcklqdq",
/*024D*/ "punpcklwd", /*024D*/ "punpcklwd",
/*024E*/ "push", /*024E*/ "push",
/*024F*/ "pushal", /*024F*/ "pusha",
/*0250*/ "pushaw", /*0250*/ "pushad",
/*0251*/ "pushf", /*0251*/ "pushf",
/*0252*/ "pushfd", /*0252*/ "pushfd",
/*0253*/ "pushfq", /*0253*/ "pushfq",

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,6 @@
#include <Zydis/Input.h> #include <Zydis/Input.h>
#include <Zydis/Decoder.h> #include <Zydis/Decoder.h>
#include <Zydis/Formatter.h> #include <Zydis/Formatter.h>
#include <Zydis/SymbolResolver.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -1551,8 +1551,9 @@ static ZydisDecoderStatus ZydisDecodeOperands(ZydisInstructionDecoder* decoder,
ZYDIS_ASSERT((operandCount > 0) && (operandCount < 6)); ZYDIS_ASSERT((operandCount > 0) && (operandCount < 6));
info->operandCount = operandCount; info->operandCount = operandCount;
for (int i = 0; i < operandCount; ++i) for (uint8_t i = 0; i < operandCount; ++i)
{ {
info->operand[i].id = i;
ZydisSemanticOperandType type = operands[i].type; ZydisSemanticOperandType type = operands[i].type;
if (type == ZYDIS_SEM_OPERAND_TYPE_UNUSED) if (type == ZYDIS_SEM_OPERAND_TYPE_UNUSED)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -36,13 +36,13 @@
/* Internal functions */ /* Internal functions */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
static bool ZydisMemoryInputNext(ZydisMemoryInput* context, uint8_t* data) static bool ZydisMemoryInputNext(ZydisMemoryInput* input, uint8_t* data)
{ {
if (context->inputBufferPos >= context->inputBufferLen) if (input->inputBufferPos >= input->inputBufferLen)
{ {
return false; return false;
} }
*data = context->inputBuffer[context->inputBufferPos++]; *data = input->inputBuffer[input->inputBufferPos++];
return true; return true;
} }
@ -73,9 +73,9 @@ ZydisStatus ZydisInputInitMemoryInput(ZydisMemoryInput* input, const void* buffe
/* Internal functions */ /* Internal functions */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
static bool ZydisFileInputNext(ZydisFileInput* context, uint8_t* data) static bool ZydisFileInputNext(ZydisFileInput* input, uint8_t* data)
{ {
int c = fgetc(context->file); int c = fgetc(input->file);
*data = (uint8_t)c; *data = (uint8_t)c;
return (c != EOF); return (c != EOF);
} }