1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 4 */ 5 6#include <stdio.h> 7#include <stdlib.h> 8 9#define unlikely(cond) (cond) 10#include <asm/insn.h> 11#include "../../../arch/x86/lib/inat.c" 12#include "../../../arch/x86/lib/insn.c" 13 14#include "../../check.h" 15#include "../../elf.h" 16#include "../../arch.h" 17#include "../../warn.h" 18#include <asm/orc_types.h> 19#include "arch_elf.h" 20 21static unsigned char op_to_cfi_reg[][2] = { 22 {CFI_AX, CFI_R8}, 23 {CFI_CX, CFI_R9}, 24 {CFI_DX, CFI_R10}, 25 {CFI_BX, CFI_R11}, 26 {CFI_SP, CFI_R12}, 27 {CFI_BP, CFI_R13}, 28 {CFI_SI, CFI_R14}, 29 {CFI_DI, CFI_R15}, 30}; 31 32static int is_x86_64(const struct elf *elf) 33{ 34 switch (elf->ehdr.e_machine) { 35 case EM_X86_64: 36 return 1; 37 case EM_386: 38 return 0; 39 default: 40 WARN("unexpected ELF machine type %d", elf->ehdr.e_machine); 41 return -1; 42 } 43} 44 45bool arch_callee_saved_reg(unsigned char reg) 46{ 47 switch (reg) { 48 case CFI_BP: 49 case CFI_BX: 50 case CFI_R12: 51 case CFI_R13: 52 case CFI_R14: 53 case CFI_R15: 54 return true; 55 56 case CFI_AX: 57 case CFI_CX: 58 case CFI_DX: 59 case CFI_SI: 60 case CFI_DI: 61 case CFI_SP: 62 case CFI_R8: 63 case CFI_R9: 64 case CFI_R10: 65 case CFI_R11: 66 case CFI_RA: 67 default: 68 return false; 69 } 70} 71 72unsigned long arch_dest_reloc_offset(int addend) 73{ 74 return addend + 4; 75} 76 77unsigned long arch_jump_destination(struct instruction *insn) 78{ 79 return insn->offset + insn->len + insn->immediate; 80} 81 82#define ADD_OP(op) \ 83 if (!(op = calloc(1, sizeof(*op)))) \ 84 return -1; \ 85 else for (list_add_tail(&op->list, ops_list); op; op = NULL) 86 87int arch_decode_instruction(const struct elf *elf, const struct section *sec, 88 unsigned long offset, unsigned int maxlen, 89 unsigned int *len, enum insn_type *type, 90 unsigned long *immediate, 91 struct list_head *ops_list) 92{ 93 struct insn insn; 94 int x86_64, sign; 95 unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, 96 rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0, 97 modrm_reg = 0, sib = 0; 98 struct stack_op *op = NULL; 99 struct symbol *sym; 100 101 x86_64 = is_x86_64(elf); 102 if (x86_64 == -1) 103 return -1; 104 105 insn_init(&insn, sec->data->d_buf + offset, maxlen, x86_64); 106 insn_get_length(&insn); 107 108 if (!insn_complete(&insn)) { 109 WARN("can't decode instruction at %s:0x%lx", sec->name, offset); 110 return -1; 111 } 112 113 *len = insn.length; 114 *type = INSN_OTHER; 115 116 if (insn.vex_prefix.nbytes) 117 return 0; 118 119 op1 = insn.opcode.bytes[0]; 120 op2 = insn.opcode.bytes[1]; 121 122 if (insn.rex_prefix.nbytes) { 123 rex = insn.rex_prefix.bytes[0]; 124 rex_w = X86_REX_W(rex) >> 3; 125 rex_r = X86_REX_R(rex) >> 2; 126 rex_x = X86_REX_X(rex) >> 1; 127 rex_b = X86_REX_B(rex); 128 } 129 130 if (insn.modrm.nbytes) { 131 modrm = insn.modrm.bytes[0]; 132 modrm_mod = X86_MODRM_MOD(modrm); 133 modrm_reg = X86_MODRM_REG(modrm); 134 modrm_rm = X86_MODRM_RM(modrm); 135 } 136 137 if (insn.sib.nbytes) 138 sib = insn.sib.bytes[0]; 139 140 switch (op1) { 141 142 case 0x1: 143 case 0x29: 144 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) { 145 146 /* add/sub reg, %rsp */ 147 ADD_OP(op) { 148 op->src.type = OP_SRC_ADD; 149 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 150 op->dest.type = OP_DEST_REG; 151 op->dest.reg = CFI_SP; 152 } 153 } 154 break; 155 156 case 0x50 ... 0x57: 157 158 /* push reg */ 159 ADD_OP(op) { 160 op->src.type = OP_SRC_REG; 161 op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; 162 op->dest.type = OP_DEST_PUSH; 163 } 164 165 break; 166 167 case 0x58 ... 0x5f: 168 169 /* pop reg */ 170 ADD_OP(op) { 171 op->src.type = OP_SRC_POP; 172 op->dest.type = OP_DEST_REG; 173 op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; 174 } 175 176 break; 177 178 case 0x68: 179 case 0x6a: 180 /* push immediate */ 181 ADD_OP(op) { 182 op->src.type = OP_SRC_CONST; 183 op->dest.type = OP_DEST_PUSH; 184 } 185 break; 186 187 case 0x70 ... 0x7f: 188 *type = INSN_JUMP_CONDITIONAL; 189 break; 190 191 case 0x81: 192 case 0x83: 193 if (rex != 0x48) 194 break; 195 196 if (modrm == 0xe4) { 197 /* and imm, %rsp */ 198 ADD_OP(op) { 199 op->src.type = OP_SRC_AND; 200 op->src.reg = CFI_SP; 201 op->src.offset = insn.immediate.value; 202 op->dest.type = OP_DEST_REG; 203 op->dest.reg = CFI_SP; 204 } 205 break; 206 } 207 208 if (modrm == 0xc4) 209 sign = 1; 210 else if (modrm == 0xec) 211 sign = -1; 212 else 213 break; 214 215 /* add/sub imm, %rsp */ 216 ADD_OP(op) { 217 op->src.type = OP_SRC_ADD; 218 op->src.reg = CFI_SP; 219 op->src.offset = insn.immediate.value * sign; 220 op->dest.type = OP_DEST_REG; 221 op->dest.reg = CFI_SP; 222 } 223 break; 224 225 case 0x89: 226 if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) { 227 228 /* mov %rsp, reg */ 229 ADD_OP(op) { 230 op->src.type = OP_SRC_REG; 231 op->src.reg = CFI_SP; 232 op->dest.type = OP_DEST_REG; 233 op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b]; 234 } 235 break; 236 } 237 238 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) { 239 240 /* mov reg, %rsp */ 241 ADD_OP(op) { 242 op->src.type = OP_SRC_REG; 243 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 244 op->dest.type = OP_DEST_REG; 245 op->dest.reg = CFI_SP; 246 } 247 break; 248 } 249 250 /* fallthrough */ 251 case 0x88: 252 if (!rex_b && 253 (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) { 254 255 /* mov reg, disp(%rbp) */ 256 ADD_OP(op) { 257 op->src.type = OP_SRC_REG; 258 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 259 op->dest.type = OP_DEST_REG_INDIRECT; 260 op->dest.reg = CFI_BP; 261 op->dest.offset = insn.displacement.value; 262 } 263 264 } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) { 265 266 /* mov reg, disp(%rsp) */ 267 ADD_OP(op) { 268 op->src.type = OP_SRC_REG; 269 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 270 op->dest.type = OP_DEST_REG_INDIRECT; 271 op->dest.reg = CFI_SP; 272 op->dest.offset = insn.displacement.value; 273 } 274 } 275 276 break; 277 278 case 0x8b: 279 if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) { 280 281 /* mov disp(%rbp), reg */ 282 ADD_OP(op) { 283 op->src.type = OP_SRC_REG_INDIRECT; 284 op->src.reg = CFI_BP; 285 op->src.offset = insn.displacement.value; 286 op->dest.type = OP_DEST_REG; 287 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 288 } 289 290 } else if (rex_w && !rex_b && sib == 0x24 && 291 modrm_mod != 3 && modrm_rm == 4) { 292 293 /* mov disp(%rsp), reg */ 294 ADD_OP(op) { 295 op->src.type = OP_SRC_REG_INDIRECT; 296 op->src.reg = CFI_SP; 297 op->src.offset = insn.displacement.value; 298 op->dest.type = OP_DEST_REG; 299 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 300 } 301 } 302 303 break; 304 305 case 0x8d: 306 if (sib == 0x24 && rex_w && !rex_b && !rex_x) { 307 308 ADD_OP(op) { 309 if (!insn.displacement.value) { 310 /* lea (%rsp), reg */ 311 op->src.type = OP_SRC_REG; 312 } else { 313 /* lea disp(%rsp), reg */ 314 op->src.type = OP_SRC_ADD; 315 op->src.offset = insn.displacement.value; 316 } 317 op->src.reg = CFI_SP; 318 op->dest.type = OP_DEST_REG; 319 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 320 } 321 322 } else if (rex == 0x48 && modrm == 0x65) { 323 324 /* lea disp(%rbp), %rsp */ 325 ADD_OP(op) { 326 op->src.type = OP_SRC_ADD; 327 op->src.reg = CFI_BP; 328 op->src.offset = insn.displacement.value; 329 op->dest.type = OP_DEST_REG; 330 op->dest.reg = CFI_SP; 331 } 332 333 } else if (rex == 0x49 && modrm == 0x62 && 334 insn.displacement.value == -8) { 335 336 /* 337 * lea -0x8(%r10), %rsp 338 * 339 * Restoring rsp back to its original value after a 340 * stack realignment. 341 */ 342 ADD_OP(op) { 343 op->src.type = OP_SRC_ADD; 344 op->src.reg = CFI_R10; 345 op->src.offset = -8; 346 op->dest.type = OP_DEST_REG; 347 op->dest.reg = CFI_SP; 348 } 349 350 } else if (rex == 0x49 && modrm == 0x65 && 351 insn.displacement.value == -16) { 352 353 /* 354 * lea -0x10(%r13), %rsp 355 * 356 * Restoring rsp back to its original value after a 357 * stack realignment. 358 */ 359 ADD_OP(op) { 360 op->src.type = OP_SRC_ADD; 361 op->src.reg = CFI_R13; 362 op->src.offset = -16; 363 op->dest.type = OP_DEST_REG; 364 op->dest.reg = CFI_SP; 365 } 366 } 367 368 break; 369 370 case 0x8f: 371 /* pop to mem */ 372 ADD_OP(op) { 373 op->src.type = OP_SRC_POP; 374 op->dest.type = OP_DEST_MEM; 375 } 376 break; 377 378 case 0x90: 379 *type = INSN_NOP; 380 break; 381 382 case 0x9c: 383 /* pushf */ 384 ADD_OP(op) { 385 op->src.type = OP_SRC_CONST; 386 op->dest.type = OP_DEST_PUSHF; 387 } 388 break; 389 390 case 0x9d: 391 /* popf */ 392 ADD_OP(op) { 393 op->src.type = OP_SRC_POPF; 394 op->dest.type = OP_DEST_MEM; 395 } 396 break; 397 398 case 0x0f: 399 400 if (op2 == 0x01) { 401 402 if (modrm == 0xca) 403 *type = INSN_CLAC; 404 else if (modrm == 0xcb) 405 *type = INSN_STAC; 406 407 } else if (op2 >= 0x80 && op2 <= 0x8f) { 408 409 *type = INSN_JUMP_CONDITIONAL; 410 411 } else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 || 412 op2 == 0x35) { 413 414 /* sysenter, sysret */ 415 *type = INSN_CONTEXT_SWITCH; 416 417 } else if (op2 == 0x0b || op2 == 0xb9) { 418 419 /* ud2 */ 420 *type = INSN_BUG; 421 422 } else if (op2 == 0x0d || op2 == 0x1f) { 423 424 /* nopl/nopw */ 425 *type = INSN_NOP; 426 427 } else if (op2 == 0xa0 || op2 == 0xa8) { 428 429 /* push fs/gs */ 430 ADD_OP(op) { 431 op->src.type = OP_SRC_CONST; 432 op->dest.type = OP_DEST_PUSH; 433 } 434 435 } else if (op2 == 0xa1 || op2 == 0xa9) { 436 437 /* pop fs/gs */ 438 ADD_OP(op) { 439 op->src.type = OP_SRC_POP; 440 op->dest.type = OP_DEST_MEM; 441 } 442 } 443 444 break; 445 446 case 0xc9: 447 /* 448 * leave 449 * 450 * equivalent to: 451 * mov bp, sp 452 * pop bp 453 */ 454 ADD_OP(op) 455 op->dest.type = OP_DEST_LEAVE; 456 457 break; 458 459 case 0xcc: 460 /* int3 */ 461 *type = INSN_TRAP; 462 break; 463 464 case 0xe3: 465 /* jecxz/jrcxz */ 466 *type = INSN_JUMP_CONDITIONAL; 467 break; 468 469 case 0xe9: 470 case 0xeb: 471 *type = INSN_JUMP_UNCONDITIONAL; 472 break; 473 474 case 0xc2: 475 case 0xc3: 476 *type = INSN_RETURN; 477 break; 478 479 case 0xcf: /* iret */ 480 /* 481 * Handle sync_core(), which has an IRET to self. 482 * All other IRET are in STT_NONE entry code. 483 */ 484 sym = find_symbol_containing(sec, offset); 485 if (sym && sym->type == STT_FUNC) { 486 ADD_OP(op) { 487 /* add $40, %rsp */ 488 op->src.type = OP_SRC_ADD; 489 op->src.reg = CFI_SP; 490 op->src.offset = 5*8; 491 op->dest.type = OP_DEST_REG; 492 op->dest.reg = CFI_SP; 493 } 494 break; 495 } 496 497 /* fallthrough */ 498 499 case 0xca: /* retf */ 500 case 0xcb: /* retf */ 501 *type = INSN_CONTEXT_SWITCH; 502 break; 503 504 case 0xe8: 505 *type = INSN_CALL; 506 /* 507 * For the impact on the stack, a CALL behaves like 508 * a PUSH of an immediate value (the return address). 509 */ 510 ADD_OP(op) { 511 op->src.type = OP_SRC_CONST; 512 op->dest.type = OP_DEST_PUSH; 513 } 514 break; 515 516 case 0xfc: 517 *type = INSN_CLD; 518 break; 519 520 case 0xfd: 521 *type = INSN_STD; 522 break; 523 524 case 0xff: 525 if (modrm_reg == 2 || modrm_reg == 3) 526 527 *type = INSN_CALL_DYNAMIC; 528 529 else if (modrm_reg == 4) 530 531 *type = INSN_JUMP_DYNAMIC; 532 533 else if (modrm_reg == 5) 534 535 /* jmpf */ 536 *type = INSN_CONTEXT_SWITCH; 537 538 else if (modrm_reg == 6) { 539 540 /* push from mem */ 541 ADD_OP(op) { 542 op->src.type = OP_SRC_CONST; 543 op->dest.type = OP_DEST_PUSH; 544 } 545 } 546 547 break; 548 549 default: 550 break; 551 } 552 553 *immediate = insn.immediate.nbytes ? insn.immediate.value : 0; 554 555 return 0; 556} 557 558void arch_initial_func_cfi_state(struct cfi_init_state *state) 559{ 560 int i; 561 562 for (i = 0; i < CFI_NUM_REGS; i++) { 563 state->regs[i].base = CFI_UNDEFINED; 564 state->regs[i].offset = 0; 565 } 566 567 /* initial CFA (call frame address) */ 568 state->cfa.base = CFI_SP; 569 state->cfa.offset = 8; 570 571 /* initial RA (return address) */ 572 state->regs[CFI_RA].base = CFI_CFA; 573 state->regs[CFI_RA].offset = -8; 574} 575 576const char *arch_nop_insn(int len) 577{ 578 static const char nops[5][5] = { 579 /* 1 */ { 0x90 }, 580 /* 2 */ { 0x66, 0x90 }, 581 /* 3 */ { 0x0f, 0x1f, 0x00 }, 582 /* 4 */ { 0x0f, 0x1f, 0x40, 0x00 }, 583 /* 5 */ { 0x0f, 0x1f, 0x44, 0x00, 0x00 }, 584 }; 585 586 if (len < 1 || len > 5) { 587 WARN("invalid NOP size: %d\n", len); 588 return NULL; 589 } 590 591 return nops[len-1]; 592} 593 594#define BYTE_RET 0xC3 595 596const char *arch_ret_insn(int len) 597{ 598 static const char ret[5][5] = { 599 { BYTE_RET }, 600 { BYTE_RET, 0xcc }, 601 { BYTE_RET, 0xcc, 0x90 }, 602 { BYTE_RET, 0xcc, 0x66, 0x90 }, 603 { BYTE_RET, 0xcc, 0x0f, 0x1f, 0x00 }, 604 }; 605 606 if (len < 1 || len > 5) { 607 WARN("invalid RET size: %d\n", len); 608 return NULL; 609 } 610 611 return ret[len-1]; 612} 613 614int arch_decode_hint_reg(u8 sp_reg, int *base) 615{ 616 switch (sp_reg) { 617 case ORC_REG_UNDEFINED: 618 *base = CFI_UNDEFINED; 619 break; 620 case ORC_REG_SP: 621 *base = CFI_SP; 622 break; 623 case ORC_REG_BP: 624 *base = CFI_BP; 625 break; 626 case ORC_REG_SP_INDIRECT: 627 *base = CFI_SP_INDIRECT; 628 break; 629 case ORC_REG_R10: 630 *base = CFI_R10; 631 break; 632 case ORC_REG_R13: 633 *base = CFI_R13; 634 break; 635 case ORC_REG_DI: 636 *base = CFI_DI; 637 break; 638 case ORC_REG_DX: 639 *base = CFI_DX; 640 break; 641 default: 642 return -1; 643 } 644 645 return 0; 646} 647 648bool arch_is_retpoline(struct symbol *sym) 649{ 650 return !strncmp(sym->name, "__x86_indirect_", 15); 651} 652 653bool arch_is_rethunk(struct symbol *sym) 654{ 655 return !strcmp(sym->name, "__x86_return_thunk"); 656} 657 658bool arch_is_embedded_insn(struct symbol *sym) 659{ 660 return !strcmp(sym->name, "retbleed_return_thunk") || 661 !strcmp(sym->name, "srso_safe_ret"); 662} 663