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 const char BlockContentBytes[] = {
19     0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x6f,
20     0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68,
21     0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x66,
22     0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20,
23     0x68, 0x61, 0x64, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x61,
24     0x72, 0x6f, 0x75, 0x6e, 0x64, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74,
25     0x68, 0x65, 0x20, 0x63, 0x6f, 0x6c, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d,
26     0x20, 0x4f, 0x6c, 0x64, 0x20, 0x52, 0x65, 0x67, 0x72, 0x65, 0x74, 0x20,
27     0x68, 0x61, 0x64, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x61, 0x77, 0x61, 0x79,
28     0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6a, 0x6f,
29     0x69, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c,
30     0x64, 0x20, 0x62, 0x75, 0x73, 0x68, 0x20, 0x68, 0x6f, 0x72, 0x73, 0x65,
31     0x73, 0x20, 0x2d, 0x2d, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
32     0x77, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x74, 0x68, 0x6f, 0x75,
33     0x73, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x0a,
34     0x53, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
35     0x72, 0x61, 0x63, 0x6b, 0x73, 0x20, 0x68, 0x61, 0x64, 0x20, 0x67, 0x61,
36     0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
37     0x65, 0x20, 0x66, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x41, 0x6c, 0x6c, 0x20,
38     0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6e,
39     0x64, 0x20, 0x6e, 0x6f, 0x74, 0x65, 0x64, 0x20, 0x72, 0x69, 0x64, 0x65,
40     0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
41     0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6e, 0x65, 0x61,
42     0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x61, 0x72, 0x0a, 0x48, 0x61,
43     0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61,
44     0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74,
45     0x65, 0x61, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x69, 0x67, 0x68,
46     0x74, 0x2c, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62,
47     0x75, 0x73, 0x68, 0x6d, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20,
48     0x68, 0x61, 0x72, 0x64, 0x20, 0x72, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x20,
49     0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
50     0x6c, 0x64, 0x20, 0x62, 0x75, 0x73, 0x68, 0x20, 0x68, 0x6f, 0x72, 0x73,
51     0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20,
52     0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x2d, 0x68, 0x6f,
53     0x72, 0x73, 0x65, 0x20, 0x73, 0x6e, 0x75, 0x66, 0x66, 0x73, 0x20, 0x74,
54     0x68, 0x65, 0x20, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x77, 0x69,
55     0x74, 0x68, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x00};
56 
57 static ArrayRef<char> BlockContent(BlockContentBytes);
58 
TEST(LinkGraphTest,Construction)59 TEST(LinkGraphTest, Construction) {
60   // Check that LinkGraph construction works as expected.
61   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
62               getGenericEdgeKindName);
63   EXPECT_EQ(G.getName(), "foo");
64   EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin");
65   EXPECT_EQ(G.getPointerSize(), 8U);
66   EXPECT_EQ(G.getEndianness(), support::little);
67   EXPECT_TRUE(llvm::empty(G.external_symbols()));
68   EXPECT_TRUE(llvm::empty(G.absolute_symbols()));
69   EXPECT_TRUE(llvm::empty(G.defined_symbols()));
70   EXPECT_TRUE(llvm::empty(G.blocks()));
71 }
72 
TEST(LinkGraphTest,AddressAccess)73 TEST(LinkGraphTest, AddressAccess) {
74   // Check that we can get addresses for blocks, symbols, and edges.
75   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
76               getGenericEdgeKindName);
77 
78   auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
79   orc::ExecutorAddr B1Addr(0x1000);
80   auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
81   auto &S1 = G.addDefinedSymbol(B1, 4, "S1", 4, Linkage::Strong, Scope::Default,
82                                 false, false);
83   B1.addEdge(Edge::FirstRelocation, 8, S1, 0);
84   auto &E1 = *B1.edges().begin();
85 
86   EXPECT_EQ(B1.getAddress(), B1Addr) << "Incorrect block address";
87   EXPECT_EQ(S1.getAddress(), B1Addr + 4) << "Incorrect symbol address";
88   EXPECT_EQ(B1.getFixupAddress(E1), B1Addr + 8) << "Incorrect fixup address";
89 }
90 
TEST(LinkGraphTest,BlockAndSymbolIteration)91 TEST(LinkGraphTest, BlockAndSymbolIteration) {
92   // Check that we can iterate over blocks within Sections and across sections.
93   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
94               getGenericEdgeKindName);
95   auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
96   orc::ExecutorAddr B1Addr(0x1000);
97   auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
98   orc::ExecutorAddr B2Addr(0x1000);
99   auto &B2 = G.createContentBlock(Sec1, BlockContent, B2Addr, 8, 0);
100   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
101                                 false, false);
102   auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default,
103                                 false, false);
104 
105   auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write);
106   orc::ExecutorAddr B3Addr(0x3000);
107   auto &B3 = G.createContentBlock(Sec2, BlockContent, B3Addr, 8, 0);
108   orc::ExecutorAddr B4Addr(0x4000);
109   auto &B4 = G.createContentBlock(Sec2, BlockContent, B4Addr, 8, 0);
110   auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default,
111                                 false, false);
112   auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default,
113                                 false, false);
114 
115   // Check that iteration of blocks within a section behaves as expected.
116   EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2);
117   EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1));
118   EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2));
119 
120   // Check that iteration of symbols within a section behaves as expected.
121   EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2);
122   EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1));
123   EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2));
124 
125   // Check that iteration of blocks across sections behaves as expected.
126   EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4);
127   EXPECT_TRUE(llvm::count(G.blocks(), &B1));
128   EXPECT_TRUE(llvm::count(G.blocks(), &B2));
129   EXPECT_TRUE(llvm::count(G.blocks(), &B3));
130   EXPECT_TRUE(llvm::count(G.blocks(), &B4));
131 
132   // Check that iteration of defined symbols across sections behaves as
133   // expected.
134   EXPECT_EQ(
135       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4);
136   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1));
137   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2));
138   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3));
139   EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4));
140 }
141 
TEST(LinkGraphTest,ContentAccessAndUpdate)142 TEST(LinkGraphTest, ContentAccessAndUpdate) {
143   // Check that we can make a defined symbol external.
144   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
145               getGenericEdgeKindName);
146   auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
147 
148   // Create an initial block.
149   orc::ExecutorAddr BAddr(0x1000);
150   auto &B = G.createContentBlock(Sec, BlockContent, BAddr, 8, 0);
151 
152   EXPECT_FALSE(B.isContentMutable()) << "Content unexpectedly mutable";
153   EXPECT_EQ(B.getContent().data(), BlockContent.data())
154       << "Unexpected block content data pointer";
155   EXPECT_EQ(B.getContent().size(), BlockContent.size())
156       << "Unexpected block content size";
157 
158   // Expect that attempting to get already-mutable content fails if the
159   // content is not yet mutable (debug builds only).
160 #ifndef NDEBUG
161   EXPECT_DEATH({ (void)B.getAlreadyMutableContent(); },
162                "Content is not mutable")
163       << "Unexpected mutable access allowed to immutable data";
164 #endif
165 
166   // Check that mutable content is copied on request as expected.
167   auto MutableContent = B.getMutableContent(G);
168   EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
169   EXPECT_NE(MutableContent.data(), BlockContent.data())
170       << "Unexpected mutable content data pointer";
171   EXPECT_EQ(MutableContent.size(), BlockContent.size())
172       << "Unexpected mutable content size";
173   EXPECT_TRUE(std::equal(MutableContent.begin(), MutableContent.end(),
174                          BlockContent.begin()))
175       << "Unexpected mutable content value";
176 
177   // Check that already-mutable content behaves as expected, with no
178   // further copies.
179   auto MutableContent2 = B.getMutableContent(G);
180   EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
181   EXPECT_EQ(MutableContent2.data(), MutableContent.data())
182       << "Unexpected mutable content 2 data pointer";
183   EXPECT_EQ(MutableContent2.size(), MutableContent.size())
184       << "Unexpected mutable content 2 size";
185 
186   // Check that getAlreadyMutableContent behaves as expected, with no
187   // further copies.
188   auto MutableContent3 = B.getMutableContent(G);
189   EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
190   EXPECT_EQ(MutableContent3.data(), MutableContent.data())
191       << "Unexpected mutable content 2 data pointer";
192   EXPECT_EQ(MutableContent3.size(), MutableContent.size())
193       << "Unexpected mutable content 2 size";
194 
195   // Set content back to immutable and check that everything behaves as
196   // expected again.
197   B.setContent(BlockContent);
198   EXPECT_FALSE(B.isContentMutable()) << "Content unexpectedly mutable";
199   EXPECT_EQ(B.getContent().data(), BlockContent.data())
200       << "Unexpected block content data pointer";
201   EXPECT_EQ(B.getContent().size(), BlockContent.size())
202       << "Unexpected block content size";
203 
204   // Create an initially mutable block.
205   auto &B2 = G.createMutableContentBlock(Sec, MutableContent,
206                                          orc::ExecutorAddr(0x10000), 8, 0);
207 
208   EXPECT_TRUE(B2.isContentMutable()) << "Expected B2 content to be mutable";
209 }
210 
TEST(LinkGraphTest,MakeExternal)211 TEST(LinkGraphTest, MakeExternal) {
212   // Check that we can make a defined symbol external.
213   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
214               getGenericEdgeKindName);
215   auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
216 
217   // Create an initial block.
218   auto &B1 =
219       G.createContentBlock(Sec, BlockContent, orc::ExecutorAddr(0x1000), 8, 0);
220 
221   // Add a symbol to the block.
222   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
223                                 false, false);
224 
225   EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
226   EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
227   EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
228   EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
229   EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000))
230       << "Unexpected symbol address";
231 
232   EXPECT_EQ(
233       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
234       << "Unexpected number of defined symbols";
235   EXPECT_EQ(
236       std::distance(G.external_symbols().begin(), G.external_symbols().end()),
237       0U)
238       << "Unexpected number of external symbols";
239 
240   // Make S1 external, confirm that the its flags are updated and that it is
241   // moved from the defined symbols to the externals list.
242   G.makeExternal(S1);
243 
244   EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
245   EXPECT_TRUE(S1.isExternal()) << "Symbol should be external";
246   EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
247   EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr())
248       << "Unexpected symbol address";
249 
250   EXPECT_EQ(
251       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
252       << "Unexpected number of defined symbols";
253   EXPECT_EQ(
254       std::distance(G.external_symbols().begin(), G.external_symbols().end()),
255       1U)
256       << "Unexpected number of external symbols";
257 }
258 
TEST(LinkGraphTest,MakeDefined)259 TEST(LinkGraphTest, MakeDefined) {
260   // Check that we can make an external symbol defined.
261   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
262               getGenericEdgeKindName);
263   auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
264 
265   // Create an initial block.
266   orc::ExecutorAddr B1Addr(0x1000);
267   auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0);
268 
269   // Add an external symbol.
270   auto &S1 = G.addExternalSymbol("S1", 4, Linkage::Strong);
271 
272   EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
273   EXPECT_TRUE(S1.isExternal()) << "Symbol should be external";
274   EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
275   EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr())
276       << "Unexpected symbol address";
277 
278   EXPECT_EQ(
279       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
280       << "Unexpected number of defined symbols";
281   EXPECT_EQ(
282       std::distance(G.external_symbols().begin(), G.external_symbols().end()),
283       1U)
284       << "Unexpected number of external symbols";
285 
286   // Make S1 defined, confirm that its flags are updated and that it is
287   // moved from the defined symbols to the externals list.
288   G.makeDefined(S1, B1, 0, 4, Linkage::Strong, Scope::Default, false);
289 
290   EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
291   EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
292   EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
293   EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
294   EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000U))
295       << "Unexpected symbol address";
296 
297   EXPECT_EQ(
298       std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
299       << "Unexpected number of defined symbols";
300   EXPECT_EQ(
301       std::distance(G.external_symbols().begin(), G.external_symbols().end()),
302       0U)
303       << "Unexpected number of external symbols";
304 }
305 
TEST(LinkGraphTest,TransferDefinedSymbol)306 TEST(LinkGraphTest, TransferDefinedSymbol) {
307   // Check that we can transfer a defined symbol from one block to another.
308   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
309               getGenericEdgeKindName);
310   auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
311 
312   // Create initial blocks.
313   orc::ExecutorAddr B1Addr(0x1000);
314   auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0);
315   orc::ExecutorAddr B2Addr(0x2000);
316   auto &B2 = G.createContentBlock(Sec, BlockContent, B2Addr, 8, 0);
317   orc::ExecutorAddr B3Addr(0x3000);
318   auto &B3 = G.createContentBlock(Sec, BlockContent.slice(0, 32), B3Addr, 8, 0);
319 
320   // Add a symbol.
321   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong,
322                                 Scope::Default, false, false);
323 
324   // Transfer with zero offset, explicit size.
325   G.transferDefinedSymbol(S1, B2, 0, 64);
326 
327   EXPECT_EQ(&S1.getBlock(), &B2) << "Block was not updated";
328   EXPECT_EQ(S1.getOffset(), 0U) << "Unexpected offset";
329   EXPECT_EQ(S1.getSize(), 64U) << "Size was not updated";
330 
331   // Transfer with non-zero offset, implicit truncation.
332   G.transferDefinedSymbol(S1, B3, 16, None);
333 
334   EXPECT_EQ(&S1.getBlock(), &B3) << "Block was not updated";
335   EXPECT_EQ(S1.getOffset(), 16U) << "Offset was not updated";
336   EXPECT_EQ(S1.getSize(), 16U) << "Size was not updated";
337 }
338 
TEST(LinkGraphTest,TransferDefinedSymbolAcrossSections)339 TEST(LinkGraphTest, TransferDefinedSymbolAcrossSections) {
340   // Check that we can transfer a defined symbol from an existing block in one
341   // section to another.
342   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
343               getGenericEdgeKindName);
344   auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
345   auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write);
346 
347   // Create blocks in each section.
348   orc::ExecutorAddr B1Addr(0x1000);
349   auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
350   orc::ExecutorAddr B2Addr(0x2000);
351   auto &B2 = G.createContentBlock(Sec2, BlockContent, B2Addr, 8, 0);
352 
353   // Add a symbol to section 1.
354   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong,
355                                 Scope::Default, false, false);
356 
357   // Transfer with zero offset, explicit size to section 2.
358   G.transferDefinedSymbol(S1, B2, 0, 64);
359 
360   EXPECT_EQ(&S1.getBlock(), &B2) << "Block was not updated";
361   EXPECT_EQ(S1.getOffset(), 0U) << "Unexpected offset";
362   EXPECT_EQ(S1.getSize(), 64U) << "Size was not updated";
363 
364   EXPECT_EQ(Sec1.symbols_size(), 0u) << "Symbol was not removed from Sec1";
365   EXPECT_EQ(Sec2.symbols_size(), 1u) << "Symbol was not added to Sec2";
366   if (Sec2.symbols_size() == 1) {
367     EXPECT_EQ(*Sec2.symbols().begin(), &S1) << "Unexpected symbol";
368   }
369 }
370 
TEST(LinkGraphTest,TransferBlock)371 TEST(LinkGraphTest, TransferBlock) {
372   // Check that we can transfer a block (and all associated symbols) from one
373   // section to another.
374   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
375               getGenericEdgeKindName);
376   auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
377   auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write);
378 
379   // Create an initial block.
380   orc::ExecutorAddr B1Addr(0x1000);
381   auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
382   orc::ExecutorAddr B2Addr(0x2000);
383   auto &B2 = G.createContentBlock(Sec1, BlockContent, B2Addr, 8, 0);
384 
385   // Add some symbols on B1...
386   G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong, Scope::Default,
387                      false, false);
388   G.addDefinedSymbol(B1, 1, "S2", B1.getSize() - 1, Linkage::Strong,
389                      Scope::Default, false, false);
390 
391   // ... and on B2.
392   G.addDefinedSymbol(B2, 0, "S3", B2.getSize(), Linkage::Strong, Scope::Default,
393                      false, false);
394   G.addDefinedSymbol(B2, 1, "S4", B2.getSize() - 1, Linkage::Strong,
395                      Scope::Default, false, false);
396 
397   EXPECT_EQ(Sec1.blocks_size(), 2U) << "Expected two blocks in Sec1 initially";
398   EXPECT_EQ(Sec1.symbols_size(), 4U)
399       << "Expected four symbols in Sec1 initially";
400   EXPECT_EQ(Sec2.blocks_size(), 0U) << "Expected zero blocks in Sec2 initially";
401   EXPECT_EQ(Sec2.symbols_size(), 0U)
402       << "Expected zero symbols in Sec2 initially";
403 
404   // Transfer with zero offset, explicit size.
405   G.transferBlock(B1, Sec2);
406 
407   EXPECT_EQ(Sec1.blocks_size(), 1U)
408       << "Expected one blocks in Sec1 after transfer";
409   EXPECT_EQ(Sec1.symbols_size(), 2U)
410       << "Expected two symbols in Sec1 after transfer";
411   EXPECT_EQ(Sec2.blocks_size(), 1U)
412       << "Expected one blocks in Sec2 after transfer";
413   EXPECT_EQ(Sec2.symbols_size(), 2U)
414       << "Expected two symbols in Sec2 after transfer";
415 }
416 
TEST(LinkGraphTest,MergeSections)417 TEST(LinkGraphTest, MergeSections) {
418   // Check that we can transfer a block (and all associated symbols) from one
419   // section to another.
420   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
421               getGenericEdgeKindName);
422   auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write);
423   auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write);
424   auto &Sec3 = G.createSection("__data.3", MemProt::Read | MemProt::Write);
425 
426   // Create an initial block.
427   orc::ExecutorAddr B1Addr(0x1000);
428   auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0);
429   orc::ExecutorAddr B2Addr(0x2000);
430   auto &B2 = G.createContentBlock(Sec2, BlockContent, B2Addr, 8, 0);
431   orc::ExecutorAddr B3Addr(0x3000);
432   auto &B3 = G.createContentBlock(Sec3, BlockContent, B3Addr, 8, 0);
433 
434   // Add a symbols for each block.
435   G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong, Scope::Default,
436                      false, false);
437   G.addDefinedSymbol(B2, 0, "S2", B2.getSize(), Linkage::Strong, Scope::Default,
438                      false, false);
439   G.addDefinedSymbol(B3, 0, "S3", B2.getSize(), Linkage::Strong, Scope::Default,
440                      false, false);
441 
442   EXPECT_EQ(&B1.getSection(), &Sec1);
443   EXPECT_EQ(&B2.getSection(), &Sec2);
444   EXPECT_EQ(G.sections_size(), 3U) << "Expected three sections initially";
445   EXPECT_EQ(Sec1.blocks_size(), 1U) << "Expected one block in Sec1 initially";
446   EXPECT_EQ(Sec1.symbols_size(), 1U) << "Expected one symbol in Sec1 initially";
447   EXPECT_EQ(Sec2.blocks_size(), 1U) << "Expected one block in Sec2 initially";
448   EXPECT_EQ(Sec2.symbols_size(), 1U) << "Expected one symbol in Sec2 initially";
449   EXPECT_EQ(Sec3.blocks_size(), 1U) << "Expected one block in Sec3 initially";
450   EXPECT_EQ(Sec3.symbols_size(), 1U) << "Expected one symbol in Sec3 initially";
451 
452   // Check that self-merge is a no-op.
453   G.mergeSections(Sec1, Sec1);
454 
455   EXPECT_EQ(&B1.getSection(), &Sec1)
456       << "Expected B1.getSection() to remain unchanged";
457   EXPECT_EQ(G.sections_size(), 3U)
458       << "Expected three sections after first merge";
459   EXPECT_EQ(Sec1.blocks_size(), 1U)
460       << "Expected one block in Sec1 after first merge";
461   EXPECT_EQ(Sec1.symbols_size(), 1U)
462       << "Expected one symbol in Sec1 after first merge";
463   EXPECT_EQ(Sec2.blocks_size(), 1U)
464       << "Expected one block in Sec2 after first merge";
465   EXPECT_EQ(Sec2.symbols_size(), 1U)
466       << "Expected one symbol in Sec2 after first merge";
467   EXPECT_EQ(Sec3.blocks_size(), 1U)
468       << "Expected one block in Sec3 after first merge";
469   EXPECT_EQ(Sec3.symbols_size(), 1U)
470       << "Expected one symbol in Sec3 after first merge";
471 
472   // Merge Sec2 into Sec1, removing Sec2.
473   G.mergeSections(Sec1, Sec2);
474 
475   EXPECT_EQ(&B2.getSection(), &Sec1)
476       << "Expected B2.getSection() to have been changed to &Sec1";
477   EXPECT_EQ(G.sections_size(), 2U)
478       << "Expected two sections after section merge";
479   EXPECT_EQ(Sec1.blocks_size(), 2U)
480       << "Expected two blocks in Sec1 after section merge";
481   EXPECT_EQ(Sec1.symbols_size(), 2U)
482       << "Expected two symbols in Sec1 after section merge";
483   EXPECT_EQ(Sec3.blocks_size(), 1U)
484       << "Expected one block in Sec3 after section merge";
485   EXPECT_EQ(Sec3.symbols_size(), 1U)
486       << "Expected one symbol in Sec3 after section merge";
487 
488   G.mergeSections(Sec1, Sec3, true);
489 
490   EXPECT_EQ(G.sections_size(), 2U) << "Expected two sections after third merge";
491   EXPECT_EQ(Sec1.blocks_size(), 3U)
492       << "Expected three blocks in Sec1 after third merge";
493   EXPECT_EQ(Sec1.symbols_size(), 3U)
494       << "Expected three symbols in Sec1 after third merge";
495   EXPECT_EQ(Sec3.blocks_size(), 0U)
496       << "Expected one block in Sec3 after third merge";
497   EXPECT_EQ(Sec3.symbols_size(), 0U)
498       << "Expected one symbol in Sec3 after third merge";
499 }
500 
TEST(LinkGraphTest,SplitBlock)501 TEST(LinkGraphTest, SplitBlock) {
502   // Check that the LinkGraph::splitBlock test works as expected.
503   LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little,
504               getGenericEdgeKindName);
505   auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write);
506 
507   // Create the block to split.
508   orc::ExecutorAddr B1Addr(0x1000);
509   auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0);
510 
511   // Add some symbols to the block.
512   auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default,
513                                 false, false);
514   auto &S2 = G.addDefinedSymbol(B1, 4, "S2", 4, Linkage::Strong, Scope::Default,
515                                 false, false);
516   auto &S3 = G.addDefinedSymbol(B1, 8, "S3", 4, Linkage::Strong, Scope::Default,
517                                 false, false);
518   auto &S4 = G.addDefinedSymbol(B1, 12, "S4", 4, Linkage::Strong,
519                                 Scope::Default, false, false);
520   // Add a symbol that extends beyond the split.
521   auto &S5 = G.addDefinedSymbol(B1, 0, "S5", 16, Linkage::Strong,
522                                 Scope::Default, false, false);
523 
524   // Add an extra block, EB, and target symbols, and use these to add edges
525   // from B1 to EB.
526   orc::ExecutorAddr EBAddr(0x2000);
527   auto &EB = G.createContentBlock(Sec, BlockContent, EBAddr, 8, 0);
528   auto &ES1 = G.addDefinedSymbol(EB, 0, "TS1", 4, Linkage::Strong,
529                                  Scope::Default, false, false);
530   auto &ES2 = G.addDefinedSymbol(EB, 4, "TS2", 4, Linkage::Strong,
531                                  Scope::Default, false, false);
532   auto &ES3 = G.addDefinedSymbol(EB, 8, "TS3", 4, Linkage::Strong,
533                                  Scope::Default, false, false);
534   auto &ES4 = G.addDefinedSymbol(EB, 12, "TS4", 4, Linkage::Strong,
535                                  Scope::Default, false, false);
536 
537   // Add edges from B1 to EB.
538   B1.addEdge(Edge::FirstRelocation, 0, ES1, 0);
539   B1.addEdge(Edge::FirstRelocation, 4, ES2, 0);
540   B1.addEdge(Edge::FirstRelocation, 8, ES3, 0);
541   B1.addEdge(Edge::FirstRelocation, 12, ES4, 0);
542 
543   // Split B1.
544   auto &B2 = G.splitBlock(B1, 8);
545 
546   // Check that the block addresses and content matches what we would expect.
547   EXPECT_EQ(B1.getAddress(), B1Addr + 8);
548   EXPECT_EQ(B1.getContent(), BlockContent.slice(8));
549 
550   EXPECT_EQ(B2.getAddress(), B1Addr);
551   EXPECT_EQ(B2.getContent(), BlockContent.slice(0, 8));
552 
553   // Check that symbols in B1 were transferred as expected:
554   // We expect S1 and S2 to have been transferred to B2, and S3 and S4 to have
555   // remained attached to B1. Symbols S3 and S4 should have had their offsets
556   // slid to account for the change in address of B2.
557   EXPECT_EQ(&S1.getBlock(), &B2);
558   EXPECT_EQ(S1.getOffset(), 0U);
559 
560   EXPECT_EQ(&S2.getBlock(), &B2);
561   EXPECT_EQ(S2.getOffset(), 4U);
562 
563   EXPECT_EQ(&S3.getBlock(), &B1);
564   EXPECT_EQ(S3.getOffset(), 0U);
565 
566   EXPECT_EQ(&S4.getBlock(), &B1);
567   EXPECT_EQ(S4.getOffset(), 4U);
568 
569   EXPECT_EQ(&S5.getBlock(), &B2);
570   EXPECT_EQ(S5.getOffset(), 0U);
571   // Size shrinks to fit.
572   EXPECT_EQ(S5.getSize(), 8U);
573 
574   // Check that edges in B1 have been transferred as expected:
575   // Both blocks should now have two edges each at offsets 0 and 4.
576   EXPECT_EQ(llvm::size(B1.edges()), 2);
577   if (size(B1.edges()) == 2) {
578     auto *E1 = &*B1.edges().begin();
579     auto *E2 = &*(B1.edges().begin() + 1);
580     if (E2->getOffset() < E1->getOffset())
581       std::swap(E1, E2);
582     EXPECT_EQ(E1->getOffset(), 0U);
583     EXPECT_EQ(E2->getOffset(), 4U);
584   }
585 
586   EXPECT_EQ(llvm::size(B2.edges()), 2);
587   if (size(B2.edges()) == 2) {
588     auto *E1 = &*B2.edges().begin();
589     auto *E2 = &*(B2.edges().begin() + 1);
590     if (E2->getOffset() < E1->getOffset())
591       std::swap(E1, E2);
592     EXPECT_EQ(E1->getOffset(), 0U);
593     EXPECT_EQ(E2->getOffset(), 4U);
594   }
595 }
596