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 ArrayRef<char> 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               getGenericEdgeKindName);
30   EXPECT_EQ(G.getName(), "foo");
31   EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin");
32   EXPECT_EQ(G.getPointerSize(), 8U);
33   EXPECT_EQ(G.getEndianness(), support::little);
34   EXPECT_TRUE(llvm::empty(G.external_symbols()));
35   EXPECT_TRUE(llvm::empty(G.absolute_symbols()));
36   EXPECT_TRUE(llvm::empty(G.defined_symbols()));
37   EXPECT_TRUE(llvm::empty(G.blocks()));
38 }
39 
40 TEST(LinkGraphTest, AddressAccess) {
41   // Check that we can get addresses for blocks, symbols, and edges.
42   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
43               getGenericEdgeKindName);
44 
45   auto &Sec1 = G.createSection("__data.1", RWFlags);
46   auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0);
47   auto &S1 = G.addDefinedSymbol(B1, 4, "S1", 4, Linkage::Strong, Scope::Default,
48                                 false, false);
49   B1.addEdge(Edge::FirstRelocation, 8, S1, 0);
50   auto &E1 = *B1.edges().begin();
51 
52   EXPECT_EQ(B1.getAddress(), 0x1000U) << "Incorrect block address";
53   EXPECT_EQ(S1.getAddress(), 0x1004U) << "Incorrect symbol address";
54   EXPECT_EQ(B1.getFixupAddress(E1), 0x1008U) << "Incorrect fixup address";
55 }
56 
57 TEST(LinkGraphTest, BlockAndSymbolIteration) {
58   // Check that we can iterate over blocks within Sections and across sections.
59   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
60               getGenericEdgeKindName);
61   auto &Sec1 = G.createSection("__data.1", RWFlags);
62   auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0);
63   auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0);
64   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
65                                 false, false);
66   auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default,
67                                 false, false);
68 
69   auto &Sec2 = G.createSection("__data.2", RWFlags);
70   auto &B3 = G.createContentBlock(Sec2, BlockContent, 0x3000, 8, 0);
71   auto &B4 = G.createContentBlock(Sec2, BlockContent, 0x4000, 8, 0);
72   auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default,
73                                 false, false);
74   auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default,
75                                 false, false);
76 
77   // Check that iteration of blocks within a section behaves as expected.
78   EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2);
79   EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1));
80   EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2));
81 
82   // Check that iteration of symbols within a section behaves as expected.
83   EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2);
84   EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1));
85   EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2));
86 
87   // Check that iteration of blocks across sections behaves as expected.
88   EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4);
89   EXPECT_TRUE(llvm::count(G.blocks(), &B1));
90   EXPECT_TRUE(llvm::count(G.blocks(), &B2));
91   EXPECT_TRUE(llvm::count(G.blocks(), &B3));
92   EXPECT_TRUE(llvm::count(G.blocks(), &B4));
93 
94   // Check that iteration of defined symbols across sections behaves as
95   // expected.
96   EXPECT_EQ(
97       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4);
98   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1));
99   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2));
100   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3));
101   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4));
102 }
103 
104 TEST(LinkGraphTest, MakeExternal) {
105   // Check that we can make a defined symbol external.
106   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
107               getGenericEdgeKindName);
108   auto &Sec = G.createSection("__data", RWFlags);
109 
110   // Create an initial block.
111   auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0);
112 
113   // Add a symbol to the block.
114   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
115                                 false, false);
116 
117   EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
118   EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
119   EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
120   EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
121   EXPECT_EQ(S1.getAddress(), 0x1000U) << "Unexpected symbol address";
122 
123   EXPECT_EQ(
124       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
125       << "Unexpected number of defined symbols";
126   EXPECT_EQ(
127       std::distance(G.external_symbols().begin(), G.external_symbols().end()),
128       0U)
129       << "Unexpected number of external symbols";
130 
131   // Make S1 external, confirm that the its flags are updated and that it is
132   // moved from the defined symbols to the externals list.
133   G.makeExternal(S1);
134 
135   EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
136   EXPECT_TRUE(S1.isExternal()) << "Symbol should be external";
137   EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
138   EXPECT_EQ(S1.getAddress(), 0U) << "Unexpected symbol address";
139 
140   EXPECT_EQ(
141       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
142       << "Unexpected number of defined symbols";
143   EXPECT_EQ(
144       std::distance(G.external_symbols().begin(), G.external_symbols().end()),
145       1U)
146       << "Unexpected number of external symbols";
147 }
148 
149 TEST(LinkGraphTest, MakeDefined) {
150   // Check that we can make an external symbol defined.
151   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
152               getGenericEdgeKindName);
153   auto &Sec = G.createSection("__data", RWFlags);
154 
155   // Create an initial block.
156   auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0);
157 
158   // Add an external symbol.
159   auto &S1 = G.addExternalSymbol("S1", 4, Linkage::Strong);
160 
161   EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
162   EXPECT_TRUE(S1.isExternal()) << "Symbol should be external";
163   EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
164   EXPECT_EQ(S1.getAddress(), 0U) << "Unexpected symbol address";
165 
166   EXPECT_EQ(
167       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
168       << "Unexpected number of defined symbols";
169   EXPECT_EQ(
170       std::distance(G.external_symbols().begin(), G.external_symbols().end()),
171       1U)
172       << "Unexpected number of external symbols";
173 
174   // Make S1 defined, confirm that its flags are updated and that it is
175   // moved from the defined symbols to the externals list.
176   G.makeDefined(S1, B1, 0, 4, Linkage::Strong, Scope::Default, false);
177 
178   EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
179   EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
180   EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
181   EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
182   EXPECT_EQ(S1.getAddress(), 0x1000U) << "Unexpected symbol address";
183 
184   EXPECT_EQ(
185       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
186       << "Unexpected number of defined symbols";
187   EXPECT_EQ(
188       std::distance(G.external_symbols().begin(), G.external_symbols().end()),
189       0U)
190       << "Unexpected number of external symbols";
191 }
192 
193 TEST(LinkGraphTest, SplitBlock) {
194   // Check that the LinkGraph::splitBlock test works as expected.
195   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
196               getGenericEdgeKindName);
197   auto &Sec = G.createSection("__data", RWFlags);
198 
199   // Create the block to split.
200   auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0);
201 
202   // Add some symbols to the block.
203   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
204                                 false, false);
205   auto &S2 = G.addDefinedSymbol(B1, 4, "S2", 4, Linkage::Strong, Scope::Default,
206                                 false, false);
207   auto &S3 = G.addDefinedSymbol(B1, 8, "S3", 4, Linkage::Strong, Scope::Default,
208                                 false, false);
209   auto &S4 = G.addDefinedSymbol(B1, 12, "S4", 4, Linkage::Strong,
210                                 Scope::Default, false, false);
211 
212   // Add an extra block, EB, and target symbols, and use these to add edges
213   // from B1 to EB.
214   auto &EB = G.createContentBlock(Sec, BlockContent, 0x2000, 8, 0);
215   auto &ES1 = G.addDefinedSymbol(EB, 0, "TS1", 4, Linkage::Strong,
216                                  Scope::Default, false, false);
217   auto &ES2 = G.addDefinedSymbol(EB, 4, "TS2", 4, Linkage::Strong,
218                                  Scope::Default, false, false);
219   auto &ES3 = G.addDefinedSymbol(EB, 8, "TS3", 4, Linkage::Strong,
220                                  Scope::Default, false, false);
221   auto &ES4 = G.addDefinedSymbol(EB, 12, "TS4", 4, Linkage::Strong,
222                                  Scope::Default, false, false);
223 
224   // Add edges from B1 to EB.
225   B1.addEdge(Edge::FirstRelocation, 0, ES1, 0);
226   B1.addEdge(Edge::FirstRelocation, 4, ES2, 0);
227   B1.addEdge(Edge::FirstRelocation, 8, ES3, 0);
228   B1.addEdge(Edge::FirstRelocation, 12, ES4, 0);
229 
230   // Split B1.
231   auto &B2 = G.splitBlock(B1, 8);
232 
233   // Check that the block addresses and content matches what we would expect.
234   EXPECT_EQ(B1.getAddress(), 0x1008U);
235   EXPECT_EQ(B1.getContent(), BlockContent.slice(8));
236 
237   EXPECT_EQ(B2.getAddress(), 0x1000U);
238   EXPECT_EQ(B2.getContent(), BlockContent.slice(0, 8));
239 
240   // Check that symbols in B1 were transferred as expected:
241   // We expect S1 and S2 to have been transferred to B2, and S3 and S4 to have
242   // remained attached to B1. Symbols S3 and S4 should have had their offsets
243   // slid to account for the change in address of B2.
244   EXPECT_EQ(&S1.getBlock(), &B2);
245   EXPECT_EQ(S1.getOffset(), 0U);
246 
247   EXPECT_EQ(&S2.getBlock(), &B2);
248   EXPECT_EQ(S2.getOffset(), 4U);
249 
250   EXPECT_EQ(&S3.getBlock(), &B1);
251   EXPECT_EQ(S3.getOffset(), 0U);
252 
253   EXPECT_EQ(&S4.getBlock(), &B1);
254   EXPECT_EQ(S4.getOffset(), 4U);
255 
256   // Check that edges in B1 have been transferred as expected:
257   // Both blocks should now have two edges each at offsets 0 and 4.
258   EXPECT_EQ(llvm::size(B1.edges()), 2);
259   if (size(B1.edges()) == 2) {
260     auto *E1 = &*B1.edges().begin();
261     auto *E2 = &*(B1.edges().begin() + 1);
262     if (E2->getOffset() < E1->getOffset())
263       std::swap(E1, E2);
264     EXPECT_EQ(E1->getOffset(), 0U);
265     EXPECT_EQ(E2->getOffset(), 4U);
266   }
267 
268   EXPECT_EQ(llvm::size(B2.edges()), 2);
269   if (size(B2.edges()) == 2) {
270     auto *E1 = &*B2.edges().begin();
271     auto *E2 = &*(B2.edges().begin() + 1);
272     if (E2->getOffset() < E1->getOffset())
273       std::swap(E1, E2);
274     EXPECT_EQ(E1->getOffset(), 0U);
275     EXPECT_EQ(E2->getOffset(), 4U);
276   }
277 }
278