summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2015-08-26 16:20:29 +0000
committerVedant Kumar <vsk@apple.com>2015-08-26 16:20:29 +0000
commitbf891b12b4a8fe0e64f89101e1d4ff451de923ec (patch)
tree26a34c726d316b2ba26d59e4925d69621f92e45b /llvm/lib
parentf8ec454f7d3c1c8aa42eb6dc33784e3addfe1d58 (diff)
downloadbcm5719-llvm-bf891b12b4a8fe0e64f89101e1d4ff451de923ec.tar.gz
bcm5719-llvm-bf891b12b4a8fe0e64f89101e1d4ff451de923ec.zip
[llvm-mc] Ignore opcode size prefix in 64-bit CALL disassembly
This is a fix for disassembling unusual instruction sequences in 64-bit mode w.r.t the CALL rel16 instruction. It might be desirable to move the check somewhere else, but it essentially mimics the special case handling with JCXZ in 16-bit mode. The current behavior accepts the opcode size prefix and causes the call's immediate to stop disassembling after 2 bytes. When debugging sequences of instructions with this pattern, the disassembler output becomes extremely unreliable and essentially useless (if you jump midway into what lldb thinks is a unified instruction, you'll lose %rip). So we ignore the prefix and consume all 4 bytes when disassembling a 64-bit mode binary. Note: in Vol. 2A 3-99 the Intel spec states that CALL rel16 is N.S. N.S. is defined as: Indicates an instruction syntax that requires an address override prefix in 64-bit mode and is not supported. Using an address override prefix in 64-bit mode may result in model-specific execution behavior. (Vol. 2A 3-7) Since 0x66 is an operand override prefix we should be OK (although we may want to warn about 0x67 prefixes to 0xe8). On the CPUs I tested with, they all ignore the 0x66 prefix in 64-bit mode. Patch by Matthew Barney! Differential Revision: http://reviews.llvm.org/D9573 llvm-svn: 246038
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
index f73fa75f888..e7a1d7dad98 100644
--- a/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
+++ b/llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.cpp
@@ -980,6 +980,47 @@ static int getID(struct InternalInstruction* insn, const void *miiArg) {
insn->opcode == 0xE3)
attrMask ^= ATTR_ADSIZE;
+ /*
+ * In 64-bit mode all f64 superscripted opcodes ignore opcode size prefix
+ * CALL/JMP/JCC instructions need to ignore 0x66 and consume 4 bytes
+ */
+
+ if (insn->mode == MODE_64BIT &&
+ isPrefixAtLocation(insn, 0x66, insn->necessaryPrefixLocation)) {
+ switch (insn->opcode) {
+ case 0xE8:
+ case 0xE9:
+ if (insn->opcodeType ==
+ ONEBYTE) { // breaks psubsb and other mmx instructions otherwise
+ attrMask ^= ATTR_OPSIZE;
+ insn->immediateSize = 4;
+ insn->displacementSize = 4;
+ }
+ break;
+ case 0x82:
+ case 0x83:
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ case 0x87:
+ case 0x88:
+ case 0x89:
+ case 0x8A:
+ case 0x8B:
+ case 0x8C:
+ case 0x8D:
+ case 0x8E:
+ case 0x8F:
+ if (insn->opcodeType ==
+ TWOBYTE) { // breaks lea and three byte ops otherwise
+ attrMask ^= ATTR_OPSIZE;
+ insn->immediateSize = 4;
+ insn->displacementSize = 4; // otherwise not sign extended
+ }
+ break;
+ }
+ }
+
if (getIDWithAttrMask(&instructionID, insn, attrMask))
return -1;
OpenPOWER on IntegriCloud