0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <stdio.h>
0009 #include <string.h>
0010 #include <endian.h>
0011 #include <byteswap.h>
0012 #include "../../../arch/x86/include/asm/insn.h"
0013
0014 #include "../../../arch/x86/lib/inat.c"
0015 #include "../../../arch/x86/lib/insn.c"
0016
0017 #include "event.h"
0018
0019 #include "intel-pt-insn-decoder.h"
0020 #include "dump-insn.h"
0021
0022 #if INTEL_PT_INSN_BUF_SZ < MAX_INSN_SIZE || INTEL_PT_INSN_BUF_SZ > MAX_INSN
0023 #error Instruction buffer size too small
0024 #endif
0025
0026
0027 static void intel_pt_insn_decoder(struct insn *insn,
0028 struct intel_pt_insn *intel_pt_insn)
0029 {
0030 enum intel_pt_insn_op op = INTEL_PT_OP_OTHER;
0031 enum intel_pt_insn_branch branch = INTEL_PT_BR_NO_BRANCH;
0032 int ext;
0033
0034 intel_pt_insn->rel = 0;
0035 intel_pt_insn->emulated_ptwrite = false;
0036
0037 if (insn_is_avx(insn)) {
0038 intel_pt_insn->op = INTEL_PT_OP_OTHER;
0039 intel_pt_insn->branch = INTEL_PT_BR_NO_BRANCH;
0040 intel_pt_insn->length = insn->length;
0041 return;
0042 }
0043
0044 switch (insn->opcode.bytes[0]) {
0045 case 0xf:
0046 switch (insn->opcode.bytes[1]) {
0047 case 0x01:
0048 switch (insn->modrm.bytes[0]) {
0049 case 0xc2:
0050 case 0xc3:
0051 op = INTEL_PT_OP_VMENTRY;
0052 branch = INTEL_PT_BR_INDIRECT;
0053 break;
0054 default:
0055 break;
0056 }
0057 break;
0058 case 0x05:
0059 case 0x34:
0060 op = INTEL_PT_OP_SYSCALL;
0061 branch = INTEL_PT_BR_INDIRECT;
0062 break;
0063 case 0x07:
0064 case 0x35:
0065 op = INTEL_PT_OP_SYSRET;
0066 branch = INTEL_PT_BR_INDIRECT;
0067 break;
0068 case 0x80 ... 0x8f:
0069 op = INTEL_PT_OP_JCC;
0070 branch = INTEL_PT_BR_CONDITIONAL;
0071 break;
0072 default:
0073 break;
0074 }
0075 break;
0076 case 0x70 ... 0x7f:
0077 op = INTEL_PT_OP_JCC;
0078 branch = INTEL_PT_BR_CONDITIONAL;
0079 break;
0080 case 0xc2:
0081 case 0xc3:
0082 case 0xca:
0083 case 0xcb:
0084 op = INTEL_PT_OP_RET;
0085 branch = INTEL_PT_BR_INDIRECT;
0086 break;
0087 case 0xcf:
0088 op = INTEL_PT_OP_IRET;
0089 branch = INTEL_PT_BR_INDIRECT;
0090 break;
0091 case 0xcc ... 0xce:
0092 op = INTEL_PT_OP_INT;
0093 branch = INTEL_PT_BR_INDIRECT;
0094 break;
0095 case 0xe8:
0096 op = INTEL_PT_OP_CALL;
0097 branch = INTEL_PT_BR_UNCONDITIONAL;
0098 break;
0099 case 0x9a:
0100 op = INTEL_PT_OP_CALL;
0101 branch = INTEL_PT_BR_INDIRECT;
0102 break;
0103 case 0xe0 ... 0xe2:
0104 op = INTEL_PT_OP_LOOP;
0105 branch = INTEL_PT_BR_CONDITIONAL;
0106 break;
0107 case 0xe3:
0108 op = INTEL_PT_OP_JCC;
0109 branch = INTEL_PT_BR_CONDITIONAL;
0110 break;
0111 case 0xe9:
0112 case 0xeb:
0113 op = INTEL_PT_OP_JMP;
0114 branch = INTEL_PT_BR_UNCONDITIONAL;
0115 break;
0116 case 0xea:
0117 op = INTEL_PT_OP_JMP;
0118 branch = INTEL_PT_BR_INDIRECT;
0119 break;
0120 case 0xff:
0121 ext = (insn->modrm.bytes[0] >> 3) & 0x7;
0122 switch (ext) {
0123 case 2:
0124 case 3:
0125 op = INTEL_PT_OP_CALL;
0126 branch = INTEL_PT_BR_INDIRECT;
0127 break;
0128 case 4:
0129 case 5:
0130 op = INTEL_PT_OP_JMP;
0131 branch = INTEL_PT_BR_INDIRECT;
0132 break;
0133 default:
0134 break;
0135 }
0136 break;
0137 default:
0138 break;
0139 }
0140
0141 intel_pt_insn->op = op;
0142 intel_pt_insn->branch = branch;
0143 intel_pt_insn->length = insn->length;
0144
0145 if (branch == INTEL_PT_BR_CONDITIONAL ||
0146 branch == INTEL_PT_BR_UNCONDITIONAL) {
0147 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
0148 switch (insn->immediate.nbytes) {
0149 case 1:
0150 intel_pt_insn->rel = insn->immediate.value;
0151 break;
0152 case 2:
0153 intel_pt_insn->rel =
0154 bswap_16((short)insn->immediate.value);
0155 break;
0156 case 4:
0157 intel_pt_insn->rel = bswap_32(insn->immediate.value);
0158 break;
0159 default:
0160 intel_pt_insn->rel = 0;
0161 break;
0162 }
0163 #else
0164 intel_pt_insn->rel = insn->immediate.value;
0165 #endif
0166 }
0167 }
0168
0169 int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64,
0170 struct intel_pt_insn *intel_pt_insn)
0171 {
0172 struct insn insn;
0173 int ret;
0174
0175 ret = insn_decode(&insn, buf, len,
0176 x86_64 ? INSN_MODE_64 : INSN_MODE_32);
0177 if (ret < 0 || insn.length > len)
0178 return -1;
0179
0180 intel_pt_insn_decoder(&insn, intel_pt_insn);
0181 if (insn.length < INTEL_PT_INSN_BUF_SZ)
0182 memcpy(intel_pt_insn->buf, buf, insn.length);
0183 else
0184 memcpy(intel_pt_insn->buf, buf, INTEL_PT_INSN_BUF_SZ);
0185 return 0;
0186 }
0187
0188 int arch_is_branch(const unsigned char *buf, size_t len, int x86_64)
0189 {
0190 struct intel_pt_insn in;
0191 if (intel_pt_get_insn(buf, len, x86_64, &in) < 0)
0192 return -1;
0193 return in.branch != INTEL_PT_BR_NO_BRANCH;
0194 }
0195
0196 const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused,
0197 u8 *inbuf, int inlen, int *lenp)
0198 {
0199 struct insn insn;
0200 int n, i, ret;
0201 int left;
0202
0203 ret = insn_decode(&insn, inbuf, inlen,
0204 x->is64bit ? INSN_MODE_64 : INSN_MODE_32);
0205
0206 if (ret < 0 || insn.length > inlen)
0207 return "<bad>";
0208 if (lenp)
0209 *lenp = insn.length;
0210 left = sizeof(x->out);
0211 n = snprintf(x->out, left, "insn: ");
0212 left -= n;
0213 for (i = 0; i < insn.length; i++) {
0214 n += snprintf(x->out + n, left, "%02x ", inbuf[i]);
0215 left -= n;
0216 }
0217 return x->out;
0218 }
0219
0220 const char *branch_name[] = {
0221 [INTEL_PT_OP_OTHER] = "Other",
0222 [INTEL_PT_OP_CALL] = "Call",
0223 [INTEL_PT_OP_RET] = "Ret",
0224 [INTEL_PT_OP_JCC] = "Jcc",
0225 [INTEL_PT_OP_JMP] = "Jmp",
0226 [INTEL_PT_OP_LOOP] = "Loop",
0227 [INTEL_PT_OP_IRET] = "IRet",
0228 [INTEL_PT_OP_INT] = "Int",
0229 [INTEL_PT_OP_SYSCALL] = "Syscall",
0230 [INTEL_PT_OP_SYSRET] = "Sysret",
0231 [INTEL_PT_OP_VMENTRY] = "VMentry",
0232 };
0233
0234 const char *intel_pt_insn_name(enum intel_pt_insn_op op)
0235 {
0236 return branch_name[op];
0237 }
0238
0239 int intel_pt_insn_desc(const struct intel_pt_insn *intel_pt_insn, char *buf,
0240 size_t buf_len)
0241 {
0242 switch (intel_pt_insn->branch) {
0243 case INTEL_PT_BR_CONDITIONAL:
0244 case INTEL_PT_BR_UNCONDITIONAL:
0245 return snprintf(buf, buf_len, "%s %s%d",
0246 intel_pt_insn_name(intel_pt_insn->op),
0247 intel_pt_insn->rel > 0 ? "+" : "",
0248 intel_pt_insn->rel);
0249 case INTEL_PT_BR_NO_BRANCH:
0250 case INTEL_PT_BR_INDIRECT:
0251 return snprintf(buf, buf_len, "%s",
0252 intel_pt_insn_name(intel_pt_insn->op));
0253 default:
0254 break;
0255 }
0256 return 0;
0257 }
0258
0259 int intel_pt_insn_type(enum intel_pt_insn_op op)
0260 {
0261 switch (op) {
0262 case INTEL_PT_OP_OTHER:
0263 return 0;
0264 case INTEL_PT_OP_CALL:
0265 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL;
0266 case INTEL_PT_OP_RET:
0267 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN;
0268 case INTEL_PT_OP_JCC:
0269 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL;
0270 case INTEL_PT_OP_JMP:
0271 return PERF_IP_FLAG_BRANCH;
0272 case INTEL_PT_OP_LOOP:
0273 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL;
0274 case INTEL_PT_OP_IRET:
0275 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
0276 PERF_IP_FLAG_INTERRUPT;
0277 case INTEL_PT_OP_INT:
0278 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
0279 PERF_IP_FLAG_INTERRUPT;
0280 case INTEL_PT_OP_SYSCALL:
0281 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
0282 PERF_IP_FLAG_SYSCALLRET;
0283 case INTEL_PT_OP_SYSRET:
0284 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN |
0285 PERF_IP_FLAG_SYSCALLRET;
0286 case INTEL_PT_OP_VMENTRY:
0287 return PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
0288 PERF_IP_FLAG_VMENTRY;
0289 default:
0290 return 0;
0291 }
0292 }