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/FormatterATT.h> 28 29 /* ============================================================================================== */ 30 /* Constants */ 31 /* ============================================================================================== */ 32 33 #include <Generated/FormatterStrings.inc> 34 35 /* ============================================================================================== */ 36 /* Formatter functions */ 37 /* ============================================================================================== */ 38 39 /* ---------------------------------------------------------------------------------------------- */ 40 /* Instruction */ 41 /* ---------------------------------------------------------------------------------------------- */ 42 43 ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter, 44 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 45 { 46 ZYAN_ASSERT(formatter); 47 ZYAN_ASSERT(buffer); 48 ZYAN_ASSERT(context); 49 ZYAN_ASSERT(context->instruction); 50 ZYAN_ASSERT(context->operands); 51 52 ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context)); 53 ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context)); 54 55 ZyanUPointer state_mnemonic; 56 ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic); 57 58 const ZyanI8 c = (ZyanI8)context->instruction->operand_count_visible - 1; 59 for (ZyanI8 i = c; i >= 0; --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[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 /* ---------------------------------------------------------------------------------------------- */ 197 /* Operands */ 198 /* ---------------------------------------------------------------------------------------------- */ 199 200 ZyanStatus ZydisFormatterATTFormatOperandMEM(const ZydisFormatter* formatter, 201 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 202 { 203 ZYAN_ASSERT(formatter); 204 ZYAN_ASSERT(buffer); 205 ZYAN_ASSERT(context); 206 207 ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context)); 208 209 const ZyanBool absolute = !formatter->force_relative_riprel && 210 (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE); 211 if (absolute && context->operand->mem.disp.has_displacement && 212 (context->operand->mem.index == ZYDIS_REGISTER_NONE) && 213 ((context->operand->mem.base == ZYDIS_REGISTER_NONE) || 214 (context->operand->mem.base == ZYDIS_REGISTER_EIP ) || 215 (context->operand->mem.base == ZYDIS_REGISTER_RIP ))) 216 { 217 // EIP/RIP-relative or absolute-displacement address operand 218 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context)); 219 } else 220 { 221 const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE; 222 const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE; 223 const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx; 224 225 // Regular memory operand 226 if (neither_reg_nor_idx) 227 { 228 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context)); 229 } else if (context->operand->mem.disp.has_displacement && context->operand->mem.disp.value) 230 { 231 ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context)); 232 } 233 234 if (neither_reg_nor_idx) 235 { 236 return ZYAN_STATUS_SUCCESS; 237 } 238 239 ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_ATT); 240 241 if (should_print_reg) 242 { 243 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 244 context->operand->mem.base)); 245 } 246 if (should_print_idx) 247 { 248 ZYDIS_BUFFER_APPEND(buffer, DELIM_MEMORY); 249 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context, 250 context->operand->mem.index)); 251 if (context->operand->mem.scale && 252 (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) && 253 ((context->operand->mem.scale > 1) || formatter->force_memory_scale)) 254 { 255 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DELIMITER); 256 ZYDIS_BUFFER_APPEND(buffer, DELIM_MEMORY); 257 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE); 258 ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0, 259 ZYAN_NULL, ZYAN_NULL)); 260 } 261 } 262 263 ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_ATT); 264 return ZYAN_STATUS_SUCCESS; 265 } 266 267 return ZYAN_STATUS_SUCCESS; 268 } 269 270 /* ---------------------------------------------------------------------------------------------- */ 271 /* Elemental tokens */ 272 /* ---------------------------------------------------------------------------------------------- */ 273 274 ZyanStatus ZydisFormatterATTPrintMnemonic(const ZydisFormatter* formatter, 275 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 276 { 277 ZYAN_ASSERT(formatter); 278 ZYAN_ASSERT(buffer); 279 ZYAN_ASSERT(context); 280 ZYAN_ASSERT(context->instruction); 281 ZYAN_ASSERT(context->operands); 282 283 const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped( 284 context->instruction->mnemonic); 285 if (!mnemonic) 286 { 287 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic); 288 return ZYAN_STATUS_SUCCESS; 289 } 290 291 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC); 292 if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR) 293 { 294 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_FAR_ATT, 295 formatter->case_mnemonic)); 296 } 297 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic)); 298 299 // Append operand-size suffix 300 ZyanU32 size = 0; 301 for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i) 302 { 303 const ZydisDecodedOperand* const operand = &context->operands[i]; 304 if ((operand->type == ZYDIS_OPERAND_TYPE_MEMORY) && 305 ((operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) || 306 (operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB))) 307 { 308 size = ZydisFormatterHelperGetExplicitSize(formatter, context, operand); 309 break; 310 } 311 } 312 313 switch (size) 314 { 315 case 8: ZydisStringAppendShort(&buffer->string, &STR_SIZE_8_ATT ); break; 316 case 16: ZydisStringAppendShort(&buffer->string, &STR_SIZE_16_ATT ); break; 317 case 32: ZydisStringAppendShort(&buffer->string, &STR_SIZE_32_ATT ); break; 318 case 64: ZydisStringAppendShort(&buffer->string, &STR_SIZE_64_ATT ); break; 319 case 128: ZydisStringAppendShort(&buffer->string, &STR_SIZE_128_ATT); break; 320 case 256: ZydisStringAppendShort(&buffer->string, &STR_SIZE_256_ATT); break; 321 case 512: ZydisStringAppendShort(&buffer->string, &STR_SIZE_512_ATT); break; 322 default: 323 break; 324 } 325 326 if (formatter->print_branch_size) 327 { 328 switch (context->instruction->meta.branch_type) 329 { 330 case ZYDIS_BRANCH_TYPE_NONE: 331 break; 332 case ZYDIS_BRANCH_TYPE_SHORT: 333 return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT, 334 formatter->case_mnemonic); 335 case ZYDIS_BRANCH_TYPE_NEAR: 336 return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR, 337 formatter->case_mnemonic); 338 default: 339 return ZYAN_STATUS_INVALID_ARGUMENT; 340 } 341 } 342 343 return ZYAN_STATUS_SUCCESS; 344 } 345 346 ZyanStatus ZydisFormatterATTPrintRegister(const ZydisFormatter* formatter, 347 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg) 348 { 349 ZYAN_UNUSED(context); 350 351 ZYAN_ASSERT(formatter); 352 ZYAN_ASSERT(buffer); 353 ZYAN_ASSERT(context); 354 355 ZYDIS_BUFFER_APPEND(buffer, REGISTER); 356 const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg); 357 if (!str) 358 { 359 return ZydisStringAppendShortCase(&buffer->string, &STR_INVALID_REG, 360 formatter->case_registers); 361 } 362 return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers); 363 } 364 365 ZyanStatus ZydisFormatterATTPrintAddressABS(const ZydisFormatter* formatter, 366 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 367 { 368 ZYAN_ASSERT(formatter); 369 ZYAN_ASSERT(buffer); 370 ZYAN_ASSERT(context); 371 372 if ((context->instruction->meta.branch_type != ZYDIS_BRANCH_TYPE_NONE) && 373 (context->operand->type == ZYDIS_OPERAND_TYPE_MEMORY)) 374 { 375 ZYDIS_BUFFER_APPEND(buffer, MUL); 376 } 377 378 return ZydisFormatterBasePrintAddressABS(formatter, buffer, context); 379 } 380 381 ZyanStatus ZydisFormatterATTPrintDISP(const ZydisFormatter* formatter, 382 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 383 { 384 ZYAN_ASSERT(formatter); 385 ZYAN_ASSERT(buffer); 386 ZYAN_ASSERT(context); 387 388 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT); 389 switch (formatter->disp_signedness) 390 { 391 case ZYDIS_SIGNEDNESS_AUTO: 392 case ZYDIS_SIGNEDNESS_SIGNED: 393 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->disp_base, &buffer->string, 394 context->operand->mem.disp.value, formatter->disp_padding, 395 formatter->hex_force_leading_number, ZYAN_FALSE); 396 break; 397 case ZYDIS_SIGNEDNESS_UNSIGNED: 398 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string, 399 context->operand->mem.disp.value, formatter->disp_padding, 400 formatter->hex_force_leading_number); 401 break; 402 default: 403 return ZYAN_STATUS_INVALID_ARGUMENT; 404 } 405 406 return ZYAN_STATUS_SUCCESS; 407 } 408 409 ZyanStatus ZydisFormatterATTPrintIMM(const ZydisFormatter* formatter, 410 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context) 411 { 412 ZYAN_ASSERT(formatter); 413 ZYAN_ASSERT(buffer); 414 ZYAN_ASSERT(context); 415 416 ZYDIS_BUFFER_APPEND(buffer, IMMEDIATE); 417 return ZydisFormatterBasePrintIMM(formatter, buffer, context); 418 } 419 420 /* ---------------------------------------------------------------------------------------------- */ 421 422 /* ============================================================================================== */ 423