diff options
author | Vedant Kumar <vsk@apple.com> | 2015-08-26 16:20:29 +0000 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2015-08-26 16:20:29 +0000 |
commit | bf891b12b4a8fe0e64f89101e1d4ff451de923ec (patch) | |
tree | 26a34c726d316b2ba26d59e4925d69621f92e45b /llvm/lib | |
parent | f8ec454f7d3c1c8aa42eb6dc33784e3addfe1d58 (diff) | |
download | bcm5719-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.cpp | 41 |
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; |