Formatter.c (24842B)
1 /*************************************************************************************************** 2 3 Zyan Disassembler Library (Zydis) 4 5 Original Author : Florian Bernd, Joel Hoener 6 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 25 ***************************************************************************************************/ 26 27 #include <Zycore/LibC.h> 28 #include <Zydis/Formatter.h> 29 #include <Zydis/Internal/FormatterATT.h> 30 #include <Zydis/Internal/FormatterIntel.h> 31 #include <Zydis/Internal/String.h> 32 33 /* ============================================================================================== */ 34 /* Constants */ 35 /* ============================================================================================== */ 36 37 /* ---------------------------------------------------------------------------------------------- */ 38 /* Formatter presets */ 39 /* ---------------------------------------------------------------------------------------------- */ 40 41 static const ZydisFormatter* const FORMATTER_PRESETS[ZYDIS_FORMATTER_STYLE_MAX_VALUE + 1] = 42 { 43 &FORMATTER_ATT, 44 &FORMATTER_INTEL, 45 &FORMATTER_INTEL_MASM 46 }; 47 48 /* ---------------------------------------------------------------------------------------------- */ 49 50 /* ============================================================================================== */ 51 /* Internal functions */ 52 /* ============================================================================================== */ 53 54 /* ---------------------------------------------------------------------------------------------- */ 55 /* Helper functions */ 56 /* ---------------------------------------------------------------------------------------------- */ 57 58 void ZydisFormatterBufferInit(ZydisFormatterBuffer* buffer, char* user_buffer, 59 ZyanUSize length) 60 { 61 ZYAN_ASSERT(buffer); 62 ZYAN_ASSERT(user_buffer); 63 ZYAN_ASSERT(length); 64 65 buffer->is_token_list = ZYAN_FALSE; 66 buffer->capacity = 0; 67 buffer->string.flags = ZYAN_STRING_HAS_FIXED_CAPACITY; 68 buffer->string.vector.allocator = ZYAN_NULL; 69 buffer->string.vector.growth_factor = 1; 70 buffer->string.vector.shrink_threshold = 0; 71 buffer->string.vector.destructor = ZYAN_NULL; 72 buffer->string.vector.element_size = sizeof(char); 73 buffer->string.vector.size = 1; 74 buffer->string.vector.capacity = length; 75 buffer->string.vector.data = user_buffer; 76 77 *user_buffer = '\0'; 78 } 79 80 void ZydisFormatterBufferInitTokenized(ZydisFormatterBuffer* buffer, 81 ZydisFormatterToken** first_token, void* user_buffer, ZyanUSize length) 82 { 83 ZYAN_ASSERT(buffer); 84 ZYAN_ASSERT(first_token); 85 ZYAN_ASSERT(user_buffer); 86 ZYAN_ASSERT(length); 87 88 *first_token = user_buffer; 89 (*first_token)->type = ZYDIS_TOKEN_INVALID; 90 (*first_token)->next = 0; 91 92 user_buffer = (ZyanU8*)user_buffer + sizeof(ZydisFormatterToken); 93 length -= sizeof(ZydisFormatterToken); 94 95 buffer->is_token_list = ZYAN_TRUE; 96 buffer->capacity = length; 97 buffer->string.flags = ZYAN_STRING_HAS_FIXED_CAPACITY; 98 buffer->string.vector.allocator = ZYAN_NULL; 99 buffer->string.vector.growth_factor = 1; 100 buffer->string.vector.shrink_threshold = 0; 101 buffer->string.vector.destructor = ZYAN_NULL; 102 buffer->string.vector.element_size = sizeof(char); 103 buffer->string.vector.size = 1; 104 buffer->string.vector.capacity = length; 105 buffer->string.vector.data = user_buffer; 106 107 *(char*)user_buffer = '\0'; 108 } 109 110 /* ---------------------------------------------------------------------------------------------- */ 111 112 /* ============================================================================================== */ 113 /* Exported functions */ 114 /* ============================================================================================== */ 115 116 /* ---------------------------------------------------------------------------------------------- */ 117 /* Initialization */ 118 /* ---------------------------------------------------------------------------------------------- */ 119 120 ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style) 121 { 122 if (!formatter || ((ZyanUSize)style > ZYDIS_FORMATTER_STYLE_MAX_VALUE)) 123 { 124 return ZYAN_STATUS_INVALID_ARGUMENT; 125 } 126 127 ZYAN_MEMCPY(formatter, FORMATTER_PRESETS[style], sizeof(*formatter)); 128 129 return ZYAN_STATUS_SUCCESS; 130 } 131 132 /* ---------------------------------------------------------------------------------------------- */ 133 /* Setter */ 134 /* ---------------------------------------------------------------------------------------------- */ 135 136 ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, ZydisFormatterProperty property, 137 ZyanUPointer value) 138 { 139 if (!formatter) 140 { 141 return ZYAN_STATUS_INVALID_ARGUMENT; 142 } 143 144 ZydisNumericBase base = (ZydisNumericBase)(-1); 145 ZyanU8 index = 0xFF; 146 147 switch (property) 148 { 149 case ZYDIS_FORMATTER_PROP_FORCE_SIZE: 150 { 151 formatter->force_memory_size = (value) ? ZYAN_TRUE : ZYAN_FALSE; 152 break; 153 } 154 case ZYDIS_FORMATTER_PROP_FORCE_SEGMENT: 155 { 156 formatter->force_memory_segment = (value) ? ZYAN_TRUE : ZYAN_FALSE; 157 break; 158 } 159 case ZYDIS_FORMATTER_PROP_FORCE_SCALE_ONE: 160 { 161 formatter->force_memory_scale = (value) ? ZYAN_TRUE : ZYAN_FALSE; 162 break; 163 } 164 case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES: 165 { 166 formatter->force_relative_branches = (value) ? ZYAN_TRUE : ZYAN_FALSE; 167 break; 168 } 169 case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL: 170 { 171 formatter->force_relative_riprel = (value) ? ZYAN_TRUE : ZYAN_FALSE; 172 break; 173 } 174 case ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE: 175 { 176 formatter->print_branch_size = (value) ? ZYAN_TRUE : ZYAN_FALSE; 177 break; 178 } 179 case ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES: 180 { 181 formatter->detailed_prefixes = (value) ? ZYAN_TRUE : ZYAN_FALSE; 182 break; 183 } 184 case ZYDIS_FORMATTER_PROP_ADDR_BASE: 185 { 186 if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE) 187 { 188 return ZYAN_STATUS_INVALID_ARGUMENT; 189 } 190 formatter->addr_base = (ZydisNumericBase)value; 191 break; 192 } 193 case ZYDIS_FORMATTER_PROP_ADDR_SIGNEDNESS: 194 { 195 if (value > ZYDIS_SIGNEDNESS_MAX_VALUE) 196 { 197 return ZYAN_STATUS_INVALID_ARGUMENT; 198 } 199 formatter->addr_signedness = (ZydisSignedness)value; 200 break; 201 } 202 case ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE: 203 { 204 if (((ZydisPadding)value != ZYDIS_PADDING_AUTO) && 205 (value > 0xFF)) 206 { 207 return ZYAN_STATUS_INVALID_ARGUMENT; 208 } 209 formatter->addr_padding_absolute = (ZydisPadding)value; 210 break; 211 } 212 case ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE: 213 { 214 if (((ZydisPadding)value != ZYDIS_PADDING_AUTO) && 215 (value > 0xFF)) 216 { 217 return ZYAN_STATUS_INVALID_ARGUMENT; 218 } 219 formatter->addr_padding_relative = (ZydisPadding)value; 220 break; 221 } 222 case ZYDIS_FORMATTER_PROP_DISP_BASE: 223 { 224 if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE) 225 { 226 return ZYAN_STATUS_INVALID_ARGUMENT; 227 } 228 formatter->disp_base = (ZydisNumericBase)value; 229 break; 230 } 231 case ZYDIS_FORMATTER_PROP_DISP_SIGNEDNESS: 232 { 233 if (value > ZYDIS_SIGNEDNESS_MAX_VALUE) 234 { 235 return ZYAN_STATUS_INVALID_ARGUMENT; 236 } 237 formatter->disp_signedness = (ZydisSignedness)value; 238 break; 239 } 240 case ZYDIS_FORMATTER_PROP_DISP_PADDING: 241 { 242 if ((ZydisPadding)value == ZYDIS_PADDING_AUTO) 243 { 244 if ((ZyanUSize)formatter->style > ZYDIS_FORMATTER_STYLE_MAX_VALUE) 245 { 246 return ZYAN_STATUS_INVALID_ARGUMENT; 247 } 248 formatter->disp_padding = FORMATTER_PRESETS[formatter->style]->disp_padding; 249 } 250 else if (value > 0xFF) 251 { 252 return ZYAN_STATUS_INVALID_ARGUMENT; 253 } 254 formatter->disp_padding = (ZydisPadding)value; 255 break; 256 } 257 case ZYDIS_FORMATTER_PROP_IMM_BASE: 258 { 259 if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE) 260 { 261 return ZYAN_STATUS_INVALID_ARGUMENT; 262 } 263 formatter->imm_base = (ZydisNumericBase)value; 264 break; 265 } 266 case ZYDIS_FORMATTER_PROP_IMM_SIGNEDNESS: 267 { 268 if (value > ZYDIS_SIGNEDNESS_MAX_VALUE) 269 { 270 return ZYAN_STATUS_INVALID_ARGUMENT; 271 } 272 formatter->imm_signedness = (ZydisSignedness)value; 273 break; 274 } 275 case ZYDIS_FORMATTER_PROP_IMM_PADDING: 276 { 277 if ((ZydisPadding)value == ZYDIS_PADDING_AUTO) 278 { 279 if ((ZyanUSize)formatter->style > ZYDIS_FORMATTER_STYLE_MAX_VALUE) 280 { 281 return ZYAN_STATUS_INVALID_ARGUMENT; 282 } 283 formatter->imm_padding = FORMATTER_PRESETS[formatter->style]->imm_padding; 284 } 285 else if (value > 0xFF) 286 { 287 return ZYAN_STATUS_INVALID_ARGUMENT; 288 } 289 formatter->imm_padding = (ZydisPadding)value; 290 break; 291 } 292 case ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES: 293 { 294 formatter->case_prefixes = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT; 295 break; 296 } 297 case ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC: 298 { 299 formatter->case_mnemonic = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT; 300 break; 301 } 302 case ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS: 303 { 304 formatter->case_registers = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT; 305 break; 306 } 307 case ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS: 308 { 309 formatter->case_typecasts = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT; 310 break; 311 } 312 case ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS: 313 { 314 formatter->case_decorators = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT; 315 break; 316 } 317 case ZYDIS_FORMATTER_PROP_DEC_PREFIX: 318 { 319 base = ZYDIS_NUMERIC_BASE_DEC; 320 index = 0; 321 break; 322 } 323 case ZYDIS_FORMATTER_PROP_DEC_SUFFIX: 324 { 325 base = ZYDIS_NUMERIC_BASE_DEC; 326 index = 1; 327 break; 328 } 329 case ZYDIS_FORMATTER_PROP_HEX_UPPERCASE: 330 { 331 formatter->hex_uppercase = (value) ? ZYAN_TRUE : ZYAN_FALSE; 332 break; 333 } 334 case ZYDIS_FORMATTER_PROP_HEX_PREFIX: 335 { 336 base = ZYDIS_NUMERIC_BASE_HEX; 337 index = 0; 338 break; 339 } 340 case ZYDIS_FORMATTER_PROP_HEX_SUFFIX: 341 { 342 base = ZYDIS_NUMERIC_BASE_HEX; 343 index = 1; 344 break; 345 } 346 default: 347 return ZYAN_STATUS_INVALID_ARGUMENT; 348 } 349 350 // Set prefix or suffix 351 if (base != (ZydisNumericBase)(-1)) 352 { 353 if (value) 354 { 355 const ZyanUSize len = ZYAN_STRLEN((char*)value); 356 if (len > 10) 357 { 358 return ZYAN_STATUS_INVALID_ARGUMENT; 359 } 360 ZYAN_MEMCPY(formatter->number_format[base][index].buffer, (void*)value, len); 361 formatter->number_format[base][index].buffer[len] = '\0'; 362 formatter->number_format[base][index].string_data.string.vector.data = 363 formatter->number_format[base][index].buffer; 364 formatter->number_format[base][index].string_data.string.vector.size = len + 1; 365 formatter->number_format[base][index].string = 366 &formatter->number_format[base][index].string_data; 367 } else 368 { 369 formatter->number_format[base][index].string = ZYAN_NULL; 370 } 371 } 372 373 return ZYAN_STATUS_SUCCESS; 374 } 375 376 ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterFunction type, 377 const void** callback) 378 { 379 if (!formatter || !callback || ((ZyanUSize)type > ZYDIS_FORMATTER_FUNC_MAX_VALUE)) 380 { 381 return ZYAN_STATUS_INVALID_ARGUMENT; 382 } 383 384 const void* const temp = *callback; 385 386 // The following code relies on the order of the enum values and the function fields inside 387 // the `ZydisFormatter` struct 388 389 #ifdef ZYAN_DEBUG 390 const ZyanUPointer* test = (ZyanUPointer*)(&formatter->func_pre_instruction + type); 391 switch (type) 392 { 393 case ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION: 394 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_pre_instruction ); break; 395 case ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION: 396 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_post_instruction ); break; 397 case ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION: 398 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_instruction); break; 399 case ZYDIS_FORMATTER_FUNC_PRE_OPERAND: 400 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_pre_operand ); break; 401 case ZYDIS_FORMATTER_FUNC_POST_OPERAND: 402 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_post_operand ); break; 403 case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG: 404 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_reg); break; 405 case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM: 406 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_mem); break; 407 case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR: 408 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_ptr); break; 409 case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM: 410 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_imm); break; 411 case ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC: 412 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_mnemonic ); break; 413 case ZYDIS_FORMATTER_FUNC_PRINT_REGISTER: 414 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_register ); break; 415 case ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS: 416 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_address_abs ); break; 417 case ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL: 418 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_address_rel ); break; 419 case ZYDIS_FORMATTER_FUNC_PRINT_DISP: 420 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_disp ); break; 421 case ZYDIS_FORMATTER_FUNC_PRINT_IMM: 422 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_imm ); break; 423 case ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST: 424 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_typecast ); break; 425 case ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT: 426 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_segment ); break; 427 case ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES: 428 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_prefixes ); break; 429 case ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR: 430 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_decorator ); break; 431 default: 432 ZYAN_UNREACHABLE; 433 } 434 #endif 435 436 *callback = *(const void**)(&formatter->func_pre_instruction + type); 437 if (!temp) 438 { 439 return ZYAN_STATUS_SUCCESS; 440 } 441 ZYAN_MEMCPY(&formatter->func_pre_instruction + type, &temp, sizeof(ZyanUPointer)); 442 443 return ZYAN_STATUS_SUCCESS; 444 } 445 446 /* ---------------------------------------------------------------------------------------------- */ 447 /* Formatting */ 448 /* ---------------------------------------------------------------------------------------------- */ 449 450 ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter, 451 const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands, 452 ZyanU8 operand_count, char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data) 453 { 454 if (!formatter || !instruction || (operand_count && !operands) || 455 (operand_count > ZYDIS_MAX_OPERAND_COUNT) || 456 (operand_count < instruction->operand_count_visible) || !buffer || (length == 0)) 457 { 458 return ZYAN_STATUS_INVALID_ARGUMENT; 459 } 460 461 ZydisFormatterBuffer formatter_buffer; 462 ZydisFormatterBufferInit(&formatter_buffer, buffer, length); 463 464 ZydisFormatterContext context; 465 context.instruction = instruction; 466 context.operands = operands; 467 context.runtime_address = runtime_address; 468 context.operand = ZYAN_NULL; 469 context.user_data = user_data; 470 471 if (formatter->func_pre_instruction) 472 { 473 ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context)); 474 } 475 476 ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context)); 477 478 if (formatter->func_post_instruction) 479 { 480 ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context)); 481 } 482 483 return ZYAN_STATUS_SUCCESS; 484 } 485 486 ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter, 487 const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, 488 char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data) 489 { 490 if (!formatter || !instruction || !operand || !buffer || (length == 0)) 491 { 492 return ZYAN_STATUS_INVALID_ARGUMENT; 493 } 494 495 ZydisFormatterBuffer formatter_buffer; 496 ZydisFormatterBufferInit(&formatter_buffer, buffer, length); 497 498 ZydisFormatterContext context; 499 context.instruction = instruction; 500 context.operands = ZYAN_NULL; 501 context.runtime_address = runtime_address; 502 context.operand = operand; 503 context.user_data = user_data; 504 505 // We ignore `ZYDIS_STATUS_SKIP_TOKEN` for all operand-functions as it does not make any sense 506 // to skip the only operand printed by this function 507 508 if (formatter->func_pre_operand) 509 { 510 ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context)); 511 } 512 513 switch (context.operand->type) 514 { 515 case ZYDIS_OPERAND_TYPE_REGISTER: 516 ZYAN_CHECK(formatter->func_format_operand_reg(formatter, &formatter_buffer, &context)); 517 break; 518 case ZYDIS_OPERAND_TYPE_MEMORY: 519 ZYAN_CHECK(formatter->func_format_operand_mem(formatter, &formatter_buffer, &context)); 520 break; 521 case ZYDIS_OPERAND_TYPE_IMMEDIATE: 522 ZYAN_CHECK(formatter->func_format_operand_imm(formatter, &formatter_buffer, &context)); 523 break; 524 case ZYDIS_OPERAND_TYPE_POINTER: 525 ZYAN_CHECK(formatter->func_format_operand_ptr(formatter, &formatter_buffer, &context)); 526 break; 527 default: 528 return ZYAN_STATUS_INVALID_ARGUMENT; 529 } 530 531 if (formatter->func_post_operand) 532 { 533 ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context)); 534 } 535 536 return ZYAN_STATUS_SUCCESS; 537 } 538 539 /* ---------------------------------------------------------------------------------------------- */ 540 /* Tokenizing */ 541 /* ---------------------------------------------------------------------------------------------- */ 542 543 ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter, 544 const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands, 545 ZyanU8 operand_count, void* buffer, ZyanUSize length, ZyanU64 runtime_address, 546 ZydisFormatterTokenConst** token, void* user_data) 547 { 548 if (!formatter || !instruction || (operand_count && !operands) || 549 (operand_count > ZYDIS_MAX_OPERAND_COUNT) || 550 (operand_count < instruction->operand_count_visible) || !buffer || 551 (length <= sizeof(ZydisFormatterToken)) || !token) 552 { 553 return ZYAN_STATUS_INVALID_ARGUMENT; 554 } 555 556 ZydisFormatterBuffer formatter_buffer; 557 ZydisFormatterToken* first_token; 558 ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length); 559 560 ZydisFormatterContext context; 561 context.instruction = instruction; 562 context.operands = operands; 563 context.runtime_address = runtime_address; 564 context.operand = ZYAN_NULL; 565 context.user_data = user_data; 566 567 if (formatter->func_pre_instruction) 568 { 569 ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context)); 570 } 571 572 ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context)); 573 574 if (formatter->func_post_instruction) 575 { 576 ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context)); 577 } 578 579 if (first_token->next) 580 { 581 *token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) + 582 first_token->next); 583 return ZYAN_STATUS_SUCCESS; 584 } 585 586 *token = first_token; 587 return ZYAN_STATUS_SUCCESS; 588 } 589 590 ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter, 591 const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, 592 void* buffer, ZyanUSize length, ZyanU64 runtime_address, ZydisFormatterTokenConst** token, 593 void* user_data) 594 { 595 if (!formatter || !instruction || !operand || !buffer || 596 (length <= sizeof(ZydisFormatterToken)) || !token) 597 { 598 return ZYAN_STATUS_INVALID_ARGUMENT; 599 } 600 601 ZydisFormatterToken* first_token; 602 ZydisFormatterBuffer formatter_buffer; 603 ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length); 604 605 ZydisFormatterContext context; 606 context.instruction = instruction; 607 context.operands = ZYAN_NULL; 608 context.runtime_address = runtime_address; 609 context.operand = operand; 610 context.user_data = user_data; 611 612 // We ignore `ZYDIS_STATUS_SKIP_TOKEN` for all operand-functions as it does not make any sense 613 // to skip the only operand printed by this function 614 615 if (formatter->func_pre_operand) 616 { 617 ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context)); 618 } 619 620 switch (context.operand->type) 621 { 622 case ZYDIS_OPERAND_TYPE_REGISTER: 623 ZYAN_CHECK(formatter->func_format_operand_reg(formatter, &formatter_buffer, &context)); 624 break; 625 case ZYDIS_OPERAND_TYPE_MEMORY: 626 ZYAN_CHECK(formatter->func_format_operand_mem(formatter, &formatter_buffer, &context)); 627 break; 628 case ZYDIS_OPERAND_TYPE_IMMEDIATE: 629 ZYAN_CHECK(formatter->func_format_operand_imm(formatter, &formatter_buffer, &context)); 630 break; 631 case ZYDIS_OPERAND_TYPE_POINTER: 632 ZYAN_CHECK(formatter->func_format_operand_ptr(formatter, &formatter_buffer, &context)); 633 break; 634 default: 635 return ZYAN_STATUS_INVALID_ARGUMENT; 636 } 637 638 if (formatter->func_post_operand) 639 { 640 ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context)); 641 } 642 643 if (first_token->next) 644 { 645 *token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) + 646 first_token->next); 647 return ZYAN_STATUS_SUCCESS; 648 } 649 650 *token = first_token; 651 return ZYAN_STATUS_SUCCESS; 652 } 653 654 /* ============================================================================================== */ 655 656 /* ============================================================================================== */