0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/ptrace.h> /* struct pt_regs */
0015 #include "pf_in.h"
0016
0017 #ifdef __i386__
0018
0019 static unsigned char prefix_codes[] = {
0020 0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64,
0021 0x65, 0x66, 0x67
0022 };
0023
0024 static unsigned int reg_rop[] = {
0025 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F
0026 };
0027 static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB };
0028 static unsigned int imm_wop[] = { 0xC6, 0xC7 };
0029
0030 static unsigned int rw8[] = { 0x88, 0x8A, 0xC6, 0xAA };
0031 static unsigned int rw32[] = {
0032 0x89, 0x8B, 0xC7, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB
0033 };
0034 static unsigned int mw8[] = { 0x88, 0x8A, 0xC6, 0xB60F, 0xBE0F, 0xAA };
0035 static unsigned int mw16[] = { 0xB70F, 0xBF0F };
0036 static unsigned int mw32[] = { 0x89, 0x8B, 0xC7, 0xAB };
0037 static unsigned int mw64[] = {};
0038 #else
0039 static unsigned char prefix_codes[] = {
0040 0x66, 0x67, 0x2E, 0x3E, 0x26, 0x64, 0x65, 0x36,
0041 0xF0, 0xF3, 0xF2,
0042
0043 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0044 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
0045 };
0046
0047 static unsigned int reg_rop[] = {
0048 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F
0049 };
0050 static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB };
0051 static unsigned int imm_wop[] = { 0xC6, 0xC7 };
0052 static unsigned int rw8[] = { 0xC6, 0x88, 0x8A, 0xAA };
0053 static unsigned int rw32[] = {
0054 0xC7, 0x89, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB
0055 };
0056
0057 static unsigned int mw8[] = { 0xC6, 0x88, 0x8A, 0xB60F, 0xBE0F, 0xAA };
0058
0059 static unsigned int mw16[] = { 0xB70F, 0xBF0F };
0060
0061 static unsigned int mw32[] = { 0xC7 };
0062
0063 static unsigned int mw64[] = { 0x89, 0x8B, 0xAB };
0064 #endif
0065
0066 struct prefix_bits {
0067 unsigned shorted:1;
0068 unsigned enlarged:1;
0069 unsigned rexr:1;
0070 unsigned rex:1;
0071 };
0072
0073 static int skip_prefix(unsigned char *addr, struct prefix_bits *prf)
0074 {
0075 int i;
0076 unsigned char *p = addr;
0077 prf->shorted = 0;
0078 prf->enlarged = 0;
0079 prf->rexr = 0;
0080 prf->rex = 0;
0081
0082 restart:
0083 for (i = 0; i < ARRAY_SIZE(prefix_codes); i++) {
0084 if (*p == prefix_codes[i]) {
0085 if (*p == 0x66)
0086 prf->shorted = 1;
0087 #ifdef __amd64__
0088 if ((*p & 0xf8) == 0x48)
0089 prf->enlarged = 1;
0090 if ((*p & 0xf4) == 0x44)
0091 prf->rexr = 1;
0092 if ((*p & 0xf0) == 0x40)
0093 prf->rex = 1;
0094 #endif
0095 p++;
0096 goto restart;
0097 }
0098 }
0099
0100 return (p - addr);
0101 }
0102
0103 static int get_opcode(unsigned char *addr, unsigned int *opcode)
0104 {
0105 int len;
0106
0107 if (*addr == 0x0F) {
0108
0109 *opcode = *(unsigned short *)addr;
0110 len = 2;
0111 } else {
0112 *opcode = *addr;
0113 len = 1;
0114 }
0115
0116 return len;
0117 }
0118
0119 #define CHECK_OP_TYPE(opcode, array, type) \
0120 for (i = 0; i < ARRAY_SIZE(array); i++) { \
0121 if (array[i] == opcode) { \
0122 rv = type; \
0123 goto exit; \
0124 } \
0125 }
0126
0127 enum reason_type get_ins_type(unsigned long ins_addr)
0128 {
0129 unsigned int opcode;
0130 unsigned char *p;
0131 struct prefix_bits prf;
0132 int i;
0133 enum reason_type rv = OTHERS;
0134
0135 p = (unsigned char *)ins_addr;
0136 p += skip_prefix(p, &prf);
0137 p += get_opcode(p, &opcode);
0138
0139 CHECK_OP_TYPE(opcode, reg_rop, REG_READ);
0140 CHECK_OP_TYPE(opcode, reg_wop, REG_WRITE);
0141 CHECK_OP_TYPE(opcode, imm_wop, IMM_WRITE);
0142
0143 exit:
0144 return rv;
0145 }
0146 #undef CHECK_OP_TYPE
0147
0148 static unsigned int get_ins_reg_width(unsigned long ins_addr)
0149 {
0150 unsigned int opcode;
0151 unsigned char *p;
0152 struct prefix_bits prf;
0153 int i;
0154
0155 p = (unsigned char *)ins_addr;
0156 p += skip_prefix(p, &prf);
0157 p += get_opcode(p, &opcode);
0158
0159 for (i = 0; i < ARRAY_SIZE(rw8); i++)
0160 if (rw8[i] == opcode)
0161 return 1;
0162
0163 for (i = 0; i < ARRAY_SIZE(rw32); i++)
0164 if (rw32[i] == opcode)
0165 return prf.shorted ? 2 : (prf.enlarged ? 8 : 4);
0166
0167 printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode);
0168 return 0;
0169 }
0170
0171 unsigned int get_ins_mem_width(unsigned long ins_addr)
0172 {
0173 unsigned int opcode;
0174 unsigned char *p;
0175 struct prefix_bits prf;
0176 int i;
0177
0178 p = (unsigned char *)ins_addr;
0179 p += skip_prefix(p, &prf);
0180 p += get_opcode(p, &opcode);
0181
0182 for (i = 0; i < ARRAY_SIZE(mw8); i++)
0183 if (mw8[i] == opcode)
0184 return 1;
0185
0186 for (i = 0; i < ARRAY_SIZE(mw16); i++)
0187 if (mw16[i] == opcode)
0188 return 2;
0189
0190 for (i = 0; i < ARRAY_SIZE(mw32); i++)
0191 if (mw32[i] == opcode)
0192 return prf.shorted ? 2 : 4;
0193
0194 for (i = 0; i < ARRAY_SIZE(mw64); i++)
0195 if (mw64[i] == opcode)
0196 return prf.shorted ? 2 : (prf.enlarged ? 8 : 4);
0197
0198 printk(KERN_ERR "mmiotrace: Unknown opcode 0x%02x\n", opcode);
0199 return 0;
0200 }
0201
0202
0203
0204
0205
0206 enum {
0207 arg_AL = 0,
0208 arg_CL = 1,
0209 arg_DL = 2,
0210 arg_BL = 3,
0211 arg_AH = 4,
0212 arg_CH = 5,
0213 arg_DH = 6,
0214 arg_BH = 7,
0215
0216 arg_AX = 0,
0217 arg_CX = 1,
0218 arg_DX = 2,
0219 arg_BX = 3,
0220 arg_SP = 4,
0221 arg_BP = 5,
0222 arg_SI = 6,
0223 arg_DI = 7,
0224 #ifdef __amd64__
0225 arg_R8 = 8,
0226 arg_R9 = 9,
0227 arg_R10 = 10,
0228 arg_R11 = 11,
0229 arg_R12 = 12,
0230 arg_R13 = 13,
0231 arg_R14 = 14,
0232 arg_R15 = 15
0233 #endif
0234 };
0235
0236 static unsigned char *get_reg_w8(int no, int rex, struct pt_regs *regs)
0237 {
0238 unsigned char *rv = NULL;
0239
0240 switch (no) {
0241 case arg_AL:
0242 rv = (unsigned char *)®s->ax;
0243 break;
0244 case arg_BL:
0245 rv = (unsigned char *)®s->bx;
0246 break;
0247 case arg_CL:
0248 rv = (unsigned char *)®s->cx;
0249 break;
0250 case arg_DL:
0251 rv = (unsigned char *)®s->dx;
0252 break;
0253 #ifdef __amd64__
0254 case arg_R8:
0255 rv = (unsigned char *)®s->r8;
0256 break;
0257 case arg_R9:
0258 rv = (unsigned char *)®s->r9;
0259 break;
0260 case arg_R10:
0261 rv = (unsigned char *)®s->r10;
0262 break;
0263 case arg_R11:
0264 rv = (unsigned char *)®s->r11;
0265 break;
0266 case arg_R12:
0267 rv = (unsigned char *)®s->r12;
0268 break;
0269 case arg_R13:
0270 rv = (unsigned char *)®s->r13;
0271 break;
0272 case arg_R14:
0273 rv = (unsigned char *)®s->r14;
0274 break;
0275 case arg_R15:
0276 rv = (unsigned char *)®s->r15;
0277 break;
0278 #endif
0279 default:
0280 break;
0281 }
0282
0283 if (rv)
0284 return rv;
0285
0286 if (rex) {
0287
0288
0289
0290
0291 switch (no) {
0292 case arg_SI:
0293 rv = (unsigned char *)®s->si;
0294 break;
0295 case arg_DI:
0296 rv = (unsigned char *)®s->di;
0297 break;
0298 case arg_BP:
0299 rv = (unsigned char *)®s->bp;
0300 break;
0301 case arg_SP:
0302 rv = (unsigned char *)®s->sp;
0303 break;
0304 default:
0305 break;
0306 }
0307 } else {
0308 switch (no) {
0309 case arg_AH:
0310 rv = 1 + (unsigned char *)®s->ax;
0311 break;
0312 case arg_BH:
0313 rv = 1 + (unsigned char *)®s->bx;
0314 break;
0315 case arg_CH:
0316 rv = 1 + (unsigned char *)®s->cx;
0317 break;
0318 case arg_DH:
0319 rv = 1 + (unsigned char *)®s->dx;
0320 break;
0321 default:
0322 break;
0323 }
0324 }
0325
0326 if (!rv)
0327 printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no);
0328
0329 return rv;
0330 }
0331
0332 static unsigned long *get_reg_w32(int no, struct pt_regs *regs)
0333 {
0334 unsigned long *rv = NULL;
0335
0336 switch (no) {
0337 case arg_AX:
0338 rv = ®s->ax;
0339 break;
0340 case arg_BX:
0341 rv = ®s->bx;
0342 break;
0343 case arg_CX:
0344 rv = ®s->cx;
0345 break;
0346 case arg_DX:
0347 rv = ®s->dx;
0348 break;
0349 case arg_SP:
0350 rv = ®s->sp;
0351 break;
0352 case arg_BP:
0353 rv = ®s->bp;
0354 break;
0355 case arg_SI:
0356 rv = ®s->si;
0357 break;
0358 case arg_DI:
0359 rv = ®s->di;
0360 break;
0361 #ifdef __amd64__
0362 case arg_R8:
0363 rv = ®s->r8;
0364 break;
0365 case arg_R9:
0366 rv = ®s->r9;
0367 break;
0368 case arg_R10:
0369 rv = ®s->r10;
0370 break;
0371 case arg_R11:
0372 rv = ®s->r11;
0373 break;
0374 case arg_R12:
0375 rv = ®s->r12;
0376 break;
0377 case arg_R13:
0378 rv = ®s->r13;
0379 break;
0380 case arg_R14:
0381 rv = ®s->r14;
0382 break;
0383 case arg_R15:
0384 rv = ®s->r15;
0385 break;
0386 #endif
0387 default:
0388 printk(KERN_ERR "mmiotrace: Error reg no# %d\n", no);
0389 }
0390
0391 return rv;
0392 }
0393
0394 unsigned long get_ins_reg_val(unsigned long ins_addr, struct pt_regs *regs)
0395 {
0396 unsigned int opcode;
0397 int reg;
0398 unsigned char *p;
0399 struct prefix_bits prf;
0400 int i;
0401
0402 p = (unsigned char *)ins_addr;
0403 p += skip_prefix(p, &prf);
0404 p += get_opcode(p, &opcode);
0405 for (i = 0; i < ARRAY_SIZE(reg_rop); i++)
0406 if (reg_rop[i] == opcode)
0407 goto do_work;
0408
0409 for (i = 0; i < ARRAY_SIZE(reg_wop); i++)
0410 if (reg_wop[i] == opcode)
0411 goto do_work;
0412
0413 printk(KERN_ERR "mmiotrace: Not a register instruction, opcode "
0414 "0x%02x\n", opcode);
0415 goto err;
0416
0417 do_work:
0418
0419 if (opcode == 0xAA || opcode == 0xAB) {
0420 reg = arg_AX;
0421 } else {
0422 unsigned char mod_rm = *p;
0423 reg = ((mod_rm >> 3) & 0x7) | (prf.rexr << 3);
0424 }
0425 switch (get_ins_reg_width(ins_addr)) {
0426 case 1:
0427 return *get_reg_w8(reg, prf.rex, regs);
0428
0429 case 2:
0430 return *(unsigned short *)get_reg_w32(reg, regs);
0431
0432 case 4:
0433 return *(unsigned int *)get_reg_w32(reg, regs);
0434
0435 #ifdef __amd64__
0436 case 8:
0437 return *(unsigned long *)get_reg_w32(reg, regs);
0438 #endif
0439
0440 default:
0441 printk(KERN_ERR "mmiotrace: Error width# %d\n", reg);
0442 }
0443
0444 err:
0445 return 0;
0446 }
0447
0448 unsigned long get_ins_imm_val(unsigned long ins_addr)
0449 {
0450 unsigned int opcode;
0451 unsigned char mod_rm;
0452 unsigned char mod;
0453 unsigned char *p;
0454 struct prefix_bits prf;
0455 int i;
0456
0457 p = (unsigned char *)ins_addr;
0458 p += skip_prefix(p, &prf);
0459 p += get_opcode(p, &opcode);
0460 for (i = 0; i < ARRAY_SIZE(imm_wop); i++)
0461 if (imm_wop[i] == opcode)
0462 goto do_work;
0463
0464 printk(KERN_ERR "mmiotrace: Not an immediate instruction, opcode "
0465 "0x%02x\n", opcode);
0466 goto err;
0467
0468 do_work:
0469 mod_rm = *p;
0470 mod = mod_rm >> 6;
0471 p++;
0472 switch (mod) {
0473 case 0:
0474
0475
0476 if ((mod_rm & 0x7) == 0x5)
0477 p += 4;
0478 break;
0479
0480 case 1:
0481 p += 1;
0482 break;
0483
0484 case 2:
0485 p += 4;
0486 break;
0487
0488 case 3:
0489 default:
0490 printk(KERN_ERR "mmiotrace: not a memory access instruction "
0491 "at 0x%lx, rm_mod=0x%02x\n",
0492 ins_addr, mod_rm);
0493 }
0494
0495 switch (get_ins_reg_width(ins_addr)) {
0496 case 1:
0497 return *(unsigned char *)p;
0498
0499 case 2:
0500 return *(unsigned short *)p;
0501
0502 case 4:
0503 return *(unsigned int *)p;
0504
0505 #ifdef __amd64__
0506 case 8:
0507 return *(unsigned long *)p;
0508 #endif
0509
0510 default:
0511 printk(KERN_ERR "mmiotrace: Error: width.\n");
0512 }
0513
0514 err:
0515 return 0;
0516 }