29 #include <linux/module.h>
30 #include <linux/ptrace.h>
35 static unsigned char prefix_codes[] = {
36 0xF0, 0xF2, 0xF3, 0x2E, 0x36, 0x3E, 0x26, 0x64,
40 static unsigned int reg_rop[] = {
41 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F
43 static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB };
44 static unsigned int imm_wop[] = { 0xC6, 0xC7 };
46 static unsigned int rw8[] = { 0x88, 0x8A, 0xC6, 0xAA };
47 static unsigned int rw32[] = {
48 0x89, 0x8B, 0xC7, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB
50 static unsigned int mw8[] = { 0x88, 0x8A, 0xC6, 0xB60F, 0xBE0F, 0xAA };
51 static unsigned int mw16[] = { 0xB70F, 0xBF0F };
52 static unsigned int mw32[] = { 0x89, 0x8B, 0xC7, 0xAB };
53 static unsigned int mw64[] = {};
55 static unsigned char prefix_codes[] = {
56 0x66, 0x67, 0x2E, 0x3E, 0x26, 0x64, 0x65, 0x36,
59 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
60 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
63 static unsigned int reg_rop[] = {
64 0x8A, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F
66 static unsigned int reg_wop[] = { 0x88, 0x89, 0xAA, 0xAB };
67 static unsigned int imm_wop[] = { 0xC6, 0xC7 };
68 static unsigned int rw8[] = { 0xC6, 0x88, 0x8A, 0xAA };
69 static unsigned int rw32[] = {
70 0xC7, 0x89, 0x8B, 0xB60F, 0xB70F, 0xBE0F, 0xBF0F, 0xAB
73 static unsigned int mw8[] = { 0xC6, 0x88, 0x8A, 0xB60F, 0xBE0F, 0xAA };
75 static unsigned int mw16[] = { 0xB70F, 0xBF0F };
77 static unsigned int mw32[] = { 0xC7 };
79 static unsigned int mw64[] = { 0x89, 0x8B, 0xAB };
92 unsigned char *
p =
addr;
99 for (i = 0; i <
ARRAY_SIZE(prefix_codes); i++) {
100 if (*p == prefix_codes[i]) {
104 if ((*p & 0xf8) == 0x48)
106 if ((*p & 0xf4) == 0x44)
108 if ((*p & 0xf0) == 0x40)
119 static int get_opcode(
unsigned char *addr,
unsigned int *
opcode)
125 *opcode = *(
unsigned short *)addr;
135 #define CHECK_OP_TYPE(opcode, array, type) \
136 for (i = 0; i < ARRAY_SIZE(array); i++) { \
137 if (array[i] == opcode) { \
151 p = (
unsigned char *)ins_addr;
152 p += skip_prefix(p, &prf);
153 p += get_opcode(p, &opcode);
164 static unsigned int get_ins_reg_width(
unsigned long ins_addr)
171 p = (
unsigned char *)ins_addr;
172 p += skip_prefix(p, &prf);
173 p += get_opcode(p, &opcode);
176 if (rw8[i] == opcode)
180 if (rw32[i] == opcode)
194 p = (
unsigned char *)ins_addr;
195 p += skip_prefix(p, &prf);
196 p += get_opcode(p, &opcode);
199 if (mw8[i] == opcode)
203 if (mw16[i] == opcode)
207 if (
mw32[i] == opcode)
211 if (mw64[i] == opcode)
254 unsigned char *rv =
NULL;
258 rv = (
unsigned char *)®s->ax;
261 rv = (
unsigned char *)®s->bx;
264 rv = (
unsigned char *)®s->cx;
267 rv = (
unsigned char *)®s->dx;
271 rv = (
unsigned char *)®s->
r8;
274 rv = (
unsigned char *)®s->
r9;
277 rv = (
unsigned char *)®s->
r10;
280 rv = (
unsigned char *)®s->
r11;
283 rv = (
unsigned char *)®s->
r12;
286 rv = (
unsigned char *)®s->
r13;
289 rv = (
unsigned char *)®s->
r14;
292 rv = (
unsigned char *)®s->
r15;
309 rv = (
unsigned char *)®s->si;
312 rv = (
unsigned char *)®s->di;
315 rv = (
unsigned char *)®s->bp;
318 rv = (
unsigned char *)®s->
sp;
326 rv = 1 + (
unsigned char *)®s->ax;
329 rv = 1 + (
unsigned char *)®s->bx;
332 rv = 1 + (
unsigned char *)®s->cx;
335 rv = 1 + (
unsigned char *)®s->dx;
348 static unsigned long *get_reg_w32(
int no,
struct pt_regs *regs)
350 unsigned long *rv =
NULL;
418 p = (
unsigned char *)ins_addr;
419 p += skip_prefix(p, &prf);
420 p += get_opcode(p, &opcode);
422 if (reg_rop[i] == opcode)
426 if (reg_wop[i] == opcode)
435 if (opcode == 0xAA || opcode == 0xAB) {
438 unsigned char mod_rm = *
p;
439 reg = ((mod_rm >> 3) & 0x7) | (prf.
rexr << 3);
441 switch (get_ins_reg_width(ins_addr)) {
443 return *get_reg_w8(reg, prf.
rex, regs);
446 return *(
unsigned short *)get_reg_w32(reg, regs);
449 return *(
unsigned int *)get_reg_w32(reg, regs);
453 return *(
unsigned long *)get_reg_w32(reg, regs);
467 unsigned char mod_rm;
473 p = (
unsigned char *)ins_addr;
474 p += skip_prefix(p, &prf);
475 p += get_opcode(p, &opcode);
477 if (imm_wop[i] == opcode)
480 printk(
KERN_ERR "mmiotrace: Not an immediate instruction, opcode "
492 if ((mod_rm & 0x7) == 0x5)
507 "at 0x%lx, rm_mod=0x%02x\n",
511 switch (get_ins_reg_width(ins_addr)) {
513 return *(
unsigned char *)p;
516 return *(
unsigned short *)p;
519 return *(
unsigned int *)p;
523 return *(
unsigned long *)p;