|
|
| version 1.4, 2004/02/13 14:52:35 | version 1.11, 2011/01/15 17:33:32 |
|---|---|
| Line 1 | Line 1 |
| /* $Id$ */ | |
| /* | /* |
| * Copyright (c) 2004 NONAKA Kimihiro | * Copyright (c) 2004 NONAKA Kimihiro |
| * All rights reserved. | * All rights reserved. |
| Line 12 | Line 10 |
| * 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. | * documentation and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products | |
| * derived from this software without specific prior written permission. | |
| * | * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| Line 82 static const char *opcode_1byte[2][256] | Line 78 static const char *opcode_1byte[2][256] |
| /*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", | /*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", |
| "movw", "movw", "movw", "movw", "movw", "movw", "movw", "movw", | "movw", "movw", "movw", "movw", "movw", "movw", "movw", "movw", |
| /*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movw", | /*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movw", |
| "enter", "leave", "ret", "ret", "int3", "int", "into", "iret", | "enter", "leave", "retf", "retf", "int3", "int", "into", "iret", |
| /*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", | /*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", |
| "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", | "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", |
| /*e0*/ "loopne","loope", "loop", "jcxz", "inb", "inw", "outb", "outw", | /*e0*/ "loopne","loope", "loop", "jcxz", "inb", "inw", "outb", "outw", |
| Line 117 static const char *opcode_1byte[2][256] | Line 113 static const char *opcode_1byte[2][256] |
| /*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", | /*b0*/ "movb", "movb", "movb", "movb", "movb", "movb", "movb", "movb", |
| "movl", "movl", "movl", "movl", "movl", "movl", "movl", "movl", | "movl", "movl", "movl", "movl", "movl", "movl", "movl", "movl", |
| /*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movl", | /*c0*/ NULL, NULL, "ret", "ret", "les", "lds", "movb", "movl", |
| "enter", "leave", "ret", "ret", "int3", "int", "into", "iretd", | "enter", "leave", "retf", "retf", "int3", "int", "into", "iretd", |
| /*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", | /*d0*/ NULL, NULL, NULL, NULL, "aam", "aad", "salc", "xlat", |
| "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", | "esc0", "esc1", "esc2", "esc3", "esc4", "esc5", "esc6", "esc7", |
| /*e0*/ "loopne","loope", "loop", "jecxz", "inb", "inl", "outb", "outl", | /*e0*/ "loopne","loope", "loop", "jecxz", "inb", "inl", "outb", "outl", |
| Line 332 static const char *opcode2_g9[8] = { | Line 328 static const char *opcode2_g9[8] = { |
| NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL | NULL, "cmpxchg8b", NULL, NULL, NULL, NULL, NULL, NULL |
| }; | }; |
| #if 0 | |
| static const char *sep[2] = { " ", ", " }; | static const char *sep[2] = { " ", ", " }; |
| #endif | |
| /* | |
| * context | |
| */ | |
| typedef struct { | |
| DWORD val; | |
| DWORD eip; | |
| BOOL op32; | |
| BOOL as32; | |
| DWORD baseaddr; | |
| DWORD opcode[3]; | |
| DWORD modrm; | |
| DWORD sib; | |
| BOOL useseg; | |
| int seg; | |
| BYTE opbyte[32]; | |
| int nopbyte; | |
| char str[256]; | |
| size_t remain; | |
| char *next; | |
| char *prefix; | |
| char *op; | |
| char *arg[3]; | |
| int narg; | |
| char pad; | |
| } disasm_context_t; | |
| /* | /* |
| Line 375 typedef struct { | Line 339 typedef struct { |
| static int | static int |
| convert_address(disasm_context_t *ctx) | convert_address(disasm_context_t *ctx) |
| { | { |
| DWORD pde_addr; /* page directory entry address */ | UINT32 pde_addr; /* page directory entry address */ |
| DWORD pde; /* page directory entry */ | UINT32 pde; /* page directory entry */ |
| DWORD pte_addr; /* page table entry address */ | UINT32 pte_addr; /* page table entry address */ |
| DWORD pte; /* page table entry */ | UINT32 pte; /* page table entry */ |
| DWORD addr; | UINT32 addr; |
| if (CPU_STAT_SREG(CPU_CS_INDEX).valid) { | if (CPU_STAT_SREG(CPU_CS_INDEX).valid) { |
| addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + ctx->eip; | addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + ctx->eip; |
| if (CPU_STAT_PAGING) { | if (CPU_STAT_PAGING) { |
| pde_addr = CPU_STAT_PDE_BASE + ((addr >> 20) & 0xffc); | pde_addr = CPU_STAT_PDE_BASE + ((addr >> 20) & 0xffc); |
| pde = cpu_memoryread_d(pde_addr); | pde = cpu_memoryread_d(pde_addr); |
| /* XXX: check */ | |
| pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((addr >> 10) & 0xffc); | pte_addr = (pde & CPU_PDE_BASEADDR_MASK) + ((addr >> 10) & 0xffc); |
| pte = cpu_memoryread_d(pte_addr); | pte = cpu_memoryread_d(pte_addr); |
| /* XXX: check */ | |
| addr = (pte & CPU_PTE_BASEADDR_MASK) + (addr & 0x00000fff); | addr = (pte & CPU_PTE_BASEADDR_MASK) + (addr & 0x00000fff); |
| } | } |
| ctx->val = addr; | ctx->val = addr; |
| Line 399 convert_address(disasm_context_t *ctx) | Line 365 convert_address(disasm_context_t *ctx) |
| static int | static int |
| disasm_codefetch_1(disasm_context_t *ctx) | disasm_codefetch_1(disasm_context_t *ctx) |
| { | { |
| BYTE val; | UINT8 val; |
| int rv; | int rv; |
| rv = convert_address(ctx); | rv = convert_address(ctx); |
| Line 409 disasm_codefetch_1(disasm_context_t *ctx | Line 375 disasm_codefetch_1(disasm_context_t *ctx |
| val = cpu_memoryread(ctx->val); | val = cpu_memoryread(ctx->val); |
| ctx->val = val; | ctx->val = val; |
| ctx->opbyte[ctx->nopbyte++] = ctx->val; | ctx->opbyte[ctx->nopbytes++] = (UINT8)ctx->val; |
| ctx->eip++; | ctx->eip++; |
| return 0; | return 0; |
| } | } |
| #if 0 | |
| static int | static int |
| disasm_codefetch_2(disasm_context_t *ctx) | disasm_codefetch_2(disasm_context_t *ctx) |
| { | { |
| WORD val; | UINT16 val; |
| int rv; | int rv; |
| rv = disasm_codefetch_1(ctx); | rv = disasm_codefetch_1(ctx); |
| if (rv) | if (rv) |
| return rv; | return rv; |
| val = ctx->val & 0xff; | val = (UINT16)(ctx->val & 0xff); |
| rv = disasm_codefetch_1(ctx); | rv = disasm_codefetch_1(ctx); |
| if (rv) | if (rv) |
| return rv; | return rv; |
| val |= (WORD)(ctx->val & 0xff) << 8; | val |= (UINT16)(ctx->val & 0xff) << 8; |
| ctx->val = val; | ctx->val = val; |
| return 0; | return 0; |
| Line 437 disasm_codefetch_2(disasm_context_t *ctx | Line 404 disasm_codefetch_2(disasm_context_t *ctx |
| static int | static int |
| disasm_codefetch_4(disasm_context_t *ctx) | disasm_codefetch_4(disasm_context_t *ctx) |
| { | { |
| DWORD val; | UINT32 val; |
| int rv; | int rv; |
| rv = disasm_codefetch_1(ctx); | rv = disasm_codefetch_1(ctx); |
| Line 447 disasm_codefetch_4(disasm_context_t *ctx | Line 414 disasm_codefetch_4(disasm_context_t *ctx |
| rv = disasm_codefetch_1(ctx); | rv = disasm_codefetch_1(ctx); |
| if (rv) | if (rv) |
| return rv; | return rv; |
| val |= (DWORD)(ctx->val & 0xff) << 8; | val |= (UINT32)(ctx->val & 0xff) << 8; |
| rv = disasm_codefetch_1(ctx); | rv = disasm_codefetch_1(ctx); |
| if (rv) | if (rv) |
| return rv; | return rv; |
| val |= (DWORD)(ctx->val & 0xff) << 16; | val |= (UINT32)(ctx->val & 0xff) << 16; |
| rv = disasm_codefetch_1(ctx); | rv = disasm_codefetch_1(ctx); |
| if (rv) | if (rv) |
| return rv; | return rv; |
| val |= (DWORD)(ctx->val & 0xff) << 24; | val |= (UINT32)(ctx->val & 0xff) << 24; |
| ctx->val = val; | ctx->val = val; |
| return 0; | return 0; |
| Line 464 disasm_codefetch_4(disasm_context_t *ctx | Line 431 disasm_codefetch_4(disasm_context_t *ctx |
| /* | /* |
| * get effective address. | * get effective address. |
| */ | */ |
| static int | static int |
| ea16(disasm_context_t *ctx, char *buf, size_t size) | ea16(disasm_context_t *ctx, char *buf, size_t size) |
| { | { |
| Line 471 ea16(disasm_context_t *ctx, char *buf, s | Line 439 ea16(disasm_context_t *ctx, char *buf, s |
| "bx + si", "bx + di", "bp + si", "bp + di", | "bx + si", "bx + di", "bp + si", "bp + di", |
| "si", "di", "bp", "bx" | "si", "di", "bp", "bx" |
| }; | }; |
| char tmp[32]; | UINT32 val; |
| DWORD mod, rm; | UINT mod, rm; |
| DWORD val; | |
| int rv; | int rv; |
| mod = (ctx->modrm >> 6) & 3; | mod = (ctx->modrm >> 6) & 3; |
| Line 519 static int | Line 486 static int |
| ea32(disasm_context_t *ctx, char *buf, size_t size) | ea32(disasm_context_t *ctx, char *buf, size_t size) |
| { | { |
| char tmp[32]; | char tmp[32]; |
| DWORD count[9]; | UINT count[9]; |
| DWORD mod, rm; | UINT32 val; |
| DWORD sib; | UINT mod, rm; |
| DWORD scale; | UINT sib; |
| DWORD idx; | UINT scale; |
| DWORD base; | UINT idx; |
| DWORD val; | UINT base; |
| int rv; | int rv; |
| int i, n; | int i, n; |
| Line 646 ea(disasm_context_t *ctx) | Line 613 ea(disasm_context_t *ctx) |
| } else { | } else { |
| milstr_ncat(ctx->next, sep[1], ctx->remain); | milstr_ncat(ctx->next, sep[1], ctx->remain); |
| } | } |
| len += strlen(ctx->next); | len = strlen(ctx->next); |
| len = (len < ctx->remain) ? len : ctx->remain; | len = (len < ctx->remain) ? len : ctx->remain; |
| ctx->next += len; | ctx->next += len; |
| ctx->remain -= len; | ctx->remain -= len; |
| Line 664 ea(disasm_context_t *ctx) | Line 631 ea(disasm_context_t *ctx) |
| return 0; | return 0; |
| } | } |
| #endif | |
| /* | /* |
| * get opcode | * get opcode |
| */ | */ |
| static int | static int |
| op(disasm_context_t *ctx) | get_opcode(disasm_context_t *ctx) |
| { | { |
| const char *opcode; | const char *opcode; |
| DWORD type; | UINT8 op[3]; |
| BYTE op[3]; | |
| int prefix; | int prefix; |
| int len; | size_t len; |
| int rv; | int rv; |
| int i; | int i; |
| Line 684 op(disasm_context_t *ctx) | Line 651 op(disasm_context_t *ctx) |
| if (rv) | if (rv) |
| return rv; | return rv; |
| op[0] = ctx->val & 0xff; | op[0] = (UINT8)(ctx->val & 0xff); |
| if (insttable_info[op[0]] & INST_PREFIX) { | if (insttable_info[op[0]] & INST_PREFIX) { |
| if (ctx->prefix == 0) | if (ctx->prefix == 0) |
| ctx->prefix = ctx->next; | ctx->prefix = ctx->next; |
| Line 740 op(disasm_context_t *ctx) | Line 707 op(disasm_context_t *ctx) |
| if (rv) | if (rv) |
| return rv; | return rv; |
| op[1] = ctx->val & 0xff; | op[1] = (UINT8)(ctx->val & 0xff); |
| ctx->opcode[1] = op[1]; | ctx->opcode[1] = op[1]; |
| switch (op[0]) { | switch (op[0]) { |
| Line 751 op(disasm_context_t *ctx) | Line 718 op(disasm_context_t *ctx) |
| if (rv) | if (rv) |
| return rv; | return rv; |
| op[2] = ctx->val & 0xff; | op[2] = (UINT8)(ctx->val & 0xff); |
| ctx->opcode[2] = op[2]; | ctx->opcode[2] = op[2]; |
| switch (op[1]) { | switch (op[1]) { |
| Line 812 op(disasm_context_t *ctx) | Line 779 op(disasm_context_t *ctx) |
| * interface | * interface |
| */ | */ |
| int | int |
| disasm(DWORD *eip, char *buf, size_t size) | disasm(UINT32 *eip, disasm_context_t *ctx) |
| { | { |
| disasm_context_t ctx; | |
| int rv; | int rv; |
| memset(&ctx, 0, sizeof(ctx)); | memset(ctx, 0, sizeof(disasm_context_t)); |
| ctx.remain = sizeof(ctx.str) - 1; | ctx->remain = sizeof(ctx->str) - 1; |
| ctx.next = ctx.str; | ctx->next = ctx->str; |
| ctx.prefix = 0; | ctx->prefix = 0; |
| ctx.op = 0; | ctx->op = 0; |
| ctx.arg[0] = 0; | ctx->arg[0] = 0; |
| ctx.arg[1] = 0; | ctx->arg[1] = 0; |
| ctx.arg[2] = 0; | ctx->arg[2] = 0; |
| ctx.eip = *eip; | ctx->eip = *eip; |
| ctx.op32 = CPU_INST_OP32; | ctx->op32 = CPU_INST_OP32; |
| ctx.as32 = CPU_INST_AS32; | ctx->as32 = CPU_INST_AS32; |
| ctx.seg = -1; | ctx->seg = -1; |
| ctx.baseaddr = ctx.eip; | ctx->baseaddr = ctx->eip; |
| ctx.pad = ' '; | ctx->pad = ' '; |
| rv = op(&ctx); | rv = get_opcode(ctx); |
| if (rv) { | if (rv) { |
| memset(&ctx, 0, sizeof(ctx)); | memset(ctx, 0, sizeof(disasm_context_t)); |
| return rv; | return rv; |
| } | } |
| *eip = ctx->eip; | |
| *eip = ctx.eip; | |
| milstr_ncpy(buf, ctx.str, size); | |
| return 0; | return 0; |
| } | } |