Skip to content

Commit e8f71e6

Browse files
committed
Decouple operand decoding
1 parent 5df1b68 commit e8f71e6

29 files changed

+9068
-8738
lines changed

README.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,20 @@ int main()
5757
ZyanU64 runtime_address = 0x007FFFFFFF400000;
5858
ZyanUSize offset = 0;
5959
const ZyanUSize length = sizeof(data);
60+
ZydisDecoderContext context;
6061
ZydisDecodedInstruction instruction;
61-
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, data + offset, length - offset,
62-
&instruction)))
62+
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
63+
while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(&decoder, data + offset, length - offset,
64+
&instruction, operands, ZYDIS_MAX_OPERAND_COUNT_VISIBLE,
65+
ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY)))
6366
{
6467
// Print current instruction pointer.
6568
printf("%016" PRIX64 " ", runtime_address);
6669

6770
// Format & print the binary instruction structure to human readable format
6871
char buffer[256];
69-
ZydisFormatterFormatInstruction(&formatter, &instruction, buffer, sizeof(buffer),
70-
runtime_address);
72+
ZydisFormatterFormatInstruction(&formatter, &instruction, &operands,
73+
instruction.operand_count_visible, buffer, sizeof(buffer), runtime_address);
7174
puts(buffer);
7275

7376
offset += instruction.length;

examples/Formatter01.c

+8-3
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,20 @@ static void DisassembleBuffer(ZydisDecoder* decoder, ZyanU8* data, ZyanUSize len
115115
ZyanU64 runtime_address = 0x007FFFFFFF400000;
116116

117117
ZydisDecodedInstruction instruction;
118+
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
118119
char buffer[256];
119-
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(decoder, data, length, &instruction)))
120+
121+
while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(decoder, data, length, &instruction, operands,
122+
ZYDIS_MAX_OPERAND_COUNT_VISIBLE, ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY)))
120123
{
121124
ZYAN_PRINTF("%016" PRIX64 " ", runtime_address);
125+
122126
// We have to pass a `runtime_address` different to `ZYDIS_RUNTIME_ADDRESS_NONE` to
123127
// enable printing of absolute addresses
124-
ZydisFormatterFormatInstruction(&formatter, &instruction, &buffer[0], sizeof(buffer),
125-
runtime_address);
128+
ZydisFormatterFormatInstruction(&formatter, &instruction, operands,
129+
instruction.operand_count_visible, &buffer[0], sizeof(buffer), runtime_address);
126130
ZYAN_PRINTF(" %s\n", &buffer[0]);
131+
127132
data += instruction.length;
128133
length -= instruction.length;
129134
runtime_address += instruction.length;

examples/Formatter02.c

+13-7
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,16 @@ static ZyanStatus ZydisFormatterPrintMnemonic(const ZydisFormatter* formatter,
108108
user_data->omit_immediate = ZYAN_TRUE;
109109

110110
// Rewrite the instruction-mnemonic for the given instructions
111-
if (context->instruction->operand_count &&
112-
context->instruction->operands[context->instruction->operand_count - 1].type ==
111+
if (context->instruction->operand_count_visible &&
112+
context->operands[context->instruction->operand_count_visible - 1].type ==
113113
ZYDIS_OPERAND_TYPE_IMMEDIATE)
114114
{
115115
// Retrieve the `ZyanString` instance of the formatter-buffer
116116
ZyanString* string;
117117
ZYAN_CHECK(ZydisFormatterBufferGetString(buffer, &string));
118118

119-
const ZyanU8 condition_code = (ZyanU8)context->instruction->operands[
120-
context->instruction->operand_count - 1].imm.value.u;
119+
const ZyanU8 condition_code = (ZyanU8)context->operands[
120+
context->instruction->operand_count_visible - 1].imm.value.u;
121121
switch (context->instruction->mnemonic)
122122
{
123123
case ZYDIS_MNEMONIC_CMPPS:
@@ -211,14 +211,20 @@ static void DisassembleBuffer(ZydisDecoder* decoder, ZyanU8* data, ZyanUSize len
211211
ZyanU64 runtime_address = 0x007FFFFFFF400000;
212212

213213
ZydisDecodedInstruction instruction;
214+
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
214215
ZydisCustomUserData user_data;
215216
char buffer[256];
216-
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(decoder, data, length, &instruction)))
217+
218+
while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(decoder, data, length, &instruction, operands,
219+
ZYDIS_MAX_OPERAND_COUNT_VISIBLE, ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY)))
217220
{
218221
ZYAN_PRINTF("%016" PRIX64 " ", runtime_address);
219-
ZydisFormatterFormatInstructionEx(&formatter, &instruction, &buffer[0], sizeof(buffer),
220-
runtime_address, &user_data);
222+
223+
ZydisFormatterFormatInstructionEx(&formatter, &instruction, operands,
224+
instruction.operand_count_visible, &buffer[0], sizeof(buffer), runtime_address,
225+
&user_data);
221226
ZYAN_PRINTF(" %s\n", &buffer[0]);
227+
222228
data += instruction.length;
223229
length -= instruction.length;
224230
runtime_address += instruction.length;

examples/Formatter03.c

+8-3
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,16 @@ static void DisassembleBuffer(ZydisDecoder* decoder, ZyanU8* data, ZyanUSize len
7171
ZyanU64 runtime_address = 0x007FFFFFFF400000;
7272

7373
ZydisDecodedInstruction instruction;
74+
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
7475
char buffer[256];
75-
while (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(decoder, data, length, &instruction)))
76+
77+
while (ZYAN_SUCCESS(ZydisDecoderDecodeFull(decoder, data, length, &instruction, operands,
78+
ZYDIS_MAX_OPERAND_COUNT_VISIBLE, ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY)))
7679
{
7780
const ZydisFormatterToken* token;
78-
if (ZYAN_SUCCESS(ZydisFormatterTokenizeInstruction(&formatter, &instruction, &buffer[0],
79-
sizeof(buffer), runtime_address, &token)))
81+
if (ZYAN_SUCCESS(ZydisFormatterTokenizeInstruction(&formatter, &instruction, operands,
82+
instruction.operand_count_visible , &buffer[0], sizeof(buffer), runtime_address,
83+
&token)))
8084
{
8185
ZydisTokenType token_type;
8286
ZyanConstCharPointer token_value = ZYAN_NULL;
@@ -91,6 +95,7 @@ static void DisassembleBuffer(ZydisDecoder* decoder, ZyanU8* data, ZyanUSize len
9195
}
9296
}
9397
}
98+
9499
data += instruction.length;
95100
length -= instruction.length;
96101
runtime_address += instruction.length;

examples/RewriteCode.c

+11-5
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ int main(int argc, char** argv)
8989

9090
// Attempt to decode the given bytes as an X86-64 instruction.
9191
ZydisDecodedInstruction instr;
92-
ZyanStatus status = ZydisDecoderDecodeBuffer(&decoder, bytes, num_bytes, &instr);
92+
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
93+
ZyanStatus status = ZydisDecoderDecodeFull(&decoder, bytes, num_bytes, &instr, operands,
94+
ZYDIS_MAX_OPERAND_COUNT_VISIBLE, ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY);
9395
if (ZYAN_FAILED(status))
9496
{
9597
fprintf(stderr, "Failed to decode instruction: %02" PRIx32, status);
@@ -102,12 +104,14 @@ int main(int argc, char** argv)
102104

103105
// Format & print the original instruction.
104106
char fmt_buf[256];
105-
ExpectSuccess(ZydisFormatterFormatInstruction(&fmt, &instr, fmt_buf, sizeof(fmt_buf), 0));
107+
ExpectSuccess(ZydisFormatterFormatInstruction(&fmt, &instr, operands,
108+
instr.operand_count_visible, fmt_buf, sizeof(fmt_buf), 0));
106109
printf("Original instruction: %s\n", fmt_buf);
107110

108111
// Create an encoder request from the previously decoded instruction.
109112
ZydisEncoderRequest enc_req;
110-
ExpectSuccess(ZydisEncoderDecodedInstructionToEncoderRequest(&instr, &enc_req));
113+
ExpectSuccess(ZydisEncoderDecodedInstructionToEncoderRequest(&instr, operands,
114+
instr.operand_count_visible, &enc_req));
111115

112116
// Now, change some things about the instruction!
113117

@@ -152,8 +156,10 @@ int main(int argc, char** argv)
152156
ExpectSuccess(ZydisEncoderEncodeInstruction(&enc_req, new_bytes, &new_instr_length));
153157

154158
// Decode and print the new instruction. We re-use the old buffers.
155-
ExpectSuccess(ZydisDecoderDecodeBuffer(&decoder, new_bytes, new_instr_length, &instr));
156-
ExpectSuccess(ZydisFormatterFormatInstruction(&fmt, &instr, fmt_buf, sizeof(fmt_buf), 0));
159+
ExpectSuccess(ZydisDecoderDecodeFull(&decoder, new_bytes, new_instr_length, &instr,
160+
operands, ZYDIS_MAX_OPERAND_COUNT_VISIBLE, ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY));
161+
ExpectSuccess(ZydisFormatterFormatInstruction(&fmt, &instr, operands,
162+
instr.operand_count_visible, fmt_buf, sizeof(fmt_buf), 0));
157163
printf("New instruction: %s\n", fmt_buf);
158164

159165
// Print the new instruction as hex-bytes.

examples/ZydisPerfTest.c

+37-28
Original file line numberDiff line numberDiff line change
@@ -223,35 +223,38 @@ static void AdjustProcessAndThreadPriority(void)
223223
/* Internal functions */
224224
/* ============================================================================================== */
225225

226+
typedef struct TestContext_
227+
{
228+
ZydisDecoderContext context;
229+
ZydisDecodedInstruction instruction;
230+
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
231+
char format_buffer[256];
232+
ZyanBool minimal_mode;
233+
ZyanBool format;
234+
ZyanBool tokenize;
235+
} TestContext;
236+
226237
static ZyanU64 ProcessBuffer(const ZydisDecoder* decoder, const ZydisFormatter* formatter,
227-
/* const ZydisCacheTable* cache, */
228-
const ZyanU8* buffer, ZyanUSize length, ZyanBool format, ZyanBool tokenize, ZyanBool use_cache)
238+
TestContext* context, const ZyanU8* buffer, ZyanUSize length)
229239
{
230240
ZyanU64 count = 0;
231241
ZyanUSize offset = 0;
232242
ZyanStatus status;
233-
ZydisDecodedInstruction instruction_data;
234-
ZydisDecodedInstruction* instruction;
235-
char format_buffer[256];
236243

237244
while (length > offset)
238245
{
239-
if (use_cache)
240-
{
241-
ZYAN_UNREACHABLE;
242-
// status = ZydisDecoderDecodeBufferCached(decoder, cache, buffer + offset,
243-
// length - offset, &instruction);
244-
} else
245-
{
246-
status = ZydisDecoderDecodeBuffer(decoder, buffer + offset, length - offset,
247-
&instruction_data);
248-
instruction = &instruction_data;
249-
}
246+
status = ZydisDecoderDecodeInstruction(decoder, &context->context, buffer + offset,
247+
length - offset, &context->instruction);
250248

251249
if (status == ZYDIS_STATUS_NO_MORE_DATA)
252250
{
253251
break;
254252
}
253+
if (!context->minimal_mode && ZYAN_SUCCESS(status))
254+
{
255+
status = ZydisDecoderDecodeOperands(decoder, &context->context, &context->instruction,
256+
context->operands, context->instruction.operand_count);
257+
}
255258
if (!ZYAN_SUCCESS(status))
256259
{
257260
ZYAN_FPRINTF(ZYAN_STDERR, "%sUnexpected decoding error. Data: ",
@@ -266,21 +269,23 @@ static ZyanU64 ProcessBuffer(const ZydisDecoder* decoder, const ZydisFormatter*
266269
exit(EXIT_FAILURE);
267270
}
268271

269-
if (format)
272+
if (context->format)
270273
{
271-
if (tokenize)
274+
if (context->tokenize)
272275
{
273276
const ZydisFormatterToken* token;
274-
ZydisFormatterTokenizeInstruction(formatter, instruction, format_buffer,
275-
sizeof(format_buffer), offset, &token);
277+
ZydisFormatterTokenizeInstruction(formatter, &context->instruction,
278+
context->operands, context->instruction.operand_count_visible,
279+
context->format_buffer, sizeof(context->format_buffer), offset, &token);
276280
} else
277281
{
278-
ZydisFormatterFormatInstruction(formatter, instruction, format_buffer,
279-
sizeof(format_buffer), offset);
282+
ZydisFormatterFormatInstruction(formatter, &context->instruction,
283+
context->operands, context->instruction.operand_count_visible,
284+
context->format_buffer, sizeof(context->format_buffer), offset);
280285
}
281286
}
282287

283-
offset += instruction->length;
288+
offset += context->instruction.length;
284289
++count;
285290
}
286291

@@ -328,16 +333,20 @@ static void TestPerformance(const ZyanU8* buffer, ZyanUSize length, ZyanBool min
328333
}
329334
}
330335

336+
TestContext context;
337+
context.minimal_mode = minimal_mode;
338+
context.format = format;
339+
context.tokenize = tokenize;
340+
331341
// Cache warmup
332-
ProcessBuffer(&decoder, &formatter, /* cache, */ buffer, length, format, tokenize, use_cache);
342+
ProcessBuffer(&decoder, &formatter, &context, buffer, length);
333343

334344
// Testing
335345
ZyanU64 count = 0;
336346
StartCounter();
337347
for (ZyanU8 j = 0; j < 100; ++j)
338348
{
339-
count += ProcessBuffer(&decoder, &formatter, /* cache, */ buffer, length, format,
340-
tokenize, use_cache);
349+
count += ProcessBuffer(&decoder, &formatter, &context, buffer, length);
341350
}
342351
const char* color[4];
343352
color[0] = minimal_mode ? CVT100_OUT(COLOR_VALUE_G) : CVT100_OUT(COLOR_VALUE_B);
@@ -400,7 +409,8 @@ static void GenerateTestData(FILE* file, ZyanU8 encoding)
400409
default:
401410
ZYAN_UNREACHABLE;
402411
}
403-
if (ZYAN_SUCCESS(ZydisDecoderDecodeBuffer(&decoder, data, sizeof(data), &instruction)))
412+
if (ZYAN_SUCCESS(ZydisDecoderDecodeInstruction(&decoder, ZYAN_NULL, data,
413+
sizeof(data), &instruction)))
404414
{
405415
ZyanBool b = ZYAN_FALSE;
406416
switch (encoding)
@@ -438,7 +448,6 @@ static void GenerateTestData(FILE* file, ZyanU8 encoding)
438448
last = p;
439449
ZYAN_PRINTF("%3.0d%%\n", p);
440450
}
441-
442451
}
443452
}
444453
}

examples/ZydisWinKernel.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,15 @@ DriverEntry(
159159

160160
SIZE_T readOffset = 0;
161161
ZydisDecodedInstruction instruction;
162+
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT_VISIBLE];
162163
ZyanStatus status;
163164
CHAR printBuffer[128];
164165

165166
// Start the decode loop
166-
while ((status = ZydisDecoderDecodeBuffer(&decoder, (PVOID)(imageBase + entryPointRva + readOffset),
167-
length - readOffset, &instruction)) != ZYDIS_STATUS_NO_MORE_DATA)
167+
while ((status = ZydisDecoderDecodeFull(&decoder,
168+
(PVOID)(imageBase + entryPointRva + readOffset), length - readOffset, &instruction,
169+
operands, ZYDIS_MAX_OPERAND_COUNT_VISIBLE, ZYDIS_DFLAG_VISIBLE_OPERANDS_ONLY)) !=
170+
ZYDIS_STATUS_NO_MORE_DATA)
168171
{
169172
NT_ASSERT(ZYAN_SUCCESS(status));
170173
if (!ZYAN_SUCCESS(status))
@@ -176,7 +179,8 @@ DriverEntry(
176179
// Format and print the instruction
177180
const ZyanU64 instrAddress = (ZyanU64)(imageBase + entryPointRva + readOffset);
178181
ZydisFormatterFormatInstruction(
179-
&formatter, &instruction, printBuffer, sizeof(printBuffer), instrAddress);
182+
&formatter, &instruction, operands, instruction.operand_count_visible, printBuffer,
183+
sizeof(printBuffer), instrAddress);
180184
Print("+%-4X 0x%-16llX\t\t%hs\n", (ULONG)readOffset, instrAddress, printBuffer);
181185

182186
readOffset += instruction.length;

0 commit comments

Comments
 (0)