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 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_mod == 3 && modrm_reg == 4) { 226 227 /* mov %rsp, reg */ 228 ADD_OP(op) { 229 op->src.type = OP_SRC_REG; 230 op->src.reg = CFI_SP; 231 op->dest.type = OP_DEST_REG; 232 op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b]; 233 } 234 break; 235 } 236 237 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) { 238 239 /* mov reg, %rsp */ 240 ADD_OP(op) { 241 op->src.type = OP_SRC_REG; 242 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 243 op->dest.type = OP_DEST_REG; 244 op->dest.reg = CFI_SP; 245 } 246 break; 247 } 248 249 /* fallthrough */ 250 case 0x88: 251 if (!rex_b && 252 (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) { 253 254 /* mov reg, disp(%rbp) */ 255 ADD_OP(op) { 256 op->src.type = OP_SRC_REG; 257 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 258 op->dest.type = OP_DEST_REG_INDIRECT; 259 op->dest.reg = CFI_BP; 260 op->dest.offset = insn.displacement.value; 261 } 262 263 } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) { 264 265 /* mov reg, disp(%rsp) */ 266 ADD_OP(op) { 267 op->src.type = OP_SRC_REG; 268 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 269 op->dest.type = OP_DEST_REG_INDIRECT; 270 op->dest.reg = CFI_SP; 271 op->dest.offset = insn.displacement.value; 272 } 273 } 274 275 break; 276 277 case 0x8b: 278 if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) { 279 280 /* mov disp(%rbp), reg */ 281 ADD_OP(op) { 282 op->src.type = OP_SRC_REG_INDIRECT; 283 op->src.reg = CFI_BP; 284 op->src.offset = insn.displacement.value; 285 op->dest.type = OP_DEST_REG; 286 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 287 } 288 289 } else if (rex_w && !rex_b && sib == 0x24 && 290 modrm_mod != 3 && modrm_rm == 4) { 291 292 /* mov disp(%rsp), reg */ 293 ADD_OP(op) { 294 op->src.type = OP_SRC_REG_INDIRECT; 295 op->src.reg = CFI_SP; 296 op->src.offset = insn.displacement.value; 297 op->dest.type = OP_DEST_REG; 298 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 299 } 300 } 301 302 break; 303 304 case 0x8d: 305 if (sib == 0x24 && rex_w && !rex_b && !rex_x) { 306 307 ADD_OP(op) { 308 if (!insn.displacement.value) { 309 /* lea (%rsp), reg */ 310 op->src.type = OP_SRC_REG; 311 } else { 312 /* lea disp(%rsp), reg */ 313 op->src.type = OP_SRC_ADD; 314 op->src.offset = insn.displacement.value; 315 } 316 op->src.reg = CFI_SP; 317 op->dest.type = OP_DEST_REG; 318 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 319 } 320 321 } else if (rex == 0x48 && modrm == 0x65) { 322 323 /* lea disp(%rbp), %rsp */ 324 ADD_OP(op) { 325 op->src.type = OP_SRC_ADD; 326 op->src.reg = CFI_BP; 327 op->src.offset = insn.displacement.value; 328 op->dest.type = OP_DEST_REG; 329 op->dest.reg = CFI_SP; 330 } 331 332 } else if (rex == 0x49 && modrm == 0x62 && 333 insn.displacement.value == -8) { 334 335 /* 336 * lea -0x8(%r10), %rsp 337 * 338 * Restoring rsp back to its original value after a 339 * stack realignment. 340 */ 341 ADD_OP(op) { 342 op->src.type = OP_SRC_ADD; 343 op->src.reg = CFI_R10; 344 op->src.offset = -8; 345 op->dest.type = OP_DEST_REG; 346 op->dest.reg = CFI_SP; 347 } 348 349 } else if (rex == 0x49 && modrm == 0x65 && 350 insn.displacement.value == -16) { 351 352 /* 353 * lea -0x10(%r13), %rsp 354 * 355 * Restoring rsp back to its original value after a 356 * stack realignment. 357 */ 358 ADD_OP(op) { 359 op->src.type = OP_SRC_ADD; 360 op->src.reg = CFI_R13; 361 op->src.offset = -16; 362 op->dest.type = OP_DEST_REG; 363 op->dest.reg = CFI_SP; 364 } 365 } 366 367 break; 368 369 case 0x8f: 370 /* pop to mem */ 371 ADD_OP(op) { 372 op->src.type = OP_SRC_POP; 373 op->dest.type = OP_DEST_MEM; 374 } 375 break; 376 377 case 0x90: 378 *type = INSN_NOP; 379 break; 380 381 case 0x9c: 382 /* pushf */ 383 ADD_OP(op) { 384 op->src.type = OP_SRC_CONST; 385 op->dest.type = OP_DEST_PUSHF; 386 } 387 break; 388 389 case 0x9d: 390 /* popf */ 391 ADD_OP(op) { 392 op->src.type = OP_SRC_POPF; 393 op->dest.type = OP_DEST_MEM; 394 } 395 break; 396 397 case 0x0f: 398 399 if (op2 == 0x01) { 400 401 if (modrm == 0xca) 402 *type = INSN_CLAC; 403 else if (modrm == 0xcb) 404 *type = INSN_STAC; 405 406 } else if (op2 >= 0x80 && op2 <= 0x8f) { 407 408 *type = INSN_JUMP_CONDITIONAL; 409 410 } else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 || 411 op2 == 0x35) { 412 413 /* sysenter, sysret */ 414 *type = INSN_CONTEXT_SWITCH; 415 416 } else if (op2 == 0x0b || op2 == 0xb9) { 417 418 /* ud2 */ 419 *type = INSN_BUG; 420 421 } else if (op2 == 0x0d || op2 == 0x1f) { 422 423 /* nopl/nopw */ 424 *type = INSN_NOP; 425 426 } else if (op2 == 0xa0 || op2 == 0xa8) { 427 428 /* push fs/gs */ 429 ADD_OP(op) { 430 op->src.type = OP_SRC_CONST; 431 op->dest.type = OP_DEST_PUSH; 432 } 433 434 } else if (op2 == 0xa1 || op2 == 0xa9) { 435 436 /* pop fs/gs */ 437 ADD_OP(op) { 438 op->src.type = OP_SRC_POP; 439 op->dest.type = OP_DEST_MEM; 440 } 441 } 442 443 break; 444 445 case 0xc9: 446 /* 447 * leave 448 * 449 * equivalent to: 450 * mov bp, sp 451 * pop bp 452 */ 453 ADD_OP(op) 454 op->dest.type = OP_DEST_LEAVE; 455 456 break; 457 458 case 0xe3: 459 /* jecxz/jrcxz */ 460 *type = INSN_JUMP_CONDITIONAL; 461 break; 462 463 case 0xe9: 464 case 0xeb: 465 *type = INSN_JUMP_UNCONDITIONAL; 466 break; 467 468 case 0xc2: 469 case 0xc3: 470 *type = INSN_RETURN; 471 break; 472 473 case 0xcf: /* iret */ 474 /* 475 * Handle sync_core(), which has an IRET to self. 476 * All other IRET are in STT_NONE entry code. 477 */ 478 sym = find_symbol_containing(sec, offset); 479 if (sym && sym->type == STT_FUNC) { 480 ADD_OP(op) { 481 /* add $40, %rsp */ 482 op->src.type = OP_SRC_ADD; 483 op->src.reg = CFI_SP; 484 op->src.offset = 5*8; 485 op->dest.type = OP_DEST_REG; 486 op->dest.reg = CFI_SP; 487 } 488 break; 489 } 490 491 /* fallthrough */ 492 493 case 0xca: /* retf */ 494 case 0xcb: /* retf */ 495 *type = INSN_CONTEXT_SWITCH; 496 break; 497 498 case 0xe8: 499 *type = INSN_CALL; 500 /* 501 * For the impact on the stack, a CALL behaves like 502 * a PUSH of an immediate value (the return address). 503 */ 504 ADD_OP(op) { 505 op->src.type = OP_SRC_CONST; 506 op->dest.type = OP_DEST_PUSH; 507 } 508 break; 509 510 case 0xfc: 511 *type = INSN_CLD; 512 break; 513 514 case 0xfd: 515 *type = INSN_STD; 516 break; 517 518 case 0xff: 519 if (modrm_reg == 2 || modrm_reg == 3) 520 521 *type = INSN_CALL_DYNAMIC; 522 523 else if (modrm_reg == 4) 524 525 *type = INSN_JUMP_DYNAMIC; 526 527 else if (modrm_reg == 5) 528 529 /* jmpf */ 530 *type = INSN_CONTEXT_SWITCH; 531 532 else if (modrm_reg == 6) { 533 534 /* push from mem */ 535 ADD_OP(op) { 536 op->src.type = OP_SRC_CONST; 537 op->dest.type = OP_DEST_PUSH; 538 } 539 } 540 541 break; 542 543 default: 544 break; 545 } 546 547 *immediate = insn.immediate.nbytes ? insn.immediate.value : 0; 548 549 return 0; 550 } 551 552 void arch_initial_func_cfi_state(struct cfi_init_state *state) 553 { 554 int i; 555 556 for (i = 0; i < CFI_NUM_REGS; i++) { 557 state->regs[i].base = CFI_UNDEFINED; 558 state->regs[i].offset = 0; 559 } 560 561 /* initial CFA (call frame address) */ 562 state->cfa.base = CFI_SP; 563 state->cfa.offset = 8; 564 565 /* initial RA (return address) */ 566 state->regs[16].base = CFI_CFA; 567 state->regs[16].offset = -8; 568 } 569 570 const char *arch_nop_insn(int len) 571 { 572 static const char nops[5][5] = { 573 /* 1 */ { 0x90 }, 574 /* 2 */ { 0x66, 0x90 }, 575 /* 3 */ { 0x0f, 0x1f, 0x00 }, 576 /* 4 */ { 0x0f, 0x1f, 0x40, 0x00 }, 577 /* 5 */ { 0x0f, 0x1f, 0x44, 0x00, 0x00 }, 578 }; 579 580 if (len < 1 || len > 5) { 581 WARN("invalid NOP size: %d\n", len); 582 return NULL; 583 } 584 585 return nops[len-1]; 586 } 587 588 int arch_decode_hint_reg(struct instruction *insn, u8 sp_reg) 589 { 590 struct cfi_reg *cfa = &insn->cfi.cfa; 591 592 switch (sp_reg) { 593 case ORC_REG_UNDEFINED: 594 cfa->base = CFI_UNDEFINED; 595 break; 596 case ORC_REG_SP: 597 cfa->base = CFI_SP; 598 break; 599 case ORC_REG_BP: 600 cfa->base = CFI_BP; 601 break; 602 case ORC_REG_SP_INDIRECT: 603 cfa->base = CFI_SP_INDIRECT; 604 break; 605 case ORC_REG_R10: 606 cfa->base = CFI_R10; 607 break; 608 case ORC_REG_R13: 609 cfa->base = CFI_R13; 610 break; 611 case ORC_REG_DI: 612 cfa->base = CFI_DI; 613 break; 614 case ORC_REG_DX: 615 cfa->base = CFI_DX; 616 break; 617 default: 618 return -1; 619 } 620 621 return 0; 622 } 623