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