From 8d6b1b8c0104d1153a81d8f3b8074351a1d80394 Mon Sep 17 00:00:00 2001 From: DmitrievVadim Date: Fri, 29 Nov 2024 19:45:14 +0300 Subject: [PATCH] Realization of the EH section merge Change-Id: I40878e034e8e09ee44370ac8508e0491aecce011 Signed-off-by: DmitrievVadim --- lld/ELF/Adlt/Context.cpp | 3 ++- lld/ELF/Adlt/Context.h | 1 + lld/ELF/Adlt/InputFiles.cpp | 14 ++++++++++++++ lld/ELF/Adlt/SyntheticSections.cpp | 2 +- lld/ELF/Adlt/Writer.cpp | 10 +++------- lld/ELF/InputSection.cpp | 18 ++++++++++++++++- lld/ELF/InputSection.h | 5 +++++ lld/ELF/Relocations.cpp | 12 +++++++++++- lld/ELF/SyntheticSections.cpp | 31 +++++++++++++++++++++++------- lld/ELF/Writer.cpp | 27 +++++++++++++++----------- 10 files changed, 94 insertions(+), 29 deletions(-) diff --git a/lld/ELF/Adlt/Context.cpp b/lld/ELF/Adlt/Context.cpp index b1c251389916..141dc6f5f0b6 100644 --- a/lld/ELF/Adlt/Context.cpp +++ b/lld/ELF/Adlt/Context.cpp @@ -171,7 +171,8 @@ void Impl::aggregateSections() { // But we need to keep them for scanning. bool isNeededProgBits = s->type == SHT_PROGBITS && - !(s->name == ".got" || s->name == ".got.plt" || s->name == ".plt"); + !(s->name == ".got" || s->name == ".got.plt" || s->name == ".plt" || + (adlt::ctx->withEHFrame && s->name.startswith(".eh_frame_hdr"))); bool isNeededRela = config->emitRelocs && s->type == SHT_RELA && !(s->name == ".rela.dyn" || s->name == ".rela.plt"); return isBaseType || isNeededProgBits || isNeededRela; diff --git a/lld/ELF/Adlt/Context.h b/lld/ELF/Adlt/Context.h index 7065d7fe12c5..abb429328be9 100644 --- a/lld/ELF/Adlt/Context.h +++ b/lld/ELF/Adlt/Context.h @@ -106,6 +106,7 @@ public: bool withRelr = false; bool withAndroidRela = false; bool isNoteOhosAdded = false; + bool withEHFrame = false; llvm::SetVector getSoIndexesGotPlt(StringRef symName) const; void addSoIndexesGotPlt(StringRef symName, size_t orderIndx); diff --git a/lld/ELF/Adlt/InputFiles.cpp b/lld/ELF/Adlt/InputFiles.cpp index 4b947bf10010..a1ea0d0a0e1b 100644 --- a/lld/ELF/Adlt/InputFiles.cpp +++ b/lld/ELF/Adlt/InputFiles.cpp @@ -237,6 +237,16 @@ InputSectionBase *Impl::createInputSection(uint32_t indx, : check(this->template getObj().getSectionContents(shdr)); assert(parent); + + if (adlt::ctx->withEHFrame && name == ".eh_frame") { + auto *sec = make(parent, shdr.sh_flags, shdr.sh_type, + shdr.sh_entsize, shdr.sh_link, + shdr.sh_info, shdr.sh_addralign, data, + uniqueName); + init(sec); + return sec; + } + auto *sec = make(parent, shdr.sh_flags, shdr.sh_type, shdr.sh_addralign, data, uniqueName); init(sec); @@ -560,6 +570,10 @@ template void Impl::scanSections() { break; } else if (name.startswith(".debug_")) { needsUnique = false; + } else if (name.startswith(".eh_frame")) { + if (config->adltTrace && !adlt::ctx->withEHFrame) + lld::outs() << "[ADLT] EHFrame mode is ON\n"; + adlt::ctx->withEHFrame = true; } LLVM_FALLTHROUGH; case SHT_NOBITS: diff --git a/lld/ELF/Adlt/SyntheticSections.cpp b/lld/ELF/Adlt/SyntheticSections.cpp index 8477f7d4b5e4..bb36ccebe4ce 100644 --- a/lld/ELF/Adlt/SyntheticSections.cpp +++ b/lld/ELF/Adlt/SyntheticSections.cpp @@ -260,7 +260,7 @@ Impl::SoData Impl::makeSoData(const SharedFile *file) { data.initArrayName = file->getSavedUniqueName(".init_array"); data.finiArrayName = file->getSavedUniqueName(".fini_array"); - data.ehFrameHdrName = file->getSavedUniqueName(".eh_frame_hdr"); + data.ehFrameHdrName = ".eh_frame_hdr"; if (elf::adlt::cfg->isNeedRelocIndexes()) { // Note: no modifications to relocationIndexes's valid size (and so, data diff --git a/lld/ELF/Adlt/Writer.cpp b/lld/ELF/Adlt/Writer.cpp index f920bef585a4..8d07ae245d26 100644 --- a/lld/ELF/Adlt/Writer.cpp +++ b/lld/ELF/Adlt/Writer.cpp @@ -112,11 +112,7 @@ void Writer::updateLoadSegments(SmallVector &phdrs) const { p->p_align = std::max(p->firstSec->alignment, p->lastSec->alignment); continue; } - // Reduce alignment for segments with single section - /*if (p->firstSec == p->lastSec) { // Set the minimal alignment - p->p_align = p->lastSec->alignment; // for the segment with 1 section - continue; - }*/ + // TODO: Reduce alignment for segments with single section // TODO: Check the size of the sections or // memory size for the segment and add alignment if they overlap. bool withOwner = p->firstSec->hasInputSections; @@ -499,11 +495,11 @@ bool Checker::isReadSection(kOsec &sec) const { // generated sections if (s == ".note.ohos.ident" || s == ".dynsym" || s == ".gnu.hash" || s == ".hash" || s == ".dynstr" || s == ".rela.dyn" || s == ".rela.plt" || - s == ".relr.dyn") + s == ".relr.dyn" || s == ".eh_frame" || s == ".eh_frame_hdr") return true; // ndso related sections if (s.startswith(".rodata") || s.startswith(".eh_frame_hdr__") || - s.startswith(".eh_frame__")) + s.startswith(".eh_frame__") || s.startswith(".gcc_except_table__")) return true; return false; } diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 32bddc76cc0f..63616c0b231d 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1484,6 +1484,15 @@ EhInputSection::EhInputSection(ObjFile &f, StringRef name) : InputSectionBase(f, header, name, InputSectionBase::EHFrame) {} +// OHOS_LOCAL begin +EhInputSection::EhInputSection(InputFile *file, uint64_t flags, uint32_t type, + uint64_t entsize, uint32_t link, uint32_t info, + uint32_t alignment, ArrayRef data, + StringRef name) + : InputSectionBase(file, flags, type, entsize, link, info, alignment, + data, name, InputSectionBase::EHFrame) {} +// OHOS_LOCAL end + SyntheticSection *EhInputSection::getParent() const { return cast_or_null(parent); } @@ -1546,7 +1555,14 @@ void EhInputSection::split(ArrayRef rels) { } uint64_t off = d.data() - rawData.data(); - pieces.emplace_back(off, this, size, getReloc(off, size, rels, relI)); + // OHOS_LOCAL begin + if (config->adlt) + pieces.emplace_back(off, this, size, getReloc(off + inputAddress, + size, rels, relI)); + else + // OHOS_LOCAL end + pieces.emplace_back(off, this, size, getReloc(off, size, rels, relI)); + d = d.slice(size); } if (msg) diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 74400ada2ff8..be6d461b3ac6 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -327,6 +327,11 @@ public: template EhInputSection(ObjFile &f, const typename ELFT::Shdr &header, StringRef name); + // OHOS_LOCAL begin + EhInputSection(InputFile *file, uint64_t flags, uint32_t type, + uint64_t entsize, uint32_t link, uint32_t info, + uint32_t alignment, ArrayRef data, StringRef name); + // OHOS_LOCAL end static bool classof(const SectionBase *s) { return s->kind() == EHFrame; } template void split(); template void split(ArrayRef rels); diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 15b2fde913a5..43e3b9f0aefa 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -450,6 +450,7 @@ public: // Offset -1 means that the piece is dead (i.e. garbage collected). if (pieces[i].outputOff == -1) return -1; + return pieces[i].outputOff + off - pieces[i].inputOff; } @@ -1400,7 +1401,16 @@ template void RelocationScanner::scanOne(RelTy *&i) { } // Get an offset in an output section this relocation is applied to. - uint64_t offset = getter.get(rel.r_offset); + // OHOS_LOCAL begin + uint64_t offset; + auto *eh = dyn_cast(&sec); + if (eh && config->adlt) { + offset = getter.get(rel.r_offset - eh->inputAddress); + if (offset != uint64_t(-1)) + offset += eh->inputAddress; + } else + offset = getter.get(rel.r_offset); + // OHOS_LOCAL end if (offset == uint64_t(-1)) return; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 5346e8e80cbc..bbb4318737af 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -359,11 +359,15 @@ EhFrameSection::EhFrameSection() // and where their relocations point to. template CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef rels) { - Symbol *personality = nullptr; unsigned firstRelI = cie.firstRelocation; + // OHOS_LOCAL begin + Symbol *personality = nullptr; if (firstRelI != (unsigned)-1) - personality = - &cie.sec->template getFile()->getRelocTargetSym(rels[firstRelI]); + personality = (!config->adlt) ? + &cie.sec->template getFile()->getRelocTargetSym(rels[firstRelI]) + : &(cast(cie.sec->file)->getRelocTargetSym( + rels[firstRelI])); + // OHOS_LOCAL end // Search for an existing CIE by CIE contents/relocation target pair. CieRecord *&rec = cieMap[{cie.data(), personality}]; @@ -393,7 +397,11 @@ Defined *EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef rels) { return nullptr; const RelTy &rel = rels[firstRelI]; - Symbol &b = sec->template getFile()->getRelocTargetSym(rel); + // OHOS_LOCAL begin + Symbol &b = !config->adlt ? + sec->template getFile()->getRelocTargetSym(rel) + : cast(sec->file)->getRelocTargetSym(rel); + // OHOS_LOCAL end // FDEs for garbage-collected or merged-by-ICF sections, or sections in // another partition, are dead. @@ -3520,8 +3528,8 @@ template void elf::splitSections() { llvm::TimeTraceScope timeScope("Split sections"); // splitIntoPieces needs to be called on each MergeInputSection // before calling finalizeContents(). - auto files = ctx->objectFiles; - parallelForEach(files, [](ELFFileBase *file) { + + auto split = [](auto *file) { for (InputSectionBase *sec : file->getSections()) { if (!sec) continue; @@ -3530,7 +3538,16 @@ template void elf::splitSections() { else if (auto *eh = dyn_cast(sec)) eh->split(); } - }); + }; + // OHOS_LOCAL begin + if (config->adlt) { + auto files = adlt::ctx->getSharedFiles(); + parallelForEach(files, split); + return; + } + // OHOS_LOCAL end + auto files = ctx->objectFiles; + parallelForEach(files, split); } MipsRldMapSection::MipsRldMapSection() diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 3b21fdffed08..e407d1ba2d42 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -430,7 +430,7 @@ template void elf::createSyntheticSections() { } if (!config->relocatable) { - if (config->ehFrameHdr) { + if (config->ehFrameHdr || (config->adlt && adlt::ctx->withEHFrame)) { part.ehFrameHdr = std::make_unique(); add(*part.ehFrameHdr); } @@ -2043,13 +2043,15 @@ template void Writer::finalizeSections() { if (sec->isLive() && isa(sec) && (sec->flags & SHF_ALLOC)) scanRelocations(*sec); - for (Partition &part : partitions) { - for (EhInputSection *sec : part.ehFrame->sections) - scanRelocations(*sec); - if (part.armExidx && part.armExidx->isLive()) - for (InputSection *sec : part.armExidx->exidxSections) + + if (!config->adlt) // OHOS_LOCAL + for (Partition &part : partitions) { + for (EhInputSection *sec : part.ehFrame->sections) scanRelocations(*sec); - } + if (part.armExidx && part.armExidx->isLive()) + for (InputSection *sec : part.armExidx->exidxSections) + scanRelocations(*sec); + } reportUndefinedSymbols(); postScanRelocations(); @@ -2545,11 +2547,14 @@ SmallVector Writer::createPhdrs(Partition &part) { // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. // OHOS_LOCAL begin - // The current implementation does not generate PT_GNU_EH_FRAME segment for - // .eh_frame_hdr sections for ADLT mode. It is assumed that the dynamic - // linker imitates it if necessary. + // The current implementation does not generate a PT_GNU_EH_FRAME segment + // for .eh_frame_hdr for ADLT mode or unless the --eh-frame-hdr option is + // specified. It is assumed that the dynamic linker will simulate it if + // necessary. // OHOS_LOCAL end - if (!config->adlt && part.ehFrame->isNeeded() && part.ehFrameHdr && + if ((config->ehFrameHdr || + (config->adlt && elf::adlt::ctx->withEHFrame)) && + part.ehFrame->isNeeded() && part.ehFrameHdr && part.ehFrame->getParent() && part.ehFrameHdr->getParent()) addHdr(PT_GNU_EH_FRAME, part.ehFrameHdr->getParent()->getPhdrFlags()) ->add(part.ehFrameHdr->getParent()); -- Gitee