1 //===------ LinkGraphTests.cpp - Unit tests for core JITLink classes ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/STLExtras.h" 10 #include "llvm/ExecutionEngine/JITLink/JITLink.h" 11 #include "llvm/Support/Endian.h" 12 #include "llvm/Support/Memory.h" 13 #include "gtest/gtest.h" 14 15 using namespace llvm; 16 using namespace llvm::jitlink; 17 18 static auto RWFlags = 19 sys::Memory::ProtectionFlags(sys::Memory::MF_READ | sys::Memory::MF_WRITE); 20 21 static const char BlockContentBytes[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 22 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 23 0x1C, 0x1D, 0x1E, 0x1F, 0x00}; 24 static StringRef BlockContent(BlockContentBytes); 25 26 TEST(LinkGraphTest, Construction) { 27 // Check that LinkGraph construction works as expected. 28 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little); 29 EXPECT_EQ(G.getName(), "foo"); 30 EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin"); 31 EXPECT_EQ(G.getPointerSize(), 8U); 32 EXPECT_EQ(G.getEndianness(), support::little); 33 EXPECT_TRUE(llvm::empty(G.external_symbols())); 34 EXPECT_TRUE(llvm::empty(G.absolute_symbols())); 35 EXPECT_TRUE(llvm::empty(G.defined_symbols())); 36 EXPECT_TRUE(llvm::empty(G.blocks())); 37 } 38 39 TEST(LinkGraphTest, AddressAccess) { 40 // Check that we can get addresses for blocks, symbols, and edges. 41 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little); 42 43 auto Sec1 = G.createSection("__data.1", RWFlags); 44 auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0); 45 auto &S1 = G.addDefinedSymbol(B1, 4, "S1", 4, Linkage::Strong, Scope::Default, 46 false, false); 47 B1.addEdge(Edge::FirstRelocation, 8, S1, 0); 48 auto &E1 = *B1.edges().begin(); 49 50 EXPECT_EQ(B1.getAddress(), 0x1000U) << "Incorrect block address"; 51 EXPECT_EQ(S1.getAddress(), 0x1004U) << "Incorrect symbol address"; 52 EXPECT_EQ(B1.getFixupAddress(E1), 0x1008U) << "Incorrect fixup address"; 53 } 54 55 TEST(LinkGraphTest, BlockAndSymbolIteration) { 56 // Check that we can iterate over blocks within Sections and across sections. 57 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little); 58 auto &Sec1 = G.createSection("__data.1", RWFlags); 59 auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0); 60 auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0); 61 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, 62 false, false); 63 auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default, 64 false, false); 65 66 auto &Sec2 = G.createSection("__data.2", RWFlags); 67 auto &B3 = G.createContentBlock(Sec2, BlockContent, 0x3000, 8, 0); 68 auto &B4 = G.createContentBlock(Sec2, BlockContent, 0x4000, 8, 0); 69 auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default, 70 false, false); 71 auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default, 72 false, false); 73 74 // Check that iteration of blocks within a section behaves as expected. 75 EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2); 76 EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1)); 77 EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2)); 78 79 // Check that iteration of symbols within a section behaves as expected. 80 EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2); 81 EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1)); 82 EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2)); 83 84 // Check that iteration of blocks across sections behaves as expected. 85 EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4); 86 EXPECT_TRUE(llvm::count(G.blocks(), &B1)); 87 EXPECT_TRUE(llvm::count(G.blocks(), &B2)); 88 EXPECT_TRUE(llvm::count(G.blocks(), &B3)); 89 EXPECT_TRUE(llvm::count(G.blocks(), &B4)); 90 91 // Check that iteration of defined symbols across sections behaves as 92 // expected. 93 EXPECT_EQ( 94 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4); 95 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1)); 96 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2)); 97 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3)); 98 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4)); 99 } 100 101 TEST(LinkGraphTest, SplitBlock) { 102 // Check that the LinkGraph::splitBlock test works as expected. 103 104 const char BlockContentBytes[] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 105 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 106 0x1C, 0x1D, 0x1E, 0x1F, 0x00}; 107 StringRef BlockContent(BlockContentBytes); 108 109 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little); 110 auto &Sec = G.createSection("__data", RWFlags); 111 112 // Create the block to split. 113 auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0); 114 115 // Add some symbols to the block. 116 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, 117 false, false); 118 auto &S2 = G.addDefinedSymbol(B1, 4, "S2", 4, Linkage::Strong, Scope::Default, 119 false, false); 120 auto &S3 = G.addDefinedSymbol(B1, 8, "S3", 4, Linkage::Strong, Scope::Default, 121 false, false); 122 auto &S4 = G.addDefinedSymbol(B1, 12, "S4", 4, Linkage::Strong, 123 Scope::Default, false, false); 124 125 // Add an extra block, EB, and target symbols, and use these to add edges 126 // from B1 to EB. 127 auto &EB = G.createContentBlock(Sec, BlockContent, 0x2000, 8, 0); 128 auto &ES1 = G.addDefinedSymbol(EB, 0, "TS1", 4, Linkage::Strong, 129 Scope::Default, false, false); 130 auto &ES2 = G.addDefinedSymbol(EB, 4, "TS2", 4, Linkage::Strong, 131 Scope::Default, false, false); 132 auto &ES3 = G.addDefinedSymbol(EB, 8, "TS3", 4, Linkage::Strong, 133 Scope::Default, false, false); 134 auto &ES4 = G.addDefinedSymbol(EB, 12, "TS4", 4, Linkage::Strong, 135 Scope::Default, false, false); 136 137 // Add edges from B1 to EB. 138 B1.addEdge(Edge::FirstRelocation, 0, ES1, 0); 139 B1.addEdge(Edge::FirstRelocation, 4, ES2, 0); 140 B1.addEdge(Edge::FirstRelocation, 8, ES3, 0); 141 B1.addEdge(Edge::FirstRelocation, 12, ES4, 0); 142 143 // Split B1. 144 auto &B2 = G.splitBlock(B1, 8); 145 146 // Check that the block addresses and content matches what we would expect. 147 EXPECT_EQ(B1.getAddress(), 0x1008U); 148 EXPECT_EQ(B1.getContent(), BlockContent.substr(8)); 149 150 EXPECT_EQ(B2.getAddress(), 0x1000U); 151 EXPECT_EQ(B2.getContent(), BlockContent.substr(0, 8)); 152 153 // Check that symbols in B1 were transferred as expected: 154 // We expect S1 and S2 to have been transferred to B2, and S3 and S4 to have 155 // remained attached to B1. Symbols S3 and S4 should have had their offsets 156 // slid to account for the change in address of B2. 157 EXPECT_EQ(&S1.getBlock(), &B2); 158 EXPECT_EQ(S1.getOffset(), 0U); 159 160 EXPECT_EQ(&S2.getBlock(), &B2); 161 EXPECT_EQ(S2.getOffset(), 4U); 162 163 EXPECT_EQ(&S3.getBlock(), &B1); 164 EXPECT_EQ(S3.getOffset(), 0U); 165 166 EXPECT_EQ(&S4.getBlock(), &B1); 167 EXPECT_EQ(S4.getOffset(), 4U); 168 169 // Check that edges in B1 have been transferred as expected: 170 // Both blocks should now have two edges each at offsets 0 and 4. 171 EXPECT_EQ(llvm::size(B1.edges()), 2); 172 if (size(B1.edges()) == 2) { 173 auto *E1 = &*B1.edges().begin(); 174 auto *E2 = &*(B1.edges().begin() + 1); 175 if (E2->getOffset() < E1->getOffset()) 176 std::swap(E1, E2); 177 EXPECT_EQ(E1->getOffset(), 0U); 178 EXPECT_EQ(E2->getOffset(), 4U); 179 } 180 181 EXPECT_EQ(llvm::size(B2.edges()), 2); 182 if (size(B2.edges()) == 2) { 183 auto *E1 = &*B2.edges().begin(); 184 auto *E2 = &*(B2.edges().begin() + 1); 185 if (E2->getOffset() < E1->getOffset()) 186 std::swap(E1, E2); 187 EXPECT_EQ(E1->getOffset(), 0U); 188 EXPECT_EQ(E2->getOffset(), 4U); 189 } 190 } 191