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