1 //===- SymbolTable.cpp ----------------------------------------------------===// 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 "SymbolTable.h" 10 #include "Config.h" 11 #include "InputChunks.h" 12 #include "InputEvent.h" 13 #include "InputGlobal.h" 14 #include "WriterUtils.h" 15 #include "lld/Common/ErrorHandler.h" 16 #include "lld/Common/Memory.h" 17 #include "llvm/ADT/SetVector.h" 18 19 #define DEBUG_TYPE "lld" 20 21 using namespace llvm; 22 using namespace llvm::wasm; 23 using namespace llvm::object; 24 using namespace lld; 25 using namespace lld::wasm; 26 27 SymbolTable *lld::wasm::Symtab; 28 29 void SymbolTable::addFile(InputFile *File) { 30 log("Processing: " + toString(File)); 31 32 // .a file 33 if (auto *F = dyn_cast<ArchiveFile>(File)) { 34 F->parse(); 35 return; 36 } 37 38 // .so file 39 if (auto *F = dyn_cast<SharedFile>(File)) { 40 SharedFiles.push_back(F); 41 return; 42 } 43 44 if (Config->Trace) 45 message(toString(File)); 46 47 // LLVM bitcode file 48 if (auto *F = dyn_cast<BitcodeFile>(File)) { 49 F->parse(); 50 BitcodeFiles.push_back(F); 51 return; 52 } 53 54 // Regular object file 55 auto *F = cast<ObjFile>(File); 56 F->parse(false); 57 ObjectFiles.push_back(F); 58 } 59 60 // This function is where all the optimizations of link-time 61 // optimization happens. When LTO is in use, some input files are 62 // not in native object file format but in the LLVM bitcode format. 63 // This function compiles bitcode files into a few big native files 64 // using LLVM functions and replaces bitcode symbols with the results. 65 // Because all bitcode files that the program consists of are passed 66 // to the compiler at once, it can do whole-program optimization. 67 void SymbolTable::addCombinedLTOObject() { 68 if (BitcodeFiles.empty()) 69 return; 70 71 // Compile bitcode files and replace bitcode symbols. 72 LTO.reset(new BitcodeCompiler); 73 for (BitcodeFile *F : BitcodeFiles) 74 LTO->add(*F); 75 76 for (StringRef Filename : LTO->compile()) { 77 auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp"), ""); 78 Obj->parse(true); 79 ObjectFiles.push_back(Obj); 80 } 81 } 82 83 void SymbolTable::reportRemainingUndefines() { 84 for (const auto& Pair : SymMap) { 85 const Symbol *Sym = SymVector[Pair.second]; 86 if (!Sym->isUndefined() || Sym->isWeak()) 87 continue; 88 if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0) 89 continue; 90 if (!Sym->IsUsedInRegularObj) 91 continue; 92 error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); 93 } 94 } 95 96 Symbol *SymbolTable::find(StringRef Name) { 97 auto It = SymMap.find(CachedHashStringRef(Name)); 98 if (It == SymMap.end() || It->second == -1) 99 return nullptr; 100 return SymVector[It->second]; 101 } 102 103 void SymbolTable::replace(StringRef Name, Symbol* Sym) { 104 auto It = SymMap.find(CachedHashStringRef(Name)); 105 SymVector[It->second] = Sym; 106 } 107 108 std::pair<Symbol *, bool> SymbolTable::insertName(StringRef Name) { 109 bool Trace = false; 110 auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()}); 111 int &SymIndex = P.first->second; 112 bool IsNew = P.second; 113 if (SymIndex == -1) { 114 SymIndex = SymVector.size(); 115 Trace = true; 116 IsNew = true; 117 } 118 119 if (!IsNew) 120 return {SymVector[SymIndex], false}; 121 122 Symbol *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 123 Sym->IsUsedInRegularObj = false; 124 Sym->CanInline = true; 125 Sym->Traced = Trace; 126 SymVector.emplace_back(Sym); 127 return {Sym, true}; 128 } 129 130 std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, 131 const InputFile *File) { 132 Symbol *S; 133 bool WasInserted; 134 std::tie(S, WasInserted) = insertName(Name); 135 136 if (!File || File->kind() == InputFile::ObjectKind) 137 S->IsUsedInRegularObj = true; 138 139 return {S, WasInserted}; 140 } 141 142 static void reportTypeError(const Symbol *Existing, const InputFile *File, 143 llvm::wasm::WasmSymbolType Type) { 144 error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " + 145 toString(Existing->getWasmType()) + " in " + 146 toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) + 147 " in " + toString(File)); 148 } 149 150 // Check the type of new symbol matches that of the symbol is replacing. 151 // Returns true if the function types match, false is there is a singature 152 // mismatch. 153 static bool signatureMatches(FunctionSymbol *Existing, 154 const WasmSignature *NewSig) { 155 const WasmSignature *OldSig = Existing->Signature; 156 157 // If either function is missing a signature (this happend for bitcode 158 // symbols) then assume they match. Any mismatch will be reported later 159 // when the LTO objects are added. 160 if (!NewSig || !OldSig) 161 return true; 162 163 return *NewSig == *OldSig; 164 } 165 166 static void checkGlobalType(const Symbol *Existing, const InputFile *File, 167 const WasmGlobalType *NewType) { 168 if (!isa<GlobalSymbol>(Existing)) { 169 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL); 170 return; 171 } 172 173 const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType(); 174 if (*NewType != *OldType) { 175 error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " + 176 toString(*OldType) + " in " + toString(Existing->getFile()) + 177 "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 178 } 179 } 180 181 static void checkEventType(const Symbol *Existing, const InputFile *File, 182 const WasmEventType *NewType, 183 const WasmSignature *NewSig) { 184 auto ExistingEvent = dyn_cast<EventSymbol>(Existing); 185 if (!isa<EventSymbol>(Existing)) { 186 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT); 187 return; 188 } 189 190 const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType(); 191 const WasmSignature *OldSig = ExistingEvent->Signature; 192 if (NewType->Attribute != OldType->Attribute) 193 error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " + 194 toString(*OldType) + " in " + toString(Existing->getFile()) + 195 "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); 196 if (*NewSig != *OldSig) 197 warn("Event signature mismatch: " + Existing->getName() + 198 "\n>>> defined as " + toString(*OldSig) + " in " + 199 toString(Existing->getFile()) + "\n>>> defined as " + 200 toString(*NewSig) + " in " + toString(File)); 201 } 202 203 static void checkDataType(const Symbol *Existing, const InputFile *File) { 204 if (!isa<DataSymbol>(Existing)) 205 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); 206 } 207 208 DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, 209 uint32_t Flags, 210 InputFunction *Function) { 211 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); 212 assert(!find(Name)); 213 SyntheticFunctions.emplace_back(Function); 214 return replaceSymbol<DefinedFunction>(insertName(Name).first, Name, 215 Flags, nullptr, Function); 216 } 217 218 // Adds an optional, linker generated, data symbols. The symbol will only be 219 // added if there is an undefine reference to it, or if it is explictly exported 220 // via the --export flag. Otherwise we don't add the symbol and return nullptr. 221 DefinedData *SymbolTable::addOptionalDataSymbol(StringRef Name, uint32_t Value, 222 uint32_t Flags) { 223 Symbol *S = find(Name); 224 if (!S && (Config->ExportAll || Config->ExportedSymbols.count(Name) != 0)) 225 S = insertName(Name).first; 226 else if (!S || S->isDefined()) 227 return nullptr; 228 LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << Name << "\n"); 229 auto *rtn = replaceSymbol<DefinedData>(S, Name, Flags); 230 rtn->setVirtualAddress(Value); 231 return rtn; 232 } 233 234 DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, 235 uint32_t Flags) { 236 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); 237 assert(!find(Name)); 238 return replaceSymbol<DefinedData>(insertName(Name).first, Name, Flags); 239 } 240 241 DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, 242 InputGlobal *Global) { 243 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global 244 << "\n"); 245 assert(!find(Name)); 246 SyntheticGlobals.emplace_back(Global); 247 return replaceSymbol<DefinedGlobal>(insertName(Name).first, Name, Flags, 248 nullptr, Global); 249 } 250 251 static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, 252 uint32_t NewFlags) { 253 // If existing symbol is undefined, replace it. 254 if (!Existing->isDefined()) { 255 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: " 256 << Existing->getName() << "\n"); 257 return true; 258 } 259 260 // Now we have two defined symbols. If the new one is weak, we can ignore it. 261 if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { 262 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n"); 263 return false; 264 } 265 266 // If the existing symbol is weak, we should replace it. 267 if (Existing->isWeak()) { 268 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n"); 269 return true; 270 } 271 272 // Neither symbol is week. They conflict. 273 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " + 274 toString(Existing->getFile()) + "\n>>> defined in " + 275 toString(NewFile)); 276 return true; 277 } 278 279 Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, 280 InputFile *File, 281 InputFunction *Function) { 282 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" 283 << (Function ? toString(Function->Signature) : "none") 284 << "]\n"); 285 Symbol *S; 286 bool WasInserted; 287 std::tie(S, WasInserted) = insert(Name, File); 288 289 auto Replace = [&](Symbol* Sym) { 290 // If the new defined function doesn't have signture (i.e. bitcode 291 // functions) but the old symbol does, then preserve the old signature 292 const WasmSignature *OldSig = S->getSignature(); 293 auto* NewSym = replaceSymbol<DefinedFunction>(Sym, Name, Flags, File, Function); 294 if (!NewSym->Signature) 295 NewSym->Signature = OldSig; 296 }; 297 298 if (WasInserted || S->isLazy()) { 299 Replace(S); 300 return S; 301 } 302 303 auto ExistingFunction = dyn_cast<FunctionSymbol>(S); 304 if (!ExistingFunction) { 305 reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION); 306 return S; 307 } 308 309 bool CheckSig = true; 310 if (auto UD = dyn_cast<UndefinedFunction>(ExistingFunction)) 311 CheckSig = UD->IsCalledDirectly; 312 313 if (CheckSig && Function && !signatureMatches(ExistingFunction, &Function->Signature)) { 314 Symbol* Variant; 315 if (getFunctionVariant(S, &Function->Signature, File, &Variant)) 316 // New variant, always replace 317 Replace(Variant); 318 else if (shouldReplace(S, File, Flags)) 319 // Variant already exists, replace it after checking shouldReplace 320 Replace(Variant); 321 322 // This variant we found take the place in the symbol table as the primary 323 // variant. 324 replace(Name, Variant); 325 return Variant; 326 } 327 328 // Existing function with matching signature. 329 if (shouldReplace(S, File, Flags)) 330 Replace(S); 331 332 return S; 333 } 334 335 Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, 336 InputFile *File, InputSegment *Segment, 337 uint32_t Address, uint32_t Size) { 338 LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address 339 << "\n"); 340 Symbol *S; 341 bool WasInserted; 342 std::tie(S, WasInserted) = insert(Name, File); 343 344 auto Replace = [&]() { 345 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); 346 }; 347 348 if (WasInserted || S->isLazy()) { 349 Replace(); 350 return S; 351 } 352 353 checkDataType(S, File); 354 355 if (shouldReplace(S, File, Flags)) 356 Replace(); 357 return S; 358 } 359 360 Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, 361 InputFile *File, InputGlobal *Global) { 362 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); 363 364 Symbol *S; 365 bool WasInserted; 366 std::tie(S, WasInserted) = insert(Name, File); 367 368 auto Replace = [&]() { 369 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); 370 }; 371 372 if (WasInserted || S->isLazy()) { 373 Replace(); 374 return S; 375 } 376 377 checkGlobalType(S, File, &Global->getType()); 378 379 if (shouldReplace(S, File, Flags)) 380 Replace(); 381 return S; 382 } 383 384 Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags, 385 InputFile *File, InputEvent *Event) { 386 LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n"); 387 388 Symbol *S; 389 bool WasInserted; 390 std::tie(S, WasInserted) = insert(Name, File); 391 392 auto Replace = [&]() { 393 replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); 394 }; 395 396 if (WasInserted || S->isLazy()) { 397 Replace(); 398 return S; 399 } 400 401 checkEventType(S, File, &Event->getType(), &Event->Signature); 402 403 if (shouldReplace(S, File, Flags)) 404 Replace(); 405 return S; 406 } 407 408 Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName, 409 StringRef ImportModule, 410 uint32_t Flags, InputFile *File, 411 const WasmSignature *Sig, 412 bool IsCalledDirectly) { 413 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << " [" 414 << (Sig ? toString(*Sig) : "none") 415 << "] IsCalledDirectly:" << IsCalledDirectly << "\n"); 416 417 Symbol *S; 418 bool WasInserted; 419 std::tie(S, WasInserted) = insert(Name, File); 420 if (S->Traced) 421 printTraceSymbolUndefined(Name, File); 422 423 auto Replace = [&]() { 424 replaceSymbol<UndefinedFunction>(S, Name, ImportName, ImportModule, Flags, 425 File, Sig, IsCalledDirectly); 426 }; 427 428 if (WasInserted) 429 Replace(); 430 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 431 Lazy->fetch(); 432 else { 433 auto ExistingFunction = dyn_cast<FunctionSymbol>(S); 434 if (!ExistingFunction) { 435 reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION); 436 return S; 437 } 438 if (!ExistingFunction->Signature && Sig) 439 ExistingFunction->Signature = Sig; 440 if (IsCalledDirectly && !signatureMatches(ExistingFunction, Sig)) 441 if (getFunctionVariant(S, Sig, File, &S)) 442 Replace(); 443 } 444 445 return S; 446 } 447 448 Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, 449 InputFile *File) { 450 LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n"); 451 452 Symbol *S; 453 bool WasInserted; 454 std::tie(S, WasInserted) = insert(Name, File); 455 if (S->Traced) 456 printTraceSymbolUndefined(Name, File); 457 458 if (WasInserted) 459 replaceSymbol<UndefinedData>(S, Name, Flags, File); 460 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 461 Lazy->fetch(); 462 else if (S->isDefined()) 463 checkDataType(S, File); 464 return S; 465 } 466 467 Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName, 468 StringRef ImportModule, uint32_t Flags, 469 InputFile *File, 470 const WasmGlobalType *Type) { 471 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n"); 472 473 Symbol *S; 474 bool WasInserted; 475 std::tie(S, WasInserted) = insert(Name, File); 476 if (S->Traced) 477 printTraceSymbolUndefined(Name, File); 478 479 if (WasInserted) 480 replaceSymbol<UndefinedGlobal>(S, Name, ImportName, ImportModule, Flags, 481 File, Type); 482 else if (auto *Lazy = dyn_cast<LazySymbol>(S)) 483 Lazy->fetch(); 484 else if (S->isDefined()) 485 checkGlobalType(S, File, Type); 486 return S; 487 } 488 489 void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { 490 LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n"); 491 StringRef Name = Sym->getName(); 492 493 Symbol *S; 494 bool WasInserted; 495 std::tie(S, WasInserted) = insertName(Name); 496 497 if (WasInserted) { 498 replaceSymbol<LazySymbol>(S, Name, 0, File, *Sym); 499 return; 500 } 501 502 if (!S->isUndefined()) 503 return; 504 505 // The existing symbol is undefined, load a new one from the archive, 506 // unless the the existing symbol is weak in which case replace the undefined 507 // symbols with a LazySymbol. 508 if (S->isWeak()) { 509 const WasmSignature *OldSig = nullptr; 510 // In the case of an UndefinedFunction we need to preserve the expected 511 // signature. 512 if (auto *F = dyn_cast<UndefinedFunction>(S)) 513 OldSig = F->Signature; 514 LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n"); 515 auto NewSym = replaceSymbol<LazySymbol>(S, Name, WASM_SYMBOL_BINDING_WEAK, 516 File, *Sym); 517 NewSym->Signature = OldSig; 518 return; 519 } 520 521 LLVM_DEBUG(dbgs() << "replacing existing undefined\n"); 522 File->addMember(Sym); 523 } 524 525 bool SymbolTable::addComdat(StringRef Name) { 526 return ComdatGroups.insert(CachedHashStringRef(Name)).second; 527 } 528 529 // The new signature doesn't match. Create a variant to the symbol with the 530 // signature encoded in the name and return that instead. These symbols are 531 // then unified later in handleSymbolVariants. 532 bool SymbolTable::getFunctionVariant(Symbol* Sym, const WasmSignature *Sig, 533 const InputFile *File, Symbol **Out) { 534 LLVM_DEBUG(dbgs() << "getFunctionVariant: " << Sym->getName() << " -> " 535 << " " << toString(*Sig) << "\n"); 536 Symbol *Variant = nullptr; 537 538 // Linear search through symbol variants. Should never be more than two 539 // or three entries here. 540 auto &Variants = SymVariants[CachedHashStringRef(Sym->getName())]; 541 if (Variants.empty()) 542 Variants.push_back(Sym); 543 544 for (Symbol* V : Variants) { 545 if (*V->getSignature() == *Sig) { 546 Variant = V; 547 break; 548 } 549 } 550 551 bool WasAdded = !Variant; 552 if (WasAdded) { 553 // Create a new variant; 554 LLVM_DEBUG(dbgs() << "added new variant\n"); 555 Variant = reinterpret_cast<Symbol *>(make<SymbolUnion>()); 556 Variants.push_back(Variant); 557 } else { 558 LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*Variant) << "\n"); 559 assert(*Variant->getSignature() == *Sig); 560 } 561 562 *Out = Variant; 563 return WasAdded; 564 } 565 566 // Set a flag for --trace-symbol so that we can print out a log message 567 // if a new symbol with the same name is inserted into the symbol table. 568 void SymbolTable::trace(StringRef Name) { 569 SymMap.insert({CachedHashStringRef(Name), -1}); 570 } 571 572 void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) { 573 // Swap symbols as instructed by -wrap. 574 int &OrigIdx = SymMap[CachedHashStringRef(Sym->getName())]; 575 int &RealIdx= SymMap[CachedHashStringRef(Real->getName())]; 576 int &WrapIdx = SymMap[CachedHashStringRef(Wrap->getName())]; 577 LLVM_DEBUG(dbgs() << "wrap: " << Sym->getName() << "\n"); 578 579 // Anyone looking up __real symbols should get the original 580 RealIdx = OrigIdx; 581 // Anyone looking up the original should get the __wrap symbol 582 OrigIdx = WrapIdx; 583 } 584 585 static const uint8_t UnreachableFn[] = { 586 0x03 /* ULEB length */, 0x00 /* ULEB num locals */, 587 0x00 /* opcode unreachable */, 0x0b /* opcode end */ 588 }; 589 590 // Replace the given symbol body with an unreachable function. 591 // This is used by handleWeakUndefines in order to generate a callable 592 // equivalent of an undefined function and also handleSymbolVariants for 593 // undefined functions that don't match the signature of the definition. 594 InputFunction *SymbolTable::replaceWithUnreachable(Symbol *Sym, 595 const WasmSignature &Sig, 596 StringRef DebugName) { 597 auto *Func = make<SyntheticFunction>(Sig, Sym->getName(), DebugName); 598 Func->setBody(UnreachableFn); 599 SyntheticFunctions.emplace_back(Func); 600 replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Sym->getFlags(), nullptr, 601 Func); 602 return Func; 603 } 604 605 // For weak undefined functions, there may be "call" instructions that reference 606 // the symbol. In this case, we need to synthesise a dummy/stub function that 607 // will abort at runtime, so that relocations can still provided an operand to 608 // the call instruction that passes Wasm validation. 609 void SymbolTable::handleWeakUndefines() { 610 for (Symbol *Sym : getSymbols()) { 611 if (!Sym->isUndefWeak()) 612 continue; 613 614 const WasmSignature *Sig = Sym->getSignature(); 615 if (!Sig) { 616 // It is possible for undefined functions not to have a signature (eg. if 617 // added via "--undefined"), but weak undefined ones do have a signature. 618 // Lazy symbols may not be functions and therefore Sig can still be null 619 // in some circumstantce. 620 assert(!isa<FunctionSymbol>(Sym)); 621 continue; 622 } 623 624 // Add a synthetic dummy for weak undefined functions. These dummies will 625 // be GC'd if not used as the target of any "call" instructions. 626 StringRef DebugName = Saver.save("undefined:" + toString(*Sym)); 627 InputFunction* Func = replaceWithUnreachable(Sym, *Sig, DebugName); 628 // Ensure it compares equal to the null pointer, and so that table relocs 629 // don't pull in the stub body (only call-operand relocs should do that). 630 Func->setTableIndex(0); 631 // Hide our dummy to prevent export. 632 Sym->setHidden(true); 633 } 634 } 635 636 static void reportFunctionSignatureMismatch(StringRef SymName, 637 FunctionSymbol *A, 638 FunctionSymbol *B, bool Error) { 639 std::string msg = ("function signature mismatch: " + SymName + 640 "\n>>> defined as " + toString(*A->Signature) + " in " + 641 toString(A->getFile()) + "\n>>> defined as " + 642 toString(*B->Signature) + " in " + toString(B->getFile())) 643 .str(); 644 if (Error) 645 error(msg); 646 else 647 warn(msg); 648 } 649 650 // Remove any variant symbols that were created due to function signature 651 // mismatches. 652 void SymbolTable::handleSymbolVariants() { 653 for (auto Pair : SymVariants) { 654 // Push the initial symbol onto the list of variants. 655 StringRef SymName = Pair.first.val(); 656 std::vector<Symbol *> &Variants = Pair.second; 657 658 #ifndef NDEBUG 659 LLVM_DEBUG(dbgs() << "symbol with (" << Variants.size() 660 << ") variants: " << SymName << "\n"); 661 for (auto *S: Variants) { 662 auto *F = cast<FunctionSymbol>(S); 663 LLVM_DEBUG(dbgs() << " variant: " + F->getName() << " " 664 << toString(*F->Signature) << "\n"); 665 } 666 #endif 667 668 // Find the one definition. 669 DefinedFunction *Defined = nullptr; 670 for (auto *Symbol : Variants) { 671 if (auto F = dyn_cast<DefinedFunction>(Symbol)) { 672 Defined = F; 673 break; 674 } 675 } 676 677 // If there are no definitions, and the undefined symbols disagree on 678 // the signature, there is not we can do since we don't know which one 679 // to use as the signature on the import. 680 if (!Defined) { 681 reportFunctionSignatureMismatch(SymName, 682 cast<FunctionSymbol>(Variants[0]), 683 cast<FunctionSymbol>(Variants[1]), true); 684 return; 685 } 686 687 for (auto *Symbol : Variants) { 688 if (Symbol != Defined) { 689 auto *F = cast<FunctionSymbol>(Symbol); 690 reportFunctionSignatureMismatch(SymName, F, Defined, false); 691 StringRef DebugName = Saver.save("unreachable:" + toString(*F)); 692 replaceWithUnreachable(F, *F->Signature, DebugName); 693 } 694 } 695 } 696 } 697