1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
//===-- TestMCDisasmInstanceRISCV.cpp -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/TargetSelect.h"
#include "gtest/gtest.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/StreamString.h"
#include "Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h"
using namespace lldb;
using namespace lldb_private;
namespace {
class TestMCDisasmInstanceRISCV : public testing::Test {
public:
static void SetUpTestCase();
static void TearDownTestCase();
protected:
};
void TestMCDisasmInstanceRISCV::SetUpTestCase() {
llvm::InitializeAllTargets();
llvm::InitializeAllAsmPrinters();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllDisassemblers();
DisassemblerLLVMC::Initialize();
}
void TestMCDisasmInstanceRISCV::TearDownTestCase() {
DisassemblerLLVMC::Terminate();
}
} // namespace
TEST_F(TestMCDisasmInstanceRISCV, TestRISCV32Instruction) {
ArchSpec arch("riscv32-*-linux");
const unsigned num_of_instructions = 5;
uint8_t data[] = {
0xef, 0x00, 0x00, 0x00, // call -- jal x1, 0
0xe7, 0x00, 0x00, 0x00, // call -- jalr x1, x0, 0
0x6f, 0x00, 0x00, 0x00, // jump -- jal x0, 0
0x67, 0x00, 0x00, 0x00, // jump -- jalr x0, x0, 0
0x67, 0x80, 0x00, 0x00 // ret -- jalr x0, x1, 0
};
DisassemblerSP disass_sp;
Address start_addr(0x100);
disass_sp = Disassembler::DisassembleBytes(
arch, nullptr, nullptr, nullptr, nullptr, start_addr, &data, sizeof(data),
num_of_instructions, false);
const InstructionList inst_list(disass_sp->GetInstructionList());
EXPECT_EQ(num_of_instructions, inst_list.GetSize());
InstructionSP inst_sp;
inst_sp = inst_list.GetInstructionAtIndex(0);
EXPECT_TRUE(inst_sp->IsCall());
EXPECT_TRUE(inst_sp->DoesBranch());
inst_sp = inst_list.GetInstructionAtIndex(1);
EXPECT_TRUE(inst_sp->IsCall());
EXPECT_TRUE(inst_sp->DoesBranch());
inst_sp = inst_list.GetInstructionAtIndex(2);
EXPECT_FALSE(inst_sp->IsCall());
EXPECT_TRUE(inst_sp->DoesBranch());
inst_sp = inst_list.GetInstructionAtIndex(3);
EXPECT_FALSE(inst_sp->IsCall());
EXPECT_TRUE(inst_sp->DoesBranch());
inst_sp = inst_list.GetInstructionAtIndex(4);
EXPECT_FALSE(inst_sp->IsCall());
EXPECT_TRUE(inst_sp->DoesBranch());
}
TEST_F(TestMCDisasmInstanceRISCV, TestOpcodeBytePrinter) {
ArchSpec arch("riscv32-*-linux");
const unsigned num_of_instructions = 7;
// clang-format off
uint8_t data[] = {
0x41, 0x11, // addi sp, sp, -0x10
0x06, 0xc6, // sw ra, 0xc(sp)
0x23, 0x2a, 0xa4, 0xfe, // sw a0, -0xc(s0)
0x23, 0x28, 0xa4, 0xfe, // sw a0, -0x10(s0)
0x22, 0x44, // lw s0, 0x8(sp)
0x3f, 0x00, 0x40, 0x09, // Fake 64-bit instruction
0x20, 0x00, 0x20, 0x00,
0x1f, 0x02, // 48 bit xqci.e.li rd=8 imm=0x1000
0x00, 0x00,
0x00, 0x10,
};
// clang-format on
// clang-format off
const char *expected_outputs[] = {
"1141",
"c606",
"fea42a23",
"fea42823",
"4422",
"0940003f 00200020",
"021f 0000 1000"
};
// clang-format on
const unsigned num_of_expected_outputs =
sizeof(expected_outputs) / sizeof(char *);
EXPECT_EQ(num_of_instructions, num_of_expected_outputs);
DisassemblerSP disass_sp;
Address start_addr(0x100);
disass_sp = Disassembler::DisassembleBytes(
arch, nullptr, nullptr, nullptr, nullptr, start_addr, &data, sizeof(data),
num_of_instructions, false);
const InstructionList inst_list(disass_sp->GetInstructionList());
EXPECT_EQ(num_of_instructions, inst_list.GetSize());
for (size_t i = 0; i < num_of_instructions; i++) {
InstructionSP inst_sp;
StreamString s;
inst_sp = inst_list.GetInstructionAtIndex(i);
inst_sp->GetOpcode().Dump(&s, 1);
ASSERT_STREQ(s.GetString().str().c_str(), expected_outputs[i]);
}
}
|