// Versions are usually assigned to symbols using version scripts, // but there's another way to assign versions to symbols. // If a symbol name contains '@', the string after it is not // actually a part of the symbol name but specifies a version. // This function takes care of it. template <class ELFT> void SymbolTable<ELFT>::scanSymbolVersions() { if (Config->VersionDefinitions.empty()) return; int MaxVersionLen = getMaxVersionLen(); // Unfortunately there's no way other than iterating over all // symbols to look for '@' characters in symbol names. // So this is inherently slow. A good news is that we do this // only when versions have been defined. for (Symbol *Sym : SymVector) { // Symbol versions for exported symbols are by nature // only for defined global symbols. SymbolBody *B = Sym->body(); if (!B->isDefined()) continue; uint8_t Visibility = B->getVisibility(); if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) continue; // Look for '@' in the symbol name. StringRef Name; uint16_t Version; std::tie(Name, Version) = getSymbolVersion(B, MaxVersionLen); if (Name.empty()) continue; B->setName(Name); Sym->VersionId = Version; } }
DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name, uint8_t Visibility) { SymbolBody *S = find(Name); if (!S || !S->isUndefined()) return nullptr; return addAbsolute(Name, Visibility); }
Defined *Undefined::getWeakAlias() { // A weak alias may be a weak alias to another symbol, so check recursively. for (SymbolBody *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias) if (auto *D = dyn_cast<Defined>(A->repl())) return D; return nullptr; }
static typename ELFT::uint getSymVA(const SymbolBody &Body, typename ELFT::uint &Addend) { typedef typename ELFT::uint uintX_t; switch (Body.kind()) { case SymbolBody::DefinedSyntheticKind: { auto &D = cast<DefinedSynthetic<ELFT>>(Body); const OutputSectionBase<ELFT> *Sec = D.Section; if (!Sec) return D.Value; if (D.Value == DefinedSynthetic<ELFT>::SectionEnd) return Sec->getVA() + Sec->getSize(); return Sec->getVA() + D.Value; } case SymbolBody::DefinedRegularKind: { auto &D = cast<DefinedRegular<ELFT>>(Body); InputSectionBase<ELFT> *SC = D.Section; // According to the ELF spec reference to a local symbol from outside // the group are not allowed. Unfortunately .eh_frame breaks that rule // and must be treated specially. For now we just replace the symbol with // 0. if (SC == &InputSection<ELFT>::Discarded) return 0; // This is an absolute symbol. if (!SC) return D.Value; uintX_t Offset = D.Value; if (D.isSection()) { Offset += Addend; Addend = 0; } uintX_t VA = SC->OutSec->getVA() + SC->getOffset(Offset); if (D.isTls()) return VA - Out<ELFT>::TlsPhdr->p_vaddr; return VA; } case SymbolBody::DefinedCommonKind: return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(Body).OffsetInBss; case SymbolBody::SharedKind: { auto &SS = cast<SharedSymbol<ELFT>>(Body); if (!SS.NeedsCopyOrPltAddr) return 0; if (SS.isFunc()) return Body.getPltVA<ELFT>(); return Out<ELFT>::Bss->getVA() + SS.OffsetInBss; } case SymbolBody::UndefinedKind: return 0; case SymbolBody::LazyArchiveKind: case SymbolBody::LazyObjectKind: assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer"); return 0; case SymbolBody::DefinedBitcodeKind: llvm_unreachable("should have been replaced"); } llvm_unreachable("invalid symbol kind"); }
std::map<std::string, SymbolBody *> SymbolTable<ELFT>::getDemangledSyms() { std::map<std::string, SymbolBody *> Result; for (Symbol *Sym : SymVector) { SymbolBody *B = Sym->body(); Result[demangle(B->getName())] = B; } return Result; }
std::vector<SymbolBody *> SymbolTable<ELFT>::findAll(StringRef Pattern) { std::vector<SymbolBody *> Res; for (Symbol *Sym : SymVector) { SymbolBody *B = Sym->body(); if (!B->isUndefined() && globMatch(Pattern, B->getName())) Res.push_back(B); } return Res; }
// We have a new defined symbol with the specified binding. Return 1 if the new // symbol should win, -1 if the new symbol should lose, or 0 if both symbols are // strong defined symbols. static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) { if (WasInserted) return 1; SymbolBody *Body = S->body(); if (Body->isLazy() || Body->isUndefined() || Body->isShared()) return 1; if (Binding == STB_WEAK) return -1; if (S->isWeak()) return 1; return 0; }
// Print out a log message for --trace-symbol. void elf::printTraceSymbol(Symbol *Sym) { SymbolBody *B = Sym->body(); outs() << getFilename(B->File); if (B->isUndefined()) outs() << ": reference to "; else if (B->isCommon()) outs() << ": common definition of "; else outs() << ": definition of "; outs() << B->getName() << "\n"; }
// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. // Used to implement --wrap. template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) { SymbolBody *B = find(Name); if (!B) return; StringSaver Saver(Alloc); Symbol *Sym = B->symbol(); Symbol *Real = addUndefined(Saver.save("__real_" + Name)); Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); // We rename symbols by replacing the old symbol's SymbolBody with the new // symbol's SymbolBody. This causes all SymbolBody pointers referring to the // old symbol to instead refer to the new symbol. memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body)); memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body)); }
StringMap<std::vector<SymbolBody *>> &SymbolTable<ELFT>::getDemangledSyms() { if (!DemangledSyms) { DemangledSyms.emplace(); for (Symbol *Sym : SymVector) { SymbolBody *B = Sym->body(); if (B->isUndefined()) continue; if (Optional<std::string> S = demangle(B->getName())) (*DemangledSyms)[*S].push_back(B); else (*DemangledSyms)[B->getName()].push_back(B); } } return *DemangledSyms; }
// This is the main function of the garbage collector. // Starting from GC-root sections, this function visits all reachable // sections to set their "Live" bits. template <class ELFT> void elf::markLive(SymbolTable<ELFT> *Symtab) { SmallVector<InputSection<ELFT> *, 256> Q; auto Enqueue = [&](InputSectionBase<ELFT> *Sec) { if (!Sec || Sec->Live) return; Sec->Live = true; if (InputSection<ELFT> *S = dyn_cast<InputSection<ELFT>>(Sec)) Q.push_back(S); }; auto MarkSymbol = [&](SymbolBody *Sym) { if (Sym) if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&Sym->repl())) Enqueue(D->Section); }; // Add GC root symbols. MarkSymbol(Config->EntrySym); MarkSymbol(Symtab->find(Config->Init)); MarkSymbol(Symtab->find(Config->Fini)); for (StringRef S : Config->Undefined) MarkSymbol(Symtab->find(S)); // Preserve externally-visible symbols if the symbols defined by this // file can interrupt other ELF file's symbols at runtime. if (Config->Shared || Config->ExportDynamic) { for (const std::pair<StringRef, Symbol *> &P : Symtab->getSymbols()) { SymbolBody *B = P.second->Body; if (B->getVisibility() == STV_DEFAULT) MarkSymbol(B); } } // Preserve special sections and those which are specified in linker // script KEEP command. for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles()) for (InputSectionBase<ELFT> *Sec : F->getSections()) if (Sec && Sec != &InputSection<ELFT>::Discarded) if (isReserved(Sec) || Script->shouldKeep<ELFT>(Sec)) Enqueue(Sec); // Mark all reachable sections. while (!Q.empty()) forEachSuccessor<ELFT>(Q.pop_back_val(), Enqueue); }
RelExpr MIPS<ELFT>::getRelExpr(uint32_t Type, const SymbolBody &S, const uint8_t *Loc) const { // See comment in the calculateMipsRelChain. if (ELFT::Is64Bits || Config->MipsN32Abi) Type &= 0xff; switch (Type) { default: return R_ABS; case R_MIPS_JALR: return R_HINT; case R_MIPS_GPREL16: case R_MIPS_GPREL32: return R_MIPS_GOTREL; case R_MIPS_26: return R_PLT; case R_MIPS_HI16: case R_MIPS_LO16: // R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate // offset between start of function and 'gp' value which by default // equal to the start of .got section. In that case we consider these // relocations as relative. if (&S == ElfSym::MipsGpDisp) return R_MIPS_GOT_GP_PC; if (&S == ElfSym::MipsLocalGp) return R_MIPS_GOT_GP; LLVM_FALLTHROUGH; case R_MIPS_GOT_OFST: return R_ABS; case R_MIPS_PC32: case R_MIPS_PC16: case R_MIPS_PC19_S2: case R_MIPS_PC21_S2: case R_MIPS_PC26_S2: case R_MIPS_PCHI16: case R_MIPS_PCLO16: return R_PC; case R_MIPS_GOT16: if (S.isLocal()) return R_MIPS_GOT_LOCAL_PAGE; LLVM_FALLTHROUGH; case R_MIPS_CALL16: case R_MIPS_GOT_DISP: case R_MIPS_TLS_GOTTPREL: return R_MIPS_GOT_OFF; case R_MIPS_CALL_HI16: case R_MIPS_CALL_LO16: case R_MIPS_GOT_HI16: case R_MIPS_GOT_LO16: return R_MIPS_GOT_OFF32; case R_MIPS_GOT_PAGE: return R_MIPS_GOT_LOCAL_PAGE; case R_MIPS_TLS_GD: return R_MIPS_TLSGD; case R_MIPS_TLS_LDM: return R_MIPS_TLSLD; } }
template <class ELFT> void LinkerScript<ELFT>::addScriptedSymbols() { for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) { auto *Cmd = dyn_cast<SymbolAssignment>(Base.get()); if (!Cmd || Cmd->Name == ".") continue; SymbolBody *B = Symtab<ELFT>::X->find(Cmd->Name); // The semantic of PROVIDE is that of introducing a symbol only if // it's not defined and there's at least a reference to it. if ((!B && !Cmd->Provide) || (B && B->isUndefined())) Symtab<ELFT>::X->addAbsolute(Cmd->Name, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT); else // Symbol already exists in symbol table. If it is provided // then we can't override its value. Cmd->Ignore = Cmd->Provide; } }
std::vector<SymbolBody *> SymbolTable<ELFT>::findAllByVersion(SymbolVersion Ver) { std::vector<SymbolBody *> Res; StringMatcher M(Ver.Name); if (Ver.IsExternCpp) { for (auto &P : getDemangledSyms()) if (M.match(P.first())) Res.insert(Res.end(), P.second.begin(), P.second.end()); return Res; } for (Symbol *Sym : SymVector) { SymbolBody *B = Sym->body(); if (!B->isUndefined() && M.match(B->getName())) Res.push_back(B); } return Res; }
static void reportUndefined(const SymbolTable<ELFT> &S, const SymbolBody &Sym) { typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; if (Config->Shared && !Config->NoUndefined) return; const Elf_Sym &SymE = cast<ELFSymbolBody<ELFT>>(Sym).Sym; ELFFileBase<ELFT> *SymFile = nullptr; for (const std::unique_ptr<ObjectFile<ELFT>> &File : S.getObjectFiles()) { Elf_Sym_Range Syms = File->getObj().symbols(File->getSymbolTable()); if (&SymE > Syms.begin() && &SymE < Syms.end()) SymFile = File.get(); } std::string Message = "undefined symbol: " + Sym.getName().str(); if (SymFile) Message += " in " + SymFile->getName().str(); if (Config->NoInhibitExec) warning(Message); else error(Message); }
void Writer<ELFT>::scanRelocs( InputSectionBase<ELFT> &C, iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) { typedef Elf_Rel_Impl<ELFT, isRela> RelType; const ObjectFile<ELFT> &File = *C.getFile(); for (const RelType &RI : Rels) { uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); SymbolBody *Body = File.getSymbolBody(SymIndex); uint32_t Type = RI.getType(Config->Mips64EL); if (Target->isTlsLocalDynamicReloc(Type)) { if (Target->isTlsOptimized(Type, nullptr)) continue; if (Out<ELFT>::LocalModuleTlsIndexOffset == uint32_t(-1)) { Out<ELFT>::LocalModuleTlsIndexOffset = Out<ELFT>::Got->addLocalModuleTlsIndex(); Out<ELFT>::RelaDyn->addReloc({&C, &RI}); } continue; } // Set "used" bit for --as-needed. if (Body && Body->isUndefined() && !Body->isWeak()) if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl())) S->File->IsUsed = true; if (Body) Body = Body->repl(); if (Body && Body->isTLS() && Target->isTlsGlobalDynamicReloc(Type)) { if (Target->isTlsOptimized(Type, Body)) continue; if (Body->isInGot()) continue; Out<ELFT>::Got->addDynTlsEntry(Body); Out<ELFT>::RelaDyn->addReloc({&C, &RI}); Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr}); Body->setUsedInDynamicReloc(); continue; } if (Body && Body->isTLS() && !Target->isTlsDynReloc(Type)) continue; bool NeedsGot = false; bool NeedsPlt = false; if (Body) { if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) { if (E->needsCopy()) continue; if (Target->relocNeedsCopy(Type, *Body)) E->OffsetInBSS = 0; } NeedsPlt = Target->relocNeedsPlt(Type, *Body); if (NeedsPlt) { if (Body->isInPlt()) continue; Out<ELFT>::Plt->addEntry(Body); } NeedsGot = Target->relocNeedsGot(Type, *Body); if (NeedsGot) { if (NeedsPlt && Target->supportsLazyRelocations()) { Out<ELFT>::GotPlt->addEntry(Body); } else { if (Body->isInGot()) continue; Out<ELFT>::Got->addEntry(Body); } } } if (Config->EMachine == EM_MIPS && NeedsGot) { // MIPS ABI has special rules to process GOT entries // and doesn't require relocation entries for them. // See "Global Offset Table" in Chapter 5 in the following document // for detailed description: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf Body->setUsedInDynamicReloc(); continue; } bool CBP = canBePreempted(Body, NeedsGot); if (!CBP && (!Config->Shared || Target->isRelRelative(Type))) continue; if (CBP) Body->setUsedInDynamicReloc(); if (NeedsPlt && Target->supportsLazyRelocations()) Out<ELFT>::RelaPlt->addReloc({&C, &RI}); else Out<ELFT>::RelaDyn->addReloc({&C, &RI}); } }
// Returns a symbol for an error message. std::string lld::toString(const SymbolBody &B) { if (Config->Demangle) if (Optional<std::string> S = demangle(B.getName())) return *S; return B.getName(); }
void BitcodeCompiler::add(BitcodeFile &F) { std::unique_ptr<IRObjectFile> Obj = check(IRObjectFile::create(F.MB, Context)); std::vector<GlobalValue *> Keep; unsigned BodyIndex = 0; ArrayRef<SymbolBody *> Bodies = F.getSymbols(); Module &M = Obj->getModule(); if (M.getDataLayoutStr().empty()) fatal("invalid bitcode file: " + F.getName() + " has no datalayout"); // 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()) { GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl()); // Ignore module asm symbols. if (!GV) continue; if (GV->hasAppendingLinkage()) { Keep.push_back(GV); continue; } if (BitcodeFile::shouldSkip(Sym)) continue; SymbolBody *B = Bodies[BodyIndex++]; if (!B || &B->repl() != B || !isa<DefinedBitcode>(B)) continue; switch (GV->getLinkage()) { default: break; case llvm::GlobalValue::LinkOnceAnyLinkage: GV->setLinkage(GlobalValue::WeakAnyLinkage); break; case llvm::GlobalValue::LinkOnceODRLinkage: GV->setLinkage(GlobalValue::WeakODRLinkage); break; } // 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. // Shared libraries need to be handled slightly differently. // For now, let's be conservative and just never internalize // symbols when creating a shared library. if (!Config->Shared && !Config->ExportDynamic && !B->isUsedInRegularObj() && !B->MustBeInDynSym) if (!Used.count(GV)) InternalizedSyms.insert(GV->getName()); Keep.push_back(GV); } Mover.move(Obj->takeModule(), Keep, [](GlobalValue &, IRMover::ValueAdder) {}); }
static typename ELFT::uint getSymVA(const SymbolBody &Body, typename ELFT::uint &Addend) { typedef typename ELFT::uint uintX_t; switch (Body.kind()) { case SymbolBody::DefinedSyntheticKind: { auto &D = cast<DefinedSynthetic>(Body); const OutputSectionBase *Sec = D.Section; if (!Sec) return D.Value; if (D.Value == uintX_t(-1)) return Sec->Addr + Sec->Size; return Sec->Addr + D.Value; } case SymbolBody::DefinedRegularKind: { auto &D = cast<DefinedRegular<ELFT>>(Body); InputSectionBase<ELFT> *IS = D.Section; // According to the ELF spec reference to a local symbol from outside // the group are not allowed. Unfortunately .eh_frame breaks that rule // and must be treated specially. For now we just replace the symbol with // 0. if (IS == &InputSection<ELFT>::Discarded) return 0; // This is an absolute symbol. if (!IS) return D.Value; uintX_t Offset = D.Value; if (D.isSection()) { Offset += Addend; Addend = 0; } uintX_t VA = (IS->OutSec ? IS->OutSec->Addr : 0) + IS->getOffset(Offset); if (D.isTls() && !Config->Relocatable) { if (!Out<ELFT>::TlsPhdr) fatal(toString(D.File) + " has a STT_TLS symbol but doesn't have a PT_TLS section"); return VA - Out<ELFT>::TlsPhdr->p_vaddr; } return VA; } case SymbolBody::DefinedCommonKind: if (!Config->DefineCommon) return 0; return In<ELFT>::Common->OutSec->Addr + In<ELFT>::Common->OutSecOff + cast<DefinedCommon>(Body).Offset; case SymbolBody::SharedKind: { auto &SS = cast<SharedSymbol<ELFT>>(Body); if (!SS.NeedsCopyOrPltAddr) return 0; if (SS.isFunc()) return Body.getPltVA<ELFT>(); return SS.getBssSectionForCopy()->Addr + SS.CopyOffset; } case SymbolBody::UndefinedKind: return 0; case SymbolBody::LazyArchiveKind: case SymbolBody::LazyObjectKind: assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer"); return 0; } llvm_unreachable("invalid symbol kind"); }