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.
This commit is contained in:
H. Peter Anvin 2009-03-18 23:10:19 -07:00
parent d1174fb1a6
commit ed37aa8070
3 changed files with 86 additions and 7 deletions

View file

@ -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;
}

View file

@ -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

View file

@ -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;