2016-05-26 03:25:48 +08:00
|
|
|
/***************************************************************************************************
|
|
|
|
|
2016-12-05 09:24:01 +08:00
|
|
|
Zyan Disassembler Library (Zydis)
|
2016-05-26 03:25:48 +08:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
***************************************************************************************************/
|
|
|
|
|
|
|
|
#include <string.h>
|
2017-09-14 06:59:23 +08:00
|
|
|
#include <Zydis/CommonTypes.h>
|
2016-05-26 03:25:48 +08:00
|
|
|
#include <Zydis/Formatter.h>
|
|
|
|
#include <Zydis/Utils.h>
|
2017-09-14 06:59:23 +08:00
|
|
|
#include <FormatHelper.h>
|
2016-05-26 03:25:48 +08:00
|
|
|
|
2016-11-26 20:08:37 +08:00
|
|
|
/* ============================================================================================== */
|
|
|
|
/* Instruction formatter */
|
|
|
|
/* ============================================================================================== */
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
/* Internal macros */
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
|
2017-09-14 06:59:23 +08:00
|
|
|
#define ZYDIS_LETTER_CASE \
|
2016-11-26 20:08:37 +08:00
|
|
|
(formatter->flags & ZYDIS_FMTFLAG_UPPERCASE) ? \
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT
|
2016-11-26 20:08:37 +08:00
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
/* Intel style */
|
2016-05-26 03:25:48 +08:00
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterPrintPrefixesIntel(const ZydisFormatter* formatter,
|
2017-10-15 00:37:59 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction, void* userData)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, "lock ", ZYDIS_LETTER_CASE);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REP)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, "rep ", ZYDIS_LETTER_CASE);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2017-07-03 09:14:01 +08:00
|
|
|
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPE)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, "repe ", ZYDIS_LETTER_CASE);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2017-07-03 09:14:01 +08:00
|
|
|
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, "repne ", ZYDIS_LETTER_CASE);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (instruction->attributes & ZYDIS_ATTRIB_HAS_BOUND)
|
2016-12-05 09:24:01 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, "bnd ", ZYDIS_LETTER_CASE);
|
2016-12-05 09:24:01 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, "xacquire ", ZYDIS_LETTER_CASE);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2017-07-03 09:14:01 +08:00
|
|
|
if (instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, "xrelease ", ZYDIS_LETTER_CASE);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterPrintMnemonicIntel(const ZydisFormatter* formatter,
|
2017-10-15 00:37:59 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction, void* userData)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2017-09-24 01:46:27 +08:00
|
|
|
char* bufEnd = *buffer + bufferLen;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
const char* mnemonic = ZydisMnemonicGetString(instruction->mnemonic);
|
2016-11-26 20:08:37 +08:00
|
|
|
if (!mnemonic)
|
|
|
|
{
|
|
|
|
mnemonic = "invalid";
|
|
|
|
}
|
2017-09-24 01:46:27 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, mnemonic, ZYDIS_LETTER_CASE));
|
|
|
|
|
|
|
|
if (instruction->attributes & ZYDIS_ATTRIB_IS_FAR_BRANCH)
|
|
|
|
{
|
|
|
|
return ZydisPrintStr(buffer, bufEnd - *buffer, " far", ZYDIS_LETTER_CASE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterFormatOperandRegIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, void* userData)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2017-07-05 01:02:11 +08:00
|
|
|
if ((operand->id == 1) && (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK))
|
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-09-20 21:46:51 +08:00
|
|
|
const char* reg = ZydisRegisterGetString(operand->reg.value);
|
2016-11-26 20:08:37 +08:00
|
|
|
if (!reg)
|
|
|
|
{
|
|
|
|
reg = "invalid";
|
|
|
|
}
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, reg, ZYDIS_LETTER_CASE);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, void* userData)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* bufEnd = *buffer + bufferLen;
|
|
|
|
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, "[", ZYDIS_LETTER_CASE_DEFAULT));
|
2016-11-26 20:08:37 +08:00
|
|
|
|
2017-06-14 02:17:20 +08:00
|
|
|
if (operand->mem.disp.hasDisplacement && (
|
2016-12-05 09:24:01 +08:00
|
|
|
(operand->mem.base == ZYDIS_REGISTER_NONE) ||
|
|
|
|
(operand->mem.base == ZYDIS_REGISTER_EIP) ||
|
|
|
|
(operand->mem.base == ZYDIS_REGISTER_RIP)) &&
|
2016-11-26 20:08:37 +08:00
|
|
|
(operand->mem.index == ZYDIS_REGISTER_NONE) && (operand->mem.scale == 0))
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-09-25 23:59:14 +08:00
|
|
|
// EIP/RIP-relative or absolute-displacement address operand
|
|
|
|
if ((formatter->addressFormat == ZYDIS_FORMATTER_ADDR_DEFAULT) ||
|
|
|
|
(formatter->addressFormat == ZYDIS_FORMATTER_ADDR_ABSOLUTE) ||
|
|
|
|
(operand->mem.base == ZYDIS_REGISTER_NONE))
|
2017-09-25 22:18:01 +08:00
|
|
|
{
|
2017-09-25 23:59:14 +08:00
|
|
|
uint64_t address;
|
|
|
|
ZYDIS_CHECK(ZydisCalcAbsoluteAddress(instruction, operand, &address));
|
2017-09-25 22:18:01 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPrintAddress(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, operand, address, userData));
|
2017-09-25 22:18:01 +08:00
|
|
|
} else
|
|
|
|
{
|
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer,
|
|
|
|
ZydisRegisterGetString(operand->mem.base), ZYDIS_LETTER_CASE));
|
|
|
|
ZYDIS_CHECK(formatter->funcPrintDisplacement(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, operand, userData));
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
} else
|
|
|
|
{
|
|
|
|
// Regular memory operand
|
|
|
|
if (operand->mem.base != ZYDIS_REGISTER_NONE)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
const char* reg = ZydisRegisterGetString(operand->mem.base);
|
|
|
|
if (!reg)
|
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, ZYDIS_LETTER_CASE));
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
if (operand->mem.index != ZYDIS_REGISTER_NONE)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
const char* reg = ZydisRegisterGetString(operand->mem.index);
|
|
|
|
if (!reg)
|
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2017-09-14 06:59:23 +08:00
|
|
|
if (operand->mem.base != ZYDIS_REGISTER_NONE)
|
|
|
|
{
|
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, "+", ZYDIS_LETTER_CASE_DEFAULT));
|
|
|
|
}
|
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, ZYDIS_LETTER_CASE));
|
2016-11-26 20:08:37 +08:00
|
|
|
if (operand->mem.scale)
|
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, "*", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-09-25 10:10:11 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintDecU(buffer, bufEnd - *buffer, operand->mem.scale, 0));
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-28 18:14:47 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPrintDisplacement(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, operand, userData));
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufEnd - *buffer, "]", ZYDIS_LETTER_CASE_DEFAULT);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterFormatOperandPtrIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, void* userData)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
2017-09-14 06:59:23 +08:00
|
|
|
char* bufEnd = *buffer + bufferLen;
|
2017-09-14 08:59:20 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintHexU(
|
2017-09-14 06:59:23 +08:00
|
|
|
buffer, bufEnd - *buffer, operand->ptr.segment, 4, ZYDIS_TRUE, ZYDIS_TRUE));
|
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexU(
|
2017-09-14 06:59:23 +08:00
|
|
|
buffer, bufEnd - *buffer, operand->ptr.offset, 8, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, void* userData)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
|
2016-11-26 20:08:37 +08:00
|
|
|
// The immediate operand contains an address
|
|
|
|
if (operand->imm.isRelative)
|
|
|
|
{
|
2016-12-05 09:24:01 +08:00
|
|
|
ZydisBool printSignedHEX = ZYDIS_FALSE;
|
2016-11-26 20:08:37 +08:00
|
|
|
switch (formatter->addressFormat)
|
|
|
|
{
|
|
|
|
case ZYDIS_FORMATTER_ADDR_DEFAULT:
|
|
|
|
case ZYDIS_FORMATTER_ADDR_ABSOLUTE:
|
|
|
|
{
|
|
|
|
uint64_t address;
|
2017-09-25 23:59:14 +08:00
|
|
|
ZYDIS_CHECK(ZydisCalcAbsoluteAddress(instruction, operand, &address));
|
2017-07-03 09:14:01 +08:00
|
|
|
return formatter->funcPrintAddress(formatter, buffer, bufferLen, instruction, operand,
|
2017-10-15 00:37:59 +08:00
|
|
|
address, userData);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
|
|
|
case ZYDIS_FORMATTER_ADDR_RELATIVE_SIGNED:
|
2016-12-05 09:24:01 +08:00
|
|
|
printSignedHEX = ZYDIS_TRUE;
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_ADDR_RELATIVE_UNSIGNED:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2017-09-14 06:59:23 +08:00
|
|
|
|
2017-09-25 22:18:01 +08:00
|
|
|
if (printSignedHEX)
|
|
|
|
{
|
|
|
|
return ZydisPrintHexS(
|
|
|
|
buffer, bufferLen, (int32_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
|
|
|
}
|
|
|
|
return ZydisPrintHexU(buffer, bufferLen, operand->imm.value.u, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2016-05-26 03:25:48 +08:00
|
|
|
|
2016-11-26 20:08:37 +08:00
|
|
|
// The immediate operand contains an actual ordinal value
|
2017-10-15 00:37:59 +08:00
|
|
|
return formatter->funcPrintImmediate(
|
|
|
|
formatter, buffer, bufferLen, instruction, operand, userData);
|
2016-11-28 18:14:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterPrintAddressIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, uint64_t address, void* userData)
|
2016-11-28 18:14:47 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-11-28 18:14:47 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2017-09-25 22:18:01 +08:00
|
|
|
switch (instruction->stackWidth)
|
2016-11-28 18:14:47 +08:00
|
|
|
{
|
2017-06-13 01:16:01 +08:00
|
|
|
case 16:
|
2017-09-25 10:10:11 +08:00
|
|
|
return ZydisPrintHexU(buffer, bufferLen, (uint16_t)address, 4, ZYDIS_TRUE, ZYDIS_TRUE);
|
2017-06-13 01:16:01 +08:00
|
|
|
case 32:
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexU(buffer, bufferLen, (uint32_t)address, 8, ZYDIS_TRUE, ZYDIS_TRUE);
|
2017-06-13 01:16:01 +08:00
|
|
|
case 64:
|
2017-09-25 10:10:11 +08:00
|
|
|
return ZydisPrintHexU(buffer, bufferLen, address, 16, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-11-28 18:14:47 +08:00
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterPrintDisplacementIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, void* userData)
|
2016-11-28 18:14:47 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-11-28 18:14:47 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2016-12-05 09:24:01 +08:00
|
|
|
|
2017-07-01 07:10:03 +08:00
|
|
|
if (operand->mem.disp.hasDisplacement && ((operand->mem.disp.value) ||
|
2016-11-28 18:14:47 +08:00
|
|
|
((operand->mem.base == ZYDIS_REGISTER_NONE) &&
|
|
|
|
(operand->mem.index == ZYDIS_REGISTER_NONE))))
|
|
|
|
{
|
2016-12-05 09:24:01 +08:00
|
|
|
ZydisBool printSignedHEX =
|
|
|
|
(formatter->displacementFormat != ZYDIS_FORMATTER_DISP_HEX_UNSIGNED);
|
2017-07-01 07:10:03 +08:00
|
|
|
if (printSignedHEX && (operand->mem.disp.value < 0) && (
|
2016-11-28 18:14:47 +08:00
|
|
|
(operand->mem.base != ZYDIS_REGISTER_NONE) ||
|
|
|
|
(operand->mem.index != ZYDIS_REGISTER_NONE)))
|
|
|
|
{
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexS(
|
2017-09-14 06:59:23 +08:00
|
|
|
buffer, bufferLen, operand->mem.disp.value, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
|
|
|
}
|
|
|
|
char* bufEnd = *buffer + bufferLen;
|
|
|
|
if ((operand->mem.base != ZYDIS_REGISTER_NONE) ||
|
|
|
|
(operand->mem.index != ZYDIS_REGISTER_NONE))
|
|
|
|
{
|
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "+", ZYDIS_LETTER_CASE_DEFAULT));
|
2016-11-28 18:14:47 +08:00
|
|
|
}
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexU(
|
|
|
|
buffer, bufEnd - *buffer, (uint64_t)operand->mem.disp.value, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-11-28 18:14:47 +08:00
|
|
|
}
|
2016-12-05 09:24:01 +08:00
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
2016-11-28 18:14:47 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, void* userData)
|
2016-11-28 18:14:47 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-11-28 18:14:47 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2016-12-05 09:24:01 +08:00
|
|
|
ZydisBool printSignedHEX = (formatter->immediateFormat == ZYDIS_FORMATTER_IMM_HEX_SIGNED);
|
2016-11-26 20:08:37 +08:00
|
|
|
if (formatter->immediateFormat == ZYDIS_FORMATTER_IMM_HEX_AUTO)
|
|
|
|
{
|
|
|
|
printSignedHEX = operand->imm.isSigned;
|
|
|
|
}
|
2017-09-14 06:59:23 +08:00
|
|
|
|
2017-07-01 07:10:03 +08:00
|
|
|
if (printSignedHEX && (operand->imm.value.s < 0))
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
|
|
|
switch (operand->size)
|
|
|
|
{
|
|
|
|
case 8:
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexS(
|
2017-09-14 06:59:23 +08:00
|
|
|
buffer, bufferLen, (int8_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
case 16:
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexS(
|
2017-09-14 06:59:23 +08:00
|
|
|
buffer, bufferLen, (int16_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
case 32:
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexS(
|
2017-09-14 06:59:23 +08:00
|
|
|
buffer, bufferLen, (int32_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
case 64:
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexS(
|
|
|
|
buffer, bufferLen, operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2017-09-22 04:16:37 +08:00
|
|
|
switch (instruction->operandWidth)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-09-22 04:16:37 +08:00
|
|
|
case 8:
|
|
|
|
return ZydisPrintHexU(
|
|
|
|
buffer, bufferLen, (uint8_t)operand->imm.value.u, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
case 16:
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexU(
|
2017-09-14 06:59:23 +08:00
|
|
|
buffer, bufferLen, (uint16_t)operand->imm.value.u, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
case 32:
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexU(
|
2017-09-21 22:53:23 +08:00
|
|
|
buffer, bufferLen, (uint32_t)operand->imm.value.u, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
case 64:
|
2017-09-14 08:59:20 +08:00
|
|
|
return ZydisPrintHexU(
|
|
|
|
buffer, bufferLen, operand->imm.value.u, 2, ZYDIS_TRUE, ZYDIS_TRUE);
|
2016-05-26 03:25:48 +08:00
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, void* userData)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2017-07-15 04:54:22 +08:00
|
|
|
// TODO: refactor
|
|
|
|
|
2016-11-26 20:08:37 +08:00
|
|
|
uint32_t typecast = 0;
|
|
|
|
if (formatter->flags & ZYDIS_FMTFLAG_FORCE_OPERANDSIZE)
|
|
|
|
{
|
2017-06-20 09:16:17 +08:00
|
|
|
if ((operand->type == ZYDIS_OPERAND_TYPE_MEMORY) && (!operand->mem.isAddressGenOnly))
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-07-03 09:14:01 +08:00
|
|
|
typecast = instruction->operands[operand->id].size;
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2017-06-20 09:16:17 +08:00
|
|
|
} else if ((operand->type == ZYDIS_OPERAND_TYPE_MEMORY) && (!operand->mem.isAddressGenOnly))
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
|
|
|
switch (operand->id)
|
|
|
|
{
|
|
|
|
case 0:
|
2017-07-05 01:02:11 +08:00
|
|
|
typecast =
|
|
|
|
((instruction->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) ||
|
|
|
|
(instruction->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) ||
|
|
|
|
(instruction->operands[0].size != instruction->operands[1].size)) ?
|
|
|
|
instruction->operands[0].size : 0;
|
2016-11-26 20:08:37 +08:00
|
|
|
if (!typecast &&
|
2017-07-03 09:14:01 +08:00
|
|
|
(instruction->operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) &&
|
2017-09-20 21:46:51 +08:00
|
|
|
(instruction->operands[1].reg.value == ZYDIS_REGISTER_CL))
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-07-03 09:14:01 +08:00
|
|
|
switch (instruction->mnemonic)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
|
|
|
case ZYDIS_MNEMONIC_RCL:
|
|
|
|
case ZYDIS_MNEMONIC_ROL:
|
|
|
|
case ZYDIS_MNEMONIC_ROR:
|
|
|
|
case ZYDIS_MNEMONIC_RCR:
|
|
|
|
case ZYDIS_MNEMONIC_SHL:
|
|
|
|
case ZYDIS_MNEMONIC_SHR:
|
|
|
|
case ZYDIS_MNEMONIC_SAR:
|
2017-07-03 09:14:01 +08:00
|
|
|
typecast = instruction->operands[0].size;
|
2016-11-26 20:08:37 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
typecast =
|
2017-07-05 01:02:11 +08:00
|
|
|
(instruction->operands[operand->id - 1].size !=
|
|
|
|
instruction->operands[operand->id].size) ?
|
|
|
|
instruction->operands[operand->id].size : 0;
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-05-26 03:25:48 +08:00
|
|
|
if (typecast)
|
|
|
|
{
|
|
|
|
char* str = "";
|
|
|
|
switch (typecast)
|
|
|
|
{
|
|
|
|
case 8:
|
|
|
|
str = "byte ptr ";
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
str = "word ptr ";
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
str = "dword ptr ";
|
|
|
|
break;
|
|
|
|
case 48:
|
|
|
|
str = "fword ptr ";
|
|
|
|
break;
|
|
|
|
case 64:
|
|
|
|
str = "qword ptr ";
|
|
|
|
break;
|
|
|
|
case 80:
|
|
|
|
str = "tbyte ptr ";
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
str = "xmmword ptr ";
|
|
|
|
break;
|
|
|
|
case 256:
|
|
|
|
str = "ymmword ptr ";
|
|
|
|
break;
|
|
|
|
case 512:
|
|
|
|
str = "zmmword ptr ";
|
|
|
|
break;
|
2016-11-12 05:03:26 +08:00
|
|
|
default:
|
|
|
|
break;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2017-09-14 06:59:23 +08:00
|
|
|
return ZydisPrintStr(buffer, bufferLen, str, ZYDIS_LETTER_CASE);
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, void* userData)
|
2016-11-27 01:41:58 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-11-27 01:41:58 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2017-09-14 06:59:23 +08:00
|
|
|
char* bufEnd = *buffer + bufferLen;
|
2016-11-27 01:41:58 +08:00
|
|
|
switch (operand->mem.segment)
|
|
|
|
{
|
|
|
|
case ZYDIS_REGISTER_ES:
|
2017-01-20 07:01:56 +08:00
|
|
|
case ZYDIS_REGISTER_CS:
|
2016-11-27 01:41:58 +08:00
|
|
|
case ZYDIS_REGISTER_FS:
|
|
|
|
case ZYDIS_REGISTER_GS:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer,
|
|
|
|
ZydisRegisterGetString(operand->mem.segment), ZYDIS_LETTER_CASE));
|
|
|
|
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
|
2017-01-20 07:01:56 +08:00
|
|
|
case ZYDIS_REGISTER_SS:
|
2016-11-27 01:41:58 +08:00
|
|
|
if ((formatter->flags & ZYDIS_FMTFLAG_FORCE_SEGMENTS) ||
|
2017-07-03 09:14:01 +08:00
|
|
|
(instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS))
|
2016-11-27 01:41:58 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer,
|
|
|
|
ZydisRegisterGetString(operand->mem.segment), ZYDIS_LETTER_CASE));
|
|
|
|
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
|
2016-11-27 01:41:58 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZYDIS_REGISTER_DS:
|
|
|
|
if ((formatter->flags & ZYDIS_FMTFLAG_FORCE_SEGMENTS) ||
|
2017-07-03 09:14:01 +08:00
|
|
|
(instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS))
|
2016-11-27 01:41:58 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer,
|
|
|
|
ZydisRegisterGetString(operand->mem.segment), ZYDIS_LETTER_CASE));
|
|
|
|
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
|
2016-11-27 01:41:58 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-12-05 09:24:01 +08:00
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
2016-11-27 01:41:58 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* formatter,
|
2017-10-14 19:39:00 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction,
|
2017-10-15 00:37:59 +08:00
|
|
|
const ZydisDecodedOperand* operand, ZydisDecoratorType type, void* userData)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
(void)userData;
|
|
|
|
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
2017-06-16 09:25:39 +08:00
|
|
|
const char* bufEnd = *buffer + bufferLen;
|
2017-07-05 01:02:11 +08:00
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case ZYDIS_DECORATOR_TYPE_MASK:
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-07-15 09:39:48 +08:00
|
|
|
if (instruction->avx.mask.reg != ZYDIS_REGISTER_K0)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-07-15 09:39:48 +08:00
|
|
|
const char* reg = ZydisRegisterGetString(instruction->avx.mask.reg);
|
2016-11-26 20:08:37 +08:00
|
|
|
if (!reg)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " {", ZYDIS_LETTER_CASE_DEFAULT));
|
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, ZYDIS_LETTER_CASE));
|
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, "}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-15 04:54:22 +08:00
|
|
|
if (instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZERO)
|
2017-06-16 22:27:37 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {z}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ZYDIS_DECORATOR_TYPE_BROADCAST:
|
|
|
|
if (!instruction->avx.broadcast.isStatic)
|
2016-11-26 20:08:37 +08:00
|
|
|
{
|
2017-07-05 01:02:11 +08:00
|
|
|
switch (instruction->avx.broadcast.mode)
|
2017-06-24 08:16:16 +08:00
|
|
|
{
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_BROADCAST_MODE_INVALID:
|
2017-06-24 08:16:16 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_BROADCAST_MODE_1_TO_2:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to2}", ZYDIS_LETTER_CASE_DEFAULT));
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_BROADCAST_MODE_1_TO_4:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to4}", ZYDIS_LETTER_CASE_DEFAULT));
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_BROADCAST_MODE_1_TO_8:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to8}", ZYDIS_LETTER_CASE_DEFAULT));
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_BROADCAST_MODE_1_TO_16:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to16}", ZYDIS_LETTER_CASE_DEFAULT));
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_BROADCAST_MODE_4_TO_8:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {4to8}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_BROADCAST_MODE_4_TO_16:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {4to16}", ZYDIS_LETTER_CASE_DEFAULT));
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_DECORATOR_TYPE_ROUNDING_CONTROL:
|
|
|
|
if (instruction->avx.hasSAE)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-09-11 03:43:52 +08:00
|
|
|
switch (instruction->avx.rounding.mode)
|
2017-06-29 01:50:33 +08:00
|
|
|
{
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_ROUNDING_MODE_INVALID:
|
|
|
|
break;
|
|
|
|
case ZYDIS_ROUNDING_MODE_RN:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(
|
|
|
|
buffer, bufEnd - *buffer, " {rn-sae}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_ROUNDING_MODE_RD:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(
|
|
|
|
buffer, bufEnd - *buffer, " {rd-sae}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-06-24 08:16:16 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_ROUNDING_MODE_RU:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(
|
|
|
|
buffer, bufEnd - *buffer, " {ru-sae}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-06-24 08:16:16 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_ROUNDING_MODE_RZ:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(
|
|
|
|
buffer, bufEnd - *buffer, " {rz-sae}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
{
|
2017-09-11 03:43:52 +08:00
|
|
|
switch (instruction->avx.rounding.mode)
|
2017-07-05 01:02:11 +08:00
|
|
|
{
|
|
|
|
case ZYDIS_ROUNDING_MODE_INVALID:
|
2017-06-24 08:16:16 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_ROUNDING_MODE_RN:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {rn}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-06-24 08:16:16 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_ROUNDING_MODE_RD:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {rd}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-06-24 08:16:16 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_ROUNDING_MODE_RU:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {ru}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-06-24 08:16:16 +08:00
|
|
|
break;
|
2017-07-05 01:02:11 +08:00
|
|
|
case ZYDIS_ROUNDING_MODE_RZ:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {rz}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-06-24 08:16:16 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2017-07-05 01:02:11 +08:00
|
|
|
}
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_DECORATOR_TYPE_SAE:
|
2017-09-11 03:43:52 +08:00
|
|
|
if (instruction->avx.hasSAE && !instruction->avx.rounding.mode)
|
2017-07-25 20:58:17 +08:00
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {sae}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-25 20:58:17 +08:00
|
|
|
}
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_DECORATOR_TYPE_SWIZZLE:
|
2017-09-11 03:43:52 +08:00
|
|
|
switch (instruction->avx.swizzle.mode)
|
2017-07-05 01:02:11 +08:00
|
|
|
{
|
|
|
|
case ZYDIS_SWIZZLE_MODE_INVALID:
|
|
|
|
case ZYDIS_SWIZZLE_MODE_DCBA:
|
|
|
|
// Nothing to do here
|
|
|
|
break;
|
|
|
|
case ZYDIS_SWIZZLE_MODE_CDAB:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {cdab}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_SWIZZLE_MODE_BADC:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {badc}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_SWIZZLE_MODE_DACB:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {dacb}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_SWIZZLE_MODE_AAAA:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {aaaa}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_SWIZZLE_MODE_BBBB:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {bbbb}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_SWIZZLE_MODE_CCCC:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {cccc}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_SWIZZLE_MODE_DDDD:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {dddd}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZYDIS_DECORATOR_TYPE_CONVERSION:
|
2017-09-11 03:43:52 +08:00
|
|
|
switch (instruction->avx.conversion.mode)
|
2017-07-05 01:02:11 +08:00
|
|
|
{
|
|
|
|
case ZYDIS_CONVERSION_MODE_INVALID:
|
|
|
|
break;
|
|
|
|
case ZYDIS_CONVERSION_MODE_FLOAT16:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {float16}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_CONVERSION_MODE_SINT8:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {sint8}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_CONVERSION_MODE_UINT8:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {uint8}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_CONVERSION_MODE_SINT16:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {sint16}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_CONVERSION_MODE_UINT16:
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {uint16}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ZYDIS_DECORATOR_TYPE_EVICTION_HINT:
|
|
|
|
if (instruction->avx.hasEvictionHint)
|
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
ZydisPrintStr(buffer, bufEnd - *buffer, " {eh}", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-07-05 01:02:11 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2017-06-16 09:25:39 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatter,
|
2017-10-15 00:37:59 +08:00
|
|
|
char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction, void* userData)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
|
2017-06-16 09:25:39 +08:00
|
|
|
char* bufEnd = *buffer + bufferLen;
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
formatter->funcPrintPrefixes(formatter, buffer, bufEnd - *buffer, instruction, userData));
|
|
|
|
ZYDIS_CHECK(
|
|
|
|
formatter->funcPrintMnemonic(formatter, buffer, bufEnd - *buffer, instruction, userData));
|
2016-11-26 20:08:37 +08:00
|
|
|
|
|
|
|
char* bufRestore = *buffer;
|
2017-07-03 09:14:01 +08:00
|
|
|
for (uint8_t i = 0; i < instruction->operandCount; ++i)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-07-03 09:14:01 +08:00
|
|
|
if (instruction->operands[i].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN)
|
2017-06-16 09:25:39 +08:00
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-08-14 23:10:24 +08:00
|
|
|
if (i == 0)
|
|
|
|
{
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " ", ZYDIS_LETTER_CASE_DEFAULT));
|
2017-08-14 23:10:24 +08:00
|
|
|
} else
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
bufRestore = *buffer;
|
2017-09-14 06:59:23 +08:00
|
|
|
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ", ", ZYDIS_LETTER_CASE_DEFAULT));
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
|
|
|
const char* bufPreOperand = *buffer;
|
2017-07-03 09:14:01 +08:00
|
|
|
switch (instruction->operands[i].type)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
case ZYDIS_OPERAND_TYPE_REGISTER:
|
|
|
|
ZYDIS_CHECK(formatter->funcFormatOperandReg(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, &instruction->operands[i], userData));
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPrintOperandSize(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, &instruction->operands[i], userData));
|
2016-11-27 01:41:58 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPrintSegment(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, &instruction->operands[i], userData));
|
2016-11-26 20:08:37 +08:00
|
|
|
const char* bufTemp = *buffer;
|
|
|
|
ZYDIS_CHECK(formatter->funcFormatOperandMem(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, &instruction->operands[i], userData));
|
2016-11-26 20:08:37 +08:00
|
|
|
if (bufTemp == *buffer)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
*buffer = (char*)bufPreOperand;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
case ZYDIS_OPERAND_TYPE_POINTER:
|
|
|
|
ZYDIS_CHECK(formatter->funcFormatOperandPtr(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, &instruction->operands[i], userData));
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
|
|
|
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
|
|
|
ZYDIS_CHECK(formatter->funcFormatOperandImm(formatter, buffer, bufEnd - *buffer,
|
2017-10-15 00:37:59 +08:00
|
|
|
instruction, &instruction->operands[i], userData));
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
|
|
|
if (bufPreOperand == *buffer)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-06-16 22:27:37 +08:00
|
|
|
// Omit whole operand, if the buffer did not change during the formatting-callback
|
2016-11-26 20:08:37 +08:00
|
|
|
*buffer = bufRestore;
|
|
|
|
*buffer[0] = 0;
|
|
|
|
} else
|
|
|
|
{
|
2017-07-03 09:14:01 +08:00
|
|
|
if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
|
|
|
|
(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-07-15 04:54:22 +08:00
|
|
|
if ((i == 0) &&
|
|
|
|
(instruction->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK))
|
|
|
|
{
|
|
|
|
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
|
|
|
|
bufEnd - *buffer, instruction, &instruction->operands[i],
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_DECORATOR_TYPE_MASK, userData));
|
2017-07-15 04:54:22 +08:00
|
|
|
}
|
|
|
|
if (instruction->operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
|
2017-07-05 01:02:11 +08:00
|
|
|
{
|
2017-07-15 04:54:22 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
|
|
|
|
bufEnd - *buffer, instruction, &instruction->operands[i],
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_DECORATOR_TYPE_BROADCAST, userData));
|
2017-07-15 04:54:22 +08:00
|
|
|
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
|
2017-07-05 01:02:11 +08:00
|
|
|
{
|
|
|
|
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
|
|
|
|
bufEnd - *buffer, instruction, &instruction->operands[i],
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_DECORATOR_TYPE_CONVERSION, userData));
|
2017-07-15 04:54:22 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
|
|
|
|
bufEnd - *buffer, instruction, &instruction->operands[i],
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_DECORATOR_TYPE_EVICTION_HINT, userData));
|
2017-07-05 01:02:11 +08:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
{
|
2017-07-15 04:54:22 +08:00
|
|
|
if ((i == (instruction->operandCount - 1)) ||
|
|
|
|
(instruction->operands[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))
|
|
|
|
{
|
2017-07-05 01:02:11 +08:00
|
|
|
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
|
|
|
|
{
|
|
|
|
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
|
|
|
|
bufEnd - *buffer, instruction, &instruction->operands[i],
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_DECORATOR_TYPE_SWIZZLE, userData));
|
2017-07-15 04:54:22 +08:00
|
|
|
}
|
2017-07-25 20:58:17 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
|
|
|
|
bufEnd - *buffer, instruction, &instruction->operands[i],
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_DECORATOR_TYPE_ROUNDING_CONTROL, userData));
|
2017-07-25 20:58:17 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
|
|
|
|
bufEnd - *buffer, instruction, &instruction->operands[i],
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_DECORATOR_TYPE_SAE, userData));
|
2017-07-05 01:02:11 +08:00
|
|
|
}
|
|
|
|
}
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
/* Exported functions */
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
ZydisStatus ZydisFormatterInit(ZydisFormatter* formatter,
|
|
|
|
ZydisFormatterStyle style)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-07-03 23:36:03 +08:00
|
|
|
return ZydisFormatterInitEx(formatter, style, 0, ZYDIS_FORMATTER_ADDR_DEFAULT,
|
|
|
|
ZYDIS_FORMATTER_DISP_DEFAULT, ZYDIS_FORMATTER_IMM_DEFAULT);
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
ZydisStatus ZydisFormatterInitEx(ZydisFormatter* formatter,
|
|
|
|
ZydisFormatterStyle style, ZydisFormatterFlags flags, ZydisFormatterAddressFormat addressFormat,
|
|
|
|
ZydisFormatterDisplacementFormat displacementFormat,
|
2016-11-26 20:08:37 +08:00
|
|
|
ZydisFormatterImmediateFormat immmediateFormat)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
if (!formatter ||
|
|
|
|
((addressFormat != ZYDIS_FORMATTER_ADDR_DEFAULT) &&
|
|
|
|
(addressFormat != ZYDIS_FORMATTER_ADDR_ABSOLUTE) &&
|
|
|
|
(addressFormat != ZYDIS_FORMATTER_ADDR_RELATIVE_SIGNED) &&
|
|
|
|
(addressFormat != ZYDIS_FORMATTER_ADDR_RELATIVE_UNSIGNED)) ||
|
|
|
|
((displacementFormat != ZYDIS_FORMATTER_DISP_DEFAULT) &&
|
|
|
|
(displacementFormat != ZYDIS_FORMATTER_DISP_HEX_SIGNED) &&
|
|
|
|
(displacementFormat != ZYDIS_FORMATTER_DISP_HEX_UNSIGNED)) ||
|
|
|
|
((immmediateFormat != ZYDIS_FORMATTER_IMM_DEFAULT) &&
|
2017-06-16 09:25:39 +08:00
|
|
|
(immmediateFormat != ZYDIS_FORMATTER_IMM_HEX_AUTO) &&
|
2016-11-26 20:08:37 +08:00
|
|
|
(immmediateFormat != ZYDIS_FORMATTER_IMM_HEX_SIGNED) &&
|
|
|
|
(immmediateFormat != ZYDIS_FORMATTER_IMM_HEX_UNSIGNED)))
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
memset(formatter, 0, sizeof(ZydisFormatter));
|
2016-05-26 03:25:48 +08:00
|
|
|
formatter->flags = flags;
|
2016-11-26 20:08:37 +08:00
|
|
|
formatter->addressFormat = addressFormat;
|
|
|
|
formatter->displacementFormat = displacementFormat;
|
|
|
|
formatter->immediateFormat = immmediateFormat;
|
2016-05-26 03:25:48 +08:00
|
|
|
|
2016-11-26 20:08:37 +08:00
|
|
|
switch (style)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
case ZYDIS_FORMATTER_STYLE_INTEL:
|
|
|
|
formatter->funcFormatInstruction = &ZydisFormatterFormatInstrIntel;
|
|
|
|
formatter->funcPrintPrefixes = &ZydisFormatterPrintPrefixesIntel;
|
|
|
|
formatter->funcPrintMnemonic = &ZydisFormatterPrintMnemonicIntel;
|
|
|
|
formatter->funcFormatOperandReg = &ZydisFormatterFormatOperandRegIntel;
|
|
|
|
formatter->funcFormatOperandMem = &ZydisFormatterFormatOperandMemIntel;
|
|
|
|
formatter->funcFormatOperandPtr = &ZydisFormatterFormatOperandPtrIntel;
|
|
|
|
formatter->funcFormatOperandImm = &ZydisFormatterFormatOperandImmIntel;
|
|
|
|
formatter->funcPrintOperandSize = &ZydisFormatterPrintOperandSizeIntel;
|
2016-11-27 01:41:58 +08:00
|
|
|
formatter->funcPrintSegment = &ZydisFormatterPrintSegmentIntel;
|
2016-11-26 20:08:37 +08:00
|
|
|
formatter->funcPrintDecorator = &ZydisFormatterPrintDecoratorIntel;
|
|
|
|
formatter->funcPrintAddress = &ZydisFormatterPrintAddressIntel;
|
2016-11-28 18:14:47 +08:00
|
|
|
formatter->funcPrintDisplacement = &ZydisFormatterPrintDisplacementIntel;
|
|
|
|
formatter->funcPrintImmediate = &ZydisFormatterPrintImmediateIntel;
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
|
|
|
default:
|
2016-05-26 03:25:48 +08:00
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
2016-05-26 03:25:48 +08:00
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
ZydisStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterHookType hook,
|
|
|
|
const void** callback)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2016-11-26 20:08:37 +08:00
|
|
|
if (!formatter || !callback)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
|
|
|
const void* temp = *callback;
|
|
|
|
|
|
|
|
// Backup the function-pointer
|
|
|
|
switch (hook)
|
|
|
|
{
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRE:
|
|
|
|
*callback = *(const void**)&formatter->funcPre;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_POST:
|
|
|
|
*callback = *(const void**)&formatter->funcPost;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_INSTRUCTION:
|
|
|
|
*callback = *(const void**)&formatter->funcFormatInstruction;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES:
|
|
|
|
*callback = *(const void**)&formatter->funcPrintPrefixes;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC:
|
|
|
|
*callback = *(const void**)&formatter->funcPrintMnemonic;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG:
|
|
|
|
*callback = *(const void**)&formatter->funcFormatOperandReg;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_MEM:
|
|
|
|
*callback = *(const void**)&formatter->funcFormatOperandMem;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_PTR:
|
|
|
|
*callback = *(const void**)&formatter->funcFormatOperandPtr;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM:
|
|
|
|
*callback = *(const void**)&formatter->funcFormatOperandImm;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE:
|
|
|
|
*callback = *(const void**)&formatter->funcPrintOperandSize;
|
|
|
|
break;
|
2016-11-27 01:41:58 +08:00
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT:
|
|
|
|
*callback = *(const void**)&formatter->funcPrintSegment;
|
|
|
|
break;
|
2016-11-26 20:08:37 +08:00
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR:
|
|
|
|
*callback = *(const void**)&formatter->funcPrintDecorator;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS:
|
|
|
|
*callback = *(const void**)&formatter->funcPrintAddress;
|
|
|
|
break;
|
2016-11-28 18:14:47 +08:00
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_DISPLACEMENT:
|
|
|
|
*callback = *(const void**)&formatter->funcPrintDisplacement;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE:
|
|
|
|
*callback = *(const void**)&formatter->funcPrintImmediate;
|
|
|
|
break;
|
2016-11-26 20:08:37 +08:00
|
|
|
default:
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The function was used to get the current function-pointer without replacing it
|
|
|
|
if (!temp)
|
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Replace the function-pointer
|
|
|
|
switch (hook)
|
|
|
|
{
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRE:
|
|
|
|
formatter->funcPre = *(ZydisFormatterNotifyFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_POST:
|
|
|
|
formatter->funcPost = *(ZydisFormatterNotifyFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_INSTRUCTION:
|
|
|
|
formatter->funcFormatInstruction = *(ZydisFormatterFormatFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES:
|
|
|
|
formatter->funcPrintPrefixes = *(ZydisFormatterFormatFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC:
|
|
|
|
formatter->funcPrintMnemonic = *(ZydisFormatterFormatFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG:
|
|
|
|
formatter->funcFormatOperandReg = *(ZydisFormatterFormatOperandFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_MEM:
|
|
|
|
formatter->funcFormatOperandMem = *(ZydisFormatterFormatOperandFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_PTR:
|
|
|
|
formatter->funcFormatOperandPtr = *(ZydisFormatterFormatOperandFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM:
|
|
|
|
formatter->funcFormatOperandImm = *(ZydisFormatterFormatOperandFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE:
|
|
|
|
formatter->funcPrintOperandSize = *(ZydisFormatterFormatOperandFunc*)&temp;
|
|
|
|
break;
|
2016-11-27 01:41:58 +08:00
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT:
|
|
|
|
formatter->funcPrintSegment = *(ZydisFormatterFormatOperandFunc*)&temp;
|
|
|
|
break;
|
2016-11-26 20:08:37 +08:00
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR:
|
2017-07-05 01:02:11 +08:00
|
|
|
formatter->funcPrintDecorator = *(ZydisFormatterFormatDecoratorFunc*)&temp;
|
2016-11-26 20:08:37 +08:00
|
|
|
break;
|
2016-11-28 18:14:47 +08:00
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS:
|
2016-11-26 20:08:37 +08:00
|
|
|
formatter->funcPrintAddress = *(ZydisFormatterFormatAddressFunc*)&temp;
|
|
|
|
break;
|
2016-11-28 18:14:47 +08:00
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_DISPLACEMENT:
|
|
|
|
formatter->funcPrintDisplacement = *(ZydisFormatterFormatOperandFunc*)&temp;
|
|
|
|
break;
|
|
|
|
case ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE:
|
|
|
|
formatter->funcPrintImmediate = *(ZydisFormatterFormatOperandFunc*)&temp;
|
|
|
|
break;
|
2016-11-26 20:08:37 +08:00
|
|
|
default:
|
2017-08-24 02:40:57 +08:00
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
|
|
|
|
2017-08-24 02:40:57 +08:00
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
|
2017-07-03 23:36:03 +08:00
|
|
|
ZydisStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter,
|
2017-07-03 09:14:01 +08:00
|
|
|
ZydisDecodedInstruction* instruction, char* buffer, size_t bufferLen)
|
2017-10-15 00:37:59 +08:00
|
|
|
{
|
|
|
|
return ZydisFormatterFormatInstructionEx(formatter, instruction, buffer, bufferLen, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ZydisStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter,
|
|
|
|
ZydisDecodedInstruction* instruction, char* buffer, size_t bufferLen, void* userData)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-07-03 09:14:01 +08:00
|
|
|
if (!formatter || !instruction || !buffer || (bufferLen == 0))
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
|
|
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
|
|
|
|
if (formatter->funcPre)
|
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_CHECK(formatter->funcPre(formatter, instruction, userData));
|
2016-11-26 20:08:37 +08:00
|
|
|
}
|
2017-10-15 00:37:59 +08:00
|
|
|
ZYDIS_CHECK(
|
|
|
|
formatter->funcFormatInstruction(formatter, &buffer, bufferLen, instruction, userData));
|
2016-11-26 20:08:37 +08:00
|
|
|
if (formatter->funcPost)
|
2016-05-26 03:25:48 +08:00
|
|
|
{
|
2017-10-15 00:37:59 +08:00
|
|
|
return formatter->funcPost(formatter, instruction, userData);
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
2016-11-26 20:08:37 +08:00
|
|
|
return ZYDIS_STATUS_SUCCESS;
|
2016-05-26 03:25:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/* ============================================================================================== */
|