diff options
-rw-r--r-- | disasm.c | 82 | ||||
-rw-r--r-- | disasm.h | 2 | ||||
-rw-r--r-- | ndisasm.c | 9 |
3 files changed, 86 insertions, 7 deletions
@@ -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; } @@ -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 @@ -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; |