1 //===-- TextX86GetControlFlowKind.cpp ------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Support/TargetSelect.h"
11 #include "gtest/gtest.h"
13 #include "lldb/Core/Address.h"
14 #include "lldb/Core/Disassembler.h"
15 #include "lldb/Target/ExecutionContext.h"
16 #include "lldb/Utility/ArchSpec.h"
18 #include "Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h"
21 using namespace lldb_private
;
24 class TestGetControlFlowKindx86
: public testing::Test
{
26 static void SetUpTestCase();
27 static void TearDownTestCase();
32 void TestGetControlFlowKindx86::SetUpTestCase() {
33 llvm::InitializeAllTargets();
34 llvm::InitializeAllAsmPrinters();
35 llvm::InitializeAllTargetMCs();
36 llvm::InitializeAllDisassemblers();
37 DisassemblerLLVMC::Initialize();
40 void TestGetControlFlowKindx86::TearDownTestCase() {
41 DisassemblerLLVMC::Terminate();
45 TEST_F(TestGetControlFlowKindx86
, TestX86_64Instruction
) {
46 ArchSpec
arch("x86_64-*-linux");
48 const unsigned num_of_instructions
= 29;
50 0x55, // other -- pushq %rbp
51 0x48, 0x89, 0xe5, // other -- movq %rsp, %rbp
53 0xe8, 0xfc, 0xfe, 0xff, 0xff, // call -- callq 0x4004c0
54 0x41, 0xff, 0x14, 0xdc, // call -- callq *(%r12,%rbx,8)
55 0xff, 0x50, 0x18, // call -- callq *0x18(%rax)
56 0xe8, 0x48, 0x0d, 0x00, 0x00, // call -- callq 0x94fe0
58 0xc3, // return -- retq
60 0xeb, 0xd3, // jump -- jmp 0x92dab
61 0xe9, 0x22, 0xff, 0xff, 0xff, // jump -- jmp 0x933ae
62 0xff, 0xe0, // jump -- jmpq *%rax
63 0xf2, 0xff, 0x25, 0x75, 0xe7, 0x39, 0x00, // jump -- repne jmpq *0x39e775
65 0x73, 0xc2, // cond jump -- jae 0x9515c
66 0x74, 0x1f, // cond jump -- je 0x400626
67 0x75, 0xea, // cond jump -- jne 0x400610
68 0x76, 0x10, // cond jump -- jbe 0x94d10
69 0x77, 0x58, // cond jump -- ja 0x1208c8
70 0x7e, 0x67, // cond jump -- jle 0x92180
71 0x78, 0x0b, // cond jump -- js 0x92dc3
72 0x0f, 0x82, 0x17, 0x01, 0x00, 0x00, // cond jump -- jb 0x9c7b0
73 0x0f, 0x83, 0xa7, 0x00, 0x00, 0x00, // cond jump -- jae 0x895c8
74 0x0f, 0x84, 0x8c, 0x00, 0x00, 0x00, // cond jump -- je 0x941f0
75 0x0f, 0x85, 0x51, 0xff, 0xff, 0xff, // cond jump -- jne 0x8952c
76 0x0f, 0x86, 0xa3, 0x02, 0x00, 0x00, // cond jump -- jbe 0x9ae10
77 0x0f, 0x87, 0xff, 0x00, 0x00, 0x00, // cond jump -- ja 0x9ab60
78 0x0f, 0x8e, 0x7e, 0x00, 0x00, 0x00, // cond jump -- jle 0x92dd8
79 0x0f, 0x86, 0xdf, 0x00, 0x00, 0x00, // cond jump -- jbe 0x921b0
81 0x0f, 0x05, // far call -- syscall
83 0x0f, 0x07, // far return -- sysret
84 0xcf, // far return -- interrupt ret
87 InstructionControlFlowKind result
[] = {
88 eInstructionControlFlowKindOther
,
89 eInstructionControlFlowKindOther
,
91 eInstructionControlFlowKindCall
,
92 eInstructionControlFlowKindCall
,
93 eInstructionControlFlowKindCall
,
94 eInstructionControlFlowKindCall
,
96 eInstructionControlFlowKindReturn
,
98 eInstructionControlFlowKindJump
,
99 eInstructionControlFlowKindJump
,
100 eInstructionControlFlowKindJump
,
101 eInstructionControlFlowKindJump
,
103 eInstructionControlFlowKindCondJump
,
104 eInstructionControlFlowKindCondJump
,
105 eInstructionControlFlowKindCondJump
,
106 eInstructionControlFlowKindCondJump
,
107 eInstructionControlFlowKindCondJump
,
108 eInstructionControlFlowKindCondJump
,
109 eInstructionControlFlowKindCondJump
,
110 eInstructionControlFlowKindCondJump
,
111 eInstructionControlFlowKindCondJump
,
112 eInstructionControlFlowKindCondJump
,
113 eInstructionControlFlowKindCondJump
,
114 eInstructionControlFlowKindCondJump
,
115 eInstructionControlFlowKindCondJump
,
116 eInstructionControlFlowKindCondJump
,
117 eInstructionControlFlowKindCondJump
,
119 eInstructionControlFlowKindFarCall
,
121 eInstructionControlFlowKindFarReturn
,
122 eInstructionControlFlowKindFarReturn
,
125 DisassemblerSP disass_sp
;
126 Address
start_addr(0x100);
128 Disassembler::DisassembleBytes(arch
, nullptr, nullptr, start_addr
, &data
,
129 sizeof (data
), num_of_instructions
, false);
131 // If we failed to get a disassembler, we can assume it is because
132 // the llvm we linked against was not built with the i386 target,
133 // and we should skip these tests without marking anything as failing.
137 const InstructionList
inst_list(disass_sp
->GetInstructionList());
138 EXPECT_EQ(num_of_instructions
, inst_list
.GetSize());
140 for (size_t i
= 0; i
< num_of_instructions
; ++i
) {
141 InstructionSP inst_sp
;
142 inst_sp
= inst_list
.GetInstructionAtIndex(i
);
143 ExecutionContext
exe_ctx(nullptr, nullptr, nullptr);
144 InstructionControlFlowKind kind
= inst_sp
->GetControlFlowKind(&exe_ctx
);
145 EXPECT_EQ(kind
, result
[i
]);
147 // Also, test the DisassemblerLLVMC::MCDisasmInstance methods.
148 if (kind
== eInstructionControlFlowKindReturn
)
149 EXPECT_FALSE(inst_sp
->IsCall());
150 if (kind
== eInstructionControlFlowKindCall
)
151 EXPECT_TRUE(inst_sp
->IsCall());
152 if (kind
== eInstructionControlFlowKindCall
||
153 kind
== eInstructionControlFlowKindJump
||
154 kind
== eInstructionControlFlowKindCondJump
||
155 kind
== eInstructionControlFlowKindReturn
)
156 EXPECT_TRUE(inst_sp
->DoesBranch());