189c9fee4SDavid Spickett //===-- TestX86GetControlFlowKind.cpp -------------------------------------===// 2ad7bcda9SWalter Erquinigo 3ad7bcda9SWalter Erquinigo // 4ad7bcda9SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5ad7bcda9SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information. 6ad7bcda9SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7ad7bcda9SWalter Erquinigo // 8ad7bcda9SWalter Erquinigo //===----------------------------------------------------------------------===// 9ad7bcda9SWalter Erquinigo 10ad7bcda9SWalter Erquinigo #include "llvm/Support/TargetSelect.h" 11ad7bcda9SWalter Erquinigo #include "gtest/gtest.h" 12ad7bcda9SWalter Erquinigo 13ad7bcda9SWalter Erquinigo #include "lldb/Core/Address.h" 14ad7bcda9SWalter Erquinigo #include "lldb/Core/Disassembler.h" 15ad7bcda9SWalter Erquinigo #include "lldb/Target/ExecutionContext.h" 16ad7bcda9SWalter Erquinigo #include "lldb/Utility/ArchSpec.h" 17ad7bcda9SWalter Erquinigo 18ad7bcda9SWalter Erquinigo #include "Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h" 19ad7bcda9SWalter Erquinigo 20ad7bcda9SWalter Erquinigo using namespace lldb; 21ad7bcda9SWalter Erquinigo using namespace lldb_private; 22ad7bcda9SWalter Erquinigo 23dfa8a15dSVenkata Ramanaiah Nalamothu namespace { 24ad7bcda9SWalter Erquinigo class TestGetControlFlowKindx86 : public testing::Test { 25ad7bcda9SWalter Erquinigo public: 26ad7bcda9SWalter Erquinigo static void SetUpTestCase(); 27ad7bcda9SWalter Erquinigo static void TearDownTestCase(); 28ad7bcda9SWalter Erquinigo 29ad7bcda9SWalter Erquinigo protected: 30ad7bcda9SWalter Erquinigo }; 31ad7bcda9SWalter Erquinigo 32ad7bcda9SWalter Erquinigo void TestGetControlFlowKindx86::SetUpTestCase() { 33ad7bcda9SWalter Erquinigo llvm::InitializeAllTargets(); 34ad7bcda9SWalter Erquinigo llvm::InitializeAllAsmPrinters(); 35ad7bcda9SWalter Erquinigo llvm::InitializeAllTargetMCs(); 36ad7bcda9SWalter Erquinigo llvm::InitializeAllDisassemblers(); 37ad7bcda9SWalter Erquinigo DisassemblerLLVMC::Initialize(); 38ad7bcda9SWalter Erquinigo } 39ad7bcda9SWalter Erquinigo 40ad7bcda9SWalter Erquinigo void TestGetControlFlowKindx86::TearDownTestCase() { 41ad7bcda9SWalter Erquinigo DisassemblerLLVMC::Terminate(); 42ad7bcda9SWalter Erquinigo } 43dfa8a15dSVenkata Ramanaiah Nalamothu } // namespace 44ad7bcda9SWalter Erquinigo 45ad7bcda9SWalter Erquinigo TEST_F(TestGetControlFlowKindx86, TestX86_64Instruction) { 46ad7bcda9SWalter Erquinigo ArchSpec arch("x86_64-*-linux"); 47ad7bcda9SWalter Erquinigo 48ad7bcda9SWalter Erquinigo const unsigned num_of_instructions = 29; 49ad7bcda9SWalter Erquinigo uint8_t data[] = { 50ad7bcda9SWalter Erquinigo 0x55, // other -- pushq %rbp 51ad7bcda9SWalter Erquinigo 0x48, 0x89, 0xe5, // other -- movq %rsp, %rbp 52ad7bcda9SWalter Erquinigo 53ad7bcda9SWalter Erquinigo 0xe8, 0xfc, 0xfe, 0xff, 0xff, // call -- callq 0x4004c0 54ad7bcda9SWalter Erquinigo 0x41, 0xff, 0x14, 0xdc, // call -- callq *(%r12,%rbx,8) 55ad7bcda9SWalter Erquinigo 0xff, 0x50, 0x18, // call -- callq *0x18(%rax) 56ad7bcda9SWalter Erquinigo 0xe8, 0x48, 0x0d, 0x00, 0x00, // call -- callq 0x94fe0 57ad7bcda9SWalter Erquinigo 58ad7bcda9SWalter Erquinigo 0xc3, // return -- retq 59ad7bcda9SWalter Erquinigo 60ad7bcda9SWalter Erquinigo 0xeb, 0xd3, // jump -- jmp 0x92dab 61ad7bcda9SWalter Erquinigo 0xe9, 0x22, 0xff, 0xff, 0xff, // jump -- jmp 0x933ae 62ad7bcda9SWalter Erquinigo 0xff, 0xe0, // jump -- jmpq *%rax 63ad7bcda9SWalter Erquinigo 0xf2, 0xff, 0x25, 0x75, 0xe7, 0x39, 0x00, // jump -- repne jmpq *0x39e775 64ad7bcda9SWalter Erquinigo 65ad7bcda9SWalter Erquinigo 0x73, 0xc2, // cond jump -- jae 0x9515c 66ad7bcda9SWalter Erquinigo 0x74, 0x1f, // cond jump -- je 0x400626 67ad7bcda9SWalter Erquinigo 0x75, 0xea, // cond jump -- jne 0x400610 68ad7bcda9SWalter Erquinigo 0x76, 0x10, // cond jump -- jbe 0x94d10 69ad7bcda9SWalter Erquinigo 0x77, 0x58, // cond jump -- ja 0x1208c8 70ad7bcda9SWalter Erquinigo 0x7e, 0x67, // cond jump -- jle 0x92180 71ad7bcda9SWalter Erquinigo 0x78, 0x0b, // cond jump -- js 0x92dc3 72ad7bcda9SWalter Erquinigo 0x0f, 0x82, 0x17, 0x01, 0x00, 0x00, // cond jump -- jb 0x9c7b0 73ad7bcda9SWalter Erquinigo 0x0f, 0x83, 0xa7, 0x00, 0x00, 0x00, // cond jump -- jae 0x895c8 74ad7bcda9SWalter Erquinigo 0x0f, 0x84, 0x8c, 0x00, 0x00, 0x00, // cond jump -- je 0x941f0 75ad7bcda9SWalter Erquinigo 0x0f, 0x85, 0x51, 0xff, 0xff, 0xff, // cond jump -- jne 0x8952c 76ad7bcda9SWalter Erquinigo 0x0f, 0x86, 0xa3, 0x02, 0x00, 0x00, // cond jump -- jbe 0x9ae10 77ad7bcda9SWalter Erquinigo 0x0f, 0x87, 0xff, 0x00, 0x00, 0x00, // cond jump -- ja 0x9ab60 78ad7bcda9SWalter Erquinigo 0x0f, 0x8e, 0x7e, 0x00, 0x00, 0x00, // cond jump -- jle 0x92dd8 79ad7bcda9SWalter Erquinigo 0x0f, 0x86, 0xdf, 0x00, 0x00, 0x00, // cond jump -- jbe 0x921b0 80ad7bcda9SWalter Erquinigo 81ad7bcda9SWalter Erquinigo 0x0f, 0x05, // far call -- syscall 82ad7bcda9SWalter Erquinigo 83ad7bcda9SWalter Erquinigo 0x0f, 0x07, // far return -- sysret 84ad7bcda9SWalter Erquinigo 0xcf, // far return -- interrupt ret 85ad7bcda9SWalter Erquinigo }; 86ad7bcda9SWalter Erquinigo 87ad7bcda9SWalter Erquinigo InstructionControlFlowKind result[] = { 88ad7bcda9SWalter Erquinigo eInstructionControlFlowKindOther, 89ad7bcda9SWalter Erquinigo eInstructionControlFlowKindOther, 90ad7bcda9SWalter Erquinigo 91ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCall, 92ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCall, 93ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCall, 94ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCall, 95ad7bcda9SWalter Erquinigo 96ad7bcda9SWalter Erquinigo eInstructionControlFlowKindReturn, 97ad7bcda9SWalter Erquinigo 98ad7bcda9SWalter Erquinigo eInstructionControlFlowKindJump, 99ad7bcda9SWalter Erquinigo eInstructionControlFlowKindJump, 100ad7bcda9SWalter Erquinigo eInstructionControlFlowKindJump, 101ad7bcda9SWalter Erquinigo eInstructionControlFlowKindJump, 102ad7bcda9SWalter Erquinigo 103ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 104ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 105ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 106ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 107ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 108ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 109ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 110ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 111ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 112ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 113ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 114ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 115ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 116ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 117ad7bcda9SWalter Erquinigo eInstructionControlFlowKindCondJump, 118ad7bcda9SWalter Erquinigo 119ad7bcda9SWalter Erquinigo eInstructionControlFlowKindFarCall, 120ad7bcda9SWalter Erquinigo 121ad7bcda9SWalter Erquinigo eInstructionControlFlowKindFarReturn, 122ad7bcda9SWalter Erquinigo eInstructionControlFlowKindFarReturn, 123ad7bcda9SWalter Erquinigo }; 124ad7bcda9SWalter Erquinigo 125ad7bcda9SWalter Erquinigo DisassemblerSP disass_sp; 126ad7bcda9SWalter Erquinigo Address start_addr(0x100); 127*f109517dSJonas Devlieghere disass_sp = Disassembler::DisassembleBytes( 128*f109517dSJonas Devlieghere arch, nullptr, nullptr, nullptr, nullptr, start_addr, &data, sizeof(data), 129*f109517dSJonas Devlieghere num_of_instructions, false); 130ad7bcda9SWalter Erquinigo 131ad7bcda9SWalter Erquinigo // If we failed to get a disassembler, we can assume it is because 132ad7bcda9SWalter Erquinigo // the llvm we linked against was not built with the i386 target, 133ad7bcda9SWalter Erquinigo // and we should skip these tests without marking anything as failing. 134254a3127SVenkata Ramanaiah Nalamothu if (!disass_sp) 135254a3127SVenkata Ramanaiah Nalamothu return; 136ad7bcda9SWalter Erquinigo 137ad7bcda9SWalter Erquinigo const InstructionList inst_list(disass_sp->GetInstructionList()); 138ad7bcda9SWalter Erquinigo EXPECT_EQ(num_of_instructions, inst_list.GetSize()); 139ad7bcda9SWalter Erquinigo 140ad7bcda9SWalter Erquinigo for (size_t i = 0; i < num_of_instructions; ++i) { 141ad7bcda9SWalter Erquinigo InstructionSP inst_sp; 142ad7bcda9SWalter Erquinigo inst_sp = inst_list.GetInstructionAtIndex(i); 1430538e543SWalter Erquinigo ExecutionContext exe_ctx(nullptr, nullptr, nullptr); 1440538e543SWalter Erquinigo InstructionControlFlowKind kind = inst_sp->GetControlFlowKind(&exe_ctx); 145ad7bcda9SWalter Erquinigo EXPECT_EQ(kind, result[i]); 146254a3127SVenkata Ramanaiah Nalamothu 147254a3127SVenkata Ramanaiah Nalamothu // Also, test the DisassemblerLLVMC::MCDisasmInstance methods. 14808201cb4SDavid Spickett if (kind == eInstructionControlFlowKindReturn) { 149254a3127SVenkata Ramanaiah Nalamothu EXPECT_FALSE(inst_sp->IsCall()); 15008201cb4SDavid Spickett } 15108201cb4SDavid Spickett 15208201cb4SDavid Spickett if (kind == eInstructionControlFlowKindCall) { 153254a3127SVenkata Ramanaiah Nalamothu EXPECT_TRUE(inst_sp->IsCall()); 15408201cb4SDavid Spickett } 15508201cb4SDavid Spickett 156254a3127SVenkata Ramanaiah Nalamothu if (kind == eInstructionControlFlowKindCall || 157254a3127SVenkata Ramanaiah Nalamothu kind == eInstructionControlFlowKindJump || 158254a3127SVenkata Ramanaiah Nalamothu kind == eInstructionControlFlowKindCondJump || 15908201cb4SDavid Spickett kind == eInstructionControlFlowKindReturn) { 160254a3127SVenkata Ramanaiah Nalamothu EXPECT_TRUE(inst_sp->DoesBranch()); 161ad7bcda9SWalter Erquinigo } 162ad7bcda9SWalter Erquinigo } 16308201cb4SDavid Spickett } 164