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