/* * readPrefixes - Consumes all of an instruction's prefix bytes, and marks the * instruction as having them. Also sets the instruction's default operand, * address, and other relevant data sizes to report operands correctly. * * @param insn - The instruction whose prefixes are to be read. * @return - 0 if the instruction could be read until the end of the prefix * bytes, and no prefixes conflicted; nonzero otherwise. */ static int readPrefixes(struct InternalInstruction* insn) { BOOL isPrefix = TRUE; BOOL prefixGroups[4] = { FALSE }; uint64_t prefixLocation; uint8_t byte = 0; BOOL hasAdSize = FALSE; BOOL hasOpSize = FALSE; dbgprintf(insn, "readPrefixes()"); while (isPrefix) { prefixLocation = insn->readerCursor; if (consumeByte(insn, &byte)) return -1; switch (byte) { case 0xf0: /* LOCK */ case 0xf2: /* REPNE/REPNZ */ case 0xf3: /* REP or REPE/REPZ */ if (prefixGroups[0]) dbgprintf(insn, "Redundant Group 1 prefix"); prefixGroups[0] = TRUE; setPrefixPresent(insn, byte, prefixLocation); break; case 0x2e: /* CS segment override -OR- Branch not taken */ case 0x36: /* SS segment override -OR- Branch taken */ case 0x3e: /* DS segment override */ case 0x26: /* ES segment override */ case 0x64: /* FS segment override */ case 0x65: /* GS segment override */ switch (byte) { case 0x2e: insn->segmentOverride = SEG_OVERRIDE_CS; break; case 0x36: insn->segmentOverride = SEG_OVERRIDE_SS; break; case 0x3e: insn->segmentOverride = SEG_OVERRIDE_DS; break; case 0x26: insn->segmentOverride = SEG_OVERRIDE_ES; break; case 0x64: insn->segmentOverride = SEG_OVERRIDE_FS; break; case 0x65: insn->segmentOverride = SEG_OVERRIDE_GS; break; default: debug("Unhandled override"); return -1; } if (prefixGroups[1]) dbgprintf(insn, "Redundant Group 2 prefix"); prefixGroups[1] = TRUE; setPrefixPresent(insn, byte, prefixLocation); break; case 0x66: /* Operand-size override */ if (prefixGroups[2]) dbgprintf(insn, "Redundant Group 3 prefix"); prefixGroups[2] = TRUE; hasOpSize = TRUE; setPrefixPresent(insn, byte, prefixLocation); break; case 0x67: /* Address-size override */ if (prefixGroups[3]) dbgprintf(insn, "Redundant Group 4 prefix"); prefixGroups[3] = TRUE; hasAdSize = TRUE; setPrefixPresent(insn, byte, prefixLocation); break; default: /* Not a prefix byte */ isPrefix = FALSE; break; } if (isPrefix) dbgprintf(insn, "Found prefix 0x%hhx", byte); } insn->vexSize = 0; if (byte == 0xc4) { uint8_t byte1; if (lookAtByte(insn, &byte1)) { dbgprintf(insn, "Couldn't read second byte of VEX"); return -1; } if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) { insn->vexSize = 3; insn->necessaryPrefixLocation = insn->readerCursor - 1; } else { unconsumeByte(insn); insn->necessaryPrefixLocation = insn->readerCursor - 1; } if (insn->vexSize == 3) { insn->vexPrefix[0] = byte; consumeByte(insn, &insn->vexPrefix[1]); consumeByte(insn, &insn->vexPrefix[2]); /* We simulate the REX prefix for simplicity's sake */ if (insn->mode == MODE_64BIT) { insn->rexPrefix = 0x40 | (wFromVEX3of3(insn->vexPrefix[2]) << 3) | (rFromVEX2of3(insn->vexPrefix[1]) << 2) | (xFromVEX2of3(insn->vexPrefix[1]) << 1) | (bFromVEX2of3(insn->vexPrefix[1]) << 0); } switch (ppFromVEX3of3(insn->vexPrefix[2])) { default: break; case VEX_PREFIX_66: hasOpSize = TRUE; break; } dbgprintf(insn, "Found VEX prefix 0x%hhx 0x%hhx 0x%hhx", insn->vexPrefix[0], insn->vexPrefix[1], insn->vexPrefix[2]); } } else if (byte == 0xc5) { uint8_t byte1; if (lookAtByte(insn, &byte1)) { dbgprintf(insn, "Couldn't read second byte of VEX"); return -1; } if (insn->mode == MODE_64BIT || (byte1 & 0xc0) == 0xc0) { insn->vexSize = 2; } else { unconsumeByte(insn); } if (insn->vexSize == 2) { insn->vexPrefix[0] = byte; consumeByte(insn, &insn->vexPrefix[1]); if (insn->mode == MODE_64BIT) { insn->rexPrefix = 0x40 | (rFromVEX2of2(insn->vexPrefix[1]) << 2); } switch (ppFromVEX2of2(insn->vexPrefix[1])) { default: break; case VEX_PREFIX_66: hasOpSize = TRUE; break; } dbgprintf(insn, "Found VEX prefix 0x%hhx 0x%hhx", insn->vexPrefix[0], insn->vexPrefix[1]); } } else { if (insn->mode == MODE_64BIT) { if ((byte & 0xf0) == 0x40) { uint8_t opcodeByte; if (lookAtByte(insn, &opcodeByte) || ((opcodeByte & 0xf0) == 0x40)) { dbgprintf(insn, "Redundant REX prefix"); return -1; } insn->rexPrefix = byte; insn->necessaryPrefixLocation = insn->readerCursor - 2; dbgprintf(insn, "Found REX prefix 0x%hhx", byte); } else { unconsumeByte(insn); insn->necessaryPrefixLocation = insn->readerCursor - 1; } } else { unconsumeByte(insn); insn->necessaryPrefixLocation = insn->readerCursor - 1; } } if (insn->mode == MODE_16BIT) { insn->registerSize = (hasOpSize ? 4 : 2); insn->addressSize = (hasAdSize ? 4 : 2); insn->displacementSize = (hasAdSize ? 4 : 2); insn->immediateSize = (hasOpSize ? 4 : 2); } else if (insn->mode == MODE_32BIT) { insn->registerSize = (hasOpSize ? 2 : 4); insn->addressSize = (hasAdSize ? 2 : 4); insn->displacementSize = (hasAdSize ? 2 : 4); insn->immediateSize = (hasOpSize ? 2 : 4); } else if (insn->mode == MODE_64BIT) { if (insn->rexPrefix && wFromREX(insn->rexPrefix)) { insn->registerSize = 8; insn->addressSize = (hasAdSize ? 4 : 8); insn->displacementSize = 4; insn->immediateSize = 4; } else if (insn->rexPrefix) { insn->registerSize = (hasOpSize ? 2 : 4); insn->addressSize = (hasAdSize ? 4 : 8); insn->displacementSize = (hasOpSize ? 2 : 4); insn->immediateSize = (hasOpSize ? 2 : 4); } else { insn->registerSize = (hasOpSize ? 2 : 4); insn->addressSize = (hasAdSize ? 4 : 8); insn->displacementSize = (hasOpSize ? 2 : 4); insn->immediateSize = (hasOpSize ? 2 : 4); } } return 0; }
/* * readPrefixes - Consumes all of an instruction's prefix bytes, and marks the * instruction as having them. Also sets the instruction's default operand, * address, and other relevant data sizes to report operands correctly. * * @param insn - The instruction whose prefixes are to be read. * @return - 0 if the instruction could be read until the end of the prefix * bytes, and no prefixes conflicted; nonzero otherwise. */ static int readPrefixes(struct InternalInstruction* insn) { BOOL isPrefix = TRUE; BOOL prefixGroups[4] = { FALSE }; uint64_t prefixLocation; uint8_t byte; BOOL hasAdSize = FALSE; BOOL hasOpSize = FALSE; dbgprintf(insn, "readPrefixes()"); while (isPrefix) { prefixLocation = insn->readerCursor; if (consumeByte(insn, &byte)) return -1; switch (byte) { case 0xf0: /* LOCK */ case 0xf2: /* REPNE/REPNZ */ case 0xf3: /* REP or REPE/REPZ */ if (prefixGroups[0]) dbgprintf(insn, "Redundant Group 1 prefix"); prefixGroups[0] = TRUE; setPrefixPresent(insn, byte, prefixLocation); break; case 0x2e: /* CS segment override -OR- Branch not taken */ case 0x36: /* SS segment override -OR- Branch taken */ case 0x3e: /* DS segment override */ case 0x26: /* ES segment override */ case 0x64: /* FS segment override */ case 0x65: /* GS segment override */ switch (byte) { case 0x2e: insn->segmentOverride = SEG_OVERRIDE_CS; break; case 0x36: insn->segmentOverride = SEG_OVERRIDE_SS; break; case 0x3e: insn->segmentOverride = SEG_OVERRIDE_DS; break; case 0x26: insn->segmentOverride = SEG_OVERRIDE_ES; break; case 0x64: insn->segmentOverride = SEG_OVERRIDE_FS; break; case 0x65: insn->segmentOverride = SEG_OVERRIDE_GS; break; default: unreachable("Unhandled override"); } if (prefixGroups[1]) dbgprintf(insn, "Redundant Group 2 prefix"); prefixGroups[1] = TRUE; setPrefixPresent(insn, byte, prefixLocation); break; case 0x66: /* Operand-size override */ if (prefixGroups[2]) dbgprintf(insn, "Redundant Group 3 prefix"); prefixGroups[2] = TRUE; hasOpSize = TRUE; setPrefixPresent(insn, byte, prefixLocation); break; case 0x67: /* Address-size override */ if (prefixGroups[3]) dbgprintf(insn, "Redundant Group 4 prefix"); prefixGroups[3] = TRUE; hasAdSize = TRUE; setPrefixPresent(insn, byte, prefixLocation); break; default: /* Not a prefix byte */ isPrefix = FALSE; break; } if (isPrefix) dbgprintf(insn, "Found prefix 0x%hhx", byte); } if (insn->mode == MODE_64BIT) { if ((byte & 0xf0) == 0x40) { uint8_t opcodeByte; if(lookAtByte(insn, &opcodeByte) || ((opcodeByte & 0xf0) == 0x40)) { dbgprintf(insn, "Redundant REX prefix"); return -1; } insn->rexPrefix = byte; insn->necessaryPrefixLocation = insn->readerCursor - 2; dbgprintf(insn, "Found REX prefix 0x%hhx", byte); } else { unconsumeByte(insn); insn->necessaryPrefixLocation = insn->readerCursor - 1; } } else { unconsumeByte(insn); } if (insn->mode == MODE_16BIT) { insn->registerSize = (hasOpSize ? 4 : 2); insn->addressSize = (hasAdSize ? 4 : 2); insn->displacementSize = (hasAdSize ? 4 : 2); insn->immediateSize = (hasOpSize ? 4 : 2); } else if (insn->mode == MODE_32BIT) { insn->registerSize = (hasOpSize ? 2 : 4); insn->addressSize = (hasAdSize ? 2 : 4); insn->displacementSize = (hasAdSize ? 2 : 4); insn->immediateSize = (hasAdSize ? 2 : 4); } else if (insn->mode == MODE_64BIT) { if (insn->rexPrefix && wFromREX(insn->rexPrefix)) { insn->registerSize = 8; insn->addressSize = (hasAdSize ? 4 : 8); insn->displacementSize = 4; insn->immediateSize = 4; } else if (insn->rexPrefix) { insn->registerSize = (hasOpSize ? 2 : 4); insn->addressSize = (hasAdSize ? 4 : 8); insn->displacementSize = (hasOpSize ? 2 : 4); insn->immediateSize = (hasOpSize ? 2 : 4); } else { insn->registerSize = (hasOpSize ? 2 : 4); insn->addressSize = (hasAdSize ? 4 : 8); insn->displacementSize = (hasOpSize ? 2 : 4); insn->immediateSize = (hasOpSize ? 2 : 4); } } return 0; }