1 /* 2 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include <stdio.h> 19 #include <stdlib.h> 20 21 #define unlikely(cond) (cond) 22 #include "insn/insn.h" 23 #include "insn/inat.c" 24 #include "insn/insn.c" 25 26 #include "../../elf.h" 27 #include "../../arch.h" 28 #include "../../warn.h" 29 30 static unsigned char op_to_cfi_reg[][2] = { 31 {CFI_AX, CFI_R8}, 32 {CFI_CX, CFI_R9}, 33 {CFI_DX, CFI_R10}, 34 {CFI_BX, CFI_R11}, 35 {CFI_SP, CFI_R12}, 36 {CFI_BP, CFI_R13}, 37 {CFI_SI, CFI_R14}, 38 {CFI_DI, CFI_R15}, 39 }; 40 41 static int is_x86_64(struct elf *elf) 42 { 43 switch (elf->ehdr.e_machine) { 44 case EM_X86_64: 45 return 1; 46 case EM_386: 47 return 0; 48 default: 49 WARN("unexpected ELF machine type %d", elf->ehdr.e_machine); 50 return -1; 51 } 52 } 53 54 bool arch_callee_saved_reg(unsigned char reg) 55 { 56 switch (reg) { 57 case CFI_BP: 58 case CFI_BX: 59 case CFI_R12: 60 case CFI_R13: 61 case CFI_R14: 62 case CFI_R15: 63 return true; 64 65 case CFI_AX: 66 case CFI_CX: 67 case CFI_DX: 68 case CFI_SI: 69 case CFI_DI: 70 case CFI_SP: 71 case CFI_R8: 72 case CFI_R9: 73 case CFI_R10: 74 case CFI_R11: 75 case CFI_RA: 76 default: 77 return false; 78 } 79 } 80 81 int arch_decode_instruction(struct elf *elf, struct section *sec, 82 unsigned long offset, unsigned int maxlen, 83 unsigned int *len, unsigned char *type, 84 unsigned long *immediate, struct stack_op *op) 85 { 86 struct insn insn; 87 int x86_64, sign; 88 unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0, 89 modrm = 0, modrm_mod = 0, modrm_rm = 0, modrm_reg = 0, 90 sib = 0; 91 92 x86_64 = is_x86_64(elf); 93 if (x86_64 == -1) 94 return -1; 95 96 insn_init(&insn, sec->data->d_buf + offset, maxlen, x86_64); 97 insn_get_length(&insn); 98 99 if (!insn_complete(&insn)) { 100 WARN_FUNC("can't decode instruction", sec, offset); 101 return -1; 102 } 103 104 *len = insn.length; 105 *type = INSN_OTHER; 106 107 if (insn.vex_prefix.nbytes) 108 return 0; 109 110 op1 = insn.opcode.bytes[0]; 111 op2 = insn.opcode.bytes[1]; 112 113 if (insn.rex_prefix.nbytes) { 114 rex = insn.rex_prefix.bytes[0]; 115 rex_w = X86_REX_W(rex) >> 3; 116 rex_r = X86_REX_R(rex) >> 2; 117 rex_b = X86_REX_B(rex); 118 } 119 120 if (insn.modrm.nbytes) { 121 modrm = insn.modrm.bytes[0]; 122 modrm_mod = X86_MODRM_MOD(modrm); 123 modrm_reg = X86_MODRM_REG(modrm); 124 modrm_rm = X86_MODRM_RM(modrm); 125 } 126 127 if (insn.sib.nbytes) 128 sib = insn.sib.bytes[0]; 129 130 switch (op1) { 131 132 case 0x1: 133 case 0x29: 134 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) { 135 136 /* add/sub reg, %rsp */ 137 *type = INSN_STACK; 138 op->src.type = OP_SRC_ADD; 139 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 140 op->dest.type = OP_SRC_REG; 141 op->dest.reg = CFI_SP; 142 } 143 break; 144 145 case 0x50 ... 0x57: 146 147 /* push reg */ 148 *type = INSN_STACK; 149 op->src.type = OP_SRC_REG; 150 op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; 151 op->dest.type = OP_DEST_PUSH; 152 153 break; 154 155 case 0x58 ... 0x5f: 156 157 /* pop reg */ 158 *type = INSN_STACK; 159 op->src.type = OP_SRC_POP; 160 op->dest.type = OP_DEST_REG; 161 op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; 162 163 break; 164 165 case 0x68: 166 case 0x6a: 167 /* push immediate */ 168 *type = INSN_STACK; 169 op->src.type = OP_SRC_CONST; 170 op->dest.type = OP_DEST_PUSH; 171 break; 172 173 case 0x70 ... 0x7f: 174 *type = INSN_JUMP_CONDITIONAL; 175 break; 176 177 case 0x81: 178 case 0x83: 179 if (rex != 0x48) 180 break; 181 182 if (modrm == 0xe4) { 183 /* and imm, %rsp */ 184 *type = INSN_STACK; 185 op->src.type = OP_SRC_AND; 186 op->src.reg = CFI_SP; 187 op->src.offset = insn.immediate.value; 188 op->dest.type = OP_DEST_REG; 189 op->dest.reg = CFI_SP; 190 break; 191 } 192 193 if (modrm == 0xc4) 194 sign = 1; 195 else if (modrm == 0xec) 196 sign = -1; 197 else 198 break; 199 200 /* add/sub imm, %rsp */ 201 *type = INSN_STACK; 202 op->src.type = OP_SRC_ADD; 203 op->src.reg = CFI_SP; 204 op->src.offset = insn.immediate.value * sign; 205 op->dest.type = OP_DEST_REG; 206 op->dest.reg = CFI_SP; 207 break; 208 209 case 0x89: 210 if (rex == 0x48 && modrm == 0xe5) { 211 212 /* mov %rsp, %rbp */ 213 *type = INSN_STACK; 214 op->src.type = OP_SRC_REG; 215 op->src.reg = CFI_SP; 216 op->dest.type = OP_DEST_REG; 217 op->dest.reg = CFI_BP; 218 break; 219 } 220 /* fallthrough */ 221 case 0x88: 222 if (!rex_b && 223 (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) { 224 225 /* mov reg, disp(%rbp) */ 226 *type = INSN_STACK; 227 op->src.type = OP_SRC_REG; 228 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 229 op->dest.type = OP_DEST_REG_INDIRECT; 230 op->dest.reg = CFI_BP; 231 op->dest.offset = insn.displacement.value; 232 233 } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) { 234 235 /* mov reg, disp(%rsp) */ 236 *type = INSN_STACK; 237 op->src.type = OP_SRC_REG; 238 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 239 op->dest.type = OP_DEST_REG_INDIRECT; 240 op->dest.reg = CFI_SP; 241 op->dest.offset = insn.displacement.value; 242 } 243 244 break; 245 246 case 0x8b: 247 if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) { 248 249 /* mov disp(%rbp), reg */ 250 *type = INSN_STACK; 251 op->src.type = OP_SRC_REG_INDIRECT; 252 op->src.reg = CFI_BP; 253 op->src.offset = insn.displacement.value; 254 op->dest.type = OP_DEST_REG; 255 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 256 257 } else if (rex_w && !rex_b && sib == 0x24 && 258 modrm_mod != 3 && modrm_rm == 4) { 259 260 /* mov disp(%rsp), reg */ 261 *type = INSN_STACK; 262 op->src.type = OP_SRC_REG_INDIRECT; 263 op->src.reg = CFI_SP; 264 op->src.offset = insn.displacement.value; 265 op->dest.type = OP_DEST_REG; 266 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 267 } 268 269 break; 270 271 case 0x8d: 272 if (rex == 0x48 && modrm == 0x65) { 273 274 /* lea disp(%rbp), %rsp */ 275 *type = INSN_STACK; 276 op->src.type = OP_SRC_ADD; 277 op->src.reg = CFI_BP; 278 op->src.offset = insn.displacement.value; 279 op->dest.type = OP_DEST_REG; 280 op->dest.reg = CFI_SP; 281 break; 282 } 283 284 if (rex == 0x48 && (modrm == 0xa4 || modrm == 0x64) && 285 sib == 0x24) { 286 287 /* lea disp(%rsp), %rsp */ 288 *type = INSN_STACK; 289 op->src.type = OP_SRC_ADD; 290 op->src.reg = CFI_SP; 291 op->src.offset = insn.displacement.value; 292 op->dest.type = OP_DEST_REG; 293 op->dest.reg = CFI_SP; 294 break; 295 } 296 297 if (rex == 0x48 && modrm == 0x2c && sib == 0x24) { 298 299 /* lea (%rsp), %rbp */ 300 *type = INSN_STACK; 301 op->src.type = OP_SRC_REG; 302 op->src.reg = CFI_SP; 303 op->dest.type = OP_DEST_REG; 304 op->dest.reg = CFI_BP; 305 break; 306 } 307 308 if (rex == 0x4c && modrm == 0x54 && sib == 0x24 && 309 insn.displacement.value == 8) { 310 311 /* 312 * lea 0x8(%rsp), %r10 313 * 314 * Here r10 is the "drap" pointer, used as a stack 315 * pointer helper when the stack gets realigned. 316 */ 317 *type = INSN_STACK; 318 op->src.type = OP_SRC_ADD; 319 op->src.reg = CFI_SP; 320 op->src.offset = 8; 321 op->dest.type = OP_DEST_REG; 322 op->dest.reg = CFI_R10; 323 break; 324 } 325 326 if (rex == 0x4c && modrm == 0x6c && sib == 0x24 && 327 insn.displacement.value == 16) { 328 329 /* 330 * lea 0x10(%rsp), %r13 331 * 332 * Here r13 is the "drap" pointer, used as a stack 333 * pointer helper when the stack gets realigned. 334 */ 335 *type = INSN_STACK; 336 op->src.type = OP_SRC_ADD; 337 op->src.reg = CFI_SP; 338 op->src.offset = 16; 339 op->dest.type = OP_DEST_REG; 340 op->dest.reg = CFI_R13; 341 break; 342 } 343 344 if (rex == 0x49 && modrm == 0x62 && 345 insn.displacement.value == -8) { 346 347 /* 348 * lea -0x8(%r10), %rsp 349 * 350 * Restoring rsp back to its original value after a 351 * stack realignment. 352 */ 353 *type = INSN_STACK; 354 op->src.type = OP_SRC_ADD; 355 op->src.reg = CFI_R10; 356 op->src.offset = -8; 357 op->dest.type = OP_DEST_REG; 358 op->dest.reg = CFI_SP; 359 break; 360 } 361 362 if (rex == 0x49 && modrm == 0x65 && 363 insn.displacement.value == -16) { 364 365 /* 366 * lea -0x10(%r13), %rsp 367 * 368 * Restoring rsp back to its original value after a 369 * stack realignment. 370 */ 371 *type = INSN_STACK; 372 op->src.type = OP_SRC_ADD; 373 op->src.reg = CFI_R13; 374 op->src.offset = -16; 375 op->dest.type = OP_DEST_REG; 376 op->dest.reg = CFI_SP; 377 break; 378 } 379 380 break; 381 382 case 0x8f: 383 /* pop to mem */ 384 *type = INSN_STACK; 385 op->src.type = OP_SRC_POP; 386 op->dest.type = OP_DEST_MEM; 387 break; 388 389 case 0x90: 390 *type = INSN_NOP; 391 break; 392 393 case 0x9c: 394 /* pushf */ 395 *type = INSN_STACK; 396 op->src.type = OP_SRC_CONST; 397 op->dest.type = OP_DEST_PUSH; 398 break; 399 400 case 0x9d: 401 /* popf */ 402 *type = INSN_STACK; 403 op->src.type = OP_SRC_POP; 404 op->dest.type = OP_DEST_MEM; 405 break; 406 407 case 0x0f: 408 409 if (op2 >= 0x80 && op2 <= 0x8f) 410 *type = INSN_JUMP_CONDITIONAL; 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 == 0x0d || op2 == 0x1f) 418 419 /* nopl/nopw */ 420 *type = INSN_NOP; 421 422 else if (op2 == 0xa0 || op2 == 0xa8) { 423 424 /* push fs/gs */ 425 *type = INSN_STACK; 426 op->src.type = OP_SRC_CONST; 427 op->dest.type = OP_DEST_PUSH; 428 429 } else if (op2 == 0xa1 || op2 == 0xa9) { 430 431 /* pop fs/gs */ 432 *type = INSN_STACK; 433 op->src.type = OP_SRC_POP; 434 op->dest.type = OP_DEST_MEM; 435 } 436 437 break; 438 439 case 0xc9: 440 /* 441 * leave 442 * 443 * equivalent to: 444 * mov bp, sp 445 * pop bp 446 */ 447 *type = INSN_STACK; 448 op->dest.type = OP_DEST_LEAVE; 449 450 break; 451 452 case 0xe3: 453 /* jecxz/jrcxz */ 454 *type = INSN_JUMP_CONDITIONAL; 455 break; 456 457 case 0xe9: 458 case 0xeb: 459 *type = INSN_JUMP_UNCONDITIONAL; 460 break; 461 462 case 0xc2: 463 case 0xc3: 464 *type = INSN_RETURN; 465 break; 466 467 case 0xca: /* retf */ 468 case 0xcb: /* retf */ 469 case 0xcf: /* iret */ 470 *type = INSN_CONTEXT_SWITCH; 471 break; 472 473 case 0xe8: 474 *type = INSN_CALL; 475 break; 476 477 case 0xff: 478 if (modrm_reg == 2 || modrm_reg == 3) 479 480 *type = INSN_CALL_DYNAMIC; 481 482 else if (modrm_reg == 4) 483 484 *type = INSN_JUMP_DYNAMIC; 485 486 else if (modrm_reg == 5) 487 488 /* jmpf */ 489 *type = INSN_CONTEXT_SWITCH; 490 491 else if (modrm_reg == 6) { 492 493 /* push from mem */ 494 *type = INSN_STACK; 495 op->src.type = OP_SRC_CONST; 496 op->dest.type = OP_DEST_PUSH; 497 } 498 499 break; 500 501 default: 502 break; 503 } 504 505 *immediate = insn.immediate.nbytes ? insn.immediate.value : 0; 506 507 return 0; 508 } 509 510 void arch_initial_func_cfi_state(struct cfi_state *state) 511 { 512 int i; 513 514 for (i = 0; i < CFI_NUM_REGS; i++) { 515 state->regs[i].base = CFI_UNDEFINED; 516 state->regs[i].offset = 0; 517 } 518 519 /* initial CFA (call frame address) */ 520 state->cfa.base = CFI_SP; 521 state->cfa.offset = 8; 522 523 /* initial RA (return address) */ 524 state->regs[16].base = CFI_CFA; 525 state->regs[16].offset = -8; 526 } 527