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