^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define unlikely(cond) (cond)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/insn.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "../../../arch/x86/lib/inat.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "../../../arch/x86/lib/insn.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "../../check.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "../../elf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "../../arch.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "../../warn.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/orc_types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static unsigned char op_to_cfi_reg[][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {CFI_AX, CFI_R8},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {CFI_CX, CFI_R9},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {CFI_DX, CFI_R10},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {CFI_BX, CFI_R11},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {CFI_SP, CFI_R12},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {CFI_BP, CFI_R13},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {CFI_SI, CFI_R14},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {CFI_DI, CFI_R15},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int is_x86_64(const struct elf *elf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) switch (elf->ehdr.e_machine) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) case EM_X86_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) case EM_386:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) WARN("unexpected ELF machine type %d", elf->ehdr.e_machine);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) bool arch_callee_saved_reg(unsigned char reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case CFI_BP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) case CFI_BX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case CFI_R12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case CFI_R13:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case CFI_R14:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case CFI_R15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case CFI_AX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case CFI_CX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case CFI_DX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) case CFI_SI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) case CFI_DI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) case CFI_SP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case CFI_R8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) case CFI_R9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) case CFI_R10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case CFI_R11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case CFI_RA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned long arch_dest_reloc_offset(int addend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return addend + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned long arch_jump_destination(struct instruction *insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return insn->offset + insn->len + insn->immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define ADD_OP(op) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (!(op = calloc(1, sizeof(*op)))) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) else for (list_add_tail(&op->list, ops_list); op; op = NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int arch_decode_instruction(const struct elf *elf, const struct section *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned long offset, unsigned int maxlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) unsigned int *len, enum insn_type *type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long *immediate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct list_head *ops_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct insn insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int x86_64, sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) modrm_reg = 0, sib = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct stack_op *op = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct symbol *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) x86_64 = is_x86_64(elf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (x86_64 == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) insn_init(&insn, sec->data->d_buf + offset, maxlen, x86_64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) insn_get_length(&insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!insn_complete(&insn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) WARN("can't decode instruction at %s:0x%lx", sec->name, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) *len = insn.length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) *type = INSN_OTHER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (insn.vex_prefix.nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) op1 = insn.opcode.bytes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) op2 = insn.opcode.bytes[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (insn.rex_prefix.nbytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) rex = insn.rex_prefix.bytes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) rex_w = X86_REX_W(rex) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) rex_r = X86_REX_R(rex) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) rex_x = X86_REX_X(rex) >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) rex_b = X86_REX_B(rex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (insn.modrm.nbytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) modrm = insn.modrm.bytes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) modrm_mod = X86_MODRM_MOD(modrm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) modrm_reg = X86_MODRM_REG(modrm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) modrm_rm = X86_MODRM_RM(modrm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (insn.sib.nbytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) sib = insn.sib.bytes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) switch (op1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) case 0x1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) case 0x29:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* add/sub reg, %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) op->src.type = OP_SRC_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) case 0x50 ... 0x57:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* push reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) op->src.type = OP_SRC_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) op->dest.type = OP_DEST_PUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) case 0x58 ... 0x5f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* pop reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) op->src.type = OP_SRC_POP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) case 0x68:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case 0x6a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* push immediate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) op->src.type = OP_SRC_CONST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) op->dest.type = OP_DEST_PUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) case 0x70 ... 0x7f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) *type = INSN_JUMP_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) case 0x81:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) case 0x83:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (rex != 0x48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (modrm == 0xe4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* and imm, %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) op->src.type = OP_SRC_AND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) op->src.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) op->src.offset = insn.immediate.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (modrm == 0xc4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) sign = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) else if (modrm == 0xec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) sign = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* add/sub imm, %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) op->src.type = OP_SRC_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) op->src.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) op->src.offset = insn.immediate.value * sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) case 0x89:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* mov %rsp, reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) op->src.type = OP_SRC_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) op->src.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* mov reg, %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) op->src.type = OP_SRC_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* fallthrough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) case 0x88:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (!rex_b &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* mov reg, disp(%rbp) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) op->src.type = OP_SRC_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) op->dest.type = OP_DEST_REG_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) op->dest.reg = CFI_BP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) op->dest.offset = insn.displacement.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* mov reg, disp(%rsp) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) op->src.type = OP_SRC_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) op->dest.type = OP_DEST_REG_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) op->dest.offset = insn.displacement.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) case 0x8b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* mov disp(%rbp), reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) op->src.type = OP_SRC_REG_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) op->src.reg = CFI_BP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) op->src.offset = insn.displacement.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) } else if (rex_w && !rex_b && sib == 0x24 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) modrm_mod != 3 && modrm_rm == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /* mov disp(%rsp), reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) op->src.type = OP_SRC_REG_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) op->src.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) op->src.offset = insn.displacement.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) case 0x8d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (!insn.displacement.value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* lea (%rsp), reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) op->src.type = OP_SRC_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* lea disp(%rsp), reg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) op->src.type = OP_SRC_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) op->src.offset = insn.displacement.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) op->src.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) } else if (rex == 0x48 && modrm == 0x65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* lea disp(%rbp), %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) op->src.type = OP_SRC_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) op->src.reg = CFI_BP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) op->src.offset = insn.displacement.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) } else if (rex == 0x49 && modrm == 0x62 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) insn.displacement.value == -8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * lea -0x8(%r10), %rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * Restoring rsp back to its original value after a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * stack realignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) op->src.type = OP_SRC_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) op->src.reg = CFI_R10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) op->src.offset = -8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) } else if (rex == 0x49 && modrm == 0x65 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) insn.displacement.value == -16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * lea -0x10(%r13), %rsp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * Restoring rsp back to its original value after a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * stack realignment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) op->src.type = OP_SRC_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) op->src.reg = CFI_R13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) op->src.offset = -16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case 0x8f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* pop to mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) op->src.type = OP_SRC_POP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) op->dest.type = OP_DEST_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) case 0x90:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) *type = INSN_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) case 0x9c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* pushf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) op->src.type = OP_SRC_CONST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) op->dest.type = OP_DEST_PUSHF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) case 0x9d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* popf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) op->src.type = OP_SRC_POPF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) op->dest.type = OP_DEST_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case 0x0f:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (op2 == 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (modrm == 0xca)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) *type = INSN_CLAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) else if (modrm == 0xcb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) *type = INSN_STAC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) } else if (op2 >= 0x80 && op2 <= 0x8f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) *type = INSN_JUMP_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) } else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) op2 == 0x35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* sysenter, sysret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) *type = INSN_CONTEXT_SWITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) } else if (op2 == 0x0b || op2 == 0xb9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* ud2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) *type = INSN_BUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) } else if (op2 == 0x0d || op2 == 0x1f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) /* nopl/nopw */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) *type = INSN_NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) } else if (op2 == 0xa0 || op2 == 0xa8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /* push fs/gs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) op->src.type = OP_SRC_CONST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) op->dest.type = OP_DEST_PUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) } else if (op2 == 0xa1 || op2 == 0xa9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /* pop fs/gs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) op->src.type = OP_SRC_POP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) op->dest.type = OP_DEST_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case 0xc9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * leave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * equivalent to:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * mov bp, sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * pop bp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ADD_OP(op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) op->dest.type = OP_DEST_LEAVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) case 0xe3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* jecxz/jrcxz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) *type = INSN_JUMP_CONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case 0xe9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) case 0xeb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) *type = INSN_JUMP_UNCONDITIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) case 0xc2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case 0xc3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) *type = INSN_RETURN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) case 0xcf: /* iret */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * Handle sync_core(), which has an IRET to self.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * All other IRET are in STT_NONE entry code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) sym = find_symbol_containing(sec, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (sym && sym->type == STT_FUNC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) /* add $40, %rsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) op->src.type = OP_SRC_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) op->src.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) op->src.offset = 5*8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) op->dest.type = OP_DEST_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) op->dest.reg = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) /* fallthrough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) case 0xca: /* retf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) case 0xcb: /* retf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) *type = INSN_CONTEXT_SWITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) case 0xe8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) *type = INSN_CALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * For the impact on the stack, a CALL behaves like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * a PUSH of an immediate value (the return address).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) op->src.type = OP_SRC_CONST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) op->dest.type = OP_DEST_PUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case 0xfc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) *type = INSN_CLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case 0xfd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *type = INSN_STD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case 0xff:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (modrm_reg == 2 || modrm_reg == 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) *type = INSN_CALL_DYNAMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) else if (modrm_reg == 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) *type = INSN_JUMP_DYNAMIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) else if (modrm_reg == 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* jmpf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) *type = INSN_CONTEXT_SWITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) else if (modrm_reg == 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* push from mem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ADD_OP(op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) op->src.type = OP_SRC_CONST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) op->dest.type = OP_DEST_PUSH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) *immediate = insn.immediate.nbytes ? insn.immediate.value : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) void arch_initial_func_cfi_state(struct cfi_init_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) for (i = 0; i < CFI_NUM_REGS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) state->regs[i].base = CFI_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) state->regs[i].offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) /* initial CFA (call frame address) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) state->cfa.base = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) state->cfa.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* initial RA (return address) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) state->regs[16].base = CFI_CFA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) state->regs[16].offset = -8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) const char *arch_nop_insn(int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static const char nops[5][5] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /* 1 */ { 0x90 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) /* 2 */ { 0x66, 0x90 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /* 3 */ { 0x0f, 0x1f, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* 4 */ { 0x0f, 0x1f, 0x40, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) /* 5 */ { 0x0f, 0x1f, 0x44, 0x00, 0x00 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (len < 1 || len > 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) WARN("invalid NOP size: %d\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return nops[len-1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int arch_decode_hint_reg(struct instruction *insn, u8 sp_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) struct cfi_reg *cfa = &insn->cfi.cfa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) switch (sp_reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) case ORC_REG_UNDEFINED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) cfa->base = CFI_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) case ORC_REG_SP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) cfa->base = CFI_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) case ORC_REG_BP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) cfa->base = CFI_BP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) case ORC_REG_SP_INDIRECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) cfa->base = CFI_SP_INDIRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case ORC_REG_R10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) cfa->base = CFI_R10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case ORC_REG_R13:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) cfa->base = CFI_R13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) case ORC_REG_DI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) cfa->base = CFI_DI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) case ORC_REG_DX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) cfa->base = CFI_DX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }