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 == 0x4c && modrm == 0x54 && sib == 0x24 && 285 insn.displacement.value == 8) { 286 287 /* 288 * lea 0x8(%rsp), %r10 289 * 290 * Here r10 is the "drap" pointer, used as a stack 291 * pointer helper when the stack gets realigned. 292 */ 293 *type = INSN_STACK; 294 op->src.type = OP_SRC_ADD; 295 op->src.reg = CFI_SP; 296 op->src.offset = 8; 297 op->dest.type = OP_DEST_REG; 298 op->dest.reg = CFI_R10; 299 break; 300 } 301 302 if (rex == 0x4c && modrm == 0x6c && sib == 0x24 && 303 insn.displacement.value == 16) { 304 305 /* 306 * lea 0x10(%rsp), %r13 307 * 308 * Here r13 is the "drap" pointer, used as a stack 309 * pointer helper when the stack gets realigned. 310 */ 311 *type = INSN_STACK; 312 op->src.type = OP_SRC_ADD; 313 op->src.reg = CFI_SP; 314 op->src.offset = 16; 315 op->dest.type = OP_DEST_REG; 316 op->dest.reg = CFI_R13; 317 break; 318 } 319 320 if (rex == 0x49 && modrm == 0x62 && 321 insn.displacement.value == -8) { 322 323 /* 324 * lea -0x8(%r10), %rsp 325 * 326 * Restoring rsp back to its original value after a 327 * stack realignment. 328 */ 329 *type = INSN_STACK; 330 op->src.type = OP_SRC_ADD; 331 op->src.reg = CFI_R10; 332 op->src.offset = -8; 333 op->dest.type = OP_DEST_REG; 334 op->dest.reg = CFI_SP; 335 break; 336 } 337 338 if (rex == 0x49 && modrm == 0x65 && 339 insn.displacement.value == -16) { 340 341 /* 342 * lea -0x10(%r13), %rsp 343 * 344 * Restoring rsp back to its original value after a 345 * stack realignment. 346 */ 347 *type = INSN_STACK; 348 op->src.type = OP_SRC_ADD; 349 op->src.reg = CFI_R13; 350 op->src.offset = -16; 351 op->dest.type = OP_DEST_REG; 352 op->dest.reg = CFI_SP; 353 break; 354 } 355 356 break; 357 358 case 0x8f: 359 /* pop to mem */ 360 *type = INSN_STACK; 361 op->src.type = OP_SRC_POP; 362 op->dest.type = OP_DEST_MEM; 363 break; 364 365 case 0x90: 366 *type = INSN_NOP; 367 break; 368 369 case 0x9c: 370 /* pushf */ 371 *type = INSN_STACK; 372 op->src.type = OP_SRC_CONST; 373 op->dest.type = OP_DEST_PUSH; 374 break; 375 376 case 0x9d: 377 /* popf */ 378 *type = INSN_STACK; 379 op->src.type = OP_SRC_POP; 380 op->dest.type = OP_DEST_MEM; 381 break; 382 383 case 0x0f: 384 385 if (op2 >= 0x80 && op2 <= 0x8f) 386 *type = INSN_JUMP_CONDITIONAL; 387 else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 || 388 op2 == 0x35) 389 390 /* sysenter, sysret */ 391 *type = INSN_CONTEXT_SWITCH; 392 393 else if (op2 == 0x0d || op2 == 0x1f) 394 395 /* nopl/nopw */ 396 *type = INSN_NOP; 397 398 else if (op2 == 0xa0 || op2 == 0xa8) { 399 400 /* push fs/gs */ 401 *type = INSN_STACK; 402 op->src.type = OP_SRC_CONST; 403 op->dest.type = OP_DEST_PUSH; 404 405 } else if (op2 == 0xa1 || op2 == 0xa9) { 406 407 /* pop fs/gs */ 408 *type = INSN_STACK; 409 op->src.type = OP_SRC_POP; 410 op->dest.type = OP_DEST_MEM; 411 } 412 413 break; 414 415 case 0xc9: 416 /* 417 * leave 418 * 419 * equivalent to: 420 * mov bp, sp 421 * pop bp 422 */ 423 *type = INSN_STACK; 424 op->dest.type = OP_DEST_LEAVE; 425 426 break; 427 428 case 0xe3: 429 /* jecxz/jrcxz */ 430 *type = INSN_JUMP_CONDITIONAL; 431 break; 432 433 case 0xe9: 434 case 0xeb: 435 *type = INSN_JUMP_UNCONDITIONAL; 436 break; 437 438 case 0xc2: 439 case 0xc3: 440 *type = INSN_RETURN; 441 break; 442 443 case 0xca: /* retf */ 444 case 0xcb: /* retf */ 445 case 0xcf: /* iret */ 446 *type = INSN_CONTEXT_SWITCH; 447 break; 448 449 case 0xe8: 450 *type = INSN_CALL; 451 break; 452 453 case 0xff: 454 if (modrm_reg == 2 || modrm_reg == 3) 455 456 *type = INSN_CALL_DYNAMIC; 457 458 else if (modrm_reg == 4) 459 460 *type = INSN_JUMP_DYNAMIC; 461 462 else if (modrm_reg == 5) 463 464 /* jmpf */ 465 *type = INSN_CONTEXT_SWITCH; 466 467 else if (modrm_reg == 6) { 468 469 /* push from mem */ 470 *type = INSN_STACK; 471 op->src.type = OP_SRC_CONST; 472 op->dest.type = OP_DEST_PUSH; 473 } 474 475 break; 476 477 default: 478 break; 479 } 480 481 *immediate = insn.immediate.nbytes ? insn.immediate.value : 0; 482 483 return 0; 484 } 485 486 void arch_initial_func_cfi_state(struct cfi_state *state) 487 { 488 int i; 489 490 for (i = 0; i < CFI_NUM_REGS; i++) { 491 state->regs[i].base = CFI_UNDEFINED; 492 state->regs[i].offset = 0; 493 } 494 495 /* initial CFA (call frame address) */ 496 state->cfa.base = CFI_SP; 497 state->cfa.offset = 8; 498 499 /* initial RA (return address) */ 500 state->regs[16].base = CFI_CFA; 501 state->regs[16].offset = -8; 502 } 503