diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-04 22:11:50 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-04 22:11:50 +0000 |
commit | 5d4d137132d719d0d20d119375b205d6a2c721ee (patch) | |
tree | 76f546a0733e158f9da39a4360937b4b59aa782d /ELF | |
parent | d93e1dfac8711cfed1a9d9cd1876a788b83945cd (diff) | |
download | src-vendor/lld/lld-trunk-r291015.tar.gz src-vendor/lld/lld-trunk-r291015.zip |
Vendor import of lld trunk r291012:vendor/lld/lld-trunk-r291015vendor/lld/lld-trunk-r291012
Diffstat (limited to 'ELF')
-rw-r--r-- | ELF/InputFiles.cpp | 2 | ||||
-rw-r--r-- | ELF/LTO.cpp | 15 | ||||
-rw-r--r-- | ELF/LTO.h | 2 | ||||
-rw-r--r-- | ELF/SymbolTable.cpp | 6 | ||||
-rw-r--r-- | ELF/Symbols.cpp | 12 | ||||
-rw-r--r-- | ELF/Symbols.h | 11 | ||||
-rw-r--r-- | ELF/Target.cpp | 7 | ||||
-rw-r--r-- | ELF/Thunks.cpp | 2 | ||||
-rw-r--r-- | ELF/Writer.cpp | 22 |
9 files changed, 53 insertions, 26 deletions
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp index 2a8659921463..f4128c5096cb 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -461,7 +461,7 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) { StringRefZ Name = this->StringTable.data() + Sym->st_name; if (Sym->st_shndx == SHN_UNDEF) return new (BAlloc) - Undefined(Name, /*IsLocal=*/true, StOther, Type, this); + Undefined<ELFT>(Name, /*IsLocal=*/true, StOther, Type, this); return new (BAlloc) DefinedRegular<ELFT>(Name, /*IsLocal=*/true, StOther, Type, Value, Size, Sec, this); diff --git a/ELF/LTO.cpp b/ELF/LTO.cpp index a3d6a141a202..b342b6195f1d 100644 --- a/ELF/LTO.cpp +++ b/ELF/LTO.cpp @@ -96,12 +96,12 @@ BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} BitcodeCompiler::~BitcodeCompiler() = default; -static void undefine(Symbol *S) { - replaceBody<Undefined>(S, S->body()->getName(), /*IsLocal=*/false, - STV_DEFAULT, S->body()->Type, nullptr); +template <class ELFT> static void undefine(Symbol *S) { + replaceBody<Undefined<ELFT>>(S, S->body()->getName(), /*IsLocal=*/false, + STV_DEFAULT, S->body()->Type, nullptr); } -void BitcodeCompiler::add(BitcodeFile &F) { +template <class ELFT> void BitcodeCompiler::add(BitcodeFile &F) { lto::InputFile &Obj = *F.Obj; unsigned SymNum = 0; std::vector<Symbol *> Syms = F.getSymbols(); @@ -126,7 +126,7 @@ void BitcodeCompiler::add(BitcodeFile &F) { R.VisibleToRegularObj = Sym->IsUsedInRegularObj || (R.Prevailing && Sym->includeInDynsym()); if (R.Prevailing) - undefine(Sym); + undefine<ELFT>(Sym); } checkError(LTOObj->add(std::move(F.Obj), Resols)); } @@ -157,3 +157,8 @@ std::vector<InputFile *> BitcodeCompiler::compile() { } return Ret; } + +template void BitcodeCompiler::template add<ELF32LE>(BitcodeFile &); +template void BitcodeCompiler::template add<ELF32BE>(BitcodeFile &); +template void BitcodeCompiler::template add<ELF64LE>(BitcodeFile &); +template void BitcodeCompiler::template add<ELF64BE>(BitcodeFile &); diff --git a/ELF/LTO.h b/ELF/LTO.h index b3d734f2d381..3cb763650e1c 100644 --- a/ELF/LTO.h +++ b/ELF/LTO.h @@ -43,7 +43,7 @@ public: BitcodeCompiler(); ~BitcodeCompiler(); - void add(BitcodeFile &F); + template <class ELFT> void add(BitcodeFile &F); std::vector<InputFile *> compile(); private: diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp index 79097e176e68..f08fa6229c1a 100644 --- a/ELF/SymbolTable.cpp +++ b/ELF/SymbolTable.cpp @@ -115,7 +115,7 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLTOObject() { // Compile bitcode files and replace bitcode symbols. LTO.reset(new BitcodeCompiler); for (BitcodeFile *F : BitcodeFiles) - LTO->add(*F); + LTO->add<ELFT>(*F); for (InputFile *File : LTO->compile()) { ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File); @@ -256,7 +256,7 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal, insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, File); if (WasInserted) { S->Binding = Binding; - replaceBody<Undefined>(S, Name, IsLocal, StOther, Type, File); + replaceBody<Undefined<ELFT>>(S, Name, IsLocal, StOther, Type, File); return S; } if (Binding != STB_WEAK) { @@ -432,7 +432,7 @@ void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name, if (S->VersionId == VER_NDX_LOCAL) S->VersionId = VER_NDX_GLOBAL; } - if (WasInserted || isa<Undefined>(S->body())) { + if (WasInserted || isa<Undefined<ELFT>>(S->body())) { replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef); if (!S->isWeak()) F->IsUsed = true; diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp index a2133f411c20..f168d37bdf0a 100644 --- a/ELF/Symbols.cpp +++ b/ELF/Symbols.cpp @@ -173,6 +173,8 @@ template <class ELFT> typename ELFT::uint SymbolBody::getThunkVA() const { return DR->ThunkData->getVA(); if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this)) return S->ThunkData->getVA(); + if (const auto *S = dyn_cast<Undefined<ELFT>>(this)) + return S->ThunkData->getVA(); fatal("getThunkVA() not supported for Symbol class\n"); } @@ -232,8 +234,9 @@ template <class ELFT> bool DefinedRegular<ELFT>::isMipsPIC() const { (Section->getFile()->getObj().getHeader()->e_flags & EF_MIPS_PIC); } -Undefined::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, - uint8_t Type, InputFile *File) +template <typename ELFT> +Undefined<ELFT>::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, + uint8_t Type, InputFile *File) : SymbolBody(SymbolBody::UndefinedKind, Name, IsLocal, StOther, Type) { this->File = File; } @@ -354,6 +357,11 @@ template uint32_t SymbolBody::template getSize<ELF32BE>() const; template uint64_t SymbolBody::template getSize<ELF64LE>() const; template uint64_t SymbolBody::template getSize<ELF64BE>() const; +template class elf::Undefined<ELF32LE>; +template class elf::Undefined<ELF32BE>; +template class elf::Undefined<ELF64LE>; +template class elf::Undefined<ELF64BE>; + template class elf::DefinedRegular<ELF32LE>; template class elf::DefinedRegular<ELF32BE>; template class elf::DefinedRegular<ELF64LE>; diff --git a/ELF/Symbols.h b/ELF/Symbols.h index c95241a5293e..cbf8fa81a138 100644 --- a/ELF/Symbols.h +++ b/ELF/Symbols.h @@ -236,7 +236,7 @@ public: const OutputSectionBase *Section; }; -class Undefined : public SymbolBody { +template <class ELFT> class Undefined : public SymbolBody { public: Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type, InputFile *F); @@ -245,6 +245,12 @@ public: return S->kind() == UndefinedKind; } + // If non-null the symbol has a Thunk that may be used as an alternative + // destination for callers of this Symbol. When linking a DSO undefined + // symbols are implicitly imported, the symbol lookup will be performed by + // the dynamic loader. A call to an undefined symbol will be given a PLT + // entry and on ARM this may need a Thunk if the caller is in Thumb state. + Thunk<ELFT> *ThunkData = nullptr; InputFile *file() { return this->File; } }; @@ -416,7 +422,8 @@ struct Symbol { // ELFT, and we verify this with the static_asserts in replaceBody. llvm::AlignedCharArrayUnion< DefinedCommon, DefinedRegular<llvm::object::ELF64LE>, DefinedSynthetic, - Undefined, SharedSymbol<llvm::object::ELF64LE>, LazyArchive, LazyObject> + Undefined<llvm::object::ELF64LE>, SharedSymbol<llvm::object::ELF64LE>, + LazyArchive, LazyObject> Body; SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); } diff --git a/ELF/Target.cpp b/ELF/Target.cpp index edae7c65c1b4..d82e654b9c4c 100644 --- a/ELF/Target.cpp +++ b/ELF/Target.cpp @@ -1730,8 +1730,11 @@ void ARMTargetInfo::writePlt(uint8_t *Buf, uint64_t GotEntryAddr, RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType, const InputFile &File, const SymbolBody &S) const { - // If S is an undefined weak symbol we don't need a Thunk - if (S.isUndefined()) + // If S is an undefined weak symbol in an executable we don't need a Thunk. + // In a DSO calls to undefined symbols, including weak ones get PLT entries + // which may need a thunk. + if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() + && !Config->Shared) return Expr; // A state change from ARM to Thumb and vice versa must go through an // interworking thunk if the relocation type is not R_ARM_CALL or diff --git a/ELF/Thunks.cpp b/ELF/Thunks.cpp index 34b630ac2510..397a0ee66319 100644 --- a/ELF/Thunks.cpp +++ b/ELF/Thunks.cpp @@ -226,6 +226,8 @@ static void addThunkARM(uint32_t Reloc, SymbolBody &S, InputSection<ELFT> &IS) { Sym->ThunkData = T; else if (auto *Sym = dyn_cast<SharedSymbol<ELFT>>(&S)) Sym->ThunkData = T; + else if (auto *Sym = dyn_cast<Undefined<ELFT>>(&S)) + Sym->ThunkData = T; else fatal("symbol not DefinedRegular or Shared"); } diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index e056384fbd44..154de8cf6d18 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -625,15 +625,12 @@ void PhdrEntry::add(OutputSectionBase *Sec) { } template <class ELFT> -static Symbol *addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec, - typename ELFT::uint Val, - uint8_t StOther = STV_HIDDEN) { - SymbolBody *S = Symtab<ELFT>::X->find(Name); - if (!S) - return nullptr; - if (!S->isUndefined() && !S->isShared()) - return S->symbol(); - return Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther); +static void addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec, + typename ELFT::uint Val, + uint8_t StOther = STV_HIDDEN) { + if (SymbolBody *S = Symtab<ELFT>::X->find(Name)) + if (S->isUndefined() || S->isShared()) + Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther); } template <class ELFT> @@ -1447,8 +1444,13 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() { } if (P.p_type == PT_LOAD) P.p_align = Config->MaxPageSize; - else if (P.p_type == PT_GNU_RELRO) + else if (P.p_type == PT_GNU_RELRO) { P.p_align = 1; + // The glibc dynamic loader rounds the size down, so we need to round up + // to protect the last page. This is a no-op on FreeBSD which always + // rounds up. + P.p_memsz = alignTo(P.p_memsz, Config->MaxPageSize); + } // The TLS pointer goes after PT_TLS. At least glibc will align it, // so round up the size to make sure the offsets are correct. |