Index: lld/ELF/InputFiles.cpp =================================================================== --- lld/ELF/InputFiles.cpp +++ lld/ELF/InputFiles.cpp @@ -888,25 +888,6 @@ return Verdefs; } -// We do not usually care about alignments of data in shared object -// files because the loader takes care of it. However, if we promote a -// DSO symbol to point to .bss due to copy relocation, we need to keep -// the original alignment requirements. We infer it in this function. -template -uint32_t SharedFile::getAlignment(ArrayRef Sections, - const Elf_Sym &Sym) { - uint64_t Ret = 1; - if (Sym.st_value) - Ret = 1ULL << countTrailingZeros((uint64_t)Sym.st_value); - if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) - Ret = std::min(Ret, Sections[Sym.st_shndx].sh_addralign); - - if (Ret > UINT32_MAX) - error(toString(this) + ": alignment too large: " + - CHECK(Sym.getName(this->StringTable), this)); - return Ret; -} - // Fully parse the shared object file. This must be called after parseSoName(). // // This function parses symbol versions. If a DSO has version information, @@ -925,7 +906,6 @@ template void SharedFile::parseRest() { Verdefs = parseVerdefs(); // parse .gnu.version_d std::vector Versyms = parseVersyms(); // parse .gnu.version - ArrayRef Sections = CHECK(this->getObj().sections(), this); // System libraries can have a lot of symbols with versions. Using a // fixed buffer for computing the versions name (foo@ver) can save a @@ -964,9 +944,8 @@ Name == "_gp_disp") continue; - uint64_t Alignment = getAlignment(Sections, Sym); if (!(Versyms[I] & VERSYM_HIDDEN)) - Symtab->addShared(Name, *this, Sym, Alignment, Idx); + Symtab->addShared(Name, *this, Sym, Idx); // Also add the symbol with the versioned name to handle undefined symbols // with explicit versions. @@ -984,7 +963,7 @@ this->StringTable.data() + Verdefs[Idx]->getAux()->vda_name; VersionedNameBuffer.clear(); Name = (Name + "@" + VerName).toStringRef(VersionedNameBuffer); - Symtab->addShared(Saver.save(Name), *this, Sym, Alignment, Idx); + Symtab->addShared(Saver.save(Name), *this, Sym, Idx); } } Index: lld/ELF/Relocations.cpp =================================================================== --- lld/ELF/Relocations.cpp +++ lld/ELF/Relocations.cpp @@ -430,10 +430,11 @@ // Determine if the symbol is read-only by scanning the DSO's program headers. const SharedFile &File = SS.getFile(); + uint64_t Value = SS.getSym().st_value; for (const Elf_Phdr &Phdr : check(File.getObj().program_headers())) if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) && - !(Phdr.p_flags & ELF::PF_W) && SS.Value >= Phdr.p_vaddr && - SS.Value < Phdr.p_vaddr + Phdr.p_memsz) + !(Phdr.p_flags & ELF::PF_W) && Value >= Phdr.p_vaddr && + Value < Phdr.p_vaddr + Phdr.p_memsz) return true; return false; } @@ -450,9 +451,10 @@ SharedFile &File = SS.getFile(); std::vector Ret; + uint64_t Value = SS.getSym().st_value; for (const Elf_Sym &S : File.getGlobalELFSyms()) { if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS || - S.st_value != SS.Value) + S.st_value != Value) continue; StringRef Name = check(S.getName(File.getStringTable())); Symbol *Sym = Symtab->find(Name); @@ -526,7 +528,7 @@ // define an accessor getV(). template static void addCopyRelSymbol(SharedSymbol &SS) { // Copy relocation against zero-sized symbol doesn't make sense. - uint64_t SymSize = SS.getSize(); + uint64_t SymSize = SS.getSym().st_size; if (SymSize == 0) fatal("cannot create a copy relocation for symbol " + toString(SS)); @@ -534,7 +536,7 @@ // memory protection by reserving space in the .bss.rel.ro section. bool IsReadOnly = isReadOnly(SS); BssSection *Sec = make(IsReadOnly ? ".bss.rel.ro" : ".bss", - SymSize, SS.Alignment); + SymSize, SS.getAlignment()); if (IsReadOnly) InX::BssRelRo->getParent()->addSection(Sec); else @@ -544,7 +546,7 @@ // dynamic symbol for each one. This causes the copy relocation to correctly // interpose any aliases. for (SharedSymbol *Sym : getSymbolsAt(SS)) - replaceWithDefined(*Sym, Sec, 0, Sym->Size); + replaceWithDefined(*Sym, Sec, 0, SymSize); InX::RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS); } Index: lld/ELF/SymbolTable.h =================================================================== --- lld/ELF/SymbolTable.h +++ lld/ELF/SymbolTable.h @@ -56,8 +56,7 @@ template void addShared(StringRef Name, SharedFile &F, - const typename ELFT::Sym &Sym, uint32_t Alignment, - uint32_t VerdefIndex); + const typename ELFT::Sym &Sym, uint32_t VerdefIndex); template void addLazyArchive(StringRef Name, ArchiveFile &F, Index: lld/ELF/SymbolTable.cpp =================================================================== --- lld/ELF/SymbolTable.cpp +++ lld/ELF/SymbolTable.cpp @@ -541,7 +541,7 @@ template void SymbolTable::addShared(StringRef Name, SharedFile &File, - const typename ELFT::Sym &Sym, uint32_t Alignment, + const typename ELFT::Sym &Sym, uint32_t VerdefIndex) { // 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 @@ -560,9 +560,9 @@ ((S->isUndefined() || S->isLazy()) && S->Visibility == STV_DEFAULT)) { uint8_t Binding = S->Binding; bool WasUndefined = S->isUndefined(); - replaceSymbol(S, File, Name, Sym.getBinding(), Sym.st_other, - Sym.getType(), Sym.st_value, Sym.st_size, - Alignment, VerdefIndex); + replaceSymbol( + S, File, Name, Sym.getBinding(), Sym.st_other, Sym.getType(), + reinterpret_cast(&Sym), VerdefIndex); if (!WasInserted) { S->Binding = Binding; if (!S->isWeak() && !Config->GcSections && WasUndefined) @@ -865,13 +865,13 @@ template void SymbolTable::addShared(StringRef, SharedFile &, const typename ELF32LE::Sym &, - uint32_t Alignment, uint32_t); + uint32_t); template void SymbolTable::addShared(StringRef, SharedFile &, const typename ELF32BE::Sym &, - uint32_t Alignment, uint32_t); + uint32_t); template void SymbolTable::addShared(StringRef, SharedFile &, const typename ELF64LE::Sym &, - uint32_t Alignment, uint32_t); + uint32_t); template void SymbolTable::addShared(StringRef, SharedFile &, const typename ELF64BE::Sym &, - uint32_t Alignment, uint32_t); + uint32_t); Index: lld/ELF/Symbols.h =================================================================== --- lld/ELF/Symbols.h +++ lld/ELF/Symbols.h @@ -232,10 +232,9 @@ static bool classof(const Symbol *S) { return S->kind() == SharedKind; } SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding, - uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size, - uint32_t Alignment, uint32_t VerdefIndex) - : Symbol(SharedKind, &File, Name, Binding, StOther, Type), - Alignment(Alignment), Value(Value), Size(Size) { + uint8_t StOther, uint8_t Type, const void *Sym, + uint32_t VerdefIndex) + : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Sym(Sym) { this->VerdefIndex = VerdefIndex; // GNU ifunc is a mechanism to allow user-supplied functions to // resolve PLT slot values at load-time. This is contrary to the @@ -261,10 +260,12 @@ return *cast>(File); } - uint32_t Alignment; + const void *Sym; + template const typename ELFT::Sym &getSym() const { + return *static_cast(Sym); + } - uint64_t Value; // st_value - uint64_t Size; // st_size + template uint32_t getAlignment() const; }; // LazyArchive and LazyObject represent a symbols that is not yet in the link, Index: lld/ELF/Symbols.cpp =================================================================== --- lld/ELF/Symbols.cpp +++ lld/ELF/Symbols.cpp @@ -144,8 +144,6 @@ uint64_t Symbol::getSize() const { if (const auto *DR = dyn_cast(this)) return DR->Size; - if (const auto *S = dyn_cast(this)) - return S->Size; return 0; } @@ -228,6 +226,28 @@ return ExportDynamic; } +// We do not usually care about alignments of data in shared object +// files because the loader takes care of it. However, if we promote a +// DSO symbol to point to .bss due to copy relocation, we need to keep +// the original alignment requirements. We infer it in this function. +template uint32_t SharedSymbol::getAlignment() const { + SharedFile &File = this->getFile(); + ArrayRef Sections = + CHECK(File.getObj().sections(), &File); + const typename ELFT::Sym &Sym = this->getSym(); + + uint64_t Ret = 1; + if (Sym.st_value) + Ret = 1ULL << countTrailingZeros((uint64_t)Sym.st_value); + if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) + Ret = std::min(Ret, Sections[Sym.st_shndx].sh_addralign); + + if (Ret > UINT32_MAX) + error(toString(&File) + ": alignment too large: " + + CHECK(Sym.getName(File.getStringTable()), &File)); + return Ret; +} + // Print out a log message for --trace-symbol. void elf::printTraceSymbol(Symbol *Sym) { std::string S; @@ -273,3 +293,8 @@ return *S; return B.getName(); } + +template uint32_t SharedSymbol::getAlignment() const; +template uint32_t SharedSymbol::getAlignment() const; +template uint32_t SharedSymbol::getAlignment() const; +template uint32_t SharedSymbol::getAlignment() const; Index: lld/test/ELF/shared-abs.s =================================================================== --- /dev/null +++ lld/test/ELF/shared-abs.s @@ -0,0 +1,6 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t.so +// RUN: ld.lld %t.so -o %t + +.globl abs +abs = 1 << 33