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