Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size, uint64_t Alignment, uint8_t Binding, uint8_t StOther, uint8_t Type, InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(N, Type, StOther & 3, /*CanOmitFromDynSym*/ false, /*IsUsedInRegularObj*/ true, File); int Cmp = compareDefined(S, WasInserted, Binding); if (Cmp > 0) { S->Binding = Binding; replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File); } else if (Cmp == 0) { auto *C = dyn_cast<DefinedCommon>(S->body()); if (!C) { // Non-common symbols take precedence over common symbols. if (Config->WarnCommon) warning("common " + S->body()->getName() + " is overridden"); return S; } if (Config->WarnCommon) warning("multiple common of " + S->body()->getName()); C->Size = std::max(C->Size, Size); C->Alignment = std::max(C->Alignment, Alignment); } return S; }
void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F, const object::Archive::Symbol Sym) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Sym.getName()); if (WasInserted) { replaceBody<LazyArchive>(S, *F, Sym, SymbolBody::UnknownType); return; } if (!S->body()->isUndefined()) return; // Weak undefined symbols should not fetch members from archives. If we were // to keep old symbol we would not know that an archive member was available // if a strong undefined symbol shows up afterwards in the link. If a strong // undefined symbol never shows up, this lazy symbol will get to the end of // the link and must be treated as the weak undefined one. We already marked // this symbol as used when we added it to the symbol table, but we also need // to preserve its type. FIXME: Move the Type field to Symbol. if (S->isWeak()) { replaceBody<LazyArchive>(S, *F, Sym, S->body()->Type); return; } MemoryBufferRef MBRef = F->getMember(&Sym); if (!MBRef.getBuffer().empty()) addFile(createObjectFile(MBRef, F->getName())); }
Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, StOther & 3, CanOmitFromDynSym, /*IsUsedInRegularObj*/ !File || !isa<BitcodeFile>(File), File); if (WasInserted) { S->Binding = Binding; replaceBody<Undefined>(S, Name, StOther, Type, File); return S; } if (Binding != STB_WEAK) { if (S->body()->isShared() || S->body()->isLazy()) S->Binding = Binding; if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(S->body())) SS->file()->IsUsed = true; } if (auto *L = dyn_cast<Lazy>(S->body())) { // An undefined weak will not fetch archive members, but we have to remember // its type. See also comment in addLazyArchive. if (S->isWeak()) L->Type = Type; else if (auto F = L->fetch()) addFile(std::move(F)); } return S; }
void Writer::fixSafeSEHSymbols() { if (!SEHTable) return; // Replace the absolute table symbol with a synthetic symbol pointing to the // SEHTable chunk so that we can emit base relocations for it and resolve // section relative relocations. Symbol *T = Symtab->find("___safe_se_handler_table"); Symbol *C = Symtab->find("___safe_se_handler_count"); replaceBody<DefinedSynthetic>(T, T->body()->getName(), SEHTable); cast<DefinedAbsolute>(C->body())->setVA(SEHTable->getSize() / 4); }
DefinedRegular<ELFT> *SymbolTable<ELFT>::addAbsolute(StringRef Name, uint8_t Visibility, uint8_t Binding) { Symbol *Sym = addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, nullptr, nullptr); return cast<DefinedRegular<ELFT>>(Sym->body()); }
void BitcodeCompiler::add(BitcodeFile &F) { lto::InputFile &Obj = *F.Obj; if (Obj.getDataLayoutStr().empty()) fatal("invalid bitcode file: " + F.getName() + " has no datalayout"); unsigned SymNum = 0; std::vector<Symbol *> Syms = F.getSymbols(); std::vector<lto::SymbolResolution> Resols(Syms.size()); // Provide a resolution to the LTO API for each symbol. for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) { Symbol *Sym = Syms[SymNum]; lto::SymbolResolution &R = Resols[SymNum]; ++SymNum; SymbolBody *B = Sym->body(); // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile // reports two symbols for module ASM defined. Without this check, lld // flags an undefined in IR with a definition in ASM as prevailing. // Once IRObjectFile is fixed to report only one symbol this hack can // be removed. R.Prevailing = !(ObjSym.getFlags() & object::BasicSymbolRef::SF_Undefined) && B->File == &F; R.VisibleToRegularObj = Sym->IsUsedInRegularObj || (R.Prevailing && Sym->includeInDynsym()); if (R.Prevailing) undefine(Sym); } checkError(LtoObj->add(std::move(F.Obj), Resols)); }
std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name, uint8_t Type, uint8_t Visibility, bool CanOmitFromDynSym, InputFile *File) { bool IsUsedInRegularObj = !File || File->kind() == InputFile::ObjectKind; Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); // Merge in the new symbol's visibility. S->Visibility = getMinVisibility(S->Visibility, Visibility); if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic)) S->ExportDynamic = true; if (IsUsedInRegularObj) S->IsUsedInRegularObj = true; if (!WasInserted && S->body()->Type != SymbolBody::UnknownType && ((Type == STT_TLS) != S->body()->isTls())) error("TLS attribute mismatch for symbol " + conflictMsg(S->body(), File)); return {S, WasInserted}; }
void SymbolTable<ELFT>::addLazyObject(StringRef Name, LazyObjectFile &Obj) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name); if (WasInserted) { replaceBody<LazyObject>(S, Name, Obj, SymbolBody::UnknownType); return; } if (!S->body()->isUndefined()) return; // See comment for addLazyArchive above. if (S->isWeak()) { replaceBody<LazyObject>(S, Name, Obj, S->body()->Type); } else { MemoryBufferRef MBRef = Obj.getBuffer(); if (!MBRef.getBuffer().empty()) addFile(createObjectFile(MBRef)); } }
Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t Binding, uint8_t StOther) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, STT_NOTYPE, StOther & 3, /*CanOmitFromDynSym*/ false, /*IsUsedInRegularObj*/ true, nullptr); int Cmp = compareDefinedNonCommon(S, WasInserted, Binding); if (Cmp > 0) replaceBody<DefinedRegular<ELFT>>(S, Name, StOther); else if (Cmp == 0) reportDuplicate(S->body(), nullptr); return S; }
Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, bool IsWeak, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *F) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, StOther & 3, CanOmitFromDynSym, /*IsUsedInRegularObj*/ false, F); int Cmp = compareDefinedNonCommon(S, WasInserted, IsWeak ? STB_WEAK : STB_GLOBAL); if (Cmp > 0) replaceBody<DefinedBitcode>(S, Name, StOther, Type, F); else if (Cmp == 0) reportDuplicate(S->body(), F); return S; }
Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N, OutputSectionBase<ELFT> *Section, uintX_t Value) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(N, STT_NOTYPE, STV_HIDDEN, /*CanOmitFromDynSym*/ false, /*IsUsedInRegularObj*/ true, nullptr); int Cmp = compareDefinedNonCommon(S, WasInserted, STB_GLOBAL); if (Cmp > 0) replaceBody<DefinedSynthetic<ELFT>>(S, N, Value, Section); else if (Cmp == 0) reportDuplicate(S->body(), nullptr); return S; }
Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, const Elf_Sym &Sym, InputSectionBase<ELFT> *Section) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Sym.getType(), Sym.getVisibility(), /*CanOmitFromDynSym*/ false, /*IsUsedInRegularObj*/ true, Section ? Section->getFile() : nullptr); int Cmp = compareDefinedNonCommon(S, WasInserted, Sym.getBinding()); if (Cmp > 0) replaceBody<DefinedRegular<ELFT>>(S, Name, Sym, Section); else if (Cmp == 0) reportDuplicate(S->body(), Section->getFile()); return S; }
Symbol *SymbolTable<ELFT>::addSynthetic(StringRef N, const OutputSectionBase *Section, uintX_t Value, uint8_t StOther) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(N, STT_NOTYPE, getVisibility(StOther), /*CanOmitFromDynSym*/ false, nullptr); int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, STB_GLOBAL, /*IsAbsolute*/ false, /*Value*/ 0); if (Cmp > 0) replaceBody<DefinedSynthetic>(S, N, Value, Section); else if (Cmp == 0) reportDuplicate(S->body(), nullptr); return S; }
Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, BitcodeFile *F) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F); int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding, /*IsAbs*/ false, /*Value*/ 0); if (Cmp > 0) replaceBody<DefinedRegular<ELFT>>(S, Name, /*IsLocal=*/false, StOther, Type, 0, 0, nullptr, F); else if (Cmp == 0) reportDuplicate(S->body(), F); return S; }
Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, uintX_t Value, uintX_t Size, uint8_t Binding, InputSectionBase<ELFT> *Section, InputFile *File) { Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), /*CanOmitFromDynSym*/ false, File); int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding, Section == nullptr, Value); if (Cmp > 0) replaceBody<DefinedRegular<ELFT>>(S, Name, /*IsLocal=*/false, StOther, Type, Value, Size, Section, File); else if (Cmp == 0) reportDuplicate(S->body(), Section, Value); return S; }
void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym, const typename ELFT::Verdef *Verdef) { // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT // as the visibility, which will leave the visibility in the symbol table // unchanged. Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, /*IsUsedInRegularObj*/ false, F); // Make sure we preempt DSO symbols with default visibility. if (Sym.getVisibility() == STV_DEFAULT) S->ExportDynamic = true; if (WasInserted || isa<Undefined>(S->body())) { replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef); if (!S->isWeak()) F->IsUsed = true; } }
void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym, const typename ELFT::Verdef *Verdef) { // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT // as the visibility, which will leave the visibility in the symbol table // unchanged. Symbol *S; bool WasInserted; std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, F); // Make sure we preempt DSO symbols with default visibility. if (Sym.getVisibility() == STV_DEFAULT) { S->ExportDynamic = true; // Exporting preempting symbols takes precedence over linker scripts. if (S->VersionId == VER_NDX_LOCAL) S->VersionId = VER_NDX_GLOBAL; } if (WasInserted || isa<Undefined<ELFT>>(S->body())) { replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef); if (!S->isWeak()) F->IsUsed = true; } }
void BitcodeCompiler::add(BitcodeFile &F) { std::unique_ptr<IRObjectFile> Obj = std::move(F.Obj); std::vector<GlobalValue *> Keep; unsigned BodyIndex = 0; ArrayRef<Symbol *> Syms = F.getSymbols(); Module &M = Obj->getModule(); if (M.getDataLayoutStr().empty()) fatal("invalid bitcode file: " + F.getName() + " has no datalayout"); // Discard non-compatible debug infos if necessary. M.materializeMetadata(); UpgradeDebugInfo(M); // If a symbol appears in @llvm.used, the linker is required // to treat the symbol as there is a reference to the symbol // that it cannot see. Therefore, we can't internalize. SmallPtrSet<GlobalValue *, 8> Used; collectUsedGlobalVariables(M, Used, /* CompilerUsed */ false); for (const BasicSymbolRef &Sym : Obj->symbols()) { uint32_t Flags = Sym.getFlags(); GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl()); if (GV && GV->hasAppendingLinkage()) Keep.push_back(GV); if (BitcodeFile::shouldSkip(Flags)) continue; Symbol *S = Syms[BodyIndex++]; if (Flags & BasicSymbolRef::SF_Undefined) { handleUndefinedAsmRefs(Sym, GV, AsmUndefinedRefs); continue; } auto *B = dyn_cast<DefinedBitcode>(S->body()); if (!B || B->File != &F) continue; // We collect the set of symbols we want to internalize here // and change the linkage after the IRMover executed, i.e. after // we imported the symbols and satisfied undefined references // to it. We can't just change linkage here because otherwise // the IRMover will just rename the symbol. if (GV && shouldInternalize(Used, S, GV)) InternalizedSyms.insert(GV->getName()); // At this point we know that either the combined LTO object will provide a // definition of a symbol, or we will internalize it. In either case, we // need to undefine the symbol. In the former case, the real definition // needs to be able to replace the original definition without conflicting. // In the latter case, we need to allow the combined LTO object to provide a // definition with the same name, for example when doing parallel codegen. undefine(S); if (!GV) // Module asm symbol. continue; switch (GV->getLinkage()) { default: break; case llvm::GlobalValue::LinkOnceAnyLinkage: GV->setLinkage(GlobalValue::WeakAnyLinkage); break; case llvm::GlobalValue::LinkOnceODRLinkage: GV->setLinkage(GlobalValue::WeakODRLinkage); break; } Keep.push_back(GV); } if (Error E = Mover.move(Obj->takeModule(), Keep, [](GlobalValue &, IRMover::ValueAdder) {})) { handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EIB) { fatal("failed to link module " + F.getName() + ": " + EIB.message()); }); } }