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 const char BlockContentBytes[] = { 19 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 0x6d, 0x6f, 20 0x76, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 21 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x66, 22 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x20, 23 0x68, 0x61, 0x64, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x61, 24 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x0a, 0x54, 0x68, 0x61, 0x74, 0x20, 0x74, 25 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6c, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 26 0x20, 0x4f, 0x6c, 0x64, 0x20, 0x52, 0x65, 0x67, 0x72, 0x65, 0x74, 0x20, 27 0x68, 0x61, 0x64, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x61, 0x77, 0x61, 0x79, 28 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x68, 0x61, 0x64, 0x20, 0x6a, 0x6f, 29 0x69, 0x6e, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 0x6c, 30 0x64, 0x20, 0x62, 0x75, 0x73, 0x68, 0x20, 0x68, 0x6f, 0x72, 0x73, 0x65, 31 0x73, 0x20, 0x2d, 0x2d, 0x20, 0x68, 0x65, 0x20, 0x77, 0x61, 0x73, 0x20, 32 0x77, 0x6f, 0x72, 0x74, 0x68, 0x20, 0x61, 0x20, 0x74, 0x68, 0x6f, 0x75, 33 0x73, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x0a, 34 0x53, 0x6f, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 35 0x72, 0x61, 0x63, 0x6b, 0x73, 0x20, 0x68, 0x61, 0x64, 0x20, 0x67, 0x61, 36 0x74, 0x68, 0x65, 0x72, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 37 0x65, 0x20, 0x66, 0x72, 0x61, 0x79, 0x2e, 0x0a, 0x41, 0x6c, 0x6c, 0x20, 38 0x74, 0x68, 0x65, 0x20, 0x74, 0x72, 0x69, 0x65, 0x64, 0x20, 0x61, 0x6e, 39 0x64, 0x20, 0x6e, 0x6f, 0x74, 0x65, 0x64, 0x20, 0x72, 0x69, 0x64, 0x65, 40 0x72, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 41 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6e, 0x65, 0x61, 42 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x61, 0x72, 0x0a, 0x48, 0x61, 43 0x64, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 44 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x6f, 0x6d, 0x65, 0x73, 0x74, 45 0x65, 0x61, 0x64, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6e, 0x69, 0x67, 0x68, 46 0x74, 0x2c, 0x0a, 0x46, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 47 0x75, 0x73, 0x68, 0x6d, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x20, 48 0x68, 0x61, 0x72, 0x64, 0x20, 0x72, 0x69, 0x64, 0x69, 0x6e, 0x67, 0x20, 49 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69, 50 0x6c, 0x64, 0x20, 0x62, 0x75, 0x73, 0x68, 0x20, 0x68, 0x6f, 0x72, 0x73, 51 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 52 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x2d, 0x68, 0x6f, 53 0x72, 0x73, 0x65, 0x20, 0x73, 0x6e, 0x75, 0x66, 0x66, 0x73, 0x20, 0x74, 54 0x68, 0x65, 0x20, 0x62, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x20, 0x77, 0x69, 55 0x74, 0x68, 0x20, 0x64, 0x65, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x2e, 0x00}; 56 57 static ArrayRef<char> BlockContent(BlockContentBytes); 58 59 TEST(LinkGraphTest, Construction) { 60 // Check that LinkGraph construction works as expected. 61 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 62 getGenericEdgeKindName); 63 EXPECT_EQ(G.getName(), "foo"); 64 EXPECT_EQ(G.getTargetTriple().str(), "x86_64-apple-darwin"); 65 EXPECT_EQ(G.getPointerSize(), 8U); 66 EXPECT_EQ(G.getEndianness(), support::little); 67 EXPECT_TRUE(llvm::empty(G.external_symbols())); 68 EXPECT_TRUE(llvm::empty(G.absolute_symbols())); 69 EXPECT_TRUE(llvm::empty(G.defined_symbols())); 70 EXPECT_TRUE(llvm::empty(G.blocks())); 71 } 72 73 TEST(LinkGraphTest, AddressAccess) { 74 // Check that we can get addresses for blocks, symbols, and edges. 75 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 76 getGenericEdgeKindName); 77 78 auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write); 79 orc::ExecutorAddr B1Addr(0x1000); 80 auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0); 81 auto &S1 = G.addDefinedSymbol(B1, 4, "S1", 4, Linkage::Strong, Scope::Default, 82 false, false); 83 B1.addEdge(Edge::FirstRelocation, 8, S1, 0); 84 auto &E1 = *B1.edges().begin(); 85 86 EXPECT_EQ(B1.getAddress(), B1Addr) << "Incorrect block address"; 87 EXPECT_EQ(S1.getAddress(), B1Addr + 4) << "Incorrect symbol address"; 88 EXPECT_EQ(B1.getFixupAddress(E1), B1Addr + 8) << "Incorrect fixup address"; 89 } 90 91 TEST(LinkGraphTest, BlockAndSymbolIteration) { 92 // Check that we can iterate over blocks within Sections and across sections. 93 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 94 getGenericEdgeKindName); 95 auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write); 96 orc::ExecutorAddr B1Addr(0x1000); 97 auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0); 98 orc::ExecutorAddr B2Addr(0x1000); 99 auto &B2 = G.createContentBlock(Sec1, BlockContent, B2Addr, 8, 0); 100 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, 101 false, false); 102 auto &S2 = G.addDefinedSymbol(B2, 4, "S2", 4, Linkage::Strong, Scope::Default, 103 false, false); 104 105 auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write); 106 orc::ExecutorAddr B3Addr(0x3000); 107 auto &B3 = G.createContentBlock(Sec2, BlockContent, B3Addr, 8, 0); 108 orc::ExecutorAddr B4Addr(0x4000); 109 auto &B4 = G.createContentBlock(Sec2, BlockContent, B4Addr, 8, 0); 110 auto &S3 = G.addDefinedSymbol(B3, 0, "S3", 4, Linkage::Strong, Scope::Default, 111 false, false); 112 auto &S4 = G.addDefinedSymbol(B4, 4, "S4", 4, Linkage::Strong, Scope::Default, 113 false, false); 114 115 // Check that iteration of blocks within a section behaves as expected. 116 EXPECT_EQ(std::distance(Sec1.blocks().begin(), Sec1.blocks().end()), 2); 117 EXPECT_TRUE(llvm::count(Sec1.blocks(), &B1)); 118 EXPECT_TRUE(llvm::count(Sec1.blocks(), &B2)); 119 120 // Check that iteration of symbols within a section behaves as expected. 121 EXPECT_EQ(std::distance(Sec1.symbols().begin(), Sec1.symbols().end()), 2); 122 EXPECT_TRUE(llvm::count(Sec1.symbols(), &S1)); 123 EXPECT_TRUE(llvm::count(Sec1.symbols(), &S2)); 124 125 // Check that iteration of blocks across sections behaves as expected. 126 EXPECT_EQ(std::distance(G.blocks().begin(), G.blocks().end()), 4); 127 EXPECT_TRUE(llvm::count(G.blocks(), &B1)); 128 EXPECT_TRUE(llvm::count(G.blocks(), &B2)); 129 EXPECT_TRUE(llvm::count(G.blocks(), &B3)); 130 EXPECT_TRUE(llvm::count(G.blocks(), &B4)); 131 132 // Check that iteration of defined symbols across sections behaves as 133 // expected. 134 EXPECT_EQ( 135 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 4); 136 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S1)); 137 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S2)); 138 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S3)); 139 EXPECT_TRUE(llvm::count(G.defined_symbols(), &S4)); 140 } 141 142 TEST(LinkGraphTest, ContentAccessAndUpdate) { 143 // Check that we can make a defined symbol external. 144 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 145 getGenericEdgeKindName); 146 auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write); 147 148 // Create an initial block. 149 orc::ExecutorAddr BAddr(0x1000); 150 auto &B = G.createContentBlock(Sec, BlockContent, BAddr, 8, 0); 151 152 EXPECT_FALSE(B.isContentMutable()) << "Content unexpectedly mutable"; 153 EXPECT_EQ(B.getContent().data(), BlockContent.data()) 154 << "Unexpected block content data pointer"; 155 EXPECT_EQ(B.getContent().size(), BlockContent.size()) 156 << "Unexpected block content size"; 157 158 // Expect that attempting to get already-mutable content fails if the 159 // content is not yet mutable (debug builds only). 160 #ifndef NDEBUG 161 EXPECT_DEATH({ (void)B.getAlreadyMutableContent(); }, 162 "Content is not mutable") 163 << "Unexpected mutable access allowed to immutable data"; 164 #endif 165 166 // Check that mutable content is copied on request as expected. 167 auto MutableContent = B.getMutableContent(G); 168 EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable"; 169 EXPECT_NE(MutableContent.data(), BlockContent.data()) 170 << "Unexpected mutable content data pointer"; 171 EXPECT_EQ(MutableContent.size(), BlockContent.size()) 172 << "Unexpected mutable content size"; 173 EXPECT_TRUE(std::equal(MutableContent.begin(), MutableContent.end(), 174 BlockContent.begin())) 175 << "Unexpected mutable content value"; 176 177 // Check that already-mutable content behaves as expected, with no 178 // further copies. 179 auto MutableContent2 = B.getMutableContent(G); 180 EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable"; 181 EXPECT_EQ(MutableContent2.data(), MutableContent.data()) 182 << "Unexpected mutable content 2 data pointer"; 183 EXPECT_EQ(MutableContent2.size(), MutableContent.size()) 184 << "Unexpected mutable content 2 size"; 185 186 // Check that getAlreadyMutableContent behaves as expected, with no 187 // further copies. 188 auto MutableContent3 = B.getMutableContent(G); 189 EXPECT_TRUE(B.isContentMutable()) << "Content unexpectedly immutable"; 190 EXPECT_EQ(MutableContent3.data(), MutableContent.data()) 191 << "Unexpected mutable content 2 data pointer"; 192 EXPECT_EQ(MutableContent3.size(), MutableContent.size()) 193 << "Unexpected mutable content 2 size"; 194 195 // Set content back to immutable and check that everything behaves as 196 // expected again. 197 B.setContent(BlockContent); 198 EXPECT_FALSE(B.isContentMutable()) << "Content unexpectedly mutable"; 199 EXPECT_EQ(B.getContent().data(), BlockContent.data()) 200 << "Unexpected block content data pointer"; 201 EXPECT_EQ(B.getContent().size(), BlockContent.size()) 202 << "Unexpected block content size"; 203 204 // Create an initially mutable block. 205 auto &B2 = G.createMutableContentBlock(Sec, MutableContent, 206 orc::ExecutorAddr(0x10000), 8, 0); 207 208 EXPECT_TRUE(B2.isContentMutable()) << "Expected B2 content to be mutable"; 209 } 210 211 TEST(LinkGraphTest, MakeExternal) { 212 // Check that we can make a defined symbol external. 213 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 214 getGenericEdgeKindName); 215 auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write); 216 217 // Create an initial block. 218 auto &B1 = 219 G.createContentBlock(Sec, BlockContent, orc::ExecutorAddr(0x1000), 8, 0); 220 221 // Add a symbol to the block. 222 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, 223 false, false); 224 225 EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined"; 226 EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external"; 227 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute"; 228 EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block"; 229 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000)) 230 << "Unexpected symbol address"; 231 232 EXPECT_EQ( 233 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U) 234 << "Unexpected number of defined symbols"; 235 EXPECT_EQ( 236 std::distance(G.external_symbols().begin(), G.external_symbols().end()), 237 0U) 238 << "Unexpected number of external symbols"; 239 240 // Make S1 external, confirm that the its flags are updated and that it is 241 // moved from the defined symbols to the externals list. 242 G.makeExternal(S1); 243 244 EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined"; 245 EXPECT_TRUE(S1.isExternal()) << "Symbol should be external"; 246 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute"; 247 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr()) 248 << "Unexpected symbol address"; 249 250 EXPECT_EQ( 251 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U) 252 << "Unexpected number of defined symbols"; 253 EXPECT_EQ( 254 std::distance(G.external_symbols().begin(), G.external_symbols().end()), 255 1U) 256 << "Unexpected number of external symbols"; 257 } 258 259 TEST(LinkGraphTest, MakeDefined) { 260 // Check that we can make an external symbol defined. 261 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 262 getGenericEdgeKindName); 263 auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write); 264 265 // Create an initial block. 266 orc::ExecutorAddr B1Addr(0x1000); 267 auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0); 268 269 // Add an external symbol. 270 auto &S1 = G.addExternalSymbol("S1", 4, Linkage::Strong); 271 272 EXPECT_FALSE(S1.isDefined()) << "Symbol should not be defined"; 273 EXPECT_TRUE(S1.isExternal()) << "Symbol should be external"; 274 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute"; 275 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr()) 276 << "Unexpected symbol address"; 277 278 EXPECT_EQ( 279 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 0U) 280 << "Unexpected number of defined symbols"; 281 EXPECT_EQ( 282 std::distance(G.external_symbols().begin(), G.external_symbols().end()), 283 1U) 284 << "Unexpected number of external symbols"; 285 286 // Make S1 defined, confirm that its flags are updated and that it is 287 // moved from the defined symbols to the externals list. 288 G.makeDefined(S1, B1, 0, 4, Linkage::Strong, Scope::Default, false); 289 290 EXPECT_TRUE(S1.isDefined()) << "Symbol should be defined"; 291 EXPECT_FALSE(S1.isExternal()) << "Symbol should not be external"; 292 EXPECT_FALSE(S1.isAbsolute()) << "Symbol should not be absolute"; 293 EXPECT_TRUE(&S1.getBlock()) << "Symbol should have a non-null block"; 294 EXPECT_EQ(S1.getAddress(), orc::ExecutorAddr(0x1000U)) 295 << "Unexpected symbol address"; 296 297 EXPECT_EQ( 298 std::distance(G.defined_symbols().begin(), G.defined_symbols().end()), 1U) 299 << "Unexpected number of defined symbols"; 300 EXPECT_EQ( 301 std::distance(G.external_symbols().begin(), G.external_symbols().end()), 302 0U) 303 << "Unexpected number of external symbols"; 304 } 305 306 TEST(LinkGraphTest, TransferDefinedSymbol) { 307 // Check that we can transfer a defined symbol from one block to another. 308 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 309 getGenericEdgeKindName); 310 auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write); 311 312 // Create initial blocks. 313 orc::ExecutorAddr B1Addr(0x1000); 314 auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0); 315 orc::ExecutorAddr B2Addr(0x2000); 316 auto &B2 = G.createContentBlock(Sec, BlockContent, B2Addr, 8, 0); 317 orc::ExecutorAddr B3Addr(0x3000); 318 auto &B3 = G.createContentBlock(Sec, BlockContent.slice(0, 32), B3Addr, 8, 0); 319 320 // Add a symbol. 321 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong, 322 Scope::Default, false, false); 323 324 // Transfer with zero offset, explicit size. 325 G.transferDefinedSymbol(S1, B2, 0, 64); 326 327 EXPECT_EQ(&S1.getBlock(), &B2) << "Block was not updated"; 328 EXPECT_EQ(S1.getOffset(), 0U) << "Unexpected offset"; 329 EXPECT_EQ(S1.getSize(), 64U) << "Size was not updated"; 330 331 // Transfer with non-zero offset, implicit truncation. 332 G.transferDefinedSymbol(S1, B3, 16, None); 333 334 EXPECT_EQ(&S1.getBlock(), &B3) << "Block was not updated"; 335 EXPECT_EQ(S1.getOffset(), 16U) << "Offset was not updated"; 336 EXPECT_EQ(S1.getSize(), 16U) << "Size was not updated"; 337 } 338 339 TEST(LinkGraphTest, TransferDefinedSymbolAcrossSections) { 340 // Check that we can transfer a defined symbol from an existing block in one 341 // section to another. 342 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 343 getGenericEdgeKindName); 344 auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write); 345 auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write); 346 347 // Create blocks in each section. 348 orc::ExecutorAddr B1Addr(0x1000); 349 auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0); 350 orc::ExecutorAddr B2Addr(0x2000); 351 auto &B2 = G.createContentBlock(Sec2, BlockContent, B2Addr, 8, 0); 352 353 // Add a symbol to section 1. 354 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong, 355 Scope::Default, false, false); 356 357 // Transfer with zero offset, explicit size to section 2. 358 G.transferDefinedSymbol(S1, B2, 0, 64); 359 360 EXPECT_EQ(&S1.getBlock(), &B2) << "Block was not updated"; 361 EXPECT_EQ(S1.getOffset(), 0U) << "Unexpected offset"; 362 EXPECT_EQ(S1.getSize(), 64U) << "Size was not updated"; 363 364 EXPECT_EQ(Sec1.symbols_size(), 0u) << "Symbol was not removed from Sec1"; 365 EXPECT_EQ(Sec2.symbols_size(), 1u) << "Symbol was not added to Sec2"; 366 if (Sec2.symbols_size() == 1) { 367 EXPECT_EQ(*Sec2.symbols().begin(), &S1) << "Unexpected symbol"; 368 } 369 } 370 371 TEST(LinkGraphTest, TransferBlock) { 372 // Check that we can transfer a block (and all associated symbols) from one 373 // section to another. 374 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 375 getGenericEdgeKindName); 376 auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write); 377 auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write); 378 379 // Create an initial block. 380 orc::ExecutorAddr B1Addr(0x1000); 381 auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0); 382 orc::ExecutorAddr B2Addr(0x2000); 383 auto &B2 = G.createContentBlock(Sec1, BlockContent, B2Addr, 8, 0); 384 385 // Add some symbols on B1... 386 G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong, Scope::Default, 387 false, false); 388 G.addDefinedSymbol(B1, 1, "S2", B1.getSize() - 1, Linkage::Strong, 389 Scope::Default, false, false); 390 391 // ... and on B2. 392 G.addDefinedSymbol(B2, 0, "S3", B2.getSize(), Linkage::Strong, Scope::Default, 393 false, false); 394 G.addDefinedSymbol(B2, 1, "S4", B2.getSize() - 1, Linkage::Strong, 395 Scope::Default, false, false); 396 397 EXPECT_EQ(Sec1.blocks_size(), 2U) << "Expected two blocks in Sec1 initially"; 398 EXPECT_EQ(Sec1.symbols_size(), 4U) 399 << "Expected four symbols in Sec1 initially"; 400 EXPECT_EQ(Sec2.blocks_size(), 0U) << "Expected zero blocks in Sec2 initially"; 401 EXPECT_EQ(Sec2.symbols_size(), 0U) 402 << "Expected zero symbols in Sec2 initially"; 403 404 // Transfer with zero offset, explicit size. 405 G.transferBlock(B1, Sec2); 406 407 EXPECT_EQ(Sec1.blocks_size(), 1U) 408 << "Expected one blocks in Sec1 after transfer"; 409 EXPECT_EQ(Sec1.symbols_size(), 2U) 410 << "Expected two symbols in Sec1 after transfer"; 411 EXPECT_EQ(Sec2.blocks_size(), 1U) 412 << "Expected one blocks in Sec2 after transfer"; 413 EXPECT_EQ(Sec2.symbols_size(), 2U) 414 << "Expected two symbols in Sec2 after transfer"; 415 } 416 417 TEST(LinkGraphTest, MergeSections) { 418 // Check that we can transfer a block (and all associated symbols) from one 419 // section to another. 420 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 421 getGenericEdgeKindName); 422 auto &Sec1 = G.createSection("__data.1", MemProt::Read | MemProt::Write); 423 auto &Sec2 = G.createSection("__data.2", MemProt::Read | MemProt::Write); 424 auto &Sec3 = G.createSection("__data.3", MemProt::Read | MemProt::Write); 425 426 // Create an initial block. 427 orc::ExecutorAddr B1Addr(0x1000); 428 auto &B1 = G.createContentBlock(Sec1, BlockContent, B1Addr, 8, 0); 429 orc::ExecutorAddr B2Addr(0x2000); 430 auto &B2 = G.createContentBlock(Sec2, BlockContent, B2Addr, 8, 0); 431 orc::ExecutorAddr B3Addr(0x3000); 432 auto &B3 = G.createContentBlock(Sec3, BlockContent, B3Addr, 8, 0); 433 434 // Add a symbols for each block. 435 G.addDefinedSymbol(B1, 0, "S1", B1.getSize(), Linkage::Strong, Scope::Default, 436 false, false); 437 G.addDefinedSymbol(B2, 0, "S2", B2.getSize(), Linkage::Strong, Scope::Default, 438 false, false); 439 G.addDefinedSymbol(B3, 0, "S3", B2.getSize(), Linkage::Strong, Scope::Default, 440 false, false); 441 442 EXPECT_EQ(&B1.getSection(), &Sec1); 443 EXPECT_EQ(&B2.getSection(), &Sec2); 444 EXPECT_EQ(G.sections_size(), 3U) << "Expected three sections initially"; 445 EXPECT_EQ(Sec1.blocks_size(), 1U) << "Expected one block in Sec1 initially"; 446 EXPECT_EQ(Sec1.symbols_size(), 1U) << "Expected one symbol in Sec1 initially"; 447 EXPECT_EQ(Sec2.blocks_size(), 1U) << "Expected one block in Sec2 initially"; 448 EXPECT_EQ(Sec2.symbols_size(), 1U) << "Expected one symbol in Sec2 initially"; 449 EXPECT_EQ(Sec3.blocks_size(), 1U) << "Expected one block in Sec3 initially"; 450 EXPECT_EQ(Sec3.symbols_size(), 1U) << "Expected one symbol in Sec3 initially"; 451 452 // Check that self-merge is a no-op. 453 G.mergeSections(Sec1, Sec1); 454 455 EXPECT_EQ(&B1.getSection(), &Sec1) 456 << "Expected B1.getSection() to remain unchanged"; 457 EXPECT_EQ(G.sections_size(), 3U) 458 << "Expected three sections after first merge"; 459 EXPECT_EQ(Sec1.blocks_size(), 1U) 460 << "Expected one block in Sec1 after first merge"; 461 EXPECT_EQ(Sec1.symbols_size(), 1U) 462 << "Expected one symbol in Sec1 after first merge"; 463 EXPECT_EQ(Sec2.blocks_size(), 1U) 464 << "Expected one block in Sec2 after first merge"; 465 EXPECT_EQ(Sec2.symbols_size(), 1U) 466 << "Expected one symbol in Sec2 after first merge"; 467 EXPECT_EQ(Sec3.blocks_size(), 1U) 468 << "Expected one block in Sec3 after first merge"; 469 EXPECT_EQ(Sec3.symbols_size(), 1U) 470 << "Expected one symbol in Sec3 after first merge"; 471 472 // Merge Sec2 into Sec1, removing Sec2. 473 G.mergeSections(Sec1, Sec2); 474 475 EXPECT_EQ(&B2.getSection(), &Sec1) 476 << "Expected B2.getSection() to have been changed to &Sec1"; 477 EXPECT_EQ(G.sections_size(), 2U) 478 << "Expected two sections after section merge"; 479 EXPECT_EQ(Sec1.blocks_size(), 2U) 480 << "Expected two blocks in Sec1 after section merge"; 481 EXPECT_EQ(Sec1.symbols_size(), 2U) 482 << "Expected two symbols in Sec1 after section merge"; 483 EXPECT_EQ(Sec3.blocks_size(), 1U) 484 << "Expected one block in Sec3 after section merge"; 485 EXPECT_EQ(Sec3.symbols_size(), 1U) 486 << "Expected one symbol in Sec3 after section merge"; 487 488 G.mergeSections(Sec1, Sec3, true); 489 490 EXPECT_EQ(G.sections_size(), 2U) << "Expected two sections after third merge"; 491 EXPECT_EQ(Sec1.blocks_size(), 3U) 492 << "Expected three blocks in Sec1 after third merge"; 493 EXPECT_EQ(Sec1.symbols_size(), 3U) 494 << "Expected three symbols in Sec1 after third merge"; 495 EXPECT_EQ(Sec3.blocks_size(), 0U) 496 << "Expected one block in Sec3 after third merge"; 497 EXPECT_EQ(Sec3.symbols_size(), 0U) 498 << "Expected one symbol in Sec3 after third merge"; 499 } 500 501 TEST(LinkGraphTest, SplitBlock) { 502 // Check that the LinkGraph::splitBlock test works as expected. 503 LinkGraph G("foo", Triple("x86_64-apple-darwin"), 8, support::little, 504 getGenericEdgeKindName); 505 auto &Sec = G.createSection("__data", MemProt::Read | MemProt::Write); 506 507 // Create the block to split. 508 orc::ExecutorAddr B1Addr(0x1000); 509 auto &B1 = G.createContentBlock(Sec, BlockContent, B1Addr, 8, 0); 510 511 // Add some symbols to the block. 512 auto &S1 = G.addDefinedSymbol(B1, 0, "S1", 4, Linkage::Strong, Scope::Default, 513 false, false); 514 auto &S2 = G.addDefinedSymbol(B1, 4, "S2", 4, Linkage::Strong, Scope::Default, 515 false, false); 516 auto &S3 = G.addDefinedSymbol(B1, 8, "S3", 4, Linkage::Strong, Scope::Default, 517 false, false); 518 auto &S4 = G.addDefinedSymbol(B1, 12, "S4", 4, Linkage::Strong, 519 Scope::Default, false, false); 520 // Add a symbol that extends beyond the split. 521 auto &S5 = G.addDefinedSymbol(B1, 0, "S5", 16, Linkage::Strong, 522 Scope::Default, false, false); 523 524 // Add an extra block, EB, and target symbols, and use these to add edges 525 // from B1 to EB. 526 orc::ExecutorAddr EBAddr(0x2000); 527 auto &EB = G.createContentBlock(Sec, BlockContent, EBAddr, 8, 0); 528 auto &ES1 = G.addDefinedSymbol(EB, 0, "TS1", 4, Linkage::Strong, 529 Scope::Default, false, false); 530 auto &ES2 = G.addDefinedSymbol(EB, 4, "TS2", 4, Linkage::Strong, 531 Scope::Default, false, false); 532 auto &ES3 = G.addDefinedSymbol(EB, 8, "TS3", 4, Linkage::Strong, 533 Scope::Default, false, false); 534 auto &ES4 = G.addDefinedSymbol(EB, 12, "TS4", 4, Linkage::Strong, 535 Scope::Default, false, false); 536 537 // Add edges from B1 to EB. 538 B1.addEdge(Edge::FirstRelocation, 0, ES1, 0); 539 B1.addEdge(Edge::FirstRelocation, 4, ES2, 0); 540 B1.addEdge(Edge::FirstRelocation, 8, ES3, 0); 541 B1.addEdge(Edge::FirstRelocation, 12, ES4, 0); 542 543 // Split B1. 544 auto &B2 = G.splitBlock(B1, 8); 545 546 // Check that the block addresses and content matches what we would expect. 547 EXPECT_EQ(B1.getAddress(), B1Addr + 8); 548 EXPECT_EQ(B1.getContent(), BlockContent.slice(8)); 549 550 EXPECT_EQ(B2.getAddress(), B1Addr); 551 EXPECT_EQ(B2.getContent(), BlockContent.slice(0, 8)); 552 553 // Check that symbols in B1 were transferred as expected: 554 // We expect S1 and S2 to have been transferred to B2, and S3 and S4 to have 555 // remained attached to B1. Symbols S3 and S4 should have had their offsets 556 // slid to account for the change in address of B2. 557 EXPECT_EQ(&S1.getBlock(), &B2); 558 EXPECT_EQ(S1.getOffset(), 0U); 559 560 EXPECT_EQ(&S2.getBlock(), &B2); 561 EXPECT_EQ(S2.getOffset(), 4U); 562 563 EXPECT_EQ(&S3.getBlock(), &B1); 564 EXPECT_EQ(S3.getOffset(), 0U); 565 566 EXPECT_EQ(&S4.getBlock(), &B1); 567 EXPECT_EQ(S4.getOffset(), 4U); 568 569 EXPECT_EQ(&S5.getBlock(), &B2); 570 EXPECT_EQ(S5.getOffset(), 0U); 571 // Size shrinks to fit. 572 EXPECT_EQ(S5.getSize(), 8U); 573 574 // Check that edges in B1 have been transferred as expected: 575 // Both blocks should now have two edges each at offsets 0 and 4. 576 EXPECT_EQ(llvm::size(B1.edges()), 2); 577 if (size(B1.edges()) == 2) { 578 auto *E1 = &*B1.edges().begin(); 579 auto *E2 = &*(B1.edges().begin() + 1); 580 if (E2->getOffset() < E1->getOffset()) 581 std::swap(E1, E2); 582 EXPECT_EQ(E1->getOffset(), 0U); 583 EXPECT_EQ(E2->getOffset(), 4U); 584 } 585 586 EXPECT_EQ(llvm::size(B2.edges()), 2); 587 if (size(B2.edges()) == 2) { 588 auto *E1 = &*B2.edges().begin(); 589 auto *E2 = &*(B2.edges().begin() + 1); 590 if (E2->getOffset() < E1->getOffset()) 591 std::swap(E1, E2); 592 EXPECT_EQ(E1->getOffset(), 0U); 593 EXPECT_EQ(E2->getOffset(), 4U); 594 } 595 } 596