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_AGEN) || 205 (context->operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB)) 206 { 207 ZYAN_CHECK(formatter->func_print_typecast(formatter, buffer, context)); 208 } 209 ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context)); 210 211 ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_INTEL); 212 213 const ZyanBool absolute = !formatter->force_relative_riprel && 214 (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE); 215 if (absolute && context->operand->mem.disp.has_displacement && 216 (context->operand->mem.index == ZYDIS_REGISTER_NONE) && 217 ((context->operand->mem.base == ZYDIS_REGISTER_NONE) || 218 (context->operand->mem.base == ZYDIS_REGISTER_EIP ) || 219 (context->operand->mem.base == ZYDIS_REGISTER_RIP ))) 220 { 221 // EIP/RIP-relative or absolute-displacement address operand 222 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context)); 223 } else 224 { 225 const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE; 226 const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE; 227 const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx; 228 229 // Regular memory operand 230 if (should_print_reg) 231 { 232 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 233 context->operand->mem.base)); 234 } 235 if (should_print_idx) 236 { 237 if (context->operand->mem.base != ZYDIS_REGISTER_NONE) 238 { 239 ZYDIS_BUFFER_APPEND(buffer, ADD); 240 } 241 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 242 context->operand->mem.index)); 243 if (context->operand->mem.scale && 244 (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) && 245 ((context->operand->mem.scale > 1) || formatter->force_memory_scale)) 246 { 247 ZYDIS_BUFFER_APPEND(buffer, MUL); 248 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 249 ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0, 250 ZYAN_NULL, ZYAN_NULL)); 251 } 252 } 253 if (neither_reg_nor_idx) 254 { 255 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context)); 256 } else if (context->operand->mem.disp.has_displacement && context->operand->mem.disp.value) 257 { 258 ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context)); 259 } 260 } 261 262 ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_INTEL); 263 return ZYAN_STATUS_SUCCESS; 264 } 265 266 ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter, 267 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 268 { 269 ZYAN_ASSERT(formatter); 270 ZYAN_ASSERT(buffer); 271 ZYAN_ASSERT(context); 272 273 const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped( 274 context->instruction->mnemonic); 275 if (!mnemonic) 276 { 277 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic); 278 return ZYAN_STATUS_SUCCESS; 279 } 280 281 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC); 282 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic)); 283 if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR) 284 { 285 return ZydisStringAppendShortCase(&buffer->string, &STR_FAR, formatter->case_mnemonic); 286 } 287 if (formatter->print_branch_size) 288 { 289 switch (context->instruction->meta.branch_type) 290 { 291 case ZYDIS_BRANCH_TYPE_NONE: 292 break; 293 case ZYDIS_BRANCH_TYPE_SHORT: 294 return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT, 295 formatter->case_mnemonic); 296 case ZYDIS_BRANCH_TYPE_NEAR: 297 return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR, 298 formatter->case_mnemonic); 299 default: 300 return ZYAN_STATUS_INVALID_ARGUMENT; 301 } 302 } 303 304 return ZYAN_STATUS_SUCCESS; 305 } 306 307 ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter, 308 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg) 309 { 310 ZYAN_UNUSED(context); 311 312 ZYAN_ASSERT(formatter); 313 ZYAN_ASSERT(buffer); 314 ZYAN_ASSERT(context); 315 316 const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg); 317 if (!str) 318 { 319 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_REG, formatter->case_registers); 320 return ZYAN_STATUS_SUCCESS; 321 } 322 323 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_REGISTER); 324 return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers); 325 } 326 327 ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter, 328 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 329 { 330 ZYAN_ASSERT(formatter); 331 ZYAN_ASSERT(buffer); 332 ZYAN_ASSERT(context); 333 334 switch (formatter->disp_signedness) 335 { 336 case ZYDIS_SIGNEDNESS_AUTO: 337 case ZYDIS_SIGNEDNESS_SIGNED: 338 if (context->operand->mem.disp.value < 0) 339 { 340 if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) || 341 (context->operand->mem.index != ZYDIS_REGISTER_NONE)) 342 { 343 ZYDIS_BUFFER_APPEND(buffer, SUB); 344 } 345 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT); 346 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string, 347 ZyanAbsI64(context->operand->mem.disp.value), formatter->disp_padding, 348 formatter->hex_force_leading_number); 349 break; 350 } 351 ZYAN_FALLTHROUGH; 352 case ZYDIS_SIGNEDNESS_UNSIGNED: 353 if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) || 354 (context->operand->mem.index != ZYDIS_REGISTER_NONE)) 355 { 356 ZYDIS_BUFFER_APPEND(buffer, ADD); 357 } 358 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT); 359 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string, 360 context->operand->mem.disp.value, formatter->disp_padding, 361 formatter->hex_force_leading_number); 362 break; 363 default: 364 return ZYAN_STATUS_INVALID_ARGUMENT; 365 } 366 367 return ZYAN_STATUS_SUCCESS; 368 } 369 370 ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter, 371 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 372 { 373 ZYAN_ASSERT(formatter); 374 ZYAN_ASSERT(buffer); 375 ZYAN_ASSERT(context); 376 377 switch (ZydisFormatterHelperGetExplicitSize(formatter, context, context->operand)) 378 { 379 case 8: ZYDIS_BUFFER_APPEND(buffer, SIZE_8_INTEL ); break; 380 case 16: ZYDIS_BUFFER_APPEND(buffer, SIZE_16_INTEL ); break; 381 case 32: ZYDIS_BUFFER_APPEND(buffer, SIZE_32_INTEL ); break; 382 case 48: ZYDIS_BUFFER_APPEND(buffer, SIZE_48 ); break; 383 case 64: ZYDIS_BUFFER_APPEND(buffer, SIZE_64_INTEL ); break; 384 case 80: ZYDIS_BUFFER_APPEND(buffer, SIZE_80 ); break; 385 case 128: ZYDIS_BUFFER_APPEND(buffer, SIZE_128_INTEL); break; 386 case 256: ZYDIS_BUFFER_APPEND(buffer, SIZE_256_INTEL); break; 387 case 512: ZYDIS_BUFFER_APPEND(buffer, SIZE_512_INTEL); break; 388 default: 389 break; 390 } 391 392 return ZYAN_STATUS_SUCCESS; 393 } 394 395 /* ---------------------------------------------------------------------------------------------- */ 396 /* MASM */ 397 /* ---------------------------------------------------------------------------------------------- */ 398 399 ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter, 400 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 401 { 402 ZYAN_ASSERT(formatter); 403 ZYAN_ASSERT(buffer); 404 ZYAN_ASSERT(context); 405 406 // Force the formatter to always call our MASM `ZYDIS_FORMATTER_PRINT_ADDRESS_ABS` function. 407 // This implicitly omits printing of the `RIP`/`EIP` registers for `RIP`/`EIP`-relative 408 // memory operands 409 context->runtime_address = 0; 410 411 return ZydisFormatterIntelFormatInstruction(formatter, buffer, context); 412 } 413 414 ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter, 415 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 416 { 417 ZYAN_ASSERT(formatter); 418 ZYAN_ASSERT(buffer); 419 ZYAN_ASSERT(context); 420 421 ZyanU64 address; 422 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address)); 423 424 ZyanU8 padding = (formatter->addr_padding_relative == 425 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative; 426 if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) && 427 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX)) 428 { 429 switch (context->instruction->address_width) 430 { 431 case 16: 432 padding = 4; 433 address = (ZyanU16)address; 434 break; 435 case 32: 436 padding = 8; 437 address = (ZyanU32)address; 438 break; 439 case 64: 440 padding = 16; 441 break; 442 default: 443 return ZYAN_STATUS_INVALID_ARGUMENT; 444 } 445 } 446 447 ZYDIS_BUFFER_APPEND(buffer, ADDR_RELATIVE); 448 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, padding, 449 formatter->hex_force_leading_number, ZYAN_TRUE); 450 451 return ZYAN_STATUS_SUCCESS; 452 } 453 454 /* ---------------------------------------------------------------------------------------------- */ 455 456 /* ============================================================================================== */ 457