1 //===- X86MCDisassemblerTest.cpp - Tests for X86 MCDisassembler -----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/MC/MCAsmInfo.h"
10 #include "llvm/MC/MCContext.h"
11 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
12 #include "llvm/MC/MCDisassembler/MCSymbolizer.h"
13 #include "llvm/MC/MCInst.h"
14 #include "llvm/MC/MCRegisterInfo.h"
15 #include "llvm/MC/MCSubtargetInfo.h"
16 #include "llvm/MC/MCTargetOptions.h"
17 #include "llvm/MC/TargetRegistry.h"
18 #include "llvm/Support/TargetSelect.h"
19 #include "gtest/gtest.h"
26 const char *TripleName
= "x86_64-unknown-elf";
27 std::unique_ptr
<MCRegisterInfo
> MRI
;
28 std::unique_ptr
<MCAsmInfo
> MAI
;
29 std::unique_ptr
<MCContext
> Ctx
;
30 std::unique_ptr
<MCSubtargetInfo
> STI
;
31 std::unique_ptr
<MCDisassembler
> DisAsm
;
34 LLVMInitializeX86TargetInfo();
35 LLVMInitializeX86TargetMC();
36 LLVMInitializeX86Disassembler();
38 // If we didn't build x86, do not run the test.
40 const Target
*TheTarget
= TargetRegistry::lookupTarget(TripleName
, Error
);
44 MRI
.reset(TheTarget
->createMCRegInfo(TripleName
));
45 MAI
.reset(TheTarget
->createMCAsmInfo(*MRI
, TripleName
, MCTargetOptions()));
46 STI
.reset(TheTarget
->createMCSubtargetInfo(TripleName
, "", ""));
47 Ctx
= std::make_unique
<MCContext
>(Triple(TripleName
), MAI
.get(), MRI
.get(),
50 DisAsm
.reset(TheTarget
->createMCDisassembler(*STI
, *Ctx
));
53 operator MCContext
&() { return *Ctx
; };
56 Context
&getContext() {
61 class X86MCSymbolizerTest
: public MCSymbolizer
{
63 X86MCSymbolizerTest(MCContext
&MC
) : MCSymbolizer(MC
, nullptr) {}
64 ~X86MCSymbolizerTest() {}
71 std::vector
<OpInfo
> Operands
;
72 uint64_t InstructionSize
= 0;
79 bool tryAddingSymbolicOperand(MCInst
&Inst
, raw_ostream
&CStream
,
80 int64_t Value
, uint64_t Address
, bool IsBranch
,
81 uint64_t Offset
, uint64_t OpSize
,
82 uint64_t InstSize
) override
{
83 Operands
.push_back({Value
, Offset
, OpSize
});
84 InstructionSize
= InstSize
;
88 void tryAddingPcLoadReferenceComment(raw_ostream
&cStream
, int64_t Value
,
89 uint64_t Address
) override
{}
94 TEST(X86Disassembler
, X86MCSymbolizerTest
) {
95 X86MCSymbolizerTest
*TestSymbolizer
= new X86MCSymbolizerTest(getContext());
96 getContext().DisAsm
->setSymbolizer(
97 std::unique_ptr
<MCSymbolizer
>(TestSymbolizer
));
99 MCDisassembler::DecodeStatus Status
;
103 auto checkBytes
= [&](ArrayRef
<uint8_t> Bytes
) {
104 TestSymbolizer
->reset();
106 getContext().DisAsm
->getInstruction(Inst
, InstSize
, Bytes
, 0, nulls());
107 ASSERT_TRUE(Status
== MCDisassembler::Success
);
108 EXPECT_EQ(TestSymbolizer
->InstructionSize
, InstSize
);
111 auto checkOperand
= [&](size_t OpNo
, int64_t Value
, uint64_t Offset
,
113 ASSERT_TRUE(TestSymbolizer
->Operands
.size() > OpNo
);
114 EXPECT_EQ(TestSymbolizer
->Operands
[OpNo
].Value
, Value
);
115 EXPECT_EQ(TestSymbolizer
->Operands
[OpNo
].Offset
, Offset
);
116 EXPECT_EQ(TestSymbolizer
->Operands
[OpNo
].Size
, Size
);
119 // movq $0x80000, 0x80000
121 {0x48, 0xc7, 0x04, 0x25, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00});
122 checkOperand(0, 0x80000, 4, 4);
123 checkOperand(1, 0x80000, 8, 4);
125 // movq $0x2a, 0x123(%rax,%r14,8)
127 {0x4a, 0xc7, 0x84, 0xf0, 0x23, 0x01, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00});
128 checkOperand(0, 291, 4, 4);
129 checkOperand(1, 42, 8, 4);
131 // movq $0xffffffffffffefe8, -0x1(%rip)
132 // Test that the value of the rip-relative operand is set correctly.
133 // The instruction address is 0 and the size is 12 bytes.
135 {0x48, 0xc7, 0x05, 0xff, 0xff, 0xff, 0xff, 0xe8, 0xef, 0xff, 0xff});
136 checkOperand(0, /*next instr address*/ 11 - /*disp*/ 1, 3, 4);
137 checkOperand(1, 0xffffffffffffefe8, 7, 4);
139 // movq $0xfffffffffffffef5, (%r12)
140 // Test that the displacement operand has a size of 0, since it is not
141 // explicitly specified in the instruction.
142 checkBytes({0x49, 0xc7, 0x04, 0x24, 0xf5, 0xfe, 0xff, 0xff});
143 checkOperand(0, 0, 4, 0);
144 checkOperand(1, 0xfffffffffffffef5, 4, 4);
146 // mov %ax, 0x1568179(%rbx)
147 // Test that the displacement operand size is not affected by the operand
148 // size override prefix.
149 checkBytes({0x66, 0x89, 0x83, 0x79, 0x81, 0x56, 0x01});
150 checkOperand(0, 0x1568179, 3, 4);