diff options
Diffstat (limited to 'contrib/llvm-project/lld/ELF/SyntheticSections.cpp')
-rw-r--r-- | contrib/llvm-project/lld/ELF/SyntheticSections.cpp | 120 |
1 files changed, 79 insertions, 41 deletions
diff --git a/contrib/llvm-project/lld/ELF/SyntheticSections.cpp b/contrib/llvm-project/lld/ELF/SyntheticSections.cpp index 7778ae5f78e6..b8a2ebeefce9 100644 --- a/contrib/llvm-project/lld/ELF/SyntheticSections.cpp +++ b/contrib/llvm-project/lld/ELF/SyntheticSections.cpp @@ -15,12 +15,15 @@ #include "SyntheticSections.h" #include "Config.h" +#include "DWARF.h" +#include "EhFrame.h" #include "InputFiles.h" #include "LinkerScript.h" #include "OutputSections.h" #include "SymbolTable.h" #include "Symbols.h" #include "Target.h" +#include "Thunks.h" #include "Writer.h" #include "lld/Common/CommonLinkerContext.h" #include "lld/Common/DWARF.h" @@ -29,16 +32,13 @@ #include "llvm/ADT/SetOperations.h" #include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" -#include "llvm/Object/ELFObjectFile.h" -#include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" #include "llvm/Support/LEB128.h" -#include "llvm/Support/MD5.h" #include "llvm/Support/Parallel.h" #include "llvm/Support/TimeProfiler.h" #include <cstdlib> -#include <thread> using namespace llvm; using namespace llvm::dwarf; @@ -113,7 +113,7 @@ std::unique_ptr<MipsAbiFlagsSection<ELFT>> MipsAbiFlagsSection<ELFT>::create() { create = true; std::string filename = toString(sec->file); - const size_t size = sec->data().size(); + const size_t size = sec->rawData.size(); // Older version of BFD (such as the default FreeBSD linker) concatenate // .MIPS.abiflags instead of merging. To allow for this case (or potential // zero padding) we ignore everything after the first Elf_Mips_ABIFlags @@ -122,7 +122,7 @@ std::unique_ptr<MipsAbiFlagsSection<ELFT>> MipsAbiFlagsSection<ELFT>::create() { Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); return nullptr; } - auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data()); + auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->rawData.data()); if (s->version != 0) { error(filename + ": unexpected .MIPS.abiflags version " + Twine(s->version)); @@ -185,7 +185,7 @@ std::unique_ptr<MipsOptionsSection<ELFT>> MipsOptionsSection<ELFT>::create() { sec->markDead(); std::string filename = toString(sec->file); - ArrayRef<uint8_t> d = sec->data(); + ArrayRef<uint8_t> d = sec->rawData; while (!d.empty()) { if (d.size() < sizeof(Elf_Mips_Options)) { @@ -241,12 +241,12 @@ std::unique_ptr<MipsReginfoSection<ELFT>> MipsReginfoSection<ELFT>::create() { for (InputSectionBase *sec : sections) { sec->markDead(); - if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) { + if (sec->rawData.size() != sizeof(Elf_Mips_RegInfo)) { error(toString(sec->file) + ": invalid size of .reginfo section"); return nullptr; } - auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data()); + auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->rawData.data()); reginfo.ri_gprmask |= r->ri_gprmask; sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value; }; @@ -410,7 +410,8 @@ void EhFrameSection::addRecords(EhInputSection *sec, ArrayRef<RelTy> rels) { return; size_t offset = piece.inputOff; - uint32_t id = read32(piece.data().data() + 4); + const uint32_t id = + endian::read32<ELFT::TargetEndianness>(piece.data().data() + 4); if (id == 0) { offsetToCie[offset] = addCie<ELFT>(piece, rels); continue; @@ -1335,7 +1336,7 @@ DynamicSection<ELFT>::computeContents() { addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH, part.dynStrTab->addString(config->rpath)); - for (SharedFile *file : sharedFiles) + for (SharedFile *file : ctx->sharedFiles) if (file->isNeeded) addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); @@ -1504,7 +1505,7 @@ DynamicSection<ELFT>::computeContents() { if (part.verNeed && part.verNeed->isNeeded()) { addInSec(DT_VERNEED, *part.verNeed); unsigned needNum = 0; - for (SharedFile *f : sharedFiles) + for (SharedFile *f : ctx->sharedFiles) if (!f->vernauxs.empty()) ++needNum; addInt(DT_VERNEEDNUM, needNum); @@ -1588,9 +1589,14 @@ int64_t DynamicReloc::computeAddend() const { } uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const { - if (needsDynSymIndex()) - return symTab->getSymbolIndex(sym); - return 0; + if (!needsDynSymIndex()) + return 0; + + size_t index = symTab->getSymbolIndex(sym); + assert((index != 0 || (type != target->gotRel && type != target->pltRel) || + !mainPart->dynSymTab->getParent()) && + "GOT or PLT relocation must refer to symbol in dynamic symbol table"); + return index; } RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type, @@ -2158,9 +2164,7 @@ void SymbolTableBaseSection::sortSymTabSymbols() { void SymbolTableBaseSection::addSymbol(Symbol *b) { // Adding a local symbol to a .dynsym is a bug. assert(this->type != SHT_DYNSYM || !b->isLocal()); - - bool hashIt = b->isLocal() && config->optimize >= 2; - symbols.push_back({b, strTabSec.addString(b->getName(), hashIt)}); + symbols.push_back({b, strTabSec.addString(b->getName(), false)}); } size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) { @@ -2194,7 +2198,7 @@ SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &strTabSec) } static BssSection *getCommonSec(Symbol *sym) { - if (!config->defineCommon) + if (config->relocatable) if (auto *d = dyn_cast<Defined>(sym)) return dyn_cast_or_null<BssSection>(d->section); return nullptr; @@ -2236,8 +2240,8 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) { eSym->st_other |= sym->stOther & STO_AARCH64_VARIANT_PCS; if (BssSection *commonSec = getCommonSec(sym)) { - // st_value is usually an address of a symbol, but that has a special - // meaning for uninstantiated common symbols (--no-define-common). + // When -r is specified, a COMMON symbol is not allocated. Its st_shndx + // holds SHN_COMMON and st_value holds the alignment. eSym->st_shndx = SHN_COMMON; eSym->st_value = commonSec->alignment; eSym->st_size = cast<Defined>(sym)->size; @@ -2322,7 +2326,7 @@ bool SymtabShndxSection::isNeeded() const { // a .symtab_shndx section when the amount of output sections is huge. size_t size = 0; for (SectionCommand *cmd : script->sectionCommands) - if (isa<OutputSection>(cmd)) + if (isa<OutputDesc>(cmd)) ++size; return size >= SHN_LORESERVE; } @@ -2837,7 +2841,7 @@ static SmallVector<GdbIndexSection::GdbSymbol, 0> createSymbols( // Instantiate GdbSymbols while uniqufying them by name. auto symbols = std::make_unique<SmallVector<GdbSymbol, 0>[]>(numShards); - parallelForEachN(0, concurrency, [&](size_t threadId) { + parallelFor(0, concurrency, [&](size_t threadId) { uint32_t i = 0; for (ArrayRef<NameAttrEntry> entries : nameAttrs) { for (const NameAttrEntry &ent : entries) { @@ -2917,7 +2921,7 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() { SmallVector<GdbChunk, 0> chunks(files.size()); SmallVector<SmallVector<NameAttrEntry, 0>, 0> nameAttrs(files.size()); - parallelForEachN(0, files.size(), [&](size_t i) { + parallelFor(0, files.size(), [&](size_t i) { // To keep memory usage low, we don't want to keep cached DWARFContext, so // avoid getDwarf() here. ObjFile<ELFT> *file = cast<ObjFile<ELFT>>(files[i]); @@ -3175,21 +3179,30 @@ VersionNeedSection<ELFT>::VersionNeedSection() ".gnu.version_r") {} template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { - for (SharedFile *f : sharedFiles) { + for (SharedFile *f : ctx->sharedFiles) { if (f->vernauxs.empty()) continue; verneeds.emplace_back(); Verneed &vn = verneeds.back(); vn.nameStrTab = getPartition().dynStrTab->addString(f->soName); + bool isLibc = config->relrGlibc && f->soName.startswith("libc.so."); + bool isGlibc2 = false; for (unsigned i = 0; i != f->vernauxs.size(); ++i) { if (f->vernauxs[i] == 0) continue; auto *verdef = reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]); - vn.vernauxs.push_back( - {verdef->vd_hash, f->vernauxs[i], - getPartition().dynStrTab->addString(f->getStringTable().data() + - verdef->getAux()->vda_name)}); + StringRef ver(f->getStringTable().data() + verdef->getAux()->vda_name); + if (isLibc && ver.startswith("GLIBC_2.")) + isGlibc2 = true; + vn.vernauxs.push_back({verdef->vd_hash, f->vernauxs[i], + getPartition().dynStrTab->addString(ver)}); + } + if (isGlibc2) { + const char *ver = "GLIBC_ABI_DT_RELR"; + vn.vernauxs.push_back({hashSysV(ver), + ++SharedFile::vernauxNum + getVerDefNum(), + getPartition().dynStrTab->addString(ver)}); } } @@ -3274,8 +3287,8 @@ void MergeTailSection::finalizeContents() { } void MergeNoTailSection::writeTo(uint8_t *buf) { - parallelForEachN(0, numShards, - [&](size_t i) { shards[i].write(buf + shardOffsets[i]); }); + parallelFor(0, numShards, + [&](size_t i) { shards[i].write(buf + shardOffsets[i]); }); } // This function is very hot (i.e. it can take several seconds to finish) @@ -3299,7 +3312,7 @@ void MergeNoTailSection::finalizeContents() { numShards)); // Add section pieces to the builders. - parallelForEachN(0, concurrency, [&](size_t threadId) { + parallelFor(0, concurrency, [&](size_t threadId) { for (MergeInputSection *sec : sections) { for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) { if (!sec->pieces[i].live) @@ -3336,7 +3349,7 @@ template <class ELFT> void elf::splitSections() { llvm::TimeTraceScope timeScope("Split sections"); // splitIntoPieces needs to be called on each MergeInputSection // before calling finalizeContents(). - parallelForEach(objectFiles, [](ELFFileBase *file) { + parallelForEach(ctx->objectFiles, [](ELFFileBase *file) { for (InputSectionBase *sec : file->getSections()) { if (!sec) continue; @@ -3540,7 +3553,7 @@ void ARMExidxSyntheticSection::writeTo(uint8_t *buf) { for (InputSection *isec : executableSections) { assert(isec->getParent() != nullptr); if (InputSection *d = findExidxSection(isec)) { - memcpy(buf + offset, d->data().data(), d->data().size()); + memcpy(buf + offset, d->rawData.data(), d->rawData.size()); d->relocateAlloc(buf + d->outSecOff, buf + d->outSecOff + d->getSize()); offset += d->getSize(); } else { @@ -3565,10 +3578,6 @@ bool ARMExidxSyntheticSection::isNeeded() const { [](InputSection *isec) { return isec->isLive(); }); } -bool ARMExidxSyntheticSection::classof(const SectionBase *d) { - return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX; -} - ThunkSection::ThunkSection(OutputSection *os, uint64_t off) : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, config->emachine == EM_PPC64 ? 16 : 4, ".text.thunk") { @@ -3708,9 +3717,9 @@ static uint8_t getAbiVersion() { return 0; } - if (config->emachine == EM_AMDGPU) { - uint8_t ver = objectFiles[0]->abiVersion; - for (InputFile *file : makeArrayRef(objectFiles).slice(1)) + if (config->emachine == EM_AMDGPU && !ctx->objectFiles.empty()) { + uint8_t ver = ctx->objectFiles[0]->abiVersion; + for (InputFile *file : makeArrayRef(ctx->objectFiles).slice(1)) if (file->abiVersion != ver) error("incompatible ABI version: " + toString(file)); return ver; @@ -3844,6 +3853,35 @@ void InStruct::reset() { symTabShndx.reset(); } +constexpr char kMemtagAndroidNoteName[] = "Android"; +void MemtagAndroidNote::writeTo(uint8_t *buf) { + assert(sizeof(kMemtagAndroidNoteName) == 8); // ABI check for Android 11 & 12. + assert((config->androidMemtagStack || config->androidMemtagHeap) && + "Should only be synthesizing a note if heap || stack is enabled."); + + write32(buf, sizeof(kMemtagAndroidNoteName)); + write32(buf + 4, sizeof(uint32_t)); + write32(buf + 8, ELF::NT_ANDROID_TYPE_MEMTAG); + memcpy(buf + 12, kMemtagAndroidNoteName, sizeof(kMemtagAndroidNoteName)); + buf += 12 + sizeof(kMemtagAndroidNoteName); + + uint32_t value = 0; + value |= config->androidMemtagMode; + if (config->androidMemtagHeap) + value |= ELF::NT_MEMTAG_HEAP; + // Note, MTE stack is an ABI break. Attempting to run an MTE stack-enabled + // binary on Android 11 or 12 will result in a checkfail in the loader. + if (config->androidMemtagStack) + value |= ELF::NT_MEMTAG_STACK; + write32(buf, value); // note value +} + +size_t MemtagAndroidNote::getSize() const { + return sizeof(llvm::ELF::Elf64_Nhdr) + + /*namesz=*/sizeof(kMemtagAndroidNoteName) + + /*descsz=*/sizeof(uint32_t); +} + InStruct elf::in; std::vector<Partition> elf::partitions; |