decode.c (14893B)
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#define CONFIG_64BIT 1 15#include <asm/nops.h> 16 17#include <asm/orc_types.h> 18#include <objtool/check.h> 19#include <objtool/elf.h> 20#include <objtool/arch.h> 21#include <objtool/warn.h> 22#include <objtool/endianness.h> 23#include <objtool/builtin.h> 24#include <arch/elf.h> 25 26static int is_x86_64(const struct elf *elf) 27{ 28 switch (elf->ehdr.e_machine) { 29 case EM_X86_64: 30 return 1; 31 case EM_386: 32 return 0; 33 default: 34 WARN("unexpected ELF machine type %d", elf->ehdr.e_machine); 35 return -1; 36 } 37} 38 39bool arch_callee_saved_reg(unsigned char reg) 40{ 41 switch (reg) { 42 case CFI_BP: 43 case CFI_BX: 44 case CFI_R12: 45 case CFI_R13: 46 case CFI_R14: 47 case CFI_R15: 48 return true; 49 50 case CFI_AX: 51 case CFI_CX: 52 case CFI_DX: 53 case CFI_SI: 54 case CFI_DI: 55 case CFI_SP: 56 case CFI_R8: 57 case CFI_R9: 58 case CFI_R10: 59 case CFI_R11: 60 case CFI_RA: 61 default: 62 return false; 63 } 64} 65 66unsigned long arch_dest_reloc_offset(int addend) 67{ 68 return addend + 4; 69} 70 71unsigned long arch_jump_destination(struct instruction *insn) 72{ 73 return insn->offset + insn->len + insn->immediate; 74} 75 76#define ADD_OP(op) \ 77 if (!(op = calloc(1, sizeof(*op)))) \ 78 return -1; \ 79 else for (list_add_tail(&op->list, ops_list); op; op = NULL) 80 81/* 82 * Helpers to decode ModRM/SIB: 83 * 84 * r/m| AX CX DX BX | SP | BP | SI DI | 85 * | R8 R9 R10 R11 | R12 | R13 | R14 R15 | 86 * Mod+----------------+-----+-----+---------+ 87 * 00 | [r/m] |[SIB]|[IP+]| [r/m] | 88 * 01 | [r/m + d8] |[S+d]| [r/m + d8] | 89 * 10 | [r/m + d32] |[S+D]| [r/m + d32] | 90 * 11 | r/ m | 91 */ 92 93#define mod_is_mem() (modrm_mod != 3) 94#define mod_is_reg() (modrm_mod == 3) 95 96#define is_RIP() ((modrm_rm & 7) == CFI_BP && modrm_mod == 0) 97#define have_SIB() ((modrm_rm & 7) == CFI_SP && mod_is_mem()) 98 99#define rm_is(reg) (have_SIB() ? \ 100 sib_base == (reg) && sib_index == CFI_SP : \ 101 modrm_rm == (reg)) 102 103#define rm_is_mem(reg) (mod_is_mem() && !is_RIP() && rm_is(reg)) 104#define rm_is_reg(reg) (mod_is_reg() && modrm_rm == (reg)) 105 106static bool has_notrack_prefix(struct insn *insn) 107{ 108 int i; 109 110 for (i = 0; i < insn->prefixes.nbytes; i++) { 111 if (insn->prefixes.bytes[i] == 0x3e) 112 return true; 113 } 114 115 return false; 116} 117 118int arch_decode_instruction(struct objtool_file *file, const struct section *sec, 119 unsigned long offset, unsigned int maxlen, 120 unsigned int *len, enum insn_type *type, 121 unsigned long *immediate, 122 struct list_head *ops_list) 123{ 124 const struct elf *elf = file->elf; 125 struct insn insn; 126 int x86_64, ret; 127 unsigned char op1, op2, op3, prefix, 128 rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, rex_x = 0, 129 modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0, 130 sib = 0, /* sib_scale = 0, */ sib_index = 0, sib_base = 0; 131 struct stack_op *op = NULL; 132 struct symbol *sym; 133 u64 imm; 134 135 x86_64 = is_x86_64(elf); 136 if (x86_64 == -1) 137 return -1; 138 139 ret = insn_decode(&insn, sec->data->d_buf + offset, maxlen, 140 x86_64 ? INSN_MODE_64 : INSN_MODE_32); 141 if (ret < 0) { 142 WARN("can't decode instruction at %s:0x%lx", sec->name, offset); 143 return -1; 144 } 145 146 *len = insn.length; 147 *type = INSN_OTHER; 148 149 if (insn.vex_prefix.nbytes) 150 return 0; 151 152 prefix = insn.prefixes.bytes[0]; 153 154 op1 = insn.opcode.bytes[0]; 155 op2 = insn.opcode.bytes[1]; 156 op3 = insn.opcode.bytes[2]; 157 158 if (insn.rex_prefix.nbytes) { 159 rex = insn.rex_prefix.bytes[0]; 160 rex_w = X86_REX_W(rex) >> 3; 161 rex_r = X86_REX_R(rex) >> 2; 162 rex_x = X86_REX_X(rex) >> 1; 163 rex_b = X86_REX_B(rex); 164 } 165 166 if (insn.modrm.nbytes) { 167 modrm = insn.modrm.bytes[0]; 168 modrm_mod = X86_MODRM_MOD(modrm); 169 modrm_reg = X86_MODRM_REG(modrm) + 8*rex_r; 170 modrm_rm = X86_MODRM_RM(modrm) + 8*rex_b; 171 } 172 173 if (insn.sib.nbytes) { 174 sib = insn.sib.bytes[0]; 175 /* sib_scale = X86_SIB_SCALE(sib); */ 176 sib_index = X86_SIB_INDEX(sib) + 8*rex_x; 177 sib_base = X86_SIB_BASE(sib) + 8*rex_b; 178 } 179 180 switch (op1) { 181 182 case 0x1: 183 case 0x29: 184 if (rex_w && rm_is_reg(CFI_SP)) { 185 186 /* add/sub reg, %rsp */ 187 ADD_OP(op) { 188 op->src.type = OP_SRC_ADD; 189 op->src.reg = modrm_reg; 190 op->dest.type = OP_DEST_REG; 191 op->dest.reg = CFI_SP; 192 } 193 } 194 break; 195 196 case 0x50 ... 0x57: 197 198 /* push reg */ 199 ADD_OP(op) { 200 op->src.type = OP_SRC_REG; 201 op->src.reg = (op1 & 0x7) + 8*rex_b; 202 op->dest.type = OP_DEST_PUSH; 203 } 204 205 break; 206 207 case 0x58 ... 0x5f: 208 209 /* pop reg */ 210 ADD_OP(op) { 211 op->src.type = OP_SRC_POP; 212 op->dest.type = OP_DEST_REG; 213 op->dest.reg = (op1 & 0x7) + 8*rex_b; 214 } 215 216 break; 217 218 case 0x68: 219 case 0x6a: 220 /* push immediate */ 221 ADD_OP(op) { 222 op->src.type = OP_SRC_CONST; 223 op->dest.type = OP_DEST_PUSH; 224 } 225 break; 226 227 case 0x70 ... 0x7f: 228 *type = INSN_JUMP_CONDITIONAL; 229 break; 230 231 case 0x80 ... 0x83: 232 /* 233 * 1000 00sw : mod OP r/m : immediate 234 * 235 * s - sign extend immediate 236 * w - imm8 / imm32 237 * 238 * OP: 000 ADD 100 AND 239 * 001 OR 101 SUB 240 * 010 ADC 110 XOR 241 * 011 SBB 111 CMP 242 */ 243 244 /* 64bit only */ 245 if (!rex_w) 246 break; 247 248 /* %rsp target only */ 249 if (!rm_is_reg(CFI_SP)) 250 break; 251 252 imm = insn.immediate.value; 253 if (op1 & 2) { /* sign extend */ 254 if (op1 & 1) { /* imm32 */ 255 imm <<= 32; 256 imm = (s64)imm >> 32; 257 } else { /* imm8 */ 258 imm <<= 56; 259 imm = (s64)imm >> 56; 260 } 261 } 262 263 switch (modrm_reg & 7) { 264 case 5: 265 imm = -imm; 266 /* fallthrough */ 267 case 0: 268 /* add/sub imm, %rsp */ 269 ADD_OP(op) { 270 op->src.type = OP_SRC_ADD; 271 op->src.reg = CFI_SP; 272 op->src.offset = imm; 273 op->dest.type = OP_DEST_REG; 274 op->dest.reg = CFI_SP; 275 } 276 break; 277 278 case 4: 279 /* and imm, %rsp */ 280 ADD_OP(op) { 281 op->src.type = OP_SRC_AND; 282 op->src.reg = CFI_SP; 283 op->src.offset = insn.immediate.value; 284 op->dest.type = OP_DEST_REG; 285 op->dest.reg = CFI_SP; 286 } 287 break; 288 289 default: 290 /* WARN ? */ 291 break; 292 } 293 294 break; 295 296 case 0x89: 297 if (!rex_w) 298 break; 299 300 if (modrm_reg == CFI_SP) { 301 302 if (mod_is_reg()) { 303 /* mov %rsp, reg */ 304 ADD_OP(op) { 305 op->src.type = OP_SRC_REG; 306 op->src.reg = CFI_SP; 307 op->dest.type = OP_DEST_REG; 308 op->dest.reg = modrm_rm; 309 } 310 break; 311 312 } else { 313 /* skip RIP relative displacement */ 314 if (is_RIP()) 315 break; 316 317 /* skip nontrivial SIB */ 318 if (have_SIB()) { 319 modrm_rm = sib_base; 320 if (sib_index != CFI_SP) 321 break; 322 } 323 324 /* mov %rsp, disp(%reg) */ 325 ADD_OP(op) { 326 op->src.type = OP_SRC_REG; 327 op->src.reg = CFI_SP; 328 op->dest.type = OP_DEST_REG_INDIRECT; 329 op->dest.reg = modrm_rm; 330 op->dest.offset = insn.displacement.value; 331 } 332 break; 333 } 334 335 break; 336 } 337 338 if (rm_is_reg(CFI_SP)) { 339 340 /* mov reg, %rsp */ 341 ADD_OP(op) { 342 op->src.type = OP_SRC_REG; 343 op->src.reg = modrm_reg; 344 op->dest.type = OP_DEST_REG; 345 op->dest.reg = CFI_SP; 346 } 347 break; 348 } 349 350 /* fallthrough */ 351 case 0x88: 352 if (!rex_w) 353 break; 354 355 if (rm_is_mem(CFI_BP)) { 356 357 /* mov reg, disp(%rbp) */ 358 ADD_OP(op) { 359 op->src.type = OP_SRC_REG; 360 op->src.reg = modrm_reg; 361 op->dest.type = OP_DEST_REG_INDIRECT; 362 op->dest.reg = CFI_BP; 363 op->dest.offset = insn.displacement.value; 364 } 365 break; 366 } 367 368 if (rm_is_mem(CFI_SP)) { 369 370 /* mov reg, disp(%rsp) */ 371 ADD_OP(op) { 372 op->src.type = OP_SRC_REG; 373 op->src.reg = modrm_reg; 374 op->dest.type = OP_DEST_REG_INDIRECT; 375 op->dest.reg = CFI_SP; 376 op->dest.offset = insn.displacement.value; 377 } 378 break; 379 } 380 381 break; 382 383 case 0x8b: 384 if (!rex_w) 385 break; 386 387 if (rm_is_mem(CFI_BP)) { 388 389 /* mov disp(%rbp), reg */ 390 ADD_OP(op) { 391 op->src.type = OP_SRC_REG_INDIRECT; 392 op->src.reg = CFI_BP; 393 op->src.offset = insn.displacement.value; 394 op->dest.type = OP_DEST_REG; 395 op->dest.reg = modrm_reg; 396 } 397 break; 398 } 399 400 if (rm_is_mem(CFI_SP)) { 401 402 /* mov disp(%rsp), reg */ 403 ADD_OP(op) { 404 op->src.type = OP_SRC_REG_INDIRECT; 405 op->src.reg = CFI_SP; 406 op->src.offset = insn.displacement.value; 407 op->dest.type = OP_DEST_REG; 408 op->dest.reg = modrm_reg; 409 } 410 break; 411 } 412 413 break; 414 415 case 0x8d: 416 if (mod_is_reg()) { 417 WARN("invalid LEA encoding at %s:0x%lx", sec->name, offset); 418 break; 419 } 420 421 /* skip non 64bit ops */ 422 if (!rex_w) 423 break; 424 425 /* skip RIP relative displacement */ 426 if (is_RIP()) 427 break; 428 429 /* skip nontrivial SIB */ 430 if (have_SIB()) { 431 modrm_rm = sib_base; 432 if (sib_index != CFI_SP) 433 break; 434 } 435 436 /* lea disp(%src), %dst */ 437 ADD_OP(op) { 438 op->src.offset = insn.displacement.value; 439 if (!op->src.offset) { 440 /* lea (%src), %dst */ 441 op->src.type = OP_SRC_REG; 442 } else { 443 /* lea disp(%src), %dst */ 444 op->src.type = OP_SRC_ADD; 445 } 446 op->src.reg = modrm_rm; 447 op->dest.type = OP_DEST_REG; 448 op->dest.reg = modrm_reg; 449 } 450 break; 451 452 case 0x8f: 453 /* pop to mem */ 454 ADD_OP(op) { 455 op->src.type = OP_SRC_POP; 456 op->dest.type = OP_DEST_MEM; 457 } 458 break; 459 460 case 0x90: 461 *type = INSN_NOP; 462 break; 463 464 case 0x9c: 465 /* pushf */ 466 ADD_OP(op) { 467 op->src.type = OP_SRC_CONST; 468 op->dest.type = OP_DEST_PUSHF; 469 } 470 break; 471 472 case 0x9d: 473 /* popf */ 474 ADD_OP(op) { 475 op->src.type = OP_SRC_POPF; 476 op->dest.type = OP_DEST_MEM; 477 } 478 break; 479 480 case 0x0f: 481 482 if (op2 == 0x01) { 483 484 if (modrm == 0xca) 485 *type = INSN_CLAC; 486 else if (modrm == 0xcb) 487 *type = INSN_STAC; 488 489 } else if (op2 >= 0x80 && op2 <= 0x8f) { 490 491 *type = INSN_JUMP_CONDITIONAL; 492 493 } else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 || 494 op2 == 0x35) { 495 496 /* sysenter, sysret */ 497 *type = INSN_CONTEXT_SWITCH; 498 499 } else if (op2 == 0x0b || op2 == 0xb9) { 500 501 /* ud2 */ 502 *type = INSN_BUG; 503 504 } else if (op2 == 0x0d || op2 == 0x1f) { 505 506 /* nopl/nopw */ 507 *type = INSN_NOP; 508 509 } else if (op2 == 0x1e) { 510 511 if (prefix == 0xf3 && (modrm == 0xfa || modrm == 0xfb)) 512 *type = INSN_ENDBR; 513 514 515 } else if (op2 == 0x38 && op3 == 0xf8) { 516 if (insn.prefixes.nbytes == 1 && 517 insn.prefixes.bytes[0] == 0xf2) { 518 /* ENQCMD cannot be used in the kernel. */ 519 WARN("ENQCMD instruction at %s:%lx", sec->name, 520 offset); 521 } 522 523 } else if (op2 == 0xa0 || op2 == 0xa8) { 524 525 /* push fs/gs */ 526 ADD_OP(op) { 527 op->src.type = OP_SRC_CONST; 528 op->dest.type = OP_DEST_PUSH; 529 } 530 531 } else if (op2 == 0xa1 || op2 == 0xa9) { 532 533 /* pop fs/gs */ 534 ADD_OP(op) { 535 op->src.type = OP_SRC_POP; 536 op->dest.type = OP_DEST_MEM; 537 } 538 } 539 540 break; 541 542 case 0xc9: 543 /* 544 * leave 545 * 546 * equivalent to: 547 * mov bp, sp 548 * pop bp 549 */ 550 ADD_OP(op) { 551 op->src.type = OP_SRC_REG; 552 op->src.reg = CFI_BP; 553 op->dest.type = OP_DEST_REG; 554 op->dest.reg = CFI_SP; 555 } 556 ADD_OP(op) { 557 op->src.type = OP_SRC_POP; 558 op->dest.type = OP_DEST_REG; 559 op->dest.reg = CFI_BP; 560 } 561 break; 562 563 case 0xcc: 564 /* int3 */ 565 *type = INSN_TRAP; 566 break; 567 568 case 0xe3: 569 /* jecxz/jrcxz */ 570 *type = INSN_JUMP_CONDITIONAL; 571 break; 572 573 case 0xe9: 574 case 0xeb: 575 *type = INSN_JUMP_UNCONDITIONAL; 576 break; 577 578 case 0xc2: 579 case 0xc3: 580 *type = INSN_RETURN; 581 break; 582 583 case 0xc7: /* mov imm, r/m */ 584 if (!opts.noinstr) 585 break; 586 587 if (insn.length == 3+4+4 && !strncmp(sec->name, ".init.text", 10)) { 588 struct reloc *immr, *disp; 589 struct symbol *func; 590 int idx; 591 592 immr = find_reloc_by_dest(elf, (void *)sec, offset+3); 593 disp = find_reloc_by_dest(elf, (void *)sec, offset+7); 594 595 if (!immr || strcmp(immr->sym->name, "pv_ops")) 596 break; 597 598 idx = (immr->addend + 8) / sizeof(void *); 599 600 func = disp->sym; 601 if (disp->sym->type == STT_SECTION) 602 func = find_symbol_by_offset(disp->sym->sec, disp->addend); 603 if (!func) { 604 WARN("no func for pv_ops[]"); 605 return -1; 606 } 607 608 objtool_pv_add(file, idx, func); 609 } 610 611 break; 612 613 case 0xcf: /* iret */ 614 /* 615 * Handle sync_core(), which has an IRET to self. 616 * All other IRET are in STT_NONE entry code. 617 */ 618 sym = find_symbol_containing(sec, offset); 619 if (sym && sym->type == STT_FUNC) { 620 ADD_OP(op) { 621 /* add $40, %rsp */ 622 op->src.type = OP_SRC_ADD; 623 op->src.reg = CFI_SP; 624 op->src.offset = 5*8; 625 op->dest.type = OP_DEST_REG; 626 op->dest.reg = CFI_SP; 627 } 628 break; 629 } 630 631 /* fallthrough */ 632 633 case 0xca: /* retf */ 634 case 0xcb: /* retf */ 635 *type = INSN_CONTEXT_SWITCH; 636 break; 637 638 case 0xe8: 639 *type = INSN_CALL; 640 /* 641 * For the impact on the stack, a CALL behaves like 642 * a PUSH of an immediate value (the return address). 643 */ 644 ADD_OP(op) { 645 op->src.type = OP_SRC_CONST; 646 op->dest.type = OP_DEST_PUSH; 647 } 648 break; 649 650 case 0xfc: 651 *type = INSN_CLD; 652 break; 653 654 case 0xfd: 655 *type = INSN_STD; 656 break; 657 658 case 0xff: 659 if (modrm_reg == 2 || modrm_reg == 3) { 660 661 *type = INSN_CALL_DYNAMIC; 662 if (has_notrack_prefix(&insn)) 663 WARN("notrack prefix found at %s:0x%lx", sec->name, offset); 664 665 } else if (modrm_reg == 4) { 666 667 *type = INSN_JUMP_DYNAMIC; 668 if (has_notrack_prefix(&insn)) 669 WARN("notrack prefix found at %s:0x%lx", sec->name, offset); 670 671 } else if (modrm_reg == 5) { 672 673 /* jmpf */ 674 *type = INSN_CONTEXT_SWITCH; 675 676 } else if (modrm_reg == 6) { 677 678 /* push from mem */ 679 ADD_OP(op) { 680 op->src.type = OP_SRC_CONST; 681 op->dest.type = OP_DEST_PUSH; 682 } 683 } 684 685 break; 686 687 default: 688 break; 689 } 690 691 *immediate = insn.immediate.nbytes ? insn.immediate.value : 0; 692 693 return 0; 694} 695 696void arch_initial_func_cfi_state(struct cfi_init_state *state) 697{ 698 int i; 699 700 for (i = 0; i < CFI_NUM_REGS; i++) { 701 state->regs[i].base = CFI_UNDEFINED; 702 state->regs[i].offset = 0; 703 } 704 705 /* initial CFA (call frame address) */ 706 state->cfa.base = CFI_SP; 707 state->cfa.offset = 8; 708 709 /* initial RA (return address) */ 710 state->regs[CFI_RA].base = CFI_CFA; 711 state->regs[CFI_RA].offset = -8; 712} 713 714const char *arch_nop_insn(int len) 715{ 716 static const char nops[5][5] = { 717 { BYTES_NOP1 }, 718 { BYTES_NOP2 }, 719 { BYTES_NOP3 }, 720 { BYTES_NOP4 }, 721 { BYTES_NOP5 }, 722 }; 723 724 if (len < 1 || len > 5) { 725 WARN("invalid NOP size: %d\n", len); 726 return NULL; 727 } 728 729 return nops[len-1]; 730} 731 732#define BYTE_RET 0xC3 733 734const char *arch_ret_insn(int len) 735{ 736 static const char ret[5][5] = { 737 { BYTE_RET }, 738 { BYTE_RET, 0xcc }, 739 { BYTE_RET, 0xcc, BYTES_NOP1 }, 740 { BYTE_RET, 0xcc, BYTES_NOP2 }, 741 { BYTE_RET, 0xcc, BYTES_NOP3 }, 742 }; 743 744 if (len < 1 || len > 5) { 745 WARN("invalid RET size: %d\n", len); 746 return NULL; 747 } 748 749 return ret[len-1]; 750} 751 752int arch_decode_hint_reg(u8 sp_reg, int *base) 753{ 754 switch (sp_reg) { 755 case ORC_REG_UNDEFINED: 756 *base = CFI_UNDEFINED; 757 break; 758 case ORC_REG_SP: 759 *base = CFI_SP; 760 break; 761 case ORC_REG_BP: 762 *base = CFI_BP; 763 break; 764 case ORC_REG_SP_INDIRECT: 765 *base = CFI_SP_INDIRECT; 766 break; 767 case ORC_REG_R10: 768 *base = CFI_R10; 769 break; 770 case ORC_REG_R13: 771 *base = CFI_R13; 772 break; 773 case ORC_REG_DI: 774 *base = CFI_DI; 775 break; 776 case ORC_REG_DX: 777 *base = CFI_DX; 778 break; 779 default: 780 return -1; 781 } 782 783 return 0; 784} 785 786bool arch_is_retpoline(struct symbol *sym) 787{ 788 return !strncmp(sym->name, "__x86_indirect_", 15); 789}