mirror of https://github.com/x64dbg/zydis
Implemented basic prefix encoding
This commit is contained in:
parent
3d2365b6ed
commit
0793090388
|
@ -36,50 +36,21 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Types */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @brief Defines the @c ZydisInstructionEncoder struct.
|
||||
*
|
||||
* All fields in this struct are private and may change anytime.
|
||||
*/
|
||||
typedef struct ZydisInstructionEncoder_
|
||||
{
|
||||
/**
|
||||
* @brief The output buffer.
|
||||
*/
|
||||
struct
|
||||
{
|
||||
uint8_t* buffer;
|
||||
size_t bufferLen;
|
||||
} output;
|
||||
} ZydisInstructionEncoder;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Exported functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
/**
|
||||
* @brief Initializes the given @c ZydisInstructionEncoder instance.
|
||||
* @param decoder A pointer to the @c ZydisInstructionEncoder instance.
|
||||
* @return A zydis status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZydisStatus ZydisEncoderInitInstructionEncoder(ZydisInstructionEncoder* encoder);
|
||||
|
||||
/**
|
||||
* @brief Encodes the given instruction info to byte-code.
|
||||
*
|
||||
* @param encoder A pointer to the @c ZydisInstructionEncoder instance.
|
||||
* @param buffer A pointer to the output buffer.
|
||||
* @param bufferLen The length of the output buffer.
|
||||
* @param info A pointer to the @c ZydisInstructionInfo struct to be encoded.
|
||||
*
|
||||
* @return A zydis status code.
|
||||
*/
|
||||
ZYDIS_EXPORT ZydisStatus ZydisEncoderEncodeInstruction(ZydisInstructionEncoder* encoder,
|
||||
const void* buffer, size_t bufferLen, ZydisInstructionInfo* info);
|
||||
ZYDIS_EXPORT ZydisStatus ZydisEncoderEncodeInstruction(const void* buffer, size_t bufferLen,
|
||||
ZydisInstructionInfo* info);
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
|
|
215
src/Encoder.c
215
src/Encoder.c
|
@ -27,24 +27,217 @@
|
|||
#include <Zydis/Encoder.h>
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Implementation of public functions */
|
||||
/* Internal context */
|
||||
/* ============================================================================================== */
|
||||
|
||||
ZydisStatus ZydisEncoderInitInstructionEncoder(ZydisInstructionEncoder* encoder)
|
||||
/**
|
||||
* @brief The encoder context struct.
|
||||
*/
|
||||
typedef struct ZydisInstructionEncoder_
|
||||
{
|
||||
// Nothing yet.
|
||||
(void)encoder;
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
uint8_t* buffer;
|
||||
size_t bufferLen;
|
||||
size_t writeOffs;
|
||||
ZydisInstructionInfo* info;
|
||||
} ZydisInstructionEncoder;
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Internal helpers */
|
||||
/* ============================================================================================== */
|
||||
|
||||
static ZydisStatus ZydisEmitByte(ZydisInstructionEncoder* encoder, uint8_t byte)
|
||||
{
|
||||
if (encoder->writeOffs + 1 >= encoder->bufferLen)
|
||||
{
|
||||
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
encoder->buffer[encoder->writeOffs++] = byte;
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ZydisStatus ZydisEncoderEncodeInstruction(ZydisInstructionEncoder* encoder,
|
||||
void* buffer, size_t bufferLen, ZydisInstructionInfo* info)
|
||||
static ZydisStatus ZydisEncodeLegacyPrefixes(ZydisInstructionEncoder* encoder)
|
||||
{
|
||||
if (!encoder || !info) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
if (!buffer || !bufferLen) return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
ZYDIS_ASSERT(encoder);
|
||||
uint64_t attribs = encoder->info->attributes;
|
||||
|
||||
encoder->output.buffer = (uint8_t*)buffer;
|
||||
encoder->output.bufferLen = bufferLen;
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_LOCK)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0xF0));
|
||||
}
|
||||
if (attribs & (ZYDIS_ATTRIB_HAS_REP | ZYDIS_ATTRIB_HAS_REPE | ZYDIS_ATTRIB_HAS_XRELEASE))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0xF3));
|
||||
}
|
||||
if (attribs & (ZYDIS_ATTRIB_HAS_REPNE | ZYDIS_ATTRIB_HAS_BOUND | ZYDIS_ATTRIB_HAS_XACQUIRE))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0xF2));
|
||||
}
|
||||
if (attribs & (ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN | ZYDIS_ATTRIB_HAS_SEGMENT_CS))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x2E));
|
||||
}
|
||||
if (attribs & (ZYDIS_ATTRIB_HAS_BRANCH_TAKEN | ZYDIS_ATTRIB_HAS_SEGMENT_DS))
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x3E));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_SEGMENT_SS)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x36));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_SEGMENT_ES)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x26));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_SEGMENT_FS)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x64));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_SEGMENT_GS)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x65));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_OPERANDSIZE)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x66));
|
||||
}
|
||||
if (attribs & ZYDIS_ATTRIB_HAS_ADDRESSSIZE)
|
||||
{
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x67));
|
||||
}
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeREX(ZydisInstructionEncoder *encoder)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
0x40 |
|
||||
(encoder->info->details.rex.W & 0x01) << 3 |
|
||||
(encoder->info->details.rex.R & 0x01) << 2 |
|
||||
(encoder->info->details.rex.X & 0x01) << 1 |
|
||||
(encoder->info->details.rex.B & 0x01) << 0
|
||||
));
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeVEX(ZydisInstructionEncoder *encoder)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
|
||||
// Write opcode.
|
||||
uint8_t opcode = encoder->info->details.vex.data[0];
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, opcode));
|
||||
|
||||
// Write prefix' "operands".
|
||||
switch (opcode)
|
||||
{
|
||||
case 0xC4:
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.vex.R & 0x01) << 7 |
|
||||
(encoder->info->details.vex.X & 0x01) << 6 |
|
||||
(encoder->info->details.vex.B & 0x01) << 5 |
|
||||
(encoder->info->details.vex.m_mmmm & 0x1F) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.vex.W & 0x01) << 7 |
|
||||
(encoder->info->details.vex.vvvv & 0x0F) << 3 |
|
||||
(encoder->info->details.vex.L & 0x01) << 2 |
|
||||
(encoder->info->details.vex.pp & 0x03) << 0
|
||||
));
|
||||
break;
|
||||
case 0xC5:
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.vex.R & 0x01) << 7 |
|
||||
(encoder->info->details.vex.vvvv & 0x0F) << 3 |
|
||||
(encoder->info->details.vex.L & 0x01) << 2 |
|
||||
(encoder->info->details.vex.pp & 0x03) << 0
|
||||
));
|
||||
break;
|
||||
default:
|
||||
ZYDIS_UNREACHABLE; // TODO: return error instead
|
||||
}
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeEVEX(ZydisInstructionEncoder *encoder)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x62));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.evex.R & 0x01) << 7 |
|
||||
(encoder->info->details.evex.X & 0x01) << 6 |
|
||||
(encoder->info->details.evex.B & 0x01) << 5 |
|
||||
(encoder->info->details.evex.R2 & 0x01) << 4 |
|
||||
(encoder->info->details.evex.mm & 0x03) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.evex.W & 0x01) << 7 |
|
||||
(encoder->info->details.evex.vvvv & 0x0F) << 3 |
|
||||
(encoder->info->details.evex.pp & 0x03) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.evex.z & 0x01) << 7 |
|
||||
(encoder->info->details.evex.L2 & 0x01) << 6 |
|
||||
(encoder->info->details.evex.L & 0x01) << 5 |
|
||||
(encoder->info->details.evex.b & 0x01) << 4 |
|
||||
(encoder->info->details.evex.V2 & 0x01) << 3 |
|
||||
(encoder->info->details.evex.aaa & 0x07) << 0
|
||||
));
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static ZydisStatus ZydisEncodeXOP(ZydisInstructionEncoder *encoder)
|
||||
{
|
||||
ZYDIS_ASSERT(encoder);
|
||||
|
||||
ZYDIS_CHECK(ZydisEmitByte(encoder, 0x8F));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.xop.R & 0x01) << 7 |
|
||||
(encoder->info->details.xop.X & 0x01) << 6 |
|
||||
(encoder->info->details.xop.B & 0x01) << 5 |
|
||||
(encoder->info->details.xop.m_mmmm & 0x1F) << 0
|
||||
));
|
||||
ZYDIS_CHECK(ZydisEmitByte(
|
||||
encoder,
|
||||
(encoder->info->details.xop.W & 0x01) << 7 |
|
||||
(encoder->info->details.xop.vvvv & 0x0F) << 3 |
|
||||
(encoder->info->details.xop.L & 0x01) << 2 |
|
||||
(encoder->info->details.xop.pp & 0x03) << 0
|
||||
));
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
/* Implementation of public functions */
|
||||
/* ============================================================================================== */
|
||||
|
||||
ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t bufferLen,
|
||||
ZydisInstructionInfo* info)
|
||||
{
|
||||
if (!info) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||
if (!buffer || !bufferLen) return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
|
||||
|
||||
ZydisInstructionEncoder encoder;
|
||||
encoder.buffer = (uint8_t*)buffer;
|
||||
encoder.bufferLen = bufferLen;
|
||||
encoder.writeOffs = 0;
|
||||
encoder.info = info;
|
||||
|
||||
ZYDIS_CHECK(ZydisEncodeLegacyPrefixes(&encoder));
|
||||
|
||||
return ZYDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue