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 ArrayRef<char> 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 getGenericEdgeKindName); 30 EXPECT_EQ(G.getName(), "foo"); 31 EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin"); 32 EXPECT_EQ(G.getPointerSize(), 8U); 33 EXPECT_EQ(G.getEndianness(), support::little); 34 EXPECT_TRUE(llvm::empty(G.external_symbols())); 35 EXPECT_TRUE(llvm::empty(G.absolute_symbols())); 36 EXPECT_TRUE(llvm::empty(G.defined_symbols())); 37 EXPECT_TRUE(llvm::empty(G.blocks())); 38 } 39 40 TEST(LinkGraphTest, AddressAccess) { 41 // Check that we can get addresses for blocks, symbols, and edges. 42 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 43 getGenericEdgeKindName); 44 45 auto &Sec1 = G.createSection("__data.1", RWFlags); 46 auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 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(), 0x1000U) << "Incorrect block address"; 53 EXPECT_EQ(S1.getAddress(), 0x1004U) << "Incorrect symbol address"; 54 EXPECT_EQ(B1.getFixupAddress(E1), 0x1008U) << "Incorrect fixup address"; 55 } 56 57 TEST(LinkGraphTest, BlockAndSymbolIteration) { 58 // Check that we can iterate over blocks within Sections and across sections. 59 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 60 getGenericEdgeKindName); 61 auto &Sec1 = G.createSection("__data.1", RWFlags); 62 auto &B1 = G.createContentBlock(Sec1, BlockContent, 0x1000, 8, 0); 63 auto &B2 = G.createContentBlock(Sec1, BlockContent, 0x2000, 8, 0); 64 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, 65 false, false); 66 auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default, 67 false, false); 68 69 auto &Sec2 = G.createSection("__data.2", RWFlags); 70 auto &B3 = G.createContentBlock(Sec2, BlockContent, 0x3000, 8, 0); 71 auto &B4 = G.createContentBlock(Sec2, BlockContent, 0x4000, 8, 0); 72 auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default, 73 false, false); 74 auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default, 75 false, false); 76 77 // Check that iteration of blocks within a section behaves as expected. 78 EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2); 79 EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1)); 80 EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2)); 81 82 // Check that iteration of symbols within a section behaves as expected. 83 EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2); 84 EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1)); 85 EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2)); 86 87 // Check that iteration of blocks across sections behaves as expected. 88 EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4); 89 EXPECT_TRUE(llvm::count(G.blocks(), &B1)); 90 EXPECT_TRUE(llvm::count(G.blocks(), &B2)); 91 EXPECT_TRUE(llvm::count(G.blocks(), &B3)); 92 EXPECT_TRUE(llvm::count(G.blocks(), &B4)); 93 94 // Check that iteration of defined symbols across sections behaves as 95 // expected. 96 EXPECT_EQ( 97 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4); 98 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1)); 99 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2)); 100 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3)); 101 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4)); 102 } 103 104 TEST(LinkGraphTest, MakeExternal) { 105 // Check that we can make a defined symbol external. 106 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 107 getGenericEdgeKindName); 108 auto &Sec = G.createSection("__data", RWFlags); 109 110 // Create an initial block. 111 auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0); 112 113 // Add a symbol to the block. 114 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, 115 false, false); 116 117 EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined"; 118 EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external"; 119 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute"; 120 EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block"; 121 EXPECT_EQ(S1.getAddress(), 0x1000U) << "Unexpected symbol address"; 122 123 EXPECT_EQ( 124 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U) 125 << "Unexpected number of defined symbols"; 126 EXPECT_EQ( 127 std::distance(G.external_symbols().begin(), G.external_symbols().end()), 128 0U) 129 << "Unexpected number of external symbols"; 130 131 // Make S1 external, confirm that the its flags are updated and that it is 132 // moved from the defined symbols to the externals list. 133 G.makeExternal(S1); 134 135 EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined"; 136 EXPECT_TRUE(S1.isExternal()) << "Symbol should be external"; 137 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute"; 138 EXPECT_EQ(S1.getAddress(), 0U) << "Unexpected symbol address"; 139 140 EXPECT_EQ( 141 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U) 142 << "Unexpected number of defined symbols"; 143 EXPECT_EQ( 144 std::distance(G.external_symbols().begin(), G.external_symbols().end()), 145 1U) 146 << "Unexpected number of external symbols"; 147 } 148 149 TEST(LinkGraphTest, MakeDefined) { 150 // Check that we can make an external symbol defined. 151 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 152 getGenericEdgeKindName); 153 auto &Sec = G.createSection("__data", RWFlags); 154 155 // Create an initial block. 156 auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0); 157 158 // Add an external symbol. 159 auto &S1 = G.addExternalSymbol("S1", 4, Linkage::Strong); 160 161 EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined"; 162 EXPECT_TRUE(S1.isExternal()) << "Symbol should be external"; 163 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute"; 164 EXPECT_EQ(S1.getAddress(), 0U) << "Unexpected symbol address"; 165 166 EXPECT_EQ( 167 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U) 168 << "Unexpected number of defined symbols"; 169 EXPECT_EQ( 170 std::distance(G.external_symbols().begin(), G.external_symbols().end()), 171 1U) 172 << "Unexpected number of external symbols"; 173 174 // Make S1 defined, confirm that its flags are updated and that it is 175 // moved from the defined symbols to the externals list. 176 G.makeDefined(S1, B1, 0, 4, Linkage::Strong, Scope::Default, false); 177 178 EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined"; 179 EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external"; 180 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute"; 181 EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block"; 182 EXPECT_EQ(S1.getAddress(), 0x1000U) << "Unexpected symbol address"; 183 184 EXPECT_EQ( 185 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U) 186 << "Unexpected number of defined symbols"; 187 EXPECT_EQ( 188 std::distance(G.external_symbols().begin(), G.external_symbols().end()), 189 0U) 190 << "Unexpected number of external symbols"; 191 } 192 193 TEST(LinkGraphTest, SplitBlock) { 194 // Check that the LinkGraph::splitBlock test works as expected. 195 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 196 getGenericEdgeKindName); 197 auto &Sec = G.createSection("__data", RWFlags); 198 199 // Create the block to split. 200 auto &B1 = G.createContentBlock(Sec, BlockContent, 0x1000, 8, 0); 201 202 // Add some symbols to the block. 203 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, 204 false, false); 205 auto &S2 = G.addDefinedSymbol(B1, 4, "S2", 4, Linkage::Strong, Scope::Default, 206 false, false); 207 auto &S3 = G.addDefinedSymbol(B1, 8, "S3", 4, Linkage::Strong, Scope::Default, 208 false, false); 209 auto &S4 = G.addDefinedSymbol(B1, 12, "S4", 4, Linkage::Strong, 210 Scope::Default, false, false); 211 212 // Add an extra block, EB, and target symbols, and use these to add edges 213 // from B1 to EB. 214 auto &EB = G.createContentBlock(Sec, BlockContent, 0x2000, 8, 0); 215 auto &ES1 = G.addDefinedSymbol(EB, 0, "TS1", 4, Linkage::Strong, 216 Scope::Default, false, false); 217 auto &ES2 = G.addDefinedSymbol(EB, 4, "TS2", 4, Linkage::Strong, 218 Scope::Default, false, false); 219 auto &ES3 = G.addDefinedSymbol(EB, 8, "TS3", 4, Linkage::Strong, 220 Scope::Default, false, false); 221 auto &ES4 = G.addDefinedSymbol(EB, 12, "TS4", 4, Linkage::Strong, 222 Scope::Default, false, false); 223 224 // Add edges from B1 to EB. 225 B1.addEdge(Edge::FirstRelocation, 0, ES1, 0); 226 B1.addEdge(Edge::FirstRelocation, 4, ES2, 0); 227 B1.addEdge(Edge::FirstRelocation, 8, ES3, 0); 228 B1.addEdge(Edge::FirstRelocation, 12, ES4, 0); 229 230 // Split B1. 231 auto &B2 = G.splitBlock(B1, 8); 232 233 // Check that the block addresses and content matches what we would expect. 234 EXPECT_EQ(B1.getAddress(), 0x1008U); 235 EXPECT_EQ(B1.getContent(), BlockContent.slice(8)); 236 237 EXPECT_EQ(B2.getAddress(), 0x1000U); 238 EXPECT_EQ(B2.getContent(), BlockContent.slice(0, 8)); 239 240 // Check that symbols in B1 were transferred as expected: 241 // We expect S1 and S2 to have been transferred to B2, and S3 and S4 to have 242 // remained attached to B1. Symbols S3 and S4 should have had their offsets 243 // slid to account for the change in address of B2. 244 EXPECT_EQ(&S1.getBlock(), &B2); 245 EXPECT_EQ(S1.getOffset(), 0U); 246 247 EXPECT_EQ(&S2.getBlock(), &B2); 248 EXPECT_EQ(S2.getOffset(), 4U); 249 250 EXPECT_EQ(&S3.getBlock(), &B1); 251 EXPECT_EQ(S3.getOffset(), 0U); 252 253 EXPECT_EQ(&S4.getBlock(), &B1); 254 EXPECT_EQ(S4.getOffset(), 4U); 255 256 // Check that edges in B1 have been transferred as expected: 257 // Both blocks should now have two edges each at offsets 0 and 4. 258 EXPECT_EQ(llvm::size(B1.edges()), 2); 259 if (size(B1.edges()) == 2) { 260 auto *E1 = &*B1.edges().begin(); 261 auto *E2 = &*(B1.edges().begin() + 1); 262 if (E2->getOffset() < E1->getOffset()) 263 std::swap(E1, E2); 264 EXPECT_EQ(E1->getOffset(), 0U); 265 EXPECT_EQ(E2->getOffset(), 4U); 266 } 267 268 EXPECT_EQ(llvm::size(B2.edges()), 2); 269 if (size(B2.edges()) == 2) { 270 auto *E1 = &*B2.edges().begin(); 271 auto *E2 = &*(B2.edges().begin() + 1); 272 if (E2->getOffset() < E1->getOffset()) 273 std::swap(E1, E2); 274 EXPECT_EQ(E1->getOffset(), 0U); 275 EXPECT_EQ(E2->getOffset(), 4U); 276 } 277 } 278