diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-03-20 11:40:34 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-06-04 11:58:51 +0000 |
commit | 4b6eb0e63c698094db5506763df44cc83c19f643 (patch) | |
tree | f1d30b8c10bc6db323b91538745ae8ab8b593910 /contrib/llvm-project/lld/ELF/InputSection.cpp | |
parent | 76886853f03395abb680824bcc74e98f83bd477a (diff) |
Merge llvm-project main llvmorg-14-init-10186-gff7f2cfa959b
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and
openmp to llvmorg-14-init-10186-gff7f2cfa959b.
PR: 261742
MFC after: 2 weeks
(cherry picked from commit 349cc55c9796c4596a5b9904cd3281af295f878f)
Diffstat (limited to 'contrib/llvm-project/lld/ELF/InputSection.cpp')
-rw-r--r-- | contrib/llvm-project/lld/ELF/InputSection.cpp | 105 |
1 files changed, 53 insertions, 52 deletions
diff --git a/contrib/llvm-project/lld/ELF/InputSection.cpp b/contrib/llvm-project/lld/ELF/InputSection.cpp index 7d952e9037f1..74d4dd309c79 100644 --- a/contrib/llvm-project/lld/ELF/InputSection.cpp +++ b/contrib/llvm-project/lld/ELF/InputSection.cpp @@ -70,9 +70,6 @@ InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags, if (sectionKind == SectionBase::Merge && rawData.size() > UINT32_MAX) error(toString(this) + ": section too large"); - numRelocations = 0; - areRelocsRela = false; - // The ELF spec states that a value of 0 means the section has // no alignment constraints. uint32_t v = std::max<uint32_t>(alignment, 1); @@ -117,32 +114,14 @@ static uint64_t getFlags(uint64_t flags) { return flags; } -// GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of -// March 2017) fail to infer section types for sections starting with -// ".init_array." or ".fini_array.". They set SHT_PROGBITS instead of -// SHF_INIT_ARRAY. As a result, the following assembler directive -// creates ".init_array.100" with SHT_PROGBITS, for example. -// -// .section .init_array.100, "aw" -// -// This function forces SHT_{INIT,FINI}_ARRAY so that we can handle -// incorrect inputs as if they were correct from the beginning. -static uint64_t getType(uint64_t type, StringRef name) { - if (type == SHT_PROGBITS && name.startswith(".init_array.")) - return SHT_INIT_ARRAY; - if (type == SHT_PROGBITS && name.startswith(".fini_array.")) - return SHT_FINI_ARRAY; - return type; -} - template <class ELFT> InputSectionBase::InputSectionBase(ObjFile<ELFT> &file, const typename ELFT::Shdr &hdr, StringRef name, Kind sectionKind) - : InputSectionBase(&file, getFlags(hdr.sh_flags), - getType(hdr.sh_type, name), hdr.sh_entsize, hdr.sh_link, - hdr.sh_info, hdr.sh_addralign, - getSectionContents(file, hdr), name, sectionKind) { + : InputSectionBase(&file, getFlags(hdr.sh_flags), hdr.sh_type, + hdr.sh_entsize, hdr.sh_link, hdr.sh_info, + hdr.sh_addralign, getSectionContents(file, hdr), name, + sectionKind) { // We reject object files having insanely large alignments even though // they are allowed by the spec. I think 4GB is a reasonable limitation. // We might want to relax this in the future. @@ -180,6 +159,25 @@ uint64_t InputSectionBase::getOffsetInFile() const { return secStart - fileStart; } +template <class ELFT> RelsOrRelas<ELFT> InputSectionBase::relsOrRelas() const { + if (relSecIdx == 0) + return {}; + RelsOrRelas<ELFT> ret; + const ELFFile<ELFT> obj = cast<ELFFileBase>(file)->getObj<ELFT>(); + typename ELFT::Shdr shdr = cantFail(obj.sections())[relSecIdx]; + if (shdr.sh_type == SHT_REL) { + ret.rels = makeArrayRef(reinterpret_cast<const typename ELFT::Rel *>( + obj.base() + shdr.sh_offset), + shdr.sh_size / sizeof(typename ELFT::Rel)); + } else { + assert(shdr.sh_type == SHT_RELA); + ret.relas = makeArrayRef(reinterpret_cast<const typename ELFT::Rela *>( + obj.base() + shdr.sh_offset), + shdr.sh_size / sizeof(typename ELFT::Rela)); + } + return ret; +} + uint64_t SectionBase::getOffset(uint64_t offset) const { switch (kind()) { case Output: { @@ -286,32 +284,21 @@ Defined *InputSectionBase::getEnclosingFunction(uint64_t offset) { return nullptr; } -// Returns a source location string. Used to construct an error message. +// Returns an object file location string. Used to construct an error message. template <class ELFT> std::string InputSectionBase::getLocation(uint64_t offset) { - std::string secAndOffset = (name + "+0x" + utohexstr(offset)).str(); + std::string secAndOffset = + (name + "+0x" + Twine::utohexstr(offset) + ")").str(); // We don't have file for synthetic sections. if (getFile<ELFT>() == nullptr) - return (config->outputFile + ":(" + secAndOffset + ")") - .str(); - - // First check if we can get desired values from debugging information. - if (Optional<DILineInfo> info = getFile<ELFT>()->getDILineInfo(this, offset)) - return info->FileName + ":" + std::to_string(info->Line) + ":(" + - secAndOffset + ")"; - - // File->sourceFile contains STT_FILE symbol that contains a - // source file name. If it's missing, we use an object file name. - std::string srcFile = std::string(getFile<ELFT>()->sourceFile); - if (srcFile.empty()) - srcFile = toString(file); + return (config->outputFile + ":(" + secAndOffset).str(); + std::string file = toString(getFile<ELFT>()); if (Defined *d = getEnclosingFunction<ELFT>(offset)) - return srcFile + ":(function " + toString(*d) + ": " + secAndOffset + ")"; + return file + ":(function " + toString(*d) + ": " + secAndOffset; - // If there's no symbol, print out the offset in the section. - return (srcFile + ":(" + secAndOffset + ")"); + return file + ":(" + secAndOffset; } // This function is intended to be used for constructing an error message. @@ -508,6 +495,7 @@ static uint32_t getARMUndefinedRelativeWeakVA(RelType type, uint32_t a, switch (type) { // Unresolved branch relocations to weak references resolve to next // instruction, this will be either 2 or 4 bytes on from P. + case R_ARM_THM_JUMP8: case R_ARM_THM_JUMP11: return p + 2 + a; case R_ARM_CALL: @@ -795,6 +783,8 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type, case R_PLT_PC: case R_PPC64_CALL_PLT: return sym.getPltVA() + a - p; + case R_PLT_GOTPLT: + return sym.getPltVA() + a - in.gotPlt->getVA(); case R_PPC32_PLTREL: // R_PPC_PLTREL24 uses the addend (usually 0 or 0x8000) to indicate r30 // stores _GLOBAL_OFFSET_TABLE_ or .got2+0x8000. The addend is ignored for @@ -829,7 +819,7 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type, // --noinhibit-exec, even a non-weak undefined reference may reach here. // Just return A, which matches R_ABS, and the behavior of some dynamic // loaders. - if (sym.isUndefined() || sym.isLazy()) + if (sym.isUndefined()) return a; return getTlsTpOffset(sym) + a; case R_RELAX_TLS_GD_TO_LE_NEG: @@ -843,6 +833,8 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type, return in.got->getGlobalDynAddr(sym) + a; case R_TLSDESC_PC: return in.got->getGlobalDynAddr(sym) + a - p; + case R_TLSDESC_GOTPLT: + return in.got->getGlobalDynAddr(sym) + a - in.gotPlt->getVA(); case R_AARCH64_TLSDESC_PAGE: return getAArch64Page(in.got->getGlobalDynAddr(sym) + a) - getAArch64Page(p); @@ -1009,12 +1001,15 @@ void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) { } auto *sec = cast<InputSection>(this); - if (config->relocatable) + if (config->relocatable) { relocateNonAllocForRelocatable(sec, buf); - else if (sec->areRelocsRela) - sec->relocateNonAlloc<ELFT>(buf, sec->template relas<ELFT>()); - else - sec->relocateNonAlloc<ELFT>(buf, sec->template rels<ELFT>()); + } else { + const RelsOrRelas<ELFT> rels = sec->template relsOrRelas<ELFT>(); + if (rels.areRelocsRel()) + sec->relocateNonAlloc<ELFT>(buf, rels.rels); + else + sec->relocateNonAlloc<ELFT>(buf, rels.relas); + } } void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { @@ -1328,10 +1323,11 @@ static unsigned getReloc(IntTy begin, IntTy size, const ArrayRef<RelTy> &rels, // .eh_frame is a sequence of CIE or FDE records. // This function splits an input section into records and returns them. template <class ELFT> void EhInputSection::split() { - if (areRelocsRela) - split<ELFT>(relas<ELFT>()); + const RelsOrRelas<ELFT> rels = relsOrRelas<ELFT>(); + if (rels.areRelocsRel()) + split<ELFT>(rels.rels); else - split<ELFT>(rels<ELFT>()); + split<ELFT>(rels.relas); } template <class ELFT, class RelTy> @@ -1468,6 +1464,11 @@ template void InputSection::writeTo<ELF32BE>(uint8_t *); template void InputSection::writeTo<ELF64LE>(uint8_t *); template void InputSection::writeTo<ELF64BE>(uint8_t *); +template RelsOrRelas<ELF32LE> InputSectionBase::relsOrRelas<ELF32LE>() const; +template RelsOrRelas<ELF32BE> InputSectionBase::relsOrRelas<ELF32BE>() const; +template RelsOrRelas<ELF64LE> InputSectionBase::relsOrRelas<ELF64LE>() const; +template RelsOrRelas<ELF64BE> InputSectionBase::relsOrRelas<ELF64BE>() const; + template MergeInputSection::MergeInputSection(ObjFile<ELF32LE> &, const ELF32LE::Shdr &, StringRef); template MergeInputSection::MergeInputSection(ObjFile<ELF32BE> &, |