FormatterIntel.c (17999B)
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 <Zydis/Internal/FormatterIntel.h> 28 #include <Zydis/Utils.h> 29 #include <Zycore/Format.h> 30 31 /* ============================================================================================== */ 32 /* Constants */ 33 /* ============================================================================================== */ 34 35 #include <Generated/FormatterStrings.inc> 36 37 /* ============================================================================================== */ 38 /* Formatter functions */ 39 /* ============================================================================================== */ 40 41 /* ---------------------------------------------------------------------------------------------- */ 42 /* Intel */ 43 /* ---------------------------------------------------------------------------------------------- */ 44 45 ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter, 46 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 47 { 48 ZYAN_ASSERT(formatter); 49 ZYAN_ASSERT(buffer); 50 ZYAN_ASSERT(context); 51 ZYAN_ASSERT(context->instruction); 52 ZYAN_ASSERT(context->operands); 53 54 ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context)); 55 ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context)); 56 57 ZyanUPointer state_mnemonic; 58 ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic); 59 for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i) 60 { 61 const ZydisDecodedOperand* const operand = &context->operands[i]; 62 63 // Print embedded-mask registers as decorator instead of a regular operand 64 if ((i == 1) && (operand->type == ZYDIS_OPERAND_TYPE_REGISTER) && 65 (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK)) 66 { 67 continue; 68 } 69 70 ZyanUPointer buffer_state; 71 ZYDIS_BUFFER_REMEMBER(buffer, buffer_state); 72 73 if (buffer_state != state_mnemonic) 74 { 75 ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND); 76 } else 77 { 78 ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC); 79 } 80 81 // Set current operand 82 context->operand = operand; 83 84 ZyanStatus status; 85 if (formatter->func_pre_operand) 86 { 87 status = formatter->func_pre_operand(formatter, buffer, context); 88 if (status == ZYDIS_STATUS_SKIP_TOKEN) 89 { 90 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state)); 91 continue; 92 } 93 if (!ZYAN_SUCCESS(status)) 94 { 95 return status; 96 } 97 } 98 99 switch (operand->type) 100 { 101 case ZYDIS_OPERAND_TYPE_REGISTER: 102 status = formatter->func_format_operand_reg(formatter, buffer, context); 103 break; 104 case ZYDIS_OPERAND_TYPE_MEMORY: 105 status = formatter->func_format_operand_mem(formatter, buffer, context); 106 break; 107 case ZYDIS_OPERAND_TYPE_POINTER: 108 status = formatter->func_format_operand_ptr(formatter, buffer, context); 109 break; 110 case ZYDIS_OPERAND_TYPE_IMMEDIATE: 111 status = formatter->func_format_operand_imm(formatter, buffer, context); 112 break; 113 default: 114 return ZYAN_STATUS_INVALID_ARGUMENT; 115 } 116 if (status == ZYDIS_STATUS_SKIP_TOKEN) 117 { 118 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state)); 119 continue; 120 } 121 if (!ZYAN_SUCCESS(status)) 122 { 123 return status; 124 } 125 126 if (formatter->func_post_operand) 127 { 128 status = formatter->func_post_operand(formatter, buffer, context); 129 if (status == ZYDIS_STATUS_SKIP_TOKEN) 130 { 131 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state)); 132 continue; 133 } 134 if (ZYAN_SUCCESS(status)) 135 { 136 return status; 137 } 138 } 139 140 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC) 141 if ((context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) || 142 (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) 143 { 144 if ((i == 0) && 145 (context->instruction->operand_count_visible > 1) && 146 (context->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK)) 147 { 148 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 149 ZYDIS_DECORATOR_MASK)); 150 } 151 if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY) 152 { 153 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 154 ZYDIS_DECORATOR_BC)); 155 if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX) 156 { 157 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 158 ZYDIS_DECORATOR_CONVERSION)); 159 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 160 ZYDIS_DECORATOR_EH)); 161 } 162 } else 163 { 164 ZyanBool decorate_operand; 165 if (i == (context->instruction->operand_count_visible - 1)) 166 { 167 decorate_operand = operand->type != ZYDIS_OPERAND_TYPE_IMMEDIATE; 168 } 169 else 170 { 171 decorate_operand = 172 (context->instruction->operand_count_visible > (i + 1)) && 173 ((context->operands[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) || 174 (context->operands[i + 1].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN)); 175 } 176 if (decorate_operand) 177 { 178 if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX) 179 { 180 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 181 ZYDIS_DECORATOR_SWIZZLE)); 182 } 183 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 184 ZYDIS_DECORATOR_RC)); 185 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context, 186 ZYDIS_DECORATOR_SAE)); 187 } 188 } 189 } 190 #endif 191 } 192 193 return ZYAN_STATUS_SUCCESS; 194 } 195 196 ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter, 197 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 198 { 199 ZYAN_ASSERT(formatter); 200 ZYAN_ASSERT(buffer); 201 ZYAN_ASSERT(context); 202 203 if ((context->operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) || 204 (context->operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB)) 205 { 206 ZYAN_CHECK(formatter->func_print_typecast(formatter, buffer, context)); 207 } 208 ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context)); 209 210 ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_INTEL); 211 212 const ZyanBool absolute = !formatter->force_relative_riprel && 213 (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE); 214 if (absolute && context->operand->mem.disp.has_displacement && 215 (context->operand->mem.index == ZYDIS_REGISTER_NONE) && 216 ((context->operand->mem.base == ZYDIS_REGISTER_NONE) || 217 (context->operand->mem.base == ZYDIS_REGISTER_EIP ) || 218 (context->operand->mem.base == ZYDIS_REGISTER_RIP ))) 219 { 220 // EIP/RIP-relative or absolute-displacement address operand 221 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context)); 222 } else 223 { 224 const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE; 225 const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE; 226 const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx; 227 228 // Regular memory operand 229 if (should_print_reg) 230 { 231 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 232 context->operand->mem.base)); 233 } 234 if (should_print_idx) 235 { 236 if (context->operand->mem.base != ZYDIS_REGISTER_NONE) 237 { 238 ZYDIS_BUFFER_APPEND(buffer, ADD); 239 } 240 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 241 context->operand->mem.index)); 242 if (context->operand->mem.scale && 243 (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) && 244 ((context->operand->mem.scale > 1) || formatter->force_memory_scale)) 245 { 246 ZYDIS_BUFFER_APPEND(buffer, MUL); 247 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 248 ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0, 249 ZYAN_NULL, ZYAN_NULL)); 250 } 251 } 252 if (neither_reg_nor_idx) 253 { 254 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context)); 255 } else if (context->operand->mem.disp.has_displacement && context->operand->mem.disp.value) 256 { 257 ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context)); 258 } 259 } 260 261 ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_INTEL); 262 return ZYAN_STATUS_SUCCESS; 263 } 264 265 ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter, 266 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 267 { 268 ZYAN_ASSERT(formatter); 269 ZYAN_ASSERT(buffer); 270 ZYAN_ASSERT(context); 271 272 const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped( 273 context->instruction->mnemonic); 274 if (!mnemonic) 275 { 276 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic); 277 return ZYAN_STATUS_SUCCESS; 278 } 279 280 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC); 281 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic)); 282 if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR) 283 { 284 return ZydisStringAppendShortCase(&buffer->string, &STR_FAR, formatter->case_mnemonic); 285 } 286 if (formatter->print_branch_size) 287 { 288 switch (context->instruction->meta.branch_type) 289 { 290 case ZYDIS_BRANCH_TYPE_NONE: 291 break; 292 case ZYDIS_BRANCH_TYPE_SHORT: 293 return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT, 294 formatter->case_mnemonic); 295 case ZYDIS_BRANCH_TYPE_NEAR: 296 return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR, 297 formatter->case_mnemonic); 298 default: 299 return ZYAN_STATUS_INVALID_ARGUMENT; 300 } 301 } 302 303 return ZYAN_STATUS_SUCCESS; 304 } 305 306 ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter, 307 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg) 308 { 309 ZYAN_UNUSED(context); 310 311 ZYAN_ASSERT(formatter); 312 ZYAN_ASSERT(buffer); 313 ZYAN_ASSERT(context); 314 315 const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg); 316 if (!str) 317 { 318 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_REG, formatter->case_registers); 319 return ZYAN_STATUS_SUCCESS; 320 } 321 322 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_REGISTER); 323 return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers); 324 } 325 326 ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter, 327 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 328 { 329 ZYAN_ASSERT(formatter); 330 ZYAN_ASSERT(buffer); 331 ZYAN_ASSERT(context); 332 333 switch (formatter->disp_signedness) 334 { 335 case ZYDIS_SIGNEDNESS_AUTO: 336 case ZYDIS_SIGNEDNESS_SIGNED: 337 if (context->operand->mem.disp.value < 0) 338 { 339 if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) || 340 (context->operand->mem.index != ZYDIS_REGISTER_NONE)) 341 { 342 ZYDIS_BUFFER_APPEND(buffer, SUB); 343 } 344 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT); 345 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string, 346 ZyanAbsI64(context->operand->mem.disp.value), formatter->disp_padding, 347 formatter->hex_force_leading_number); 348 break; 349 } 350 ZYAN_FALLTHROUGH; 351 case ZYDIS_SIGNEDNESS_UNSIGNED: 352 if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) || 353 (context->operand->mem.index != ZYDIS_REGISTER_NONE)) 354 { 355 ZYDIS_BUFFER_APPEND(buffer, ADD); 356 } 357 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT); 358 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string, 359 context->operand->mem.disp.value, formatter->disp_padding, 360 formatter->hex_force_leading_number); 361 break; 362 default: 363 return ZYAN_STATUS_INVALID_ARGUMENT; 364 } 365 366 return ZYAN_STATUS_SUCCESS; 367 } 368 369 ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter, 370 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 371 { 372 ZYAN_ASSERT(formatter); 373 ZYAN_ASSERT(buffer); 374 ZYAN_ASSERT(context); 375 376 switch (ZydisFormatterHelperGetExplicitSize(formatter, context, context->operand)) 377 { 378 case 8: ZYDIS_BUFFER_APPEND(buffer, SIZE_8_INTEL ); break; 379 case 16: ZYDIS_BUFFER_APPEND(buffer, SIZE_16_INTEL ); break; 380 case 32: ZYDIS_BUFFER_APPEND(buffer, SIZE_32_INTEL ); break; 381 case 48: ZYDIS_BUFFER_APPEND(buffer, SIZE_48 ); break; 382 case 64: ZYDIS_BUFFER_APPEND(buffer, SIZE_64_INTEL ); break; 383 case 80: ZYDIS_BUFFER_APPEND(buffer, SIZE_80 ); break; 384 case 128: ZYDIS_BUFFER_APPEND(buffer, SIZE_128_INTEL); break; 385 case 256: ZYDIS_BUFFER_APPEND(buffer, SIZE_256_INTEL); break; 386 case 512: ZYDIS_BUFFER_APPEND(buffer, SIZE_512_INTEL); break; 387 default: 388 break; 389 } 390 391 return ZYAN_STATUS_SUCCESS; 392 } 393 394 /* ---------------------------------------------------------------------------------------------- */ 395 /* MASM */ 396 /* ---------------------------------------------------------------------------------------------- */ 397 398 ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter, 399 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 400 { 401 ZYAN_ASSERT(formatter); 402 ZYAN_ASSERT(buffer); 403 ZYAN_ASSERT(context); 404 405 // Force the formatter to always call our MASM `ZYDIS_FORMATTER_PRINT_ADDRESS_ABS` function. 406 // This implicitly omits printing of the `RIP`/`EIP` registers for `RIP`/`EIP`-relative 407 // memory operands 408 context->runtime_address = 0; 409 410 return ZydisFormatterIntelFormatInstruction(formatter, buffer, context); 411 } 412 413 ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter, 414 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 415 { 416 ZYAN_ASSERT(formatter); 417 ZYAN_ASSERT(buffer); 418 ZYAN_ASSERT(context); 419 420 ZyanU64 address; 421 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address)); 422 423 ZyanU8 padding = (formatter->addr_padding_relative == 424 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative; 425 if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) && 426 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX)) 427 { 428 switch (context->instruction->stack_width) 429 { 430 case 16: 431 padding = 4; 432 address = (ZyanU16)address; 433 break; 434 case 32: 435 padding = 8; 436 address = (ZyanU32)address; 437 break; 438 case 64: 439 padding = 16; 440 break; 441 default: 442 return ZYAN_STATUS_INVALID_ARGUMENT; 443 } 444 } 445 446 ZYDIS_BUFFER_APPEND(buffer, ADDR_RELATIVE); 447 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, padding, 448 formatter->hex_force_leading_number, ZYAN_TRUE); 449 450 return ZYAN_STATUS_SUCCESS; 451 } 452 453 /* ---------------------------------------------------------------------------------------------- */ 454 455 /* ============================================================================================== */