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 <asm/insn.h> 23 #include "lib/inat.c" 24 #include "lib/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 rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0, 90 modrm_reg = 0, 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_x = X86_REX_X(rex) >> 1; 118 rex_b = X86_REX_B(rex); 119 } 120 121 if (insn.modrm.nbytes) { 122 modrm = insn.modrm.bytes[0]; 123 modrm_mod = X86_MODRM_MOD(modrm); 124 modrm_reg = X86_MODRM_REG(modrm); 125 modrm_rm = X86_MODRM_RM(modrm); 126 } 127 128 if (insn.sib.nbytes) 129 sib = insn.sib.bytes[0]; 130 131 switch (op1) { 132 133 case 0x1: 134 case 0x29: 135 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) { 136 137 /* add/sub reg, %rsp */ 138 *type = INSN_STACK; 139 op->src.type = OP_SRC_ADD; 140 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 141 op->dest.type = OP_DEST_REG; 142 op->dest.reg = CFI_SP; 143 } 144 break; 145 146 case 0x50 ... 0x57: 147 148 /* push reg */ 149 *type = INSN_STACK; 150 op->src.type = OP_SRC_REG; 151 op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; 152 op->dest.type = OP_DEST_PUSH; 153 154 break; 155 156 case 0x58 ... 0x5f: 157 158 /* pop reg */ 159 *type = INSN_STACK; 160 op->src.type = OP_SRC_POP; 161 op->dest.type = OP_DEST_REG; 162 op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b]; 163 164 break; 165 166 case 0x68: 167 case 0x6a: 168 /* push immediate */ 169 *type = INSN_STACK; 170 op->src.type = OP_SRC_CONST; 171 op->dest.type = OP_DEST_PUSH; 172 break; 173 174 case 0x70 ... 0x7f: 175 *type = INSN_JUMP_CONDITIONAL; 176 break; 177 178 case 0x81: 179 case 0x83: 180 if (rex != 0x48) 181 break; 182 183 if (modrm == 0xe4) { 184 /* and imm, %rsp */ 185 *type = INSN_STACK; 186 op->src.type = OP_SRC_AND; 187 op->src.reg = CFI_SP; 188 op->src.offset = insn.immediate.value; 189 op->dest.type = OP_DEST_REG; 190 op->dest.reg = CFI_SP; 191 break; 192 } 193 194 if (modrm == 0xc4) 195 sign = 1; 196 else if (modrm == 0xec) 197 sign = -1; 198 else 199 break; 200 201 /* add/sub imm, %rsp */ 202 *type = INSN_STACK; 203 op->src.type = OP_SRC_ADD; 204 op->src.reg = CFI_SP; 205 op->src.offset = insn.immediate.value * sign; 206 op->dest.type = OP_DEST_REG; 207 op->dest.reg = CFI_SP; 208 break; 209 210 case 0x89: 211 if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) { 212 213 /* mov %rsp, reg */ 214 *type = INSN_STACK; 215 op->src.type = OP_SRC_REG; 216 op->src.reg = CFI_SP; 217 op->dest.type = OP_DEST_REG; 218 op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b]; 219 break; 220 } 221 222 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) { 223 224 /* mov reg, %rsp */ 225 *type = INSN_STACK; 226 op->src.type = OP_SRC_REG; 227 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 228 op->dest.type = OP_DEST_REG; 229 op->dest.reg = CFI_SP; 230 break; 231 } 232 233 /* fallthrough */ 234 case 0x88: 235 if (!rex_b && 236 (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) { 237 238 /* mov reg, disp(%rbp) */ 239 *type = INSN_STACK; 240 op->src.type = OP_SRC_REG; 241 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 242 op->dest.type = OP_DEST_REG_INDIRECT; 243 op->dest.reg = CFI_BP; 244 op->dest.offset = insn.displacement.value; 245 246 } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) { 247 248 /* mov reg, disp(%rsp) */ 249 *type = INSN_STACK; 250 op->src.type = OP_SRC_REG; 251 op->src.reg = op_to_cfi_reg[modrm_reg][rex_r]; 252 op->dest.type = OP_DEST_REG_INDIRECT; 253 op->dest.reg = CFI_SP; 254 op->dest.offset = insn.displacement.value; 255 } 256 257 break; 258 259 case 0x8b: 260 if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) { 261 262 /* mov disp(%rbp), reg */ 263 *type = INSN_STACK; 264 op->src.type = OP_SRC_REG_INDIRECT; 265 op->src.reg = CFI_BP; 266 op->src.offset = insn.displacement.value; 267 op->dest.type = OP_DEST_REG; 268 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 269 270 } else if (rex_w && !rex_b && sib == 0x24 && 271 modrm_mod != 3 && modrm_rm == 4) { 272 273 /* mov disp(%rsp), reg */ 274 *type = INSN_STACK; 275 op->src.type = OP_SRC_REG_INDIRECT; 276 op->src.reg = CFI_SP; 277 op->src.offset = insn.displacement.value; 278 op->dest.type = OP_DEST_REG; 279 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 280 } 281 282 break; 283 284 case 0x8d: 285 if (sib == 0x24 && rex_w && !rex_b && !rex_x) { 286 287 *type = INSN_STACK; 288 if (!insn.displacement.value) { 289 /* lea (%rsp), reg */ 290 op->src.type = OP_SRC_REG; 291 } else { 292 /* lea disp(%rsp), reg */ 293 op->src.type = OP_SRC_ADD; 294 op->src.offset = insn.displacement.value; 295 } 296 op->src.reg = CFI_SP; 297 op->dest.type = OP_DEST_REG; 298 op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r]; 299 300 } else if (rex == 0x48 && modrm == 0x65) { 301 302 /* lea disp(%rbp), %rsp */ 303 *type = INSN_STACK; 304 op->src.type = OP_SRC_ADD; 305 op->src.reg = CFI_BP; 306 op->src.offset = insn.displacement.value; 307 op->dest.type = OP_DEST_REG; 308 op->dest.reg = CFI_SP; 309 310 } else if (rex == 0x49 && modrm == 0x62 && 311 insn.displacement.value == -8) { 312 313 /* 314 * lea -0x8(%r10), %rsp 315 * 316 * Restoring rsp back to its original value after a 317 * stack realignment. 318 */ 319 *type = INSN_STACK; 320 op->src.type = OP_SRC_ADD; 321 op->src.reg = CFI_R10; 322 op->src.offset = -8; 323 op->dest.type = OP_DEST_REG; 324 op->dest.reg = CFI_SP; 325 326 } else if (rex == 0x49 && modrm == 0x65 && 327 insn.displacement.value == -16) { 328 329 /* 330 * lea -0x10(%r13), %rsp 331 * 332 * Restoring rsp back to its original value after a 333 * stack realignment. 334 */ 335 *type = INSN_STACK; 336 op->src.type = OP_SRC_ADD; 337 op->src.reg = CFI_R13; 338 op->src.offset = -16; 339 op->dest.type = OP_DEST_REG; 340 op->dest.reg = CFI_SP; 341 } 342 343 break; 344 345 case 0x8f: 346 /* pop to mem */ 347 *type = INSN_STACK; 348 op->src.type = OP_SRC_POP; 349 op->dest.type = OP_DEST_MEM; 350 break; 351 352 case 0x90: 353 *type = INSN_NOP; 354 break; 355 356 case 0x9c: 357 /* pushf */ 358 *type = INSN_STACK; 359 op->src.type = OP_SRC_CONST; 360 op->dest.type = OP_DEST_PUSH; 361 break; 362 363 case 0x9d: 364 /* popf */ 365 *type = INSN_STACK; 366 op->src.type = OP_SRC_POP; 367 op->dest.type = OP_DEST_MEM; 368 break; 369 370 case 0x0f: 371 372 if (op2 >= 0x80 && op2 <= 0x8f) { 373 374 *type = INSN_JUMP_CONDITIONAL; 375 376 } else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 || 377 op2 == 0x35) { 378 379 /* sysenter, sysret */ 380 *type = INSN_CONTEXT_SWITCH; 381 382 } else if (op2 == 0x0b || op2 == 0xb9) { 383 384 /* ud2 */ 385 *type = INSN_BUG; 386 387 } else if (op2 == 0x0d || op2 == 0x1f) { 388 389 /* nopl/nopw */ 390 *type = INSN_NOP; 391 392 } else if (op2 == 0xa0 || op2 == 0xa8) { 393 394 /* push fs/gs */ 395 *type = INSN_STACK; 396 op->src.type = OP_SRC_CONST; 397 op->dest.type = OP_DEST_PUSH; 398 399 } else if (op2 == 0xa1 || op2 == 0xa9) { 400 401 /* pop fs/gs */ 402 *type = INSN_STACK; 403 op->src.type = OP_SRC_POP; 404 op->dest.type = OP_DEST_MEM; 405 } 406 407 break; 408 409 case 0xc9: 410 /* 411 * leave 412 * 413 * equivalent to: 414 * mov bp, sp 415 * pop bp 416 */ 417 *type = INSN_STACK; 418 op->dest.type = OP_DEST_LEAVE; 419 420 break; 421 422 case 0xe3: 423 /* jecxz/jrcxz */ 424 *type = INSN_JUMP_CONDITIONAL; 425 break; 426 427 case 0xe9: 428 case 0xeb: 429 *type = INSN_JUMP_UNCONDITIONAL; 430 break; 431 432 case 0xc2: 433 case 0xc3: 434 *type = INSN_RETURN; 435 break; 436 437 case 0xca: /* retf */ 438 case 0xcb: /* retf */ 439 case 0xcf: /* iret */ 440 *type = INSN_CONTEXT_SWITCH; 441 break; 442 443 case 0xe8: 444 *type = INSN_CALL; 445 break; 446 447 case 0xff: 448 if (modrm_reg == 2 || modrm_reg == 3) 449 450 *type = INSN_CALL_DYNAMIC; 451 452 else if (modrm_reg == 4) 453 454 *type = INSN_JUMP_DYNAMIC; 455 456 else if (modrm_reg == 5) 457 458 /* jmpf */ 459 *type = INSN_CONTEXT_SWITCH; 460 461 else if (modrm_reg == 6) { 462 463 /* push from mem */ 464 *type = INSN_STACK; 465 op->src.type = OP_SRC_CONST; 466 op->dest.type = OP_DEST_PUSH; 467 } 468 469 break; 470 471 default: 472 break; 473 } 474 475 *immediate = insn.immediate.nbytes ? insn.immediate.value : 0; 476 477 return 0; 478 } 479 480 void arch_initial_func_cfi_state(struct cfi_state *state) 481 { 482 int i; 483 484 for (i = 0; i < CFI_NUM_REGS; i++) { 485 state->regs[i].base = CFI_UNDEFINED; 486 state->regs[i].offset = 0; 487 } 488 489 /* initial CFA (call frame address) */ 490 state->cfa.base = CFI_SP; 491 state->cfa.offset = 8; 492 493 /* initial RA (return address) */ 494 state->regs[16].base = CFI_CFA; 495 state->regs[16].offset = -8; 496 } 497