1//===-- TestX86GetControlFlowKind.cpp -------------------------------------===//
2
3//
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
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/TargetSelect.h"
11#include "gtest/gtest.h"
12
13#include "lldb/Core/Address.h"
14#include "lldb/Core/Disassembler.h"
15#include "lldb/Target/ExecutionContext.h"
16#include "lldb/Utility/ArchSpec.h"
17
18#include "Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23namespace {
24class TestGetControlFlowKindx86 : public testing::Test {
25public:
26 static void SetUpTestCase();
27 static void TearDownTestCase();
28
29protected:
30};
31
32void TestGetControlFlowKindx86::SetUpTestCase() {
33 llvm::InitializeAllTargets();
34 llvm::InitializeAllAsmPrinters();
35 llvm::InitializeAllTargetMCs();
36 llvm::InitializeAllDisassemblers();
37 DisassemblerLLVMC::Initialize();
38}
39
40void TestGetControlFlowKindx86::TearDownTestCase() {
41 DisassemblerLLVMC::Terminate();
42}
43} // namespace
44
45TEST_F(TestGetControlFlowKindx86, TestX86_64Instruction) {
46 ArchSpec arch("x86_64-*-linux");
47
48 const unsigned num_of_instructions = 29;
49 uint8_t data[] = {
50 0x55, // other -- pushq %rbp
51 0x48, 0x89, 0xe5, // other -- movq %rsp, %rbp
52
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
57
58 0xc3, // return -- retq
59
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
64
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
80
81 0x0f, 0x05, // far call -- syscall
82
83 0x0f, 0x07, // far return -- sysret
84 0xcf, // far return -- interrupt ret
85 };
86
87 InstructionControlFlowKind result[] = {
88 eInstructionControlFlowKindOther,
89 eInstructionControlFlowKindOther,
90
91 eInstructionControlFlowKindCall,
92 eInstructionControlFlowKindCall,
93 eInstructionControlFlowKindCall,
94 eInstructionControlFlowKindCall,
95
96 eInstructionControlFlowKindReturn,
97
98 eInstructionControlFlowKindJump,
99 eInstructionControlFlowKindJump,
100 eInstructionControlFlowKindJump,
101 eInstructionControlFlowKindJump,
102
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,
118
119 eInstructionControlFlowKindFarCall,
120
121 eInstructionControlFlowKindFarReturn,
122 eInstructionControlFlowKindFarReturn,
123 };
124
125 DisassemblerSP disass_sp;
126 Address start_addr(0x100);
127 disass_sp =
128 Disassembler::DisassembleBytes(arch, plugin_name: nullptr, flavor: nullptr, start: start_addr, bytes: &data,
129 length: sizeof (data), max_num_instructions: num_of_instructions, data_from_file: false);
130
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.
134 if (!disass_sp)
135 return;
136
137 const InstructionList inst_list(disass_sp->GetInstructionList());
138 EXPECT_EQ(num_of_instructions, inst_list.GetSize());
139
140 for (size_t i = 0; i < num_of_instructions; ++i) {
141 InstructionSP inst_sp;
142 inst_sp = inst_list.GetInstructionAtIndex(idx: i);
143 ExecutionContext exe_ctx(nullptr, nullptr, nullptr);
144 InstructionControlFlowKind kind = inst_sp->GetControlFlowKind(exe_ctx: &exe_ctx);
145 EXPECT_EQ(kind, result[i]);
146
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());
157 }
158}
159

source code of lldb/unittests/Disassembler/x86/TestGetControlFlowKindx86.cpp