DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name, uint8_t Visibility) { SymbolBody *S = find(Name); if (!S || !S->isUndefined()) return nullptr; return addAbsolute(Name, Visibility); }
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"; }
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; }
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; }
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}); } }