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