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/ExecutionEngine/Orc/ObjectFileInterface.h"
12#include "llvm/Support/Memory.h"
13
14#include "llvm/Testing/Support/Error.h"
15#include "gtest/gtest.h"
16
17using namespace llvm;
18using namespace llvm::jitlink;
19
20static const char BlockContentBytes[] = {
21 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x6f,
22 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68,
23 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x66,
24 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20,
25 0x68, 0x61, 0x64, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x61,
26 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74,
27 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6c, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d,
28 0x20, 0x4f, 0x6c, 0x64, 0x20, 0x52, 0x65, 0x67, 0x72, 0x65, 0x74, 0x20,
29 0x68, 0x61, 0x64, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x61, 0x77, 0x61, 0x79,
30 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6a, 0x6f,
31 0x69, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c,
32 0x64, 0x20, 0x62, 0x75, 0x73, 0x68, 0x20, 0x68, 0x6f, 0x72, 0x73, 0x65,
33 0x73, 0x20, 0x2d, 0x2d, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20,
34 0x77, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x74, 0x68, 0x6f, 0x75,
35 0x73, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x0a,
36 0x53, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63,
37 0x72, 0x61, 0x63, 0x6b, 0x73, 0x20, 0x68, 0x61, 0x64, 0x20, 0x67, 0x61,
38 0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
39 0x65, 0x20, 0x66, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x41, 0x6c, 0x6c, 0x20,
40 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6e,
41 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x65, 0x64, 0x20, 0x72, 0x69, 0x64, 0x65,
42 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20,
43 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6e, 0x65, 0x61,
44 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x61, 0x72, 0x0a, 0x48, 0x61,
45 0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61,
46 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74,
47 0x65, 0x61, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x69, 0x67, 0x68,
48 0x74, 0x2c, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62,
49 0x75, 0x73, 0x68, 0x6d, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20,
50 0x68, 0x61, 0x72, 0x64, 0x20, 0x72, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x20,
51 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
52 0x6c, 0x64, 0x20, 0x62, 0x75, 0x73, 0x68, 0x20, 0x68, 0x6f, 0x72, 0x73,
53 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20,
54 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x2d, 0x68, 0x6f,
55 0x72, 0x73, 0x65, 0x20, 0x73, 0x6e, 0x75, 0x66, 0x66, 0x73, 0x20, 0x74,
56 0x68, 0x65, 0x20, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x77, 0x69,
57 0x74, 0x68, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x00};
58
59static ArrayRef<char> BlockContent(BlockContentBytes);
60
61TEST(LinkGraphTest, Construction) {
62 // Check that LinkGraph construction works as expected.
63 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
64 getGenericEdgeKindName);
65 EXPECT_EQ(G.getName(), "foo");
66 EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin");
67 EXPECT_EQ(G.getPointerSize(), 8U);
68 EXPECT_EQ(G.getEndianness(), llvm::endianness::little);
69 EXPECT_TRUE(G.external_symbols().empty());
70 EXPECT_TRUE(G.absolute_symbols().empty());
71 EXPECT_TRUE(G.defined_symbols().empty());
72 EXPECT_TRUE(G.blocks().empty());
73}
74
75TEST(LinkGraphTest, AddressAccess) {
76 // Check that we can get addresses for blocks, symbols, and edges.
77 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
78 getGenericEdgeKindName);
79
80 auto &Sec1 =
81 G.createSection(Name: "__data.1", Prot: orc::MemProt::Read | orc::MemProt::Write);
82 orc::ExecutorAddr B1Addr(0x1000);
83 auto &B1 = G.createContentBlock(Parent&: Sec1, Content: BlockContent, Address: B1Addr, Alignment: 8, AlignmentOffset: 0);
84 auto &S1 = G.addDefinedSymbol(Content&: B1, Offset: 4, Name: "S1", Size: 4, L: Linkage::Strong, S: Scope::Default,
85 IsCallable: false, IsLive: false);
86 B1.addEdge(K: Edge::FirstRelocation, Offset: 8, Target&: S1, Addend: 0);
87 auto &E1 = *B1.edges().begin();
88
89 EXPECT_EQ(B1.getAddress(), B1Addr) << "Incorrect block address";
90 EXPECT_EQ(S1.getAddress(), B1Addr + 4) << "Incorrect symbol address";
91 EXPECT_EQ(B1.getFixupAddress(E1), B1Addr + 8) << "Incorrect fixup address";
92}
93
94TEST(LinkGraphTest, SectionEmpty) {
95 // Check that Section::empty behaves as expected.
96 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
97 getGenericEdgeKindName);
98 auto &Sec1 =
99 G.createSection(Name: "__data.1", Prot: orc::MemProt::Read | orc::MemProt::Write);
100 auto &B =
101 G.createContentBlock(Parent&: Sec1, Content: BlockContent, Address: orc::ExecutorAddr(0x1000), Alignment: 8, AlignmentOffset: 0);
102 G.addDefinedSymbol(Content&: B, Offset: 0, Name: "S", Size: 4, L: Linkage::Strong, S: Scope::Default, IsCallable: false,
103 IsLive: false);
104
105 auto &Sec2 =
106 G.createSection(Name: "__data.2", Prot: orc::MemProt::Read | orc::MemProt::Write);
107
108 EXPECT_FALSE(Sec1.empty());
109 EXPECT_TRUE(Sec2.empty());
110}
111
112TEST(LinkGraphTest, BlockAndSymbolIteration) {
113 // Check that we can iterate over blocks within Sections and across sections.
114 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
115 getGenericEdgeKindName);
116 auto &Sec1 =
117 G.createSection(Name: "__data.1", Prot: orc::MemProt::Read | orc::MemProt::Write);
118 orc::ExecutorAddr B1Addr(0x1000);
119 auto &B1 = G.createContentBlock(Parent&: Sec1, Content: BlockContent, Address: B1Addr, Alignment: 8, AlignmentOffset: 0);
120 orc::ExecutorAddr B2Addr(0x2000);
121 auto &B2 = G.createContentBlock(Parent&: Sec1, Content: BlockContent, Address: B2Addr, Alignment: 8, AlignmentOffset: 0);
122 auto &S1 = G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S1", Size: 4, L: Linkage::Strong, S: Scope::Default,
123 IsCallable: false, IsLive: false);
124 auto &S2 = G.addDefinedSymbol(Content&: B2, Offset: 4, Name: "S2", Size: 4, L: Linkage::Strong, S: Scope::Default,
125 IsCallable: false, IsLive: false);
126
127 auto &Sec2 =
128 G.createSection(Name: "__data.2", Prot: orc::MemProt::Read | orc::MemProt::Write);
129 orc::ExecutorAddr B3Addr(0x3000);
130 auto &B3 = G.createContentBlock(Parent&: Sec2, Content: BlockContent, Address: B3Addr, Alignment: 8, AlignmentOffset: 0);
131 orc::ExecutorAddr B4Addr(0x4000);
132 auto &B4 = G.createContentBlock(Parent&: Sec2, Content: BlockContent, Address: B4Addr, Alignment: 8, AlignmentOffset: 0);
133 auto &S3 = G.addDefinedSymbol(Content&: B3, Offset: 0, Name: "S3", Size: 4, L: Linkage::Strong, S: Scope::Default,
134 IsCallable: false, IsLive: false);
135 auto &S4 = G.addDefinedSymbol(Content&: B4, Offset: 4, Name: "S4", Size: 4, L: Linkage::Strong, S: Scope::Default,
136 IsCallable: false, IsLive: false);
137
138 // Check that iteration of blocks within a section behaves as expected.
139 EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2);
140 EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1));
141 EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2));
142
143 // Check that iteration of symbols within a section behaves as expected.
144 EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2);
145 EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1));
146 EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2));
147
148 // Check that iteration of blocks across sections behaves as expected.
149 EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4);
150 EXPECT_TRUE(llvm::count(G.blocks(), &B1));
151 EXPECT_TRUE(llvm::count(G.blocks(), &B2));
152 EXPECT_TRUE(llvm::count(G.blocks(), &B3));
153 EXPECT_TRUE(llvm::count(G.blocks(), &B4));
154
155 // Check that iteration of defined symbols across sections behaves as
156 // expected.
157 EXPECT_EQ(
158 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4);
159 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1));
160 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2));
161 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3));
162 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4));
163}
164
165TEST(LinkGraphTest, ContentAccessAndUpdate) {
166 // Check that we can make a defined symbol external.
167 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
168 getGenericEdgeKindName);
169 auto &Sec =
170 G.createSection(Name: "__data", Prot: orc::MemProt::Read | orc::MemProt::Write);
171
172 // Create an initial block.
173 orc::ExecutorAddr BAddr(0x1000);
174 auto &B = G.createContentBlock(Parent&: Sec, Content: BlockContent, Address: BAddr, Alignment: 8, AlignmentOffset: 0);
175
176 EXPECT_FALSE(B.isContentMutable()) << "Content unexpectedly mutable";
177 EXPECT_EQ(B.getContent().data(), BlockContent.data())
178 << "Unexpected block content data pointer";
179 EXPECT_EQ(B.getContent().size(), BlockContent.size())
180 << "Unexpected block content size";
181
182 // Expect that attempting to get already-mutable content fails if the
183 // content is not yet mutable (debug builds only).
184#ifndef NDEBUG
185 EXPECT_DEATH({ (void)B.getAlreadyMutableContent(); },
186 "Content is not mutable")
187 << "Unexpected mutable access allowed to immutable data";
188#endif
189
190 // Check that mutable content is copied on request as expected.
191 auto MutableContent = B.getMutableContent(G);
192 EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
193 EXPECT_NE(MutableContent.data(), BlockContent.data())
194 << "Unexpected mutable content data pointer";
195 EXPECT_EQ(MutableContent.size(), BlockContent.size())
196 << "Unexpected mutable content size";
197 EXPECT_TRUE(std::equal(MutableContent.begin(), MutableContent.end(),
198 BlockContent.begin()))
199 << "Unexpected mutable content value";
200
201 // Check that already-mutable content behaves as expected, with no
202 // further copies.
203 auto MutableContent2 = B.getMutableContent(G);
204 EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
205 EXPECT_EQ(MutableContent2.data(), MutableContent.data())
206 << "Unexpected mutable content 2 data pointer";
207 EXPECT_EQ(MutableContent2.size(), MutableContent.size())
208 << "Unexpected mutable content 2 size";
209
210 // Check that getAlreadyMutableContent behaves as expected, with no
211 // further copies.
212 auto MutableContent3 = B.getMutableContent(G);
213 EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable";
214 EXPECT_EQ(MutableContent3.data(), MutableContent.data())
215 << "Unexpected mutable content 2 data pointer";
216 EXPECT_EQ(MutableContent3.size(), MutableContent.size())
217 << "Unexpected mutable content 2 size";
218
219 // Check that we can obtain a writer and reader over the content.
220 // Check that we can get a BinaryStreamReader for B.
221 auto Writer = G.getBlockContentWriter(B);
222 EXPECT_THAT_ERROR(Writer.writeInteger((uint32_t)0xcafef00d), Succeeded());
223
224 auto Reader = G.getBlockContentReader(B);
225 uint32_t Initial32Bits = 0;
226 EXPECT_THAT_ERROR(Reader.readInteger(Initial32Bits), Succeeded());
227 EXPECT_EQ(Initial32Bits, (uint32_t)0xcafef00d);
228
229 // Set content back to immutable and check that everything behaves as
230 // expected again.
231 B.setContent(BlockContent);
232 EXPECT_FALSE(B.isContentMutable()) << "Content unexpectedly mutable";
233 EXPECT_EQ(B.getContent().data(), BlockContent.data())
234 << "Unexpected block content data pointer";
235 EXPECT_EQ(B.getContent().size(), BlockContent.size())
236 << "Unexpected block content size";
237
238 // Create an initially mutable block.
239 auto &B2 = G.createMutableContentBlock(Parent&: Sec, MutableContent,
240 Address: orc::ExecutorAddr(0x10000), Alignment: 8, AlignmentOffset: 0);
241
242 EXPECT_TRUE(B2.isContentMutable()) << "Expected B2 content to be mutable";
243 EXPECT_EQ(B2.getSize(), MutableContent.size());
244
245 // Create a mutable content block with initial zero-fill.
246 auto &B3 =
247 G.createMutableContentBlock(Parent&: Sec, ContentSize: 16, Address: orc::ExecutorAddr(0x2000), Alignment: 8, AlignmentOffset: 0);
248 EXPECT_TRUE(B3.isContentMutable()) << "Expected B2 content to be mutable";
249 EXPECT_EQ(B3.getSize(), 16U);
250 EXPECT_TRUE(llvm::all_of(B3.getAlreadyMutableContent(),
251 [](char C) { return C == 0; }));
252}
253
254TEST(LinkGraphTest, MakeExternal) {
255 // Check that we can make defined and absolute symbols external.
256 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
257 getGenericEdgeKindName);
258 auto &Sec =
259 G.createSection(Name: "__data", Prot: orc::MemProt::Read | orc::MemProt::Write);
260
261 // Create an initial block.
262 auto &B1 =
263 G.createContentBlock(Parent&: Sec, Content: BlockContent, Address: orc::ExecutorAddr(0x1000), Alignment: 8, AlignmentOffset: 0);
264
265 // Add a symbol to the block.
266 auto &S1 = G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S1", Size: 4, L: Linkage::Strong, S: Scope::Default,
267 IsCallable: false, IsLive: false);
268
269 EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
270 EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
271 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
272 EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
273 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000))
274 << "Unexpected symbol address";
275
276 EXPECT_EQ(
277 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
278 << "Unexpected number of defined symbols";
279 EXPECT_EQ(
280 std::distance(G.external_symbols().begin(), G.external_symbols().end()),
281 0U)
282 << "Unexpected number of external symbols";
283
284 // Add an absolute symbol.
285 auto &S2 = G.addAbsoluteSymbol(Name: "S2", Address: orc::ExecutorAddr(0x2000), Size: 0,
286 L: Linkage::Strong, S: Scope::Default, IsLive: true);
287
288 EXPECT_TRUE(S2.isAbsolute()) << "Symbol should be absolute";
289 EXPECT_EQ(
290 std::distance(G.absolute_symbols().begin(), G.absolute_symbols().end()),
291 1U)
292 << "Unexpected number of symbols";
293
294 // Make S1 and S2 external, confirm that the its flags are updated and that it
295 // is moved from the defined/absolute symbols lists to the externals list.
296 G.makeExternal(Sym&: S1);
297 G.makeExternal(Sym&: S2);
298
299 EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
300 EXPECT_TRUE(S1.isExternal()) << "Symbol should be external";
301 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
302 EXPECT_FALSE(S2.isDefined()) << "Symbol should not be defined";
303 EXPECT_TRUE(S2.isExternal()) << "Symbol should be external";
304 EXPECT_FALSE(S2.isAbsolute()) << "Symbol should not be absolute";
305
306 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr())
307 << "Unexpected symbol address";
308 EXPECT_EQ(S2.getAddress(), orc::ExecutorAddr())
309 << "Unexpected symbol address";
310
311 EXPECT_EQ(
312 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
313 << "Unexpected number of defined symbols";
314 EXPECT_EQ(
315 std::distance(G.external_symbols().begin(), G.external_symbols().end()),
316 2U)
317 << "Unexpected number of external symbols";
318 EXPECT_EQ(
319 std::distance(G.absolute_symbols().begin(), G.absolute_symbols().end()),
320 0U)
321 << "Unexpected number of external symbols";
322}
323
324TEST(LinkGraphTest, MakeAbsolute) {
325 // Check that we can make defined and external symbols absolute.
326 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
327 getGenericEdgeKindName);
328 auto &Sec =
329 G.createSection(Name: "__data", Prot: orc::MemProt::Read | orc::MemProt::Write);
330
331 // Create an initial block.
332 auto &B1 =
333 G.createContentBlock(Parent&: Sec, Content: BlockContent, Address: orc::ExecutorAddr(0x1000), Alignment: 8, AlignmentOffset: 0);
334
335 // Add a symbol to the block.
336 auto &S1 = G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S1", Size: 4, L: Linkage::Strong, S: Scope::Default,
337 IsCallable: false, IsLive: false);
338
339 EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
340 EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
341 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
342 EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
343 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000))
344 << "Unexpected symbol address";
345
346 EXPECT_EQ(
347 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
348 << "Unexpected number of defined symbols";
349 EXPECT_EQ(
350 std::distance(G.external_symbols().begin(), G.external_symbols().end()),
351 0U)
352 << "Unexpected number of external symbols";
353
354 // Add an external symbol.
355 auto &S2 = G.addExternalSymbol(Name: "S2", Size: 0, IsWeaklyReferenced: true);
356
357 EXPECT_TRUE(S2.isExternal()) << "Symbol should be external";
358 EXPECT_EQ(
359 std::distance(G.external_symbols().begin(), G.external_symbols().end()),
360 1U)
361 << "Unexpected number of symbols";
362
363 // Make S1 and S2 absolute, confirm that the its flags are updated and that it
364 // is moved from the defined/external symbols lists to the absolutes list.
365 orc::ExecutorAddr S1AbsAddr(0xA000);
366 orc::ExecutorAddr S2AbsAddr(0xB000);
367 G.makeAbsolute(Sym&: S1, Address: S1AbsAddr);
368 G.makeAbsolute(Sym&: S2, Address: S2AbsAddr);
369
370 EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
371 EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
372 EXPECT_TRUE(S1.isAbsolute()) << "Symbol should be absolute";
373 EXPECT_FALSE(S2.isDefined()) << "Symbol should not be defined";
374 EXPECT_FALSE(S2.isExternal()) << "Symbol should not be absolute";
375 EXPECT_TRUE(S2.isAbsolute()) << "Symbol should be absolute";
376
377 EXPECT_EQ(S1.getAddress(), S1AbsAddr) << "Unexpected symbol address";
378 EXPECT_EQ(S2.getAddress(), S2AbsAddr) << "Unexpected symbol address";
379
380 EXPECT_EQ(
381 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
382 << "Unexpected number of defined symbols";
383 EXPECT_EQ(
384 std::distance(G.external_symbols().begin(), G.external_symbols().end()),
385 0U)
386 << "Unexpected number of external symbols";
387 EXPECT_EQ(
388 std::distance(G.absolute_symbols().begin(), G.absolute_symbols().end()),
389 2U)
390 << "Unexpected number of external symbols";
391}
392
393TEST(LinkGraphTest, MakeDefined) {
394 // Check that we can make an external symbol defined.
395 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
396 getGenericEdgeKindName);
397 auto &Sec =
398 G.createSection(Name: "__data", Prot: orc::MemProt::Read | orc::MemProt::Write);
399
400 // Create an initial block.
401 orc::ExecutorAddr B1Addr(0x1000);
402 auto &B1 = G.createContentBlock(Parent&: Sec, Content: BlockContent, Address: B1Addr, Alignment: 8, AlignmentOffset: 0);
403
404 // Add an external symbol.
405 auto &S1 = G.addExternalSymbol(Name: "S1", Size: 4, IsWeaklyReferenced: true);
406
407 EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined";
408 EXPECT_TRUE(S1.isExternal()) << "Symbol should be external";
409 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
410 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr())
411 << "Unexpected symbol address";
412
413 EXPECT_EQ(
414 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U)
415 << "Unexpected number of defined symbols";
416 EXPECT_EQ(
417 std::distance(G.external_symbols().begin(), G.external_symbols().end()),
418 1U)
419 << "Unexpected number of external symbols";
420
421 // Make S1 defined, confirm that its flags are updated and that it is
422 // moved from the defined symbols to the externals list.
423 G.makeDefined(Sym&: S1, Content&: B1, Offset: 0, Size: 4, L: Linkage::Strong, S: Scope::Default, IsLive: false);
424
425 EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined";
426 EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external";
427 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute";
428 EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block";
429 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000U))
430 << "Unexpected symbol address";
431
432 EXPECT_EQ(
433 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U)
434 << "Unexpected number of defined symbols";
435 EXPECT_EQ(
436 std::distance(G.external_symbols().begin(), G.external_symbols().end()),
437 0U)
438 << "Unexpected number of external symbols";
439}
440
441TEST(LinkGraphTest, TransferDefinedSymbol) {
442 // Check that we can transfer a defined symbol from one block to another.
443 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
444 getGenericEdgeKindName);
445 auto &Sec =
446 G.createSection(Name: "__data", Prot: orc::MemProt::Read | orc::MemProt::Write);
447
448 // Create initial blocks.
449 orc::ExecutorAddr B1Addr(0x1000);
450 auto &B1 = G.createContentBlock(Parent&: Sec, Content: BlockContent, Address: B1Addr, Alignment: 8, AlignmentOffset: 0);
451 orc::ExecutorAddr B2Addr(0x2000);
452 auto &B2 = G.createContentBlock(Parent&: Sec, Content: BlockContent, Address: B2Addr, Alignment: 8, AlignmentOffset: 0);
453 orc::ExecutorAddr B3Addr(0x3000);
454 auto &B3 = G.createContentBlock(Parent&: Sec, Content: BlockContent.slice(N: 0, M: 32), Address: B3Addr, Alignment: 8, AlignmentOffset: 0);
455
456 // Add a symbol.
457 auto &S1 = G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S1", Size: B1.getSize(), L: Linkage::Strong,
458 S: Scope::Default, IsCallable: false, IsLive: false);
459
460 // Transfer with zero offset, explicit size.
461 G.transferDefinedSymbol(Sym&: S1, DestBlock&: B2, NewOffset: 0, ExplicitNewSize: 64);
462
463 EXPECT_EQ(&S1.getBlock(), &B2) << "Block was not updated";
464 EXPECT_EQ(S1.getOffset(), 0U) << "Unexpected offset";
465 EXPECT_EQ(S1.getSize(), 64U) << "Size was not updated";
466
467 // Transfer with non-zero offset, implicit truncation.
468 G.transferDefinedSymbol(Sym&: S1, DestBlock&: B3, NewOffset: 16, ExplicitNewSize: std::nullopt);
469
470 EXPECT_EQ(&S1.getBlock(), &B3) << "Block was not updated";
471 EXPECT_EQ(S1.getOffset(), 16U) << "Offset was not updated";
472 EXPECT_EQ(S1.getSize(), 16U) << "Size was not updated";
473}
474
475TEST(LinkGraphTest, TransferDefinedSymbolAcrossSections) {
476 // Check that we can transfer a defined symbol from an existing block in one
477 // section to another.
478 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
479 getGenericEdgeKindName);
480 auto &Sec1 =
481 G.createSection(Name: "__data.1", Prot: orc::MemProt::Read | orc::MemProt::Write);
482 auto &Sec2 =
483 G.createSection(Name: "__data.2", Prot: orc::MemProt::Read | orc::MemProt::Write);
484
485 // Create blocks in each section.
486 orc::ExecutorAddr B1Addr(0x1000);
487 auto &B1 = G.createContentBlock(Parent&: Sec1, Content: BlockContent, Address: B1Addr, Alignment: 8, AlignmentOffset: 0);
488 orc::ExecutorAddr B2Addr(0x2000);
489 auto &B2 = G.createContentBlock(Parent&: Sec2, Content: BlockContent, Address: B2Addr, Alignment: 8, AlignmentOffset: 0);
490
491 // Add a symbol to section 1.
492 auto &S1 = G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S1", Size: B1.getSize(), L: Linkage::Strong,
493 S: Scope::Default, IsCallable: false, IsLive: false);
494
495 // Transfer with zero offset, explicit size to section 2.
496 G.transferDefinedSymbol(Sym&: S1, DestBlock&: B2, NewOffset: 0, ExplicitNewSize: 64);
497
498 EXPECT_EQ(&S1.getBlock(), &B2) << "Block was not updated";
499 EXPECT_EQ(S1.getOffset(), 0U) << "Unexpected offset";
500 EXPECT_EQ(S1.getSize(), 64U) << "Size was not updated";
501
502 EXPECT_EQ(Sec1.symbols_size(), 0u) << "Symbol was not removed from Sec1";
503 EXPECT_EQ(Sec2.symbols_size(), 1u) << "Symbol was not added to Sec2";
504 if (Sec2.symbols_size() == 1) {
505 EXPECT_EQ(*Sec2.symbols().begin(), &S1) << "Unexpected symbol";
506 }
507}
508
509TEST(LinkGraphTest, TransferBlock) {
510 // Check that we can transfer a block (and all associated symbols) from one
511 // section to another.
512 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
513 getGenericEdgeKindName);
514 auto &Sec1 =
515 G.createSection(Name: "__data.1", Prot: orc::MemProt::Read | orc::MemProt::Write);
516 auto &Sec2 =
517 G.createSection(Name: "__data.2", Prot: orc::MemProt::Read | orc::MemProt::Write);
518
519 // Create an initial block.
520 orc::ExecutorAddr B1Addr(0x1000);
521 auto &B1 = G.createContentBlock(Parent&: Sec1, Content: BlockContent, Address: B1Addr, Alignment: 8, AlignmentOffset: 0);
522 orc::ExecutorAddr B2Addr(0x2000);
523 auto &B2 = G.createContentBlock(Parent&: Sec1, Content: BlockContent, Address: B2Addr, Alignment: 8, AlignmentOffset: 0);
524
525 // Add some symbols on B1...
526 G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S1", Size: B1.getSize(), L: Linkage::Strong, S: Scope::Default,
527 IsCallable: false, IsLive: false);
528 G.addDefinedSymbol(Content&: B1, Offset: 1, Name: "S2", Size: B1.getSize() - 1, L: Linkage::Strong,
529 S: Scope::Default, IsCallable: false, IsLive: false);
530
531 // ... and on B2.
532 G.addDefinedSymbol(Content&: B2, Offset: 0, Name: "S3", Size: B2.getSize(), L: Linkage::Strong, S: Scope::Default,
533 IsCallable: false, IsLive: false);
534 G.addDefinedSymbol(Content&: B2, Offset: 1, Name: "S4", Size: B2.getSize() - 1, L: Linkage::Strong,
535 S: Scope::Default, IsCallable: false, IsLive: false);
536
537 EXPECT_EQ(Sec1.blocks_size(), 2U) << "Expected two blocks in Sec1 initially";
538 EXPECT_EQ(Sec1.symbols_size(), 4U)
539 << "Expected four symbols in Sec1 initially";
540 EXPECT_EQ(Sec2.blocks_size(), 0U) << "Expected zero blocks in Sec2 initially";
541 EXPECT_EQ(Sec2.symbols_size(), 0U)
542 << "Expected zero symbols in Sec2 initially";
543
544 // Transfer with zero offset, explicit size.
545 G.transferBlock(B&: B1, NewSection&: Sec2);
546
547 EXPECT_EQ(Sec1.blocks_size(), 1U)
548 << "Expected one blocks in Sec1 after transfer";
549 EXPECT_EQ(Sec1.symbols_size(), 2U)
550 << "Expected two symbols in Sec1 after transfer";
551 EXPECT_EQ(Sec2.blocks_size(), 1U)
552 << "Expected one blocks in Sec2 after transfer";
553 EXPECT_EQ(Sec2.symbols_size(), 2U)
554 << "Expected two symbols in Sec2 after transfer";
555}
556
557TEST(LinkGraphTest, MergeSections) {
558 // Check that we can transfer a block (and all associated symbols) from one
559 // section to another.
560 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
561 getGenericEdgeKindName);
562 auto &Sec1 =
563 G.createSection(Name: "__data.1", Prot: orc::MemProt::Read | orc::MemProt::Write);
564 auto &Sec2 =
565 G.createSection(Name: "__data.2", Prot: orc::MemProt::Read | orc::MemProt::Write);
566 auto &Sec3 =
567 G.createSection(Name: "__data.3", Prot: orc::MemProt::Read | orc::MemProt::Write);
568
569 // Create an initial block.
570 orc::ExecutorAddr B1Addr(0x1000);
571 auto &B1 = G.createContentBlock(Parent&: Sec1, Content: BlockContent, Address: B1Addr, Alignment: 8, AlignmentOffset: 0);
572 orc::ExecutorAddr B2Addr(0x2000);
573 auto &B2 = G.createContentBlock(Parent&: Sec2, Content: BlockContent, Address: B2Addr, Alignment: 8, AlignmentOffset: 0);
574 orc::ExecutorAddr B3Addr(0x3000);
575 auto &B3 = G.createContentBlock(Parent&: Sec3, Content: BlockContent, Address: B3Addr, Alignment: 8, AlignmentOffset: 0);
576
577 // Add a symbols for each block.
578 G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S1", Size: B1.getSize(), L: Linkage::Strong, S: Scope::Default,
579 IsCallable: false, IsLive: false);
580 G.addDefinedSymbol(Content&: B2, Offset: 0, Name: "S2", Size: B2.getSize(), L: Linkage::Strong, S: Scope::Default,
581 IsCallable: false, IsLive: false);
582 G.addDefinedSymbol(Content&: B3, Offset: 0, Name: "S3", Size: B2.getSize(), L: Linkage::Strong, S: Scope::Default,
583 IsCallable: false, IsLive: false);
584
585 EXPECT_EQ(&B1.getSection(), &Sec1);
586 EXPECT_EQ(&B2.getSection(), &Sec2);
587 EXPECT_EQ(G.sections_size(), 3U) << "Expected three sections initially";
588 EXPECT_EQ(Sec1.blocks_size(), 1U) << "Expected one block in Sec1 initially";
589 EXPECT_EQ(Sec1.symbols_size(), 1U) << "Expected one symbol in Sec1 initially";
590 EXPECT_EQ(Sec2.blocks_size(), 1U) << "Expected one block in Sec2 initially";
591 EXPECT_EQ(Sec2.symbols_size(), 1U) << "Expected one symbol in Sec2 initially";
592 EXPECT_EQ(Sec3.blocks_size(), 1U) << "Expected one block in Sec3 initially";
593 EXPECT_EQ(Sec3.symbols_size(), 1U) << "Expected one symbol in Sec3 initially";
594
595 // Check that self-merge is a no-op.
596 G.mergeSections(DstSection&: Sec1, SrcSection&: Sec1);
597
598 EXPECT_EQ(&B1.getSection(), &Sec1)
599 << "Expected B1.getSection() to remain unchanged";
600 EXPECT_EQ(G.sections_size(), 3U)
601 << "Expected three sections after first merge";
602 EXPECT_EQ(Sec1.blocks_size(), 1U)
603 << "Expected one block in Sec1 after first merge";
604 EXPECT_EQ(Sec1.symbols_size(), 1U)
605 << "Expected one symbol in Sec1 after first merge";
606 EXPECT_EQ(Sec2.blocks_size(), 1U)
607 << "Expected one block in Sec2 after first merge";
608 EXPECT_EQ(Sec2.symbols_size(), 1U)
609 << "Expected one symbol in Sec2 after first merge";
610 EXPECT_EQ(Sec3.blocks_size(), 1U)
611 << "Expected one block in Sec3 after first merge";
612 EXPECT_EQ(Sec3.symbols_size(), 1U)
613 << "Expected one symbol in Sec3 after first merge";
614
615 // Merge Sec2 into Sec1, removing Sec2.
616 G.mergeSections(DstSection&: Sec1, SrcSection&: Sec2);
617
618 EXPECT_EQ(&B2.getSection(), &Sec1)
619 << "Expected B2.getSection() to have been changed to &Sec1";
620 EXPECT_EQ(G.sections_size(), 2U)
621 << "Expected two sections after section merge";
622 EXPECT_EQ(Sec1.blocks_size(), 2U)
623 << "Expected two blocks in Sec1 after section merge";
624 EXPECT_EQ(Sec1.symbols_size(), 2U)
625 << "Expected two symbols in Sec1 after section merge";
626 EXPECT_EQ(Sec3.blocks_size(), 1U)
627 << "Expected one block in Sec3 after section merge";
628 EXPECT_EQ(Sec3.symbols_size(), 1U)
629 << "Expected one symbol in Sec3 after section merge";
630
631 G.mergeSections(DstSection&: Sec1, SrcSection&: Sec3, PreserveSrcSection: true);
632
633 EXPECT_EQ(G.sections_size(), 2U) << "Expected two sections after third merge";
634 EXPECT_EQ(Sec1.blocks_size(), 3U)
635 << "Expected three blocks in Sec1 after third merge";
636 EXPECT_EQ(Sec1.symbols_size(), 3U)
637 << "Expected three symbols in Sec1 after third merge";
638 EXPECT_EQ(Sec3.blocks_size(), 0U)
639 << "Expected one block in Sec3 after third merge";
640 EXPECT_EQ(Sec3.symbols_size(), 0U)
641 << "Expected one symbol in Sec3 after third merge";
642}
643
644TEST(LinkGraphTest, SplitBlock) {
645 // Check that the LinkGraph::splitBlock test works as expected.
646 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
647 getGenericEdgeKindName);
648 auto &Sec =
649 G.createSection(Name: "__data", Prot: orc::MemProt::Read | orc::MemProt::Write);
650
651 // Create the block to split.
652 orc::ExecutorAddr B1Addr(0x1000);
653 auto &B1 = G.createContentBlock(Parent&: Sec, Content: BlockContent, Address: B1Addr, Alignment: 8, AlignmentOffset: 0);
654
655 // Add some symbols to the block.
656 auto &S1 = G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S1", Size: 4, L: Linkage::Strong, S: Scope::Default,
657 IsCallable: false, IsLive: false);
658 auto &S2 = G.addDefinedSymbol(Content&: B1, Offset: 4, Name: "S2", Size: 4, L: Linkage::Strong, S: Scope::Default,
659 IsCallable: false, IsLive: false);
660 auto &S3 = G.addDefinedSymbol(Content&: B1, Offset: 8, Name: "S3", Size: 4, L: Linkage::Strong, S: Scope::Default,
661 IsCallable: false, IsLive: false);
662 auto &S4 = G.addDefinedSymbol(Content&: B1, Offset: 12, Name: "S4", Size: 4, L: Linkage::Strong,
663 S: Scope::Default, IsCallable: false, IsLive: false);
664 // Add a symbol that extends beyond the split.
665 auto &S5 = G.addDefinedSymbol(Content&: B1, Offset: 0, Name: "S5", Size: 16, L: Linkage::Strong,
666 S: Scope::Default, IsCallable: false, IsLive: false);
667
668 // Add an extra block, EB, and target symbols, and use these to add edges
669 // from B1 to EB.
670 orc::ExecutorAddr EBAddr(0x2000);
671 auto &EB = G.createContentBlock(Parent&: Sec, Content: BlockContent, Address: EBAddr, Alignment: 8, AlignmentOffset: 0);
672 auto &ES1 = G.addDefinedSymbol(Content&: EB, Offset: 0, Name: "TS1", Size: 4, L: Linkage::Strong,
673 S: Scope::Default, IsCallable: false, IsLive: false);
674 auto &ES2 = G.addDefinedSymbol(Content&: EB, Offset: 4, Name: "TS2", Size: 4, L: Linkage::Strong,
675 S: Scope::Default, IsCallable: false, IsLive: false);
676 auto &ES3 = G.addDefinedSymbol(Content&: EB, Offset: 8, Name: "TS3", Size: 4, L: Linkage::Strong,
677 S: Scope::Default, IsCallable: false, IsLive: false);
678 auto &ES4 = G.addDefinedSymbol(Content&: EB, Offset: 12, Name: "TS4", Size: 4, L: Linkage::Strong,
679 S: Scope::Default, IsCallable: false, IsLive: false);
680
681 // Add edges from B1 to EB.
682 B1.addEdge(K: Edge::FirstRelocation, Offset: 0, Target&: ES1, Addend: 0);
683 B1.addEdge(K: Edge::FirstRelocation, Offset: 4, Target&: ES2, Addend: 0);
684 B1.addEdge(K: Edge::FirstRelocation, Offset: 8, Target&: ES3, Addend: 0);
685 B1.addEdge(K: Edge::FirstRelocation, Offset: 12, Target&: ES4, Addend: 0);
686
687 // Split B1.
688 auto &B2 = G.splitBlock(B&: B1, SplitIndex: 8);
689
690 // Check that the block addresses and content matches what we would expect.
691 EXPECT_EQ(B1.getAddress(), B1Addr + 8);
692 EXPECT_EQ(B1.getContent(), BlockContent.slice(8));
693
694 EXPECT_EQ(B2.getAddress(), B1Addr);
695 EXPECT_EQ(B2.getContent(), BlockContent.slice(0, 8));
696
697 // Check that symbols in B1 were transferred as expected:
698 // We expect S1 and S2 to have been transferred to B2, and S3 and S4 to have
699 // remained attached to B1. Symbols S3 and S4 should have had their offsets
700 // slid to account for the change in address of B2.
701 EXPECT_EQ(&S1.getBlock(), &B2);
702 EXPECT_EQ(S1.getOffset(), 0U);
703
704 EXPECT_EQ(&S2.getBlock(), &B2);
705 EXPECT_EQ(S2.getOffset(), 4U);
706
707 EXPECT_EQ(&S3.getBlock(), &B1);
708 EXPECT_EQ(S3.getOffset(), 0U);
709
710 EXPECT_EQ(&S4.getBlock(), &B1);
711 EXPECT_EQ(S4.getOffset(), 4U);
712
713 EXPECT_EQ(&S5.getBlock(), &B2);
714 EXPECT_EQ(S5.getOffset(), 0U);
715 // Size shrinks to fit.
716 EXPECT_EQ(S5.getSize(), 8U);
717
718 // Check that edges in B1 have been transferred as expected:
719 // Both blocks should now have two edges each at offsets 0 and 4.
720 EXPECT_EQ(llvm::size(B1.edges()), 2);
721 if (size(Range: B1.edges()) == 2) {
722 auto *E1 = &*B1.edges().begin();
723 auto *E2 = &*(B1.edges().begin() + 1);
724 if (E2->getOffset() < E1->getOffset())
725 std::swap(a&: E1, b&: E2);
726 EXPECT_EQ(E1->getOffset(), 0U);
727 EXPECT_EQ(E2->getOffset(), 4U);
728 }
729
730 EXPECT_EQ(llvm::size(B2.edges()), 2);
731 if (size(Range: B2.edges()) == 2) {
732 auto *E1 = &*B2.edges().begin();
733 auto *E2 = &*(B2.edges().begin() + 1);
734 if (E2->getOffset() < E1->getOffset())
735 std::swap(a&: E1, b&: E2);
736 EXPECT_EQ(E1->getOffset(), 0U);
737 EXPECT_EQ(E2->getOffset(), 4U);
738 }
739}
740
741TEST(LinkGraphTest, GraphAllocationMethods) {
742 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
743 getGenericEdgeKindName);
744
745 // Test allocation of sized, uninitialized buffer.
746 auto Buf1 = G.allocateBuffer(Size: 10);
747 EXPECT_EQ(Buf1.size(), 10U);
748
749 // Test allocation of content-backed buffer.
750 char Buf2Src[] = {1, static_cast<char>(-1), 0, 42};
751 auto Buf2 = G.allocateContent(Source: ArrayRef<char>(Buf2Src));
752 EXPECT_EQ(Buf2, ArrayRef<char>(Buf2Src));
753
754 // Test c-string allocation from StringRef.
755 StringRef Buf3Src = "hello";
756 auto Buf3 = G.allocateCString(Source: Buf3Src);
757 EXPECT_TRUE(llvm::equal(Buf3.drop_back(1), Buf3Src));
758 EXPECT_EQ(Buf3.back(), '\0');
759}
760
761TEST(LinkGraphTest, IsCStringBlockTest) {
762 // Check that the LinkGraph::splitBlock test works as expected.
763 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
764 getGenericEdgeKindName);
765 auto &Sec =
766 G.createSection(Name: "__data", Prot: orc::MemProt::Read | orc::MemProt::Write);
767
768 char CString[] = "hello, world!";
769 char NotACString[] = {0, 1, 0, 1, 0};
770
771 auto &CStringBlock =
772 G.createContentBlock(Parent&: Sec, Content: CString, Address: orc::ExecutorAddr(), Alignment: 1, AlignmentOffset: 0);
773 auto &NotACStringBlock =
774 G.createContentBlock(Parent&: Sec, Content: NotACString, Address: orc::ExecutorAddr(), Alignment: 1, AlignmentOffset: 0);
775 auto &SizeOneZeroFillBlock =
776 G.createZeroFillBlock(Parent&: Sec, Size: 1, Address: orc::ExecutorAddr(), Alignment: 1, AlignmentOffset: 0);
777 auto &LargerZeroFillBlock =
778 G.createZeroFillBlock(Parent&: Sec, Size: 2, Address: orc::ExecutorAddr(), Alignment: 1, AlignmentOffset: 0);
779
780 EXPECT_TRUE(isCStringBlock(CStringBlock));
781 EXPECT_FALSE(isCStringBlock(NotACStringBlock));
782 EXPECT_TRUE(isCStringBlock(SizeOneZeroFillBlock));
783 EXPECT_FALSE(isCStringBlock(LargerZeroFillBlock));
784}
785
786TEST(LinkGraphTest, BasicLayoutHonorsNoAlloc) {
787 // Check that BasicLayout honors NoAlloc.
788 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, llvm::endianness::little,
789 getGenericEdgeKindName);
790
791 // Create a regular section and block.
792 auto &Sec1 =
793 G.createSection(Name: "__data", Prot: orc::MemProt::Read | orc::MemProt::Write);
794 G.createContentBlock(Parent&: Sec1, Content: BlockContent.slice(N: 0, M: 8), Address: orc::ExecutorAddr(), Alignment: 8,
795 AlignmentOffset: 0);
796
797 // Create a NoAlloc section and block.
798 auto &Sec2 =
799 G.createSection(Name: "__metadata", Prot: orc::MemProt::Read | orc::MemProt::Write);
800 Sec2.setMemLifetime(orc::MemLifetime::NoAlloc);
801 G.createContentBlock(Parent&: Sec2, Content: BlockContent.slice(N: 0, M: 8), Address: orc::ExecutorAddr(), Alignment: 8,
802 AlignmentOffset: 0);
803
804 BasicLayout BL(G);
805
806 EXPECT_EQ(std::distance(BL.segments().begin(), BL.segments().end()), 1U);
807 EXPECT_EQ(BL.segments().begin()->first,
808 orc::MemProt::Read | orc::MemProt::Write);
809 auto &SegInfo = BL.segments().begin()->second;
810 EXPECT_EQ(SegInfo.Alignment, 8U);
811 EXPECT_EQ(SegInfo.ContentSize, 8U);
812}
813

source code of llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp