Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1056,7 +1056,7 @@ // We need to create some reserved symbols such as _end. Create them. if (!Config->Relocatable) - addReservedSymbols(); + addReservedSymbols(); // Apply version scripts. Symtab->scanVersionScript(); Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -109,6 +109,9 @@ // Cache for toString(). Only toString() should use this member. mutable std::string ToStringCache; + std::string getSrcMsg(const Symbol &Sym, InputSectionBase &Sec, + uint64_t Offset); + protected: InputFile(Kind K, MemoryBufferRef M); std::vector Sections; @@ -327,7 +330,7 @@ public: explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {} static bool classof(const InputFile *F) { return F->kind() == BinaryKind; } - template void parse(); + void parse(); }; InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -32,6 +32,7 @@ using namespace llvm; using namespace llvm::ELF; using namespace llvm::object; +using namespace llvm::sys; using namespace llvm::sys::fs; using namespace lld; @@ -69,6 +70,50 @@ return MBRef; } +// Concatenates arguments to construct a string representing an error location. +static std::string createFileLineMsg(StringRef Path, unsigned Line) { + std::string Filename = path::filename(Path); + std::string Lineno = ":" + std::to_string(Line); + if (Filename == Path) + return Filename + Lineno; + return Filename + Lineno + " (" + Path.str() + Lineno + ")"; +} + +template +static std::string getSrcMsgAux(ObjFile &File, const Symbol &Sym, + InputSectionBase &Sec, uint64_t Offset) { + // In DWARF, functions and variables are stored to different places. + // First, lookup a function for a given offset. + if (Optional Info = File.getDILineInfo(&Sec, Offset)) + return createFileLineMsg(Info->FileName, Info->Line); + + // If it failed, lookup again as a variable. + if (Optional> FileLine = + File.getVariableLoc(Sym.getName())) + return createFileLineMsg(FileLine->first, FileLine->second); + + // File.SourceFile contains STT_FILE symbol, and that is a last resort. + return File.SourceFile; +} + +std::string InputFile::getSrcMsg(const Symbol &Sym, InputSectionBase &Sec, + uint64_t Offset) { + if (kind() != ObjKind) + return ""; + switch (Config->EKind) { + default: + llvm_unreachable("Invalid kind"); + case ELF32LEKind: + return getSrcMsgAux(cast>(*this), Sym, Sec, Offset); + case ELF32BEKind: + return getSrcMsgAux(cast>(*this), Sym, Sec, Offset); + case ELF64LEKind: + return getSrcMsgAux(cast>(*this), Sym, Sec, Offset); + case ELF64BEKind: + return getSrcMsgAux(cast>(*this), Sym, Sec, Offset); + } +} + template void ObjFile::initializeDwarf() { DWARFContext Dwarf(make_unique>(this)); const DWARFObject &Obj = Dwarf.getDWARFObj(); @@ -646,8 +691,8 @@ if (Sec == &InputSection::Discarded) return Symtab->addUndefined(Name, Binding, StOther, Type, /*CanOmitFromDynSym=*/false, this); - return Symtab->addRegular(Name, StOther, Type, Value, Size, Binding, - Sec, this); + return Symtab->addRegular(Name, StOther, Type, Value, Size, Binding, Sec, + this); } } @@ -979,7 +1024,7 @@ return (Endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind; } -template void BinaryFile::parse() { +void BinaryFile::parse() { ArrayRef Data = toArrayRef(MB.getBuffer()); auto *Section = make(nullptr, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 8, Data, ".data"); @@ -994,12 +1039,12 @@ if (!isAlnum(S[I])) S[I] = '_'; - Symtab->addRegular(Saver.save(S + "_start"), STV_DEFAULT, STT_OBJECT, 0, - 0, STB_GLOBAL, Section, nullptr); - Symtab->addRegular(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT, - Data.size(), 0, STB_GLOBAL, Section, nullptr); - Symtab->addRegular(Saver.save(S + "_size"), STV_DEFAULT, STT_OBJECT, - Data.size(), 0, STB_GLOBAL, nullptr, nullptr); + Symtab->addRegular(Saver.save(S + "_start"), STV_DEFAULT, STT_OBJECT, 0, 0, + STB_GLOBAL, Section, nullptr); + Symtab->addRegular(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT, + Data.size(), 0, STB_GLOBAL, Section, nullptr); + Symtab->addRegular(Saver.save(S + "_size"), STV_DEFAULT, STT_OBJECT, + Data.size(), 0, STB_GLOBAL, nullptr, nullptr); } static bool isBitcode(MemoryBufferRef MB) { @@ -1143,8 +1188,3 @@ template class elf::SharedFile; template class elf::SharedFile; template class elf::SharedFile; - -template void BinaryFile::parse(); -template void BinaryFile::parse(); -template void BinaryFile::parse(); -template void BinaryFile::parse(); Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -168,7 +168,6 @@ // Returns a source location string. Used to construct an error message. template std::string getLocation(uint64_t Offset); - template std::string getSrcMsg(const Symbol &Sym, uint64_t Offset); std::string getObjMsg(uint64_t Offset); Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -24,7 +24,6 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/Path.h" #include "llvm/Support/Threading.h" #include "llvm/Support/xxhash.h" #include @@ -263,40 +262,17 @@ return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); } -// Concatenates arguments to construct a string representing an error location. -static std::string createFileLineMsg(StringRef Path, unsigned Line) { - std::string Filename = path::filename(Path); - std::string Lineno = ":" + std::to_string(Line); - if (Filename == Path) - return Filename + Lineno; - return Filename + Lineno + " (" + Path.str() + Lineno + ")"; -} - // This function is intended to be used for constructing an error message. // The returned message looks like this: // // foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42) // // Returns an empty string if there's no way to get line info. -template std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) { // Synthetic sections don't have input files. - ObjFile *File = getFile(); if (!File) return ""; - - // In DWARF, functions and variables are stored to different places. - // First, lookup a function for a given offset. - if (Optional Info = File->getDILineInfo(this, Offset)) - return createFileLineMsg(Info->FileName, Info->Line); - - // If it failed, lookup again as a variable. - if (Optional> FileLine = - File->getVariableLoc(Sym.getName())) - return createFileLineMsg(FileLine->first, FileLine->second); - - // File->SourceFile contains STT_FILE symbol, and that is a last resort. - return File->SourceFile; + return File->getSrcMsg(Sym, *this, Offset); } // Returns a filename string along with an optional section name. This @@ -1019,15 +995,6 @@ template std::string InputSectionBase::getLocation(uint64_t); template std::string InputSectionBase::getLocation(uint64_t); -template std::string InputSectionBase::getSrcMsg(const Symbol &, - uint64_t); -template std::string InputSectionBase::getSrcMsg(const Symbol &, - uint64_t); -template std::string InputSectionBase::getSrcMsg(const Symbol &, - uint64_t); -template std::string InputSectionBase::getSrcMsg(const Symbol &, - uint64_t); - template void InputSection::writeTo(uint8_t *); template void InputSection::writeTo(uint8_t *); template void InputSection::writeTo(uint8_t *); Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -70,12 +70,11 @@ // >>> defined in /home/alice/src/foo.o // >>> referenced by bar.c:12 (/home/alice/src/bar.c:12) // >>> /home/alice/src/bar.o:(.text+0x1) -template static std::string getLocation(InputSectionBase &S, const Symbol &Sym, uint64_t Off) { std::string Msg = "\n>>> defined in " + toString(Sym.File) + "\n>>> referenced by "; - std::string Src = S.getSrcMsg(Sym, Off); + std::string Src = S.getSrcMsg(Sym, Off); if (!Src.empty()) Msg += Src + "\n>>> "; return Msg + S.getObjMsg(Off); @@ -365,7 +364,6 @@ // // If this function returns false, that means we need to emit a // dynamic relocation so that the relocation will be fixed at load-time. -template static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, InputSectionBase &S, uint64_t RelOff) { // These expressions always compute a constant @@ -410,7 +408,7 @@ return true; error("relocation " + toString(Type) + " cannot refer to absolute symbol: " + - toString(Sym) + getLocation(S, Sym, RelOff)); + toString(Sym) + getLocation(S, Sym, RelOff)); return true; } @@ -591,13 +589,13 @@ "can't create dynamic relocation " + toString(Type) + " against " + (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) + " in readonly segment; recompile object files with -fPIC" + - getLocation(S, Sym, RelOff)); + getLocation(S, Sym, RelOff)); return Expr; } if (Sym.getVisibility() != STV_DEFAULT) { error("cannot preempt symbol: " + toString(Sym) + - getLocation(S, Sym, RelOff)); + getLocation(S, Sym, RelOff)); return Expr; } @@ -609,7 +607,7 @@ error("unresolvable relocation " + toString(Type) + " against symbol '" + toString(*B) + "'; recompile with -fPIC or remove '-z nocopyreloc'" + - getLocation(S, Sym, RelOff)); + getLocation(S, Sym, RelOff)); addCopyRelSymbol(B); } @@ -712,7 +710,6 @@ // Report an undefined symbol if necessary. // Returns true if this function printed out an error message. -template static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec, uint64_t Offset) { if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll) @@ -729,7 +726,7 @@ std::string Msg = "undefined symbol: " + toString(Sym) + "\n>>> referenced by "; - std::string Src = Sec.getSrcMsg(Sym, Offset); + std::string Src = Sec.getSrcMsg(Sym, Offset); if (!Src.empty()) Msg += Src + "\n>>> "; Msg += Sec.getObjMsg(Offset); @@ -889,7 +886,7 @@ continue; // Skip if the target symbol is an erroneous undefined symbol. - if (maybeReportUndefined(Sym, Sec, Rel.r_offset)) + if (maybeReportUndefined(Sym, Sec, Rel.r_offset)) continue; RelExpr Expr = @@ -928,7 +925,7 @@ Expr = fromPlt(Expr); bool IsConstant = - isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Rel.r_offset); + isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Rel.r_offset); Expr = adjustExpr(Sym, Expr, Type, Sec, Rel.r_offset, IsConstant); if (errorCount()) @@ -987,7 +984,7 @@ errorOrWarn( "relocation " + toString(Type) + " cannot be used against shared object; recompile with -fPIC" + - getLocation(Sec, Sym, Offset)); + getLocation(Sec, Sym, Offset)); InX::RelaDyn->addReloc( {Target->getDynRel(Type), &Sec, Offset, false, &Sym, Addend}); Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -42,7 +42,6 @@ ArrayRef getSymbols() const { return SymVector; } - template Defined *addAbsolute(StringRef Name, uint8_t Visibility = llvm::ELF::STV_HIDDEN, uint8_t Binding = llvm::ELF::STB_GLOBAL); @@ -51,7 +50,6 @@ template Symbol *addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther, uint8_t Type, bool CanOmitFromDynSym, InputFile *File); - template Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, uint8_t Binding, SectionBase *Section, InputFile *File); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -70,7 +70,7 @@ // Binary file if (auto *F = dyn_cast(File)) { BinaryFiles.push_back(F); - F->parse(); + F->parse(); return; } @@ -135,11 +135,10 @@ } } -template Defined *SymbolTable::addAbsolute(StringRef Name, uint8_t Visibility, uint8_t Binding) { - Symbol *Sym = addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, - nullptr, nullptr); + Symbol *Sym = + addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, nullptr, nullptr); return cast(Sym); } @@ -424,9 +423,8 @@ toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); } -template static void reportDuplicate(Symbol *Sym, InputSectionBase *ErrSec, - typename ELFT::uint ErrOffset) { + uint64_t ErrOffset) { Defined *D = cast(Sym); if (!D->Section || !ErrSec) { reportDuplicate(Sym, ErrSec ? ErrSec->File : nullptr); @@ -441,9 +439,9 @@ // >>> defined at baz.c:563 // >>> baz.o in archive libbaz.a auto *Sec1 = cast(D->Section); - std::string Src1 = Sec1->getSrcMsg(*Sym, D->Value); + std::string Src1 = Sec1->getSrcMsg(*Sym, D->Value); std::string Obj1 = Sec1->getObjMsg(D->Value); - std::string Src2 = ErrSec->getSrcMsg(*Sym, ErrOffset); + std::string Src2 = ErrSec->getSrcMsg(*Sym, ErrOffset); std::string Obj2 = ErrSec->getObjMsg(ErrOffset); std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at "; @@ -456,7 +454,6 @@ warnOrError(Msg); } -template Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, uint8_t Binding, SectionBase *Section, InputFile *File) { @@ -470,8 +467,7 @@ replaceSymbol(S, File, Name, Binding, StOther, Type, Value, Size, Section); else if (Cmp == 0) - reportDuplicate(S, dyn_cast_or_null(Section), - Value); + reportDuplicate(S, dyn_cast_or_null(Section), Value); return S; } @@ -797,28 +793,6 @@ template void SymbolTable::addCombinedLTOObject(); template void SymbolTable::addCombinedLTOObject(); -template Symbol *SymbolTable::addRegular(StringRef, uint8_t, uint8_t, - uint64_t, uint64_t, uint8_t, - SectionBase *, InputFile *); -template Symbol *SymbolTable::addRegular(StringRef, uint8_t, uint8_t, - uint64_t, uint64_t, uint8_t, - SectionBase *, InputFile *); -template Symbol *SymbolTable::addRegular(StringRef, uint8_t, uint8_t, - uint64_t, uint64_t, uint8_t, - SectionBase *, InputFile *); -template Symbol *SymbolTable::addRegular(StringRef, uint8_t, uint8_t, - uint64_t, uint64_t, uint8_t, - SectionBase *, InputFile *); - -template Defined *SymbolTable::addAbsolute(StringRef, uint8_t, - uint8_t); -template Defined *SymbolTable::addAbsolute(StringRef, uint8_t, - uint8_t); -template Defined *SymbolTable::addAbsolute(StringRef, uint8_t, - uint8_t); -template Defined *SymbolTable::addAbsolute(StringRef, uint8_t, - uint8_t); - template Symbol * SymbolTable::addLazyArchive(StringRef, ArchiveFile &, const object::Archive::Symbol); Index: ELF/Writer.h =================================================================== --- ELF/Writer.h +++ ELF/Writer.h @@ -46,7 +46,7 @@ bool HasLMA = false; }; -template void addReservedSymbols(); +void addReservedSymbols(); llvm::StringRef getOutputSectionName(InputSectionBase *S); template uint32_t calcMipsEFlags(); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -156,35 +156,34 @@ V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); } -template static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec, uint64_t Val, uint8_t StOther = STV_HIDDEN, uint8_t Binding = STB_GLOBAL) { Symbol *S = Symtab->find(Name); if (!S || S->isDefined()) return nullptr; - Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, - /*Size=*/0, Binding, Sec, - /*File=*/nullptr); + Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, + /*Size=*/0, Binding, Sec, + /*File=*/nullptr); return cast(Sym); } // The linker is expected to define some symbols depending on // the linking result. This function defines such symbols. -template void elf::addReservedSymbols() { +void elf::addReservedSymbols() { if (Config->EMachine == EM_MIPS) { // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer // so that it points to an absolute address which by default is relative // to GOT. Default offset is 0x7ff0. // See "Global Data Symbols" in Chapter 6 in the following document: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf - ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL); + ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL); // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between // start of function and 'gp' pointer into GOT. if (Symtab->find("_gp_disp")) ElfSym::MipsGpDisp = - Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL); + Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL); // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' // pointer. This symbol is used in the code generated by .cpload pseudo-op @@ -192,10 +191,10 @@ // https://sourceware.org/ml/binutils/2004-12/msg00094.html if (Symtab->find("__gnu_local_gp")) ElfSym::MipsLocalGp = - Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL); + Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL); } - ElfSym::GlobalOffsetTable = addOptionalRegular( + ElfSym::GlobalOffsetTable = addOptionalRegular( "_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff); // __ehdr_start is the location of ELF file headers. Note that we define @@ -209,14 +208,14 @@ // different in different DSOs, so we chose the start address of the DSO. for (const char *Name : {"__ehdr_start", "__executable_start", "__dso_handle"}) - addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN); + addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN); // If linker script do layout we do not need to create any standart symbols. if (Script->HasSectionsCommand) return; auto Add = [](StringRef S, int64_t Pos) { - return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT); + return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT); }; ElfSym::Bss = Add("__bss_start", 0); @@ -834,10 +833,10 @@ if (!Config->Static) return; StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); + addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; - addOptionalRegular(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK); + addOptionalRegular(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK); } template @@ -1385,9 +1384,9 @@ // Even the author of gold doesn't remember why gold behaves that way. // https://sourceware.org/ml/binutils/2002-03/msg00360.html if (InX::DynSymTab) - Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, - /*Size=*/0, STB_WEAK, InX::Dynamic, - /*File=*/nullptr); + Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, + /*Size=*/0, STB_WEAK, InX::Dynamic, + /*File=*/nullptr); // Define __rel[a]_iplt_{start,end} symbols if needed. addRelIpltSymbols(); @@ -1534,13 +1533,13 @@ // These symbols resolve to the image base if the section does not exist. // A special value -1 indicates end of the section. if (OS) { - addOptionalRegular(Start, OS, 0); - addOptionalRegular(End, OS, -1); + addOptionalRegular(Start, OS, 0); + addOptionalRegular(End, OS, -1); } else { if (Config->Pic) OS = Out::ElfHeader; - addOptionalRegular(Start, OS, 0); - addOptionalRegular(End, OS, 0); + addOptionalRegular(Start, OS, 0); + addOptionalRegular(End, OS, 0); } }; @@ -1562,8 +1561,8 @@ StringRef S = Sec->Name; if (!isValidCIdentifier(S)) return; - addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); - addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); + addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); + addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT); } static bool needsPtLoad(OutputSection *Sec) { @@ -2063,8 +2062,3 @@ template void elf::writeResult(); template void elf::writeResult(); template void elf::writeResult(); - -template void elf::addReservedSymbols(); -template void elf::addReservedSymbols(); -template void elf::addReservedSymbols(); -template void elf::addReservedSymbols();