brintos

brintos / llvm-project-archived public Read only

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