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