From ed37aa8070cabf80de269508cbf022bc2b464d26 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 18 Mar 2009 23:10:19 -0700 Subject: [PATCH] disasm: when no instruction is found, consider a naked prefix If we can't find a matching instruction, rather than printing it as a "db" literal, consider first if we can disassemble it as a naked prefix. --- disasm.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- disasm.h | 2 +- ndisasm.c | 9 +++--- 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/disasm.c b/disasm.c index 63fd37be..f4104186 100644 --- a/disasm.c +++ b/disasm.c @@ -1420,8 +1420,86 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, return length; } -int32_t eatbyte(uint8_t *data, char *output, int outbufsize) +/* + * This is called when we don't have a complete instruction. If it + * is a standalone *single-byte* prefix show it as such, otherwise + * print it as a literal. + */ +int32_t eatbyte(uint8_t *data, char *output, int outbufsize, int segsize) { - snprintf(output, outbufsize, "db 0x%02X", *data); + uint8_t byte = *data; + const char *str = NULL; + + switch (byte) { + case 0xF2: + str = "rep"; + break; + case 0xF3: + str = "repne"; + break; + case 0x9B: + str = "wait"; + break; + case 0xF0: + str = "lock"; + break; + case 0x2E: + str = "cs"; + break; + case 0x36: + str = "ss"; + break; + case 0x3E: + str = "ss"; + break; + case 0x26: + str = "es"; + break; + case 0x64: + str = "fs"; + break; + case 0x65: + str = "gs"; + break; + case 0x66: + str = (segsize == 16) ? "o32" : "o16"; + break; + case 0x67: + str = (segsize == 32) ? "a16" : "a32"; + break; + case REX_P + 0x0: + case REX_P + 0x1: + case REX_P + 0x2: + case REX_P + 0x3: + case REX_P + 0x4: + case REX_P + 0x5: + case REX_P + 0x6: + case REX_P + 0x7: + case REX_P + 0x8: + case REX_P + 0x9: + case REX_P + 0xA: + case REX_P + 0xB: + case REX_P + 0xC: + case REX_P + 0xD: + case REX_P + 0xE: + case REX_P + 0xF: + if (segsize == 64) { + snprintf(output, outbufsize, "rex%s%s%s%s%s", + (byte == REX_P) ? "" : ".", + (byte & REX_W) ? "w" : "", + (byte & REX_R) ? "r" : "", + (byte & REX_X) ? "x" : "", + (byte & REX_B) ? "b" : ""); + break; + } + /* else fall through */ + default: + snprintf(output, outbufsize, "db 0x%02x", byte); + break; + } + + if (str) + strcpy(output, str); + return 1; } diff --git a/disasm.h b/disasm.h index 56785ce6..6467730a 100644 --- a/disasm.h +++ b/disasm.h @@ -13,6 +13,6 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize, int32_t offset, int autosync, uint32_t prefer); -int32_t eatbyte(uint8_t *data, char *output, int outbufsize); +int32_t eatbyte(uint8_t *data, char *output, int outbufsize, int segsize); #endif diff --git a/ndisasm.c b/ndisasm.c index 766119b9..75fc3256 100644 --- a/ndisasm.c +++ b/ndisasm.c @@ -273,7 +273,8 @@ int main(int argc, char **argv) if ((nextsync || synclen) && (uint32_t)offset == nextsync) { if (synclen) { - fprintf(stdout, "%08"PRIX32" skipping 0x%"PRIX32" bytes\n", offset, synclen); + fprintf(stdout, "%08"PRIX32" skipping 0x%"PRIX32" bytes\n", + offset, synclen); offset += synclen; skip(synclen, fp); } @@ -282,12 +283,12 @@ int main(int argc, char **argv) } while (p > q && (p - q >= INSN_MAX || lenread == 0)) { lendis = - disasm((uint8_t *) q, outbuf, sizeof(outbuf), bits, offset, autosync, - prefer); + disasm((uint8_t *) q, outbuf, sizeof(outbuf), bits, + offset, autosync, prefer); if (!lendis || lendis > (p - q) || ((nextsync || synclen) && (uint32_t)lendis > nextsync - offset)) - lendis = eatbyte((uint8_t *) q, outbuf, sizeof(outbuf)); + lendis = eatbyte((uint8_t *) q, outbuf, sizeof(outbuf), bits); output_ins(offset, (uint8_t *) q, lendis, outbuf); q += lendis; offset += lendis;