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