1 //===------ LinkGraphTests.cpp - Unit tests for core JITLink classes ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/ADT/STLExtras.h"
10 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
11 #include "llvm/Support/Endian.h"
12 #include "llvm/Support/Memory.h"
13 #include "gtest/gtest.h"
14 
15 using namespace llvm;
16 using namespace llvm::jitlink;
17 
18 static auto RWFlags =
19     sys::Memory::ProtectionFlags(sys::Memory::MF_READ | sys::Memory::MF_WRITE);
20 
21 static const char BlockContentBytes[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
22                                          0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
23                                          0x1C, 0x1D, 0x1E, 0x1F, 0x00};
24 static StringRef BlockContent(BlockContentBytes);
25 
26 TEST(LinkGraphTest, Construction) {
27   // Check that LinkGraph construction works as expected.
28   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
29   EXPECT_EQ(G.getName(), "foo");
30   EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin");
31   EXPECT_EQ(G.getPointerSize(), 8U);
32   EXPECT_EQ(G.getEndianness(), support::little);
33   EXPECT_TRUE(llvm::empty(G.external_symbols()));
34   EXPECT_TRUE(llvm::empty(G.absolute_symbols()));
35   EXPECT_TRUE(llvm::empty(G.defined_symbols()));
36   EXPECT_TRUE(llvm::empty(G.blocks()));
37 }
38 
39 TEST(LinkGraphTest, AddressAccess) {
40   // Check that we can get addresses for blocks, symbols, and edges.
41   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
42 
43   auto Sec1 = G.createSection("__data.1", RWFlags);
44   auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0);
45   auto &S1 = G.addDefinedSymbol(B1, 4, "S1", 4, Linkage::Strong, Scope::Default,
46                                 false, false);
47   B1.addEdge(Edge::FirstRelocation, 8, S1, 0);
48   auto &E1 = *B1.edges().begin();
49 
50   EXPECT_EQ(B1.getAddress(), 0x1000U) << "Incorrect block address";
51   EXPECT_EQ(S1.getAddress(), 0x1004U) << "Incorrect symbol address";
52   EXPECT_EQ(B1.getFixupAddress(E1), 0x1008U) << "Incorrect fixup address";
53 }
54 
55 TEST(LinkGraphTest, BlockAndSymbolIteration) {
56   // Check that we can iterate over blocks within Sections and across sections.
57   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
58   auto &Sec1 = G.createSection("__data.1", RWFlags);
59   auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0);
60   auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0);
61   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
62                                 false, false);
63   auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default,
64                                 false, false);
65 
66   auto &Sec2 = G.createSection("__data.2", RWFlags);
67   auto &B3 = G.createContentBlock(Sec2, BlockContent, 0x3000, 8, 0);
68   auto &B4 = G.createContentBlock(Sec2, BlockContent, 0x4000, 8, 0);
69   auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default,
70                                 false, false);
71   auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default,
72                                 false, false);
73 
74   // Check that iteration of blocks within a section behaves as expected.
75   EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2);
76   EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1));
77   EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2));
78 
79   // Check that iteration of symbols within a section behaves as expected.
80   EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2);
81   EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1));
82   EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2));
83 
84   // Check that iteration of blocks across sections behaves as expected.
85   EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4);
86   EXPECT_TRUE(llvm::count(G.blocks(), &B1));
87   EXPECT_TRUE(llvm::count(G.blocks(), &B2));
88   EXPECT_TRUE(llvm::count(G.blocks(), &B3));
89   EXPECT_TRUE(llvm::count(G.blocks(), &B4));
90 
91   // Check that iteration of defined symbols across sections behaves as
92   // expected.
93   EXPECT_EQ(
94       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4);
95   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1));
96   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2));
97   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3));
98   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4));
99 }
100 
101 TEST(LinkGraphTest, SplitBlock) {
102   // Check that the LinkGraph::splitBlock test works as expected.
103 
104   const char BlockContentBytes[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
105                                     0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
106                                     0x1C, 0x1D, 0x1E, 0x1F, 0x00};
107   StringRef BlockContent(BlockContentBytes);
108 
109   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little);
110   auto &Sec = G.createSection("__data", RWFlags);
111 
112   // Create the block to split.
113   auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0);
114 
115   // Add some symbols to the block.
116   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
117                                 false, false);
118   auto &S2 = G.addDefinedSymbol(B1, 4, "S2", 4, Linkage::Strong, Scope::Default,
119                                 false, false);
120   auto &S3 = G.addDefinedSymbol(B1, 8, "S3", 4, Linkage::Strong, Scope::Default,
121                                 false, false);
122   auto &S4 = G.addDefinedSymbol(B1, 12, "S4", 4, Linkage::Strong,
123                                 Scope::Default, false, false);
124 
125   // Add an extra block, EB, and target symbols, and use these to add edges
126   // from B1 to EB.
127   auto &EB = G.createContentBlock(Sec, BlockContent, 0x2000, 8, 0);
128   auto &ES1 = G.addDefinedSymbol(EB, 0, "TS1", 4, Linkage::Strong,
129                                  Scope::Default, false, false);
130   auto &ES2 = G.addDefinedSymbol(EB, 4, "TS2", 4, Linkage::Strong,
131                                  Scope::Default, false, false);
132   auto &ES3 = G.addDefinedSymbol(EB, 8, "TS3", 4, Linkage::Strong,
133                                  Scope::Default, false, false);
134   auto &ES4 = G.addDefinedSymbol(EB, 12, "TS4", 4, Linkage::Strong,
135                                  Scope::Default, false, false);
136 
137   // Add edges from B1 to EB.
138   B1.addEdge(Edge::FirstRelocation, 0, ES1, 0);
139   B1.addEdge(Edge::FirstRelocation, 4, ES2, 0);
140   B1.addEdge(Edge::FirstRelocation, 8, ES3, 0);
141   B1.addEdge(Edge::FirstRelocation, 12, ES4, 0);
142 
143   // Split B1.
144   auto &B2 = G.splitBlock(B1, 8);
145 
146   // Check that the block addresses and content matches what we would expect.
147   EXPECT_EQ(B1.getAddress(), 0x1008U);
148   EXPECT_EQ(B1.getContent(), BlockContent.substr(8));
149 
150   EXPECT_EQ(B2.getAddress(), 0x1000U);
151   EXPECT_EQ(B2.getContent(), BlockContent.substr(0, 8));
152 
153   // Check that symbols in B1 were transferred as expected:
154   // We expect S1 and S2 to have been transferred to B2, and S3 and S4 to have
155   // remained attached to B1. Symbols S3 and S4 should have had their offsets
156   // slid to account for the change in address of B2.
157   EXPECT_EQ(&S1.getBlock(), &B2);
158   EXPECT_EQ(S1.getOffset(), 0U);
159 
160   EXPECT_EQ(&S2.getBlock(), &B2);
161   EXPECT_EQ(S2.getOffset(), 4U);
162 
163   EXPECT_EQ(&S3.getBlock(), &B1);
164   EXPECT_EQ(S3.getOffset(), 0U);
165 
166   EXPECT_EQ(&S4.getBlock(), &B1);
167   EXPECT_EQ(S4.getOffset(), 4U);
168 
169   // Check that edges in B1 have been transferred as expected:
170   // Both blocks should now have two edges each at offsets 0 and 4.
171   EXPECT_EQ(llvm::size(B1.edges()), 2);
172   if (size(B1.edges()) == 2) {
173     auto *E1 = &*B1.edges().begin();
174     auto *E2 = &*(B1.edges().begin() + 1);
175     if (E2->getOffset() < E1->getOffset())
176       std::swap(E1, E2);
177     EXPECT_EQ(E1->getOffset(), 0U);
178     EXPECT_EQ(E2->getOffset(), 4U);
179   }
180 
181   EXPECT_EQ(llvm::size(B2.edges()), 2);
182   if (size(B2.edges()) == 2) {
183     auto *E1 = &*B2.edges().begin();
184     auto *E2 = &*(B2.edges().begin() + 1);
185     if (E2->getOffset() < E1->getOffset())
186       std::swap(E1, E2);
187     EXPECT_EQ(E1->getOffset(), 0U);
188     EXPECT_EQ(E2->getOffset(), 4U);
189   }
190 }
191