1 //===-- TextX86GetControlFlowKind.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
20 using namespace lldb;
21 using namespace lldb_private;
22
23 class TestGetControlFlowKindx86 : public testing::Test {
24 public:
25 static void SetUpTestCase();
26 static void TearDownTestCase();
27
28 protected:
29 };
30
SetUpTestCase()31 void TestGetControlFlowKindx86::SetUpTestCase() {
32 llvm::InitializeAllTargets();
33 llvm::InitializeAllAsmPrinters();
34 llvm::InitializeAllTargetMCs();
35 llvm::InitializeAllDisassemblers();
36 DisassemblerLLVMC::Initialize();
37 }
38
TearDownTestCase()39 void TestGetControlFlowKindx86::TearDownTestCase() {
40 DisassemblerLLVMC::Terminate();
41 }
42
TEST_F(TestGetControlFlowKindx86,TestX86_64Instruction)43 TEST_F(TestGetControlFlowKindx86, TestX86_64Instruction) {
44 ArchSpec arch("x86_64-*-linux");
45
46 const unsigned num_of_instructions = 29;
47 uint8_t data[] = {
48 0x55, // other -- pushq %rbp
49 0x48, 0x89, 0xe5, // other -- movq %rsp, %rbp
50
51 0xe8, 0xfc, 0xfe, 0xff, 0xff, // call -- callq 0x4004c0
52 0x41, 0xff, 0x14, 0xdc, // call -- callq *(%r12,%rbx,8)
53 0xff, 0x50, 0x18, // call -- callq *0x18(%rax)
54 0xe8, 0x48, 0x0d, 0x00, 0x00, // call -- callq 0x94fe0
55
56 0xc3, // return -- retq
57
58 0xeb, 0xd3, // jump -- jmp 0x92dab
59 0xe9, 0x22, 0xff, 0xff, 0xff, // jump -- jmp 0x933ae
60 0xff, 0xe0, // jump -- jmpq *%rax
61 0xf2, 0xff, 0x25, 0x75, 0xe7, 0x39, 0x00, // jump -- repne jmpq *0x39e775
62
63 0x73, 0xc2, // cond jump -- jae 0x9515c
64 0x74, 0x1f, // cond jump -- je 0x400626
65 0x75, 0xea, // cond jump -- jne 0x400610
66 0x76, 0x10, // cond jump -- jbe 0x94d10
67 0x77, 0x58, // cond jump -- ja 0x1208c8
68 0x7e, 0x67, // cond jump -- jle 0x92180
69 0x78, 0x0b, // cond jump -- js 0x92dc3
70 0x0f, 0x82, 0x17, 0x01, 0x00, 0x00, // cond jump -- jb 0x9c7b0
71 0x0f, 0x83, 0xa7, 0x00, 0x00, 0x00, // cond jump -- jae 0x895c8
72 0x0f, 0x84, 0x8c, 0x00, 0x00, 0x00, // cond jump -- je 0x941f0
73 0x0f, 0x85, 0x51, 0xff, 0xff, 0xff, // cond jump -- jne 0x8952c
74 0x0f, 0x86, 0xa3, 0x02, 0x00, 0x00, // cond jump -- jbe 0x9ae10
75 0x0f, 0x87, 0xff, 0x00, 0x00, 0x00, // cond jump -- ja 0x9ab60
76 0x0f, 0x8e, 0x7e, 0x00, 0x00, 0x00, // cond jump -- jle 0x92dd8
77 0x0f, 0x86, 0xdf, 0x00, 0x00, 0x00, // cond jump -- jbe 0x921b0
78
79 0x0f, 0x05, // far call -- syscall
80
81 0x0f, 0x07, // far return -- sysret
82 0xcf, // far return -- interrupt ret
83 };
84
85 InstructionControlFlowKind result[] = {
86 eInstructionControlFlowKindOther,
87 eInstructionControlFlowKindOther,
88
89 eInstructionControlFlowKindCall,
90 eInstructionControlFlowKindCall,
91 eInstructionControlFlowKindCall,
92 eInstructionControlFlowKindCall,
93
94 eInstructionControlFlowKindReturn,
95
96 eInstructionControlFlowKindJump,
97 eInstructionControlFlowKindJump,
98 eInstructionControlFlowKindJump,
99 eInstructionControlFlowKindJump,
100
101 eInstructionControlFlowKindCondJump,
102 eInstructionControlFlowKindCondJump,
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
117 eInstructionControlFlowKindFarCall,
118
119 eInstructionControlFlowKindFarReturn,
120 eInstructionControlFlowKindFarReturn,
121 };
122
123 DisassemblerSP disass_sp;
124 Address start_addr(0x100);
125 disass_sp =
126 Disassembler::DisassembleBytes(arch, nullptr, nullptr, start_addr, &data,
127 sizeof (data), num_of_instructions, false);
128
129 // If we failed to get a disassembler, we can assume it is because
130 // the llvm we linked against was not built with the i386 target,
131 // and we should skip these tests without marking anything as failing.
132
133 if (disass_sp) {
134 const InstructionList inst_list(disass_sp->GetInstructionList());
135 EXPECT_EQ(num_of_instructions, inst_list.GetSize());
136
137 for (size_t i = 0; i < num_of_instructions; ++i) {
138 InstructionSP inst_sp;
139 inst_sp = inst_list.GetInstructionAtIndex(i);
140 ExecutionContext exe_ctx (nullptr, nullptr, nullptr);
141 InstructionControlFlowKind kind = inst_sp->GetControlFlowKind(&exe_ctx);
142 EXPECT_EQ(kind, result[i]);
143 }
144 }
145 }
146