From 50a6d9b4eca923069f9b173aa85c78016dfbb171 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Sun, 27 Oct 2024 21:09:27 +0300 Subject: [PATCH 01/23] Update relaxation processing for ADLT, fixes types and offsets of relocations after relaxation Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 412 +++++++++++++++++++++++++++++++++ lld/ELF/Adlt/Arch/AArch64.h | 8 + lld/ELF/Adlt/RelaxAuxAdlt.h | 33 +++ lld/ELF/Arch/AArch64.cpp | 19 ++ lld/ELF/InputSection.cpp | 189 ++++++++++++++- lld/ELF/InputSection.h | 15 ++ lld/ELF/Writer.cpp | 6 + lld/test/ADLT/lit.local.cfg.py | 10 + lld/test/ADLT/relax-adrp-add.s | 32 +++ lld/test/ADLT/relax-adrp-ldr.s | 35 +++ 10 files changed, 747 insertions(+), 12 deletions(-) create mode 100644 lld/ELF/Adlt/RelaxAuxAdlt.h create mode 100644 lld/test/ADLT/lit.local.cfg.py create mode 100644 lld/test/ADLT/relax-adrp-add.s create mode 100644 lld/test/ADLT/relax-adrp-ldr.s diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index fad107e3fb7b..657e6c0574c3 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -8,8 +8,12 @@ // OHOS_LOCAL begin #include "Adlt/Arch/AArch64.h" +#include "Adlt/RelaxAuxAdlt.h" #include "llvm/Support/Endian.h" +#include "AArch64.h" +#include "InputSection.h" +#include "OutputSections.h" #include "Target.h" using namespace llvm; @@ -89,4 +93,412 @@ bool AArch64::isErrata(uint64_t offset) { return (impl->errataOffset && impl->errataOffset == offset) ? true : false; } +void AArch64::finalizeRelax(int passes) const { + SmallVector storage; + + for (OutputSection *osec : outputSections) { + if (!(osec->flags & SHF_EXECINSTR)) + continue; + + for (InputSection *sec : getInputSections(*osec, storage)) { + if (!sec->relaxAuxAdlt) + continue; + + RelaxAuxAdlt &aux = *sec->relaxAuxAdlt; + + if (!aux.relocDeltas) + continue; + + auto &rels = sec->relocations; + ArrayRef old = sec->rawData; + size_t newSize = old.size() - aux.relocDeltas[rels.size() - 1]; + uint8_t *newData = context().bAlloc.Allocate(newSize); + uint64_t offset = 0; + int64_t delta = 0; + sec->bytesDropped = 0; + sec->rawData = makeArrayRef(newData, newSize); + + // Update section content: rewrite instructions for relaxed relocations. + for (size_t i = 0, e = rels.size(); i != e; ++i) { + uint32_t remove = aux.relocDeltas[i] - delta; + delta = aux.relocDeltas[i]; + + if (aux.relocTypes[i] == R_AARCH64_RELAX_DUMMY) + continue; + + // Copy from last location to the current relocated location. + const Relocation &r = rels[i]; + uint64_t size = r.offset - offset; + memcpy(newData, old.data() + offset, size); + newData += size; + + int64_t skip = 0; + RelType newType = aux.relocTypes[i]; + switch (newType) { + case R_AARCH64_NONE: + if (i + 1 < rels.size() && + aux.relocTypes[i + 1] == R_AARCH64_ADR_PREL_LO21) { + skip = 4; + write32le(newData, aux.writes[i]); + } + break; + case R_AARCH64_ADR_PREL_LO21: + skip = 4; + write32le(newData, aux.writes[i]); + break; + case R_AARCH64_ADR_PREL_PG_HI21: + skip = 4; + write32le(newData, aux.writes[i]); + break; + case R_AARCH64_ADD_ABS_LO12_NC: + skip = 4; + write32le(newData, aux.writes[i]); + break; + default: + llvm_unreachable("unsupported type"); + } + + newData += skip; + offset = r.offset + skip + remove; + } + memcpy(newData, old.data() + offset, old.size() - offset); + + // Update relocs. + delta = 0; + + for (size_t i = 0, e = rels.size(); i != e;) { + uint64_t cur = rels[i].offset; + do { + rels[i].offset -= delta; + if (aux.relocTypes[i] != R_AARCH64_RELAX_DUMMY) + rels[i].type = aux.relocTypes[i]; + } while (++i != e && rels[i].offset == cur); + + delta = aux.relocDeltas[i - 1]; + } + } + } +} + +bool AArch64::relaxOnce(int pass) const { + if (pass == 0) + initSymbolAnchors(); + + SmallVector storage; + bool changed = false; + for (OutputSection *osec : outputSections) { + if (!(osec->flags & SHF_EXECINSTR)) + continue; + for (InputSection *sec : getInputSections(*osec, storage)) + changed |= relax(*sec); + } + return changed; +} + +void AArch64::initSymbolAnchors() const { + SmallVector storage; + + for (OutputSection *osec : outputSections) { + if (!(osec->flags & SHF_EXECINSTR)) + continue; + + for (InputSection *sec : getInputSections(*osec, storage)) { + sec->relaxAuxAdlt = make(); + if (sec->relocations.size()) { + sec->relaxAuxAdlt->relocDeltas = + std::make_unique(sec->relocations.size()); + sec->relaxAuxAdlt->relocTypes = + std::make_unique(sec->relocations.size()); + sec->relaxAuxAdlt->relocChanged = + std::make_unique(sec->relocations.size()); + std::fill_n(sec->relaxAuxAdlt->relocChanged.get(), + sec->relocations.size(), false); + sec->relaxAuxAdlt->writes = + std::make_unique(sec->relocations.size()); + } + } + } + + // Store anchors (st_value and st_value+st_size) for symbols relative to text + // sections. + for (InputFile *file : lld::elf::ctx->objectFiles) + for (Symbol *sym : file->getSymbols()) { + auto *d = dyn_cast(sym); + if (!d || d->file != file) + continue; + if (auto *sec = dyn_cast_or_null(d->section)) + if (sec->flags & SHF_EXECINSTR && sec->relaxAuxAdlt) { + // If sec is discarded, relaxAuxAdlt will be nullptr. + sec->relaxAuxAdlt->anchors.push_back({d->value, d, false}); + sec->relaxAuxAdlt->anchors.push_back({d->value + d->size, d, true}); + } + } + + // Sort anchors by offset so that we can find the closest relocation + // efficiently. For a zero size symbol, ensure that its start anchor precedes + // its end anchor. For two symbols with anchors at the same offset, their + // order does not matter. + for (OutputSection *osec : outputSections) { + if (!(osec->flags & SHF_EXECINSTR)) + continue; + for (InputSection *sec : getInputSections(*osec, storage)) { + llvm::sort(sec->relaxAuxAdlt->anchors, [](auto &a, auto &b) { + return std::make_pair(a.offset, a.end) < + std::make_pair(b.offset, b.end); + }); + } + } +} + +bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, + Relocation &adrpRel, Relocation &ldrRel, + uint32_t &remove) const { + // When the definition of sym is not preemptible then we may + // be able to relax + // ADRP xn, :got: sym + // LDR xn, [ xn :got_lo12: sym] + // to + // ADRP xn, sym + // ADD xn, xn, :lo_12: sym + + if (adrpRel.type != R_AARCH64_ADR_GOT_PAGE || + ldrRel.type != R_AARCH64_LD64_GOT_LO12_NC) + return false; + + // Check if the relocations apply to consecutive instructions. + if (adrpRel.offset + 4 != ldrRel.offset) + return false; + + // Check if the relocations reference the same symbol and + // skip undefined, preemptible and STT_GNU_IFUNC symbols. + if (!adrpRel.sym || adrpRel.sym != ldrRel.sym || !adrpRel.sym->isDefined() || + adrpRel.sym->isPreemptible || adrpRel.sym->isGnuIFunc()) + return false; + + // Check if the addends of the both relocations are zero. + if (adrpRel.addend != 0 || ldrRel.addend != 0) + return false; + + uint32_t adrpInstr = read32le(sec.rawData.data() + adrpRel.offset); + uint32_t ldrInstr = read32le(sec.rawData.data() + ldrRel.offset); + + // Check if the first instruction is ADRP and the second instruction is LDR. + if ((adrpInstr & 0x9f000000) != 0x90000000 || + (ldrInstr & 0x3b000000) != 0x39000000) + return false; + + // Check the value of the sf bit. + if (!(ldrInstr >> 31)) + return false; + + uint32_t adrpDestReg = adrpInstr & 0x1f; + uint32_t ldrDestReg = ldrInstr & 0x1f; + uint32_t ldrSrcReg = (ldrInstr >> 5) & 0x1f; + + // Check if ADPR and LDR use the same register. + if (adrpDestReg != ldrDestReg || adrpDestReg != ldrSrcReg) + return false; + + const Symbol &sym = *adrpRel.sym; + + // GOT references to absolute symbols can't be relaxed to use ADRP/ADD in + // position-independent code because these instructions produce a relative + // address. + if (config->isPic && !cast(sym).section) + return false; + + uint64_t secAddr = sec.getOutputSection()->addr; + + // Check if the address difference is within 4GB range. + int64_t val = + getAArch64Page(sym.getVA()) - getAArch64Page(secAddr + adrpRel.offset); + + if (val != llvm::SignExtend64(val, 33)) + return false; + + sec.relaxAuxAdlt->relocTypes[i] = R_AARCH64_ADR_PREL_PG_HI21; + sec.relaxAuxAdlt->relocChanged[i] = true; + sec.relaxAuxAdlt->writes[i] = 0x90000000 | adrpDestReg; + + sec.relaxAuxAdlt->relocTypes[i + 1] = R_AARCH64_ADD_ABS_LO12_NC; + sec.relaxAuxAdlt->writes[i + 1] = + 0x91000000 | adrpDestReg | (adrpDestReg << 5); + sec.relaxAuxAdlt->relocChanged[i + 1] = true; + + Relocation adrpSymRel = {R_AARCH64_PAGE_PC, R_AARCH64_ADR_PREL_PG_HI21, + adrpRel.offset, /*addend=*/0, adrpRel.sym}; + + Relocation addRel = {R_ABS, R_AARCH64_ADD_ABS_LO12_NC, ldrRel.offset, + /*addend=*/0, adrpRel.sym}; + + const TargetInfo &baseTarget = *elf::target; + + baseTarget.relocate( + const_cast(sec.rawData.data()) + adrpSymRel.offset, adrpSymRel, + SignExtend64(getAArch64Page(sym.getVA()) - + getAArch64Page(secAddr + adrpSymRel.offset), + 64)); + baseTarget.relocate(const_cast(sec.rawData.data()) + addRel.offset, + addRel, SignExtend64(sym.getVA(), 64)); + + relaxAdrpAdd(sec, i, loc, adrpSymRel, addRel, remove); + + return true; +} + +bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, + Relocation &adrpRel, Relocation &addRel, + uint32_t &remove) const { + // When the address of sym is within the range of ADR then + // we may relax + // ADRP xn, sym + // ADD xn, xn, :lo12: sym + // to + // NOP + // ADR xn, sym + + if (!config->relax || adrpRel.type != R_AARCH64_ADR_PREL_PG_HI21 || + addRel.type != R_AARCH64_ADD_ABS_LO12_NC) + return false; + + // Check if the relocations apply to consecutive instructions. + if (adrpRel.offset + 4 != addRel.offset) + return false; + + if (adrpRel.sym != addRel.sym) + return false; + + if (adrpRel.addend != 0 || addRel.addend != 0) + return false; + + uint32_t adrpInstr = read32le(sec.rawData.data() + adrpRel.offset); + uint32_t addInstr = read32le(sec.rawData.data() + addRel.offset); + + // Check if the first instruction is ADRP and the second instruction is ADD. + if ((adrpInstr & 0x9f000000) != 0x90000000 || + (addInstr & 0xffc00000) != 0x91000000) { + // If the types do not match, + // but an adrp + ldr relaxation has been performed before, + // it is worth considering this case. + if (!(sec.relaxAuxAdlt->relocTypes[i] == R_AARCH64_ADR_PREL_PG_HI21 && + sec.relaxAuxAdlt->relocTypes[i + 1] == R_AARCH64_ADD_ABS_LO12_NC)) + return false; + } + + uint32_t adrpDestReg = adrpInstr & 0x1f; + uint32_t addDestReg = addInstr & 0x1f; + uint32_t addSrcReg = (addInstr >> 5) & 0x1f; + + if (adrpDestReg != addDestReg || adrpDestReg != addSrcReg) + return false; + + Symbol &sym = *adrpRel.sym; + + uint64_t secAddr = sec.getOutputSection()->addr; + + // Check if the address difference is within 1MiB range. + int64_t val = sym.getVA() - (secAddr + addRel.offset); + if (val < -1024 * 1024 || val >= 1024 * 1024) + return false; + + sec.relaxAuxAdlt->relocTypes[i] = R_AARCH64_NONE; + sec.relaxAuxAdlt->writes[i] = 0xd503201f; // nop. + sec.relaxAuxAdlt->relocChanged[i] = true; + + sec.relaxAuxAdlt->relocTypes[i + 1] = R_AARCH64_ADR_PREL_LO21; + sec.relaxAuxAdlt->writes[i + 1] = 0x10000000 | adrpDestReg; + sec.relaxAuxAdlt->relocChanged[i + 1] = true; + + Relocation adrRel = {R_ABS, R_AARCH64_ADR_PREL_LO21, addRel.offset, + /*addend=*/0, adrpRel.sym}; + + const TargetInfo &baseTarget = *elf::target; + baseTarget.relocate(const_cast(sec.rawData.data()) + adrRel.offset, + adrRel, val); + + return true; +} + +bool AArch64::relax(InputSection &sec) const { + bool changed = false; + auto &aux = *sec.relaxAuxAdlt; + const uint64_t secAddr = sec.getVA(); + ArrayRef sa = makeArrayRef(aux.anchors); + uint64_t delta = 0; + bool safeToRelaxAdrpLdr = false; + + auto &relocs = sec.relocations; + const size_t relocs_size = sec.relocations.size(); + + // Check if R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC + // always appear in pairs. + size_t i = 0; + for (; i != relocs_size; ++i) { + if (relocs[i].type == R_AARCH64_ADR_GOT_PAGE) { + if (i + 1 < relocs_size && + relocs[i + 1].type == R_AARCH64_LD64_GOT_LO12_NC) { + ++i; + continue; + } + break; + } else if (relocs[i].type == R_AARCH64_LD64_GOT_LO12_NC) { + break; + } + } + + safeToRelaxAdrpLdr = i == relocs_size; + + std::fill_n(aux.relocTypes.get(), relocs_size, R_AARCH64_RELAX_DUMMY); + std::fill_n(aux.writes.get(), relocs_size, 0); + + for (size_t i = 0; i < relocs_size; ++i) { + Relocation &r = relocs[i]; + const uint64_t loc = secAddr + r.offset - delta; + uint32_t &cur = aux.relocDeltas[i]; + uint32_t remove = 0; + + switch (r.expr) { + case R_AARCH64_GOT_PAGE_PC: + if (i + 1 != relocs_size && !aux.relocChanged[i] && safeToRelaxAdrpLdr) + relaxAdrpLdr(sec, i, loc, r, relocs[i + 1], remove); + break; + case R_AARCH64_PAGE_PC: + if (i + 1 != relocs_size && !aux.relocChanged[i]) + relaxAdrpAdd(sec, i, loc, r, relocs[i + 1], remove); + break; + default: + break; + } + + // For all anchors whose offsets are <= r.offset, they are preceded by + // the previous relocation whose `relocDeltas` value equals `delta`. + // Decrease their st_value and update their st_size. + for (; sa.size() && sa[0].offset <= r.offset; sa = sa.slice(1)) { + if (sa[0].end) + sa[0].d->size = sa[0].offset - delta - sa[0].d->value; + else + sa[0].d->value = sa[0].offset - delta; + } + + delta += remove; + + if (delta != cur) { + cur = delta; + changed = true; + } + } + + for (const SymbolAnchorAdlt &a : sa) { + if (a.end) + a.d->size = a.offset - delta - a.d->value; + else + a.d->value = a.offset - delta; + } + + // Inform assignAddresses that the size has changed. + if (!isUInt<32>(delta)) + fatal("section size decrease is too large: " + Twine(delta)); + sec.bytesDropped = delta; + return changed; +} // OHOS_LOCAL end diff --git a/lld/ELF/Adlt/Arch/AArch64.h b/lld/ELF/Adlt/Arch/AArch64.h index 6e9d6a6a3007..1d888945af7f 100644 --- a/lld/ELF/Adlt/Arch/AArch64.h +++ b/lld/ELF/Adlt/Arch/AArch64.h @@ -10,6 +10,8 @@ #ifndef LLD_ELF_ADLT_ARCH_AARCH64_H #define LLD_ELF_ADLT_ARCH_AARCH64_H +#include "llvm/ADT/ArrayRef.h" +#include #include #include @@ -17,6 +19,8 @@ namespace lld { namespace elf { struct Relocation; +class InputSection; +class TargetInfo; namespace adlt { @@ -32,6 +36,10 @@ public: void setErrataOffset(uint64_t offset); bool isErrata(uint64_t offset); + void finalizeRelax(int passes) const; + + bool relaxOnce(int pass) const; + private: std::unique_ptr impl; }; diff --git a/lld/ELF/Adlt/RelaxAuxAdlt.h b/lld/ELF/Adlt/RelaxAuxAdlt.h new file mode 100644 index 000000000000..5c3250f7a44f --- /dev/null +++ b/lld/ELF/Adlt/RelaxAuxAdlt.h @@ -0,0 +1,33 @@ +#ifndef RELAX_AUX_ADLT_H +#define RELAX_AUX_ADLT_H + +#include "Relocations.h" +#include "Symbols.h" +#include + +namespace lld { +namespace elf { +struct SymbolAnchorAdlt { + uint64_t offset; + Defined *d; + bool end; // true for the anchor of st_value+st_size +}; + +struct RelaxAuxAdlt { + // This records symbol start and end offsets which will be adjusted according + // to the nearest relocDeltas element. + SmallVector anchors; + // For relocations[i], the actual offset is + // r_offset - (i ? relocDeltas[i-1] : 0). + std::unique_ptr relocDeltas; + // For relocations[i], the actual type is relocTypes[i]. + std::unique_ptr relocTypes; + // To check if relocations have been changed. + std::unique_ptr relocChanged; + // Instructions for modified relocations. + std::unique_ptr writes; +}; +} // namespace elf +} // namespace lld + +#endif diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 965298ccf4d7..99d7070f2637 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -58,6 +58,9 @@ public: uint64_t val) const override; void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const override; + // OHOS_LOCAL begin + bool relaxOnce(int pass) const override; + // OHOS_LOCAL end }; } // namespace @@ -85,6 +88,13 @@ AArch64::AArch64() { defaultImageBase = 0x200000; needsThunks = true; + + // OHOS_LOCAL begin + // We need to set 'false' for 'needsThunks' here + // in order for the 'relaxOne' method to be called. + if (config->adlt && config->relax) + needsThunks = false; + // OHOS_LOCAL end } RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, @@ -626,6 +636,15 @@ void AArch64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, llvm_unreachable("invalid relocation for TLS IE to LE relaxation"); } +// OHOS_LOCAL begin +bool AArch64::relaxOnce(int pass) const { + if (!config->adlt && config->relocatable) + return false; + + return adlt::ctx->adltInfo->relaxOnce(pass); +} +// OHOS_LOCAL end + AArch64Relaxer::AArch64Relaxer(ArrayRef relocs) { if (!config->relax || config->emachine != EM_AARCH64) { safeToRelaxAdrpLdr = false; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 33a2b59f2ee9..2580943ec7bf 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -357,6 +357,141 @@ InputSectionBase *InputSection::getRelocatedSection() const { return sections[info]; } +// OHOS_LOCAL begin +// This method is a copy of the copyRelocations method, but modified to support +// correct relaxation of relocations when using ADLT. +template +void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { + const TargetInfo &target = *elf::target; + + InputSectionBase *sec = getRelocatedSection(); + auto &relocs = sec->relocations; + + for (size_t i = 0; i < relocs.size(); ++i) { + RelType type = relocs[i].type; + + const SharedFileExtended *soExt = getSoExt(); + Symbol &sym = soExt->getRelocTargetSym(rels[i]); + + auto *p = reinterpret_cast(buf); + buf += sizeof(RelTy); + + /*if (config->adlt) { + if (rel.r_offset == 0x111747c) // debug hint + asm("nop"); + }*/ + + if (RelTy::IsRela) + p->r_addend = getAddend(rels[i]); + + // Output section VA is zero for -r, so r_offset is an offset within the + // section, but for --emit-relocs it is a virtual address. + p->r_offset = sec->getVA(rels[i].r_offset); + + size_t symbolIndex = in.symTab->getSymbolIndex(&sym); + + // Convert an absolute offsets to relative ones + if (sec->type == SHT_PROGBITS && + soExt->isValidProgbitsSectionName(sec->name)) + assert(sec->address && "ADLT: copyRelocs: sec->address can't be zero!"); + p->r_offset -= sec->address; + assert((int32_t)p->r_offset >= 0 && + "ADLT: copyRelocs: offset can't be negative!"); + + if (!(sym.exportDynamic || sym.dynsymIndex)) { // ignore .dynsym symbols + if (p->r_addend) + assert(symbolIndex && "ADLT: copyRelocs: wrong symbol index!" + "Is it not in the final symtab?"); + } + + if (type == R_AARCH64_NONE) { + // To relocate with type R_AARCH64_NONE, the symbol must be nulled and + // skip processing. + p->setSymbolAndType(0, 0, false); + continue; + } else { + p->setSymbolAndType(symbolIndex, type, config->isMips64EL); + } + + if (sym.type == STT_SECTION) { + // We combine multiple section symbols into only one per + // section. This means we have to update the addend. That is + // trivial for Elf_Rela, but for Elf_Rel we have to write to the + // section data. We do that by adding to the Relocation vector. + + // .eh_frame is horribly special and can reference discarded sections. To + // avoid having to parse and recreate .eh_frame, we just replace any + // relocation in it pointing to discarded sections with R_*_NONE, which + // hopefully creates a frame that is ignored at runtime. Also, don't warn + // on .gcc_except_table and debug sections. + // + // See the comment in maybeReportUndefined for PPC32 .got2 and PPC64 .toc + auto *d = dyn_cast(&sym); + if (!d) { + if (!isDebugSection(*sec) && sec->name != ".eh_frame" && + sec->name != ".gcc_except_table" && sec->name != ".got2" && + sec->name != ".toc") { + uint32_t secIdx = cast(sym).discardedSecIdx; + Elf_Shdr_Impl sec = soExt->template getELFShdrs()[secIdx]; + warn("relocation refers to a discarded section: " + + CHECK(soExt->getObj().getSectionName(sec), soExt) + + "\n>>> referenced by " + getObjMsg(p->r_offset)); + } + p->setSymbolAndType(0, 0, false); + continue; + } + + SectionBase *section = d->section; + if (!section->isLive()) { + p->setSymbolAndType(0, 0, false); + continue; + } + + int64_t addend = getAddend(rels[i]); + const uint8_t *bufLoc = sec->rawData.begin() + rels[i].r_offset; + if (!RelTy::IsRela) + addend = target.getImplicitAddend(bufLoc, type); + + if (config->emachine == EM_MIPS && + target.getRelExpr(type, sym, bufLoc) == R_MIPS_GOTREL) { + // Some MIPS relocations depend on "gp" value. By default, + // this value has 0x7ff0 offset from a .got section. But + // relocatable files produced by a compiler or a linker + // might redefine this default value and we must use it + // for a calculation of the relocation result. When we + // generate EXE or DSO it's trivial. Generating a relocatable + // output is more difficult case because the linker does + // not calculate relocations in this mode and loses + // individual "gp" values used by each input object file. + // As a workaround we add the "gp" value to the relocation + // addend and save it back to the file. + addend += sec->getSoExt()->mipsGp0; + } + + if (RelTy::IsRela) + p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr; + else if (config->relocatable && type != target.noneRel) + sec->relocations.push_back( + {R_ABS, type, rels[i].r_offset, addend, &sym}); + } else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 && + p->r_addend >= 0x8000 && (sec->getSoExt()->ppc32Got2)) { + // Similar to R_MIPS_GPREL{16,32}. If the addend of R_PPC_PLTREL24 + // indicates that r30 is relative to the input section .got2 + // (r_addend>=0x8000), after linking, r30 should be relative to the output + // section .got2 . To compensate for the shift, adjust r_addend by + // ppc32Got->outSecOff. + // OHOS_LOCAL begin + p->r_addend += sec->getSoExt()->ppc32Got2->outSecOff; + } + } + + // It's necessary to remove relocations with type R_AARCH64_NONE + // from `relocations`. + llvm::erase_if(sec->relocations, + [](Relocation &r) { return r.type == R_AARCH64_NONE; }); +} +// OHOS_LOCAL end + // This is used for -r and --emit-relocs. We can't use memcpy to copy // relocations because we need to update symbol table offset and section index // for each relocation. So we copy relocations one by one. @@ -1087,20 +1222,38 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { target.relaxGot(bufLoc, rel, targetVA); break; case R_AARCH64_GOT_PAGE_PC: - if (i + 1 < size && aarch64relaxer.tryRelaxAdrpLdr( - rel, relocations[i + 1], secAddr, buf)) { - ++i; - continue; + // OHOS_LOCAL begin + if (!(config->adlt && config->relax)) { + // OHOS_LOCAL end + if (i + 1 < size && aarch64relaxer.tryRelaxAdrpLdr( + rel, relocations[i + 1], secAddr, buf)) { + ++i; + continue; + } + target.relocate(bufLoc, rel, targetVA); + // OHOS_LOCAL begin + } else { + if (relaxAuxAdlt && !relaxAuxAdlt->relocChanged[i]) + target.relocate(bufLoc, rel, targetVA); } - target.relocate(bufLoc, rel, targetVA); + // OHOS_LOCAL end break; case R_AARCH64_PAGE_PC: - if (i + 1 < size && aarch64relaxer.tryRelaxAdrpAdd( - rel, relocations[i + 1], secAddr, buf)) { - ++i; - continue; + // OHOS_LOCAL begin + if (!(config->adlt && config->relax)) { + // OHOS_LOCAL end + if (i + 1 < size && aarch64relaxer.tryRelaxAdrpAdd( + rel, relocations[i + 1], secAddr, buf)) { + ++i; + continue; + } + target.relocate(bufLoc, rel, targetVA); + // OHOS_LOCAL begin + } else { + if (relaxAuxAdlt && !relaxAuxAdlt->relocChanged[i]) + target.relocate(bufLoc, rel, targetVA); } - target.relocate(bufLoc, rel, targetVA); + // OHOS_LOCAL end break; case R_PPC64_RELAX_GOT_PC: { // The R_PPC64_PCREL_OPT relocation must appear immediately after @@ -1291,11 +1444,23 @@ template void InputSection::writeTo(uint8_t *buf) { // If -r or --emit-relocs is given, then an InputSection // may be a relocation section. if (LLVM_UNLIKELY(type == SHT_RELA)) { - copyRelocations(buf, getDataAs()); + // OHOS_LOCAL begin + if (config->adlt && config->relax && !config->relocatable) + copyRelocationsAdlt( + buf, getDataAs()); + else + // OHOS_LOCAL end + copyRelocations(buf, getDataAs()); return; } if (LLVM_UNLIKELY(type == SHT_REL)) { - copyRelocations(buf, getDataAs()); + // OHOS_LOCAL begin + if (config->adlt && config->relax && !config->relocatable) + copyRelocationsAdlt( + buf, getDataAs()); + else + // OHOS_LOCAL end + copyRelocations(buf, getDataAs()); return; } diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 74400ada2ff8..102751db6e8d 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -18,6 +18,11 @@ #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Object/ELF.h" +// OHOS_LOCAL begin +#include "Adlt/Context.h" +#include "Adlt/RelaxAuxAdlt.h" +// OHOS_LOCAL end + namespace lld { namespace elf { @@ -218,6 +223,11 @@ public: // Auxiliary information for RISC-V linker relaxation. RISC-V does not use // jumpInstrMod. RISCVRelaxAux *relaxAux; + + // OHOS_LOCAL begin + // Auxiliary information for linker relaxation, when using ADLT. + RelaxAuxAdlt *relaxAuxAdlt; + // OHOS_LOCAL end }; // A function compiled with -fsplit-stack calling a function @@ -391,6 +401,11 @@ private: template void copyRelocations(uint8_t *buf, llvm::ArrayRef rels); + // OHOS_LOCAL begin + template + void copyRelocationsAdlt(uint8_t *buf, ArrayRef rels); + // OHOS_LOCAL end + template void copyShtGroup(uint8_t *buf); }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index abcb78242d7c..b3d5361be644 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1766,6 +1766,12 @@ template void Writer::finalizeAddressDependentContent() { if (!config->relocatable && config->emachine == EM_RISCV) riscvFinalizeRelax(pass); + // OHOS_LOCAL begin + // We need to finalize the relaxation: update types and output instructions. + if (config->adlt && !config->relocatable && config->emachine == EM_AARCH64) + elf::adlt::ctx->adltInfo->finalizeRelax(pass); + // OHOS LOCAL end + if (config->relocatable) for (OutputSection *sec : outputSections) sec->addr = 0; diff --git a/lld/test/ADLT/lit.local.cfg.py b/lld/test/ADLT/lit.local.cfg.py new file mode 100644 index 000000000000..dc9862da84ee --- /dev/null +++ b/lld/test/ADLT/lit.local.cfg.py @@ -0,0 +1,10 @@ +# -*- Python -*- +# This script contains the necessary settings to run ADLT tests. + +import os + +# We need to know the path to the SDK in lit-tests to invoke required clang. +SDK_ROOT = os.getenv("SDK_ROOT", "") + +# We can then use the %SDK_ROOT variable in llvm-lit command descriptions. +config.substitutions.append(("%SDK_ROOT", SDK_ROOT)) diff --git a/lld/test/ADLT/relax-adrp-add.s b/lld/test/ADLT/relax-adrp-add.s new file mode 100644 index 000000000000..688c873c12c3 --- /dev/null +++ b/lld/test/ADLT/relax-adrp-add.s @@ -0,0 +1,32 @@ +# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot --target=aarch64-linux-ohos -fPIC -o a.c.o -c %s +# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot -fPIC --target=aarch64-linux-ohos -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,lib_a.so -o lib_a.so a.c.o +# RUN: ld.lld --adlt lib_a.so -o libadlt_a.so --emit-relocs --relax +# RUN: llvm-objdump -xd libadlt_a.so | FileCheck %s + +# CHECK-LABEL: 0000000000001480 <_start>: +# CHECK-NEXT: 1480: d503201f nop +# CHECK-NEXT: 0000000000001480: R_AARCH64_NONE *ABS* +# CHECK-NEXT: 1484: 1002b79e adr x30, #22256 +# CHECK-NEXT: 0000000000001484: R_AARCH64_ADR_PREL_LO21 .rodata__0 +# CHECK-NEXT: 1488: d503201f nop +# CHECK-NEXT: 0000000000001488: R_AARCH64_NONE *ABS* +# CHECK-NEXT: 148c: 1002b781 adr x1, #22256 +# CHECK-NEXT: 000000000000148c: R_AARCH64_ADR_PREL_LO21 .rodata__0 +# CHECK-NEXT: 1490: d503201f nop +# CHECK-NEXT: 0000000000001490: R_AARCH64_NONE *ABS* +# CHECK-NEXT: 1494: 1002b78f adr x15, #22256 +# CHECK-NEXT: 0000000000001494: R_AARCH64_ADR_PREL_LO21 .rodata__0 +# CHECK-EMPTY: + +.rodata +x: +.word 111 +.text +.global _start +_start: + adrp x30, x + add x30, x30, :lo12:x + adrp x1, x + add x1, x1, :lo12:x + adrp x15, x + add x15, x15, :lo12:x diff --git a/lld/test/ADLT/relax-adrp-ldr.s b/lld/test/ADLT/relax-adrp-ldr.s new file mode 100644 index 000000000000..6b7b0a383311 --- /dev/null +++ b/lld/test/ADLT/relax-adrp-ldr.s @@ -0,0 +1,35 @@ +# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot --target=aarch64-linux-ohos -fPIC -o a.c.o -c %s +# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot -fPIC --target=aarch64-linux-ohos -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,lib_a.so -o lib_a.so a.c.o +# RUN: ld.lld --adlt lib_a.so -o libadlt_a.so --emit-relocs --relax +# RUN: llvm-objdump -xd libadlt_a.so | FileCheck %s + +# CHECK-LABEL: 0000000000001480 <_start>: +# CHECK-NEXT: 1480: d503201f nop +# CHECK-NEXT: 0000000000001480: R_AARCH64_NONE *ABS*+0x8 +# CHECK-NEXT: 1484: 100235c0 adr x0, #18104 +# CHECK-NEXT: 0000000000001484: R_AARCH64_ADR_PREL_LO21 .data__0+0x8 +# CHECK-NEXT: 1488: d503201f nop +# CHECK-NEXT: 0000000000001488: R_AARCH64_NONE *ABS*+0x10 +# CHECK-NEXT: 148c: 10023601 adr x1, #18112 +# CHECK-NEXT: 000000000000148c: R_AARCH64_ADR_PREL_LO21 .data__0+0x10 +# CHECK-NEXT: 1490: d503201f nop +# CHECK-NEXT: 0000000000001490: R_AARCH64_NONE *ABS*+0x18 +# CHECK-NEXT: 1494: 10023642 adr x2, #18120 +# CHECK-NEXT: 0000000000001494: R_AARCH64_ADR_PREL_LO21 .data__0+0x18 +# CHECK-EMPTY: + +.section .data +.align 3 +var1: .xword 100 +var2: .xword 200 +var3: .xword 300 + +.section .text +.global _start +_start: + adrp x0, :got:var1 + ldr x0, [x0, :got_lo12:var1] + adrp x1, :got:var2 + ldr x1, [x1, :got_lo12:var2] + adrp x2, :got:var3 + ldr x2, [x2, :got_lo12:var3] -- Gitee From 0c4667b7fd5f31763fb2d5bb23a553933237739f Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Wed, 30 Oct 2024 22:57:10 +0300 Subject: [PATCH 02/23] Refactoring copyRelocationsAdlt after rebase Signed-off-by: streshchukvitaly --- lld/ELF/InputSection.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 2580943ec7bf..0a9c74120e1c 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -370,7 +370,8 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { for (size_t i = 0; i < relocs.size(); ++i) { RelType type = relocs[i].type; - const SharedFileExtended *soExt = getSoExt(); + const SharedFileExtended *soExt = + elf::adlt::ctx->getSoExt(this->file); Symbol &sym = soExt->getRelocTargetSym(rels[i]); auto *p = reinterpret_cast(buf); @@ -391,17 +392,17 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { size_t symbolIndex = in.symTab->getSymbolIndex(&sym); // Convert an absolute offsets to relative ones - if (sec->type == SHT_PROGBITS && - soExt->isValidProgbitsSectionName(sec->name)) - assert(sec->address && "ADLT: copyRelocs: sec->address can't be zero!"); - p->r_offset -= sec->address; + if (sec->type == SHT_PROGBITS) + assert(sec->inputAddress && + "ADLT: copyRelocs: sec->inputAddress can't be zero!"); + p->r_offset -= sec->inputAddress; assert((int32_t)p->r_offset >= 0 && "ADLT: copyRelocs: offset can't be negative!"); - if (!(sym.exportDynamic || sym.dynsymIndex)) { // ignore .dynsym symbols if (p->r_addend) assert(symbolIndex && "ADLT: copyRelocs: wrong symbol index!" "Is it not in the final symtab?"); + assert(type != R_AARCH64_NONE && "ADLT: incorrect relocation type!"); } if (type == R_AARCH64_NONE) { @@ -465,7 +466,8 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { // individual "gp" values used by each input object file. // As a workaround we add the "gp" value to the relocation // addend and save it back to the file. - addend += sec->getSoExt()->mipsGp0; + if (!config->adlt) + addend += sec->getFile()->mipsGp0; } if (RelTy::IsRela) @@ -473,15 +475,16 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { else if (config->relocatable && type != target.noneRel) sec->relocations.push_back( {R_ABS, type, rels[i].r_offset, addend, &sym}); - } else if (config->emachine == EM_PPC && type == R_PPC_PLTREL24 && - p->r_addend >= 0x8000 && (sec->getSoExt()->ppc32Got2)) { + } else if (!config->adlt && config->emachine == EM_PPC && + type == R_PPC_PLTREL24 && p->r_addend >= 0x8000 && + sec->file->ppc32Got2) { // Similar to R_MIPS_GPREL{16,32}. If the addend of R_PPC_PLTREL24 // indicates that r30 is relative to the input section .got2 // (r_addend>=0x8000), after linking, r30 should be relative to the output // section .got2 . To compensate for the shift, adjust r_addend by // ppc32Got->outSecOff. - // OHOS_LOCAL begin - p->r_addend += sec->getSoExt()->ppc32Got2->outSecOff; + if (!config->adlt) + p->r_addend += sec->file->ppc32Got2->outSecOff; } } -- Gitee From d6c0078324720261b0e658da67f529d499403f05 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Sat, 2 Nov 2024 11:11:11 +0300 Subject: [PATCH 03/23] Fix bugs with relocation after relaxation, tests refactoring Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 46 ++++++++++++++++++---------------- lld/ELF/Adlt/RelaxAuxAdlt.h | 2 ++ lld/ELF/Arch/AArch64.cpp | 2 +- lld/ELF/InputSection.cpp | 16 ++++++------ lld/test/ADLT/relax-adrp-add.s | 28 +++++++++++---------- lld/test/ADLT/relax-adrp-ldr.s | 28 +++++++++++---------- 6 files changed, 66 insertions(+), 56 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 657e6c0574c3..d24b0dea2989 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -95,6 +95,7 @@ bool AArch64::isErrata(uint64_t offset) { void AArch64::finalizeRelax(int passes) const { SmallVector storage; + const TargetInfo &baseTarget = *elf::target; for (OutputSection *osec : outputSections) { if (!(osec->flags & SHF_EXECINSTR)) @@ -142,18 +143,31 @@ void AArch64::finalizeRelax(int passes) const { write32le(newData, aux.writes[i]); } break; - case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_ADR_PREL_LO21: { skip = 4; + Relocation adrRel = {R_ABS, R_AARCH64_ADR_PREL_LO21, r.offset, + /*addend=*/0, rels[i - 1].sym}; write32le(newData, aux.writes[i]); + baseTarget.relocate(newData, adrRel, aux.vals[i]); break; - case R_AARCH64_ADR_PREL_PG_HI21: + } + case R_AARCH64_ADR_PREL_PG_HI21: { skip = 4; + Relocation adrpSymRel = {R_AARCH64_PAGE_PC, + R_AARCH64_ADR_PREL_PG_HI21, r.offset, + /*addend=*/0, r.sym}; write32le(newData, aux.writes[i]); + baseTarget.relocate(newData, adrpSymRel, aux.vals[i]); break; - case R_AARCH64_ADD_ABS_LO12_NC: + } + case R_AARCH64_ADD_ABS_LO12_NC: { skip = 4; write32le(newData, aux.writes[i]); + Relocation addRel = {R_ABS, R_AARCH64_ADD_ABS_LO12_NC, r.offset, + /*addend=*/0, r.sym}; + baseTarget.relocate(newData, addRel, aux.vals[i]); break; + } default: llvm_unreachable("unsupported type"); } @@ -215,6 +229,8 @@ void AArch64::initSymbolAnchors() const { sec->relocations.size(), false); sec->relaxAuxAdlt->writes = std::make_unique(sec->relocations.size()); + sec->relaxAuxAdlt->vals = + std::make_unique(sec->relocations.size()); } } } @@ -317,13 +333,17 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, return false; sec.relaxAuxAdlt->relocTypes[i] = R_AARCH64_ADR_PREL_PG_HI21; - sec.relaxAuxAdlt->relocChanged[i] = true; sec.relaxAuxAdlt->writes[i] = 0x90000000 | adrpDestReg; + sec.relaxAuxAdlt->relocChanged[i] = true; + sec.relaxAuxAdlt->vals[i] = SignExtend64( + getAArch64Page(sym.getVA()) - getAArch64Page(secAddr + adrpRel.offset), + 64); sec.relaxAuxAdlt->relocTypes[i + 1] = R_AARCH64_ADD_ABS_LO12_NC; sec.relaxAuxAdlt->writes[i + 1] = 0x91000000 | adrpDestReg | (adrpDestReg << 5); sec.relaxAuxAdlt->relocChanged[i + 1] = true; + sec.relaxAuxAdlt->vals[i + 1] = SignExtend64(sym.getVA(), 64); Relocation adrpSymRel = {R_AARCH64_PAGE_PC, R_AARCH64_ADR_PREL_PG_HI21, adrpRel.offset, /*addend=*/0, adrpRel.sym}; @@ -331,16 +351,6 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, Relocation addRel = {R_ABS, R_AARCH64_ADD_ABS_LO12_NC, ldrRel.offset, /*addend=*/0, adrpRel.sym}; - const TargetInfo &baseTarget = *elf::target; - - baseTarget.relocate( - const_cast(sec.rawData.data()) + adrpSymRel.offset, adrpSymRel, - SignExtend64(getAArch64Page(sym.getVA()) - - getAArch64Page(secAddr + adrpSymRel.offset), - 64)); - baseTarget.relocate(const_cast(sec.rawData.data()) + addRel.offset, - addRel, SignExtend64(sym.getVA(), 64)); - relaxAdrpAdd(sec, i, loc, adrpSymRel, addRel, remove); return true; @@ -408,13 +418,7 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, sec.relaxAuxAdlt->relocTypes[i + 1] = R_AARCH64_ADR_PREL_LO21; sec.relaxAuxAdlt->writes[i + 1] = 0x10000000 | adrpDestReg; sec.relaxAuxAdlt->relocChanged[i + 1] = true; - - Relocation adrRel = {R_ABS, R_AARCH64_ADR_PREL_LO21, addRel.offset, - /*addend=*/0, adrpRel.sym}; - - const TargetInfo &baseTarget = *elf::target; - baseTarget.relocate(const_cast(sec.rawData.data()) + adrRel.offset, - adrRel, val); + sec.relaxAuxAdlt->vals[i + 1] = val; return true; } diff --git a/lld/ELF/Adlt/RelaxAuxAdlt.h b/lld/ELF/Adlt/RelaxAuxAdlt.h index 5c3250f7a44f..248635b1b287 100644 --- a/lld/ELF/Adlt/RelaxAuxAdlt.h +++ b/lld/ELF/Adlt/RelaxAuxAdlt.h @@ -26,6 +26,8 @@ struct RelaxAuxAdlt { std::unique_ptr relocChanged; // Instructions for modified relocations. std::unique_ptr writes; + // To store new values for relocations. + std::unique_ptr vals; }; } // namespace elf } // namespace lld diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 99d7070f2637..2a41a5275262 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -91,7 +91,7 @@ AArch64::AArch64() { // OHOS_LOCAL begin // We need to set 'false' for 'needsThunks' here - // in order for the 'relaxOne' method to be called. + // in order for the 'relaxOnce' method to be called. if (config->adlt && config->relax) needsThunks = false; // OHOS_LOCAL end diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 0a9c74120e1c..559b9a4fc331 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -367,8 +367,9 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { InputSectionBase *sec = getRelocatedSection(); auto &relocs = sec->relocations; - for (size_t i = 0; i < relocs.size(); ++i) { - RelType type = relocs[i].type; + for (size_t i = 0; i < rels.size(); ++i) { + RelType type = i >= relocs.size() ? rels[i].getType(config->isMips64EL) + : relocs[i].type; const SharedFileExtended *soExt = elf::adlt::ctx->getSoExt(this->file); @@ -402,7 +403,6 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { if (p->r_addend) assert(symbolIndex && "ADLT: copyRelocs: wrong symbol index!" "Is it not in the final symtab?"); - assert(type != R_AARCH64_NONE && "ADLT: incorrect relocation type!"); } if (type == R_AARCH64_NONE) { @@ -487,11 +487,6 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { p->r_addend += sec->file->ppc32Got2->outSecOff; } } - - // It's necessary to remove relocations with type R_AARCH64_NONE - // from `relocations`. - llvm::erase_if(sec->relocations, - [](Relocation &r) { return r.type == R_AARCH64_NONE; }); } // OHOS_LOCAL end @@ -1326,6 +1321,11 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { target.relocate(bufLoc, rel, targetVA); break; default: + // OHOS_LOCAL begin + // If the relocation has been changed, then it has been relocated + if (config->adlt && relaxAuxAdlt && relaxAuxAdlt->relocChanged[i]) + break; + // OHOS_LOCAL end target.relocate(bufLoc, rel, targetVA); break; } diff --git a/lld/test/ADLT/relax-adrp-add.s b/lld/test/ADLT/relax-adrp-add.s index 688c873c12c3..b66132af1f9b 100644 --- a/lld/test/ADLT/relax-adrp-add.s +++ b/lld/test/ADLT/relax-adrp-add.s @@ -1,20 +1,22 @@ -# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot --target=aarch64-linux-ohos -fPIC -o a.c.o -c %s -# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot -fPIC --target=aarch64-linux-ohos -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,lib_a.so -o lib_a.so a.c.o -# RUN: ld.lld --adlt lib_a.so -o libadlt_a.so --emit-relocs --relax -# RUN: llvm-objdump -xd libadlt_a.so | FileCheck %s +// REQUIRES: aarch64 +# RUN: rm -f relax_adrp_add.c.o lib_relax_adrp_add.so libadlt_relax_adrp_add.so +# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot --target=aarch64-linux-ohos -fPIC -o relax_adrp_add.c.o -c %s +# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot -fPIC --target=aarch64-linux-ohos -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,lib_relax_adrp_add.so -o lib_relax_adrp_add.so relax_adrp_add.c.o +# RUN: ld.lld --adlt lib_relax_adrp_add.so -o libadlt_relax_adrp_add.so --emit-relocs --relax +# RUN: llvm-objdump -xd libadlt_relax_adrp_add.so | FileCheck %s # CHECK-LABEL: 0000000000001480 <_start>: # CHECK-NEXT: 1480: d503201f nop # CHECK-NEXT: 0000000000001480: R_AARCH64_NONE *ABS* -# CHECK-NEXT: 1484: 1002b79e adr x30, #22256 +# CHECK-NEXT: 1484: 1002137e adr x30, #17004 # CHECK-NEXT: 0000000000001484: R_AARCH64_ADR_PREL_LO21 .rodata__0 # CHECK-NEXT: 1488: d503201f nop # CHECK-NEXT: 0000000000001488: R_AARCH64_NONE *ABS* -# CHECK-NEXT: 148c: 1002b781 adr x1, #22256 +# CHECK-NEXT: 148c: 10021321 adr x1, #16996 # CHECK-NEXT: 000000000000148c: R_AARCH64_ADR_PREL_LO21 .rodata__0 # CHECK-NEXT: 1490: d503201f nop # CHECK-NEXT: 0000000000001490: R_AARCH64_NONE *ABS* -# CHECK-NEXT: 1494: 1002b78f adr x15, #22256 +# CHECK-NEXT: 1494: 100212ef adr x15, #16988 # CHECK-NEXT: 0000000000001494: R_AARCH64_ADR_PREL_LO21 .rodata__0 # CHECK-EMPTY: @@ -24,9 +26,9 @@ x: .text .global _start _start: - adrp x30, x - add x30, x30, :lo12:x - adrp x1, x - add x1, x1, :lo12:x - adrp x15, x - add x15, x15, :lo12:x + adrp x30, x + add x30, x30, :lo12:x + adrp x1, x + add x1, x1, :lo12:x + adrp x15, x + add x15, x15, :lo12:x diff --git a/lld/test/ADLT/relax-adrp-ldr.s b/lld/test/ADLT/relax-adrp-ldr.s index 6b7b0a383311..8a5d01e26e2d 100644 --- a/lld/test/ADLT/relax-adrp-ldr.s +++ b/lld/test/ADLT/relax-adrp-ldr.s @@ -1,20 +1,22 @@ -# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot --target=aarch64-linux-ohos -fPIC -o a.c.o -c %s -# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot -fPIC --target=aarch64-linux-ohos -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,lib_a.so -o lib_a.so a.c.o -# RUN: ld.lld --adlt lib_a.so -o libadlt_a.so --emit-relocs --relax -# RUN: llvm-objdump -xd libadlt_a.so | FileCheck %s +// REQUIRES: aarch64 +# RUN: rm -f relax_adrp_ldr.c.o lib_relax_adrp_ldr.so libadlt_relax_adrp_ldr.so +# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot --target=aarch64-linux-ohos -fPIC -o relax_adrp_ldr.c.o -c %s +# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot -fPIC --target=aarch64-linux-ohos -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,lib_relax_adrp_ldr.so -o lib_relax_adrp_ldr.so relax_adrp_ldr.c.o +# RUN: ld.lld --adlt lib_relax_adrp_ldr.so -o libadlt_relax_adrp_ldr.so --emit-relocs --relax +# RUN: llvm-objdump -xd libadlt_relax_adrp_ldr.so | FileCheck %s # CHECK-LABEL: 0000000000001480 <_start>: # CHECK-NEXT: 1480: d503201f nop # CHECK-NEXT: 0000000000001480: R_AARCH64_NONE *ABS*+0x8 -# CHECK-NEXT: 1484: 100235c0 adr x0, #18104 +# CHECK-NEXT: 1484: 10032ea0 adr x0, #26068 # CHECK-NEXT: 0000000000001484: R_AARCH64_ADR_PREL_LO21 .data__0+0x8 # CHECK-NEXT: 1488: d503201f nop # CHECK-NEXT: 0000000000001488: R_AARCH64_NONE *ABS*+0x10 -# CHECK-NEXT: 148c: 10023601 adr x1, #18112 +# CHECK-NEXT: 148c: 10032ea1 adr x1, #26068 # CHECK-NEXT: 000000000000148c: R_AARCH64_ADR_PREL_LO21 .data__0+0x10 # CHECK-NEXT: 1490: d503201f nop # CHECK-NEXT: 0000000000001490: R_AARCH64_NONE *ABS*+0x18 -# CHECK-NEXT: 1494: 10023642 adr x2, #18120 +# CHECK-NEXT: 1494: 10032ea2 adr x2, #26068 # CHECK-NEXT: 0000000000001494: R_AARCH64_ADR_PREL_LO21 .data__0+0x18 # CHECK-EMPTY: @@ -27,9 +29,9 @@ var3: .xword 300 .section .text .global _start _start: - adrp x0, :got:var1 - ldr x0, [x0, :got_lo12:var1] - adrp x1, :got:var2 - ldr x1, [x1, :got_lo12:var2] - adrp x2, :got:var3 - ldr x2, [x2, :got_lo12:var3] + adrp x0, :got:var1 + ldr x0, [x0, :got_lo12:var1] + adrp x1, :got:var2 + ldr x1, [x1, :got_lo12:var2] + adrp x2, :got:var3 + ldr x2, [x2, :got_lo12:var3] -- Gitee From ef9b058b5cceede556580ee380f8e9247f75241f Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Sat, 2 Nov 2024 22:47:12 +0300 Subject: [PATCH 04/23] Refactoring finalizeRelax Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 60 ++++++++++------------------------- 1 file changed, 17 insertions(+), 43 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index d24b0dea2989..b64c67732c16 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -114,81 +114,55 @@ void AArch64::finalizeRelax(int passes) const { ArrayRef old = sec->rawData; size_t newSize = old.size() - aux.relocDeltas[rels.size() - 1]; uint8_t *newData = context().bAlloc.Allocate(newSize); - uint64_t offset = 0; - int64_t delta = 0; sec->bytesDropped = 0; sec->rawData = makeArrayRef(newData, newSize); + memcpy(newData, old.data(), newSize); + // Update section content: rewrite instructions for relaxed relocations. for (size_t i = 0, e = rels.size(); i != e; ++i) { - uint32_t remove = aux.relocDeltas[i] - delta; - delta = aux.relocDeltas[i]; - - if (aux.relocTypes[i] == R_AARCH64_RELAX_DUMMY) + if (!aux.relocChanged[i]) continue; - // Copy from last location to the current relocated location. - const Relocation &r = rels[i]; - uint64_t size = r.offset - offset; - memcpy(newData, old.data() + offset, size); - newData += size; - - int64_t skip = 0; + Relocation &r = rels[i]; RelType newType = aux.relocTypes[i]; + switch (newType) { case R_AARCH64_NONE: if (i + 1 < rels.size() && aux.relocTypes[i + 1] == R_AARCH64_ADR_PREL_LO21) { - skip = 4; - write32le(newData, aux.writes[i]); + write32le(newData + r.offset, aux.writes[i]); + r.type = newType; } break; case R_AARCH64_ADR_PREL_LO21: { - skip = 4; Relocation adrRel = {R_ABS, R_AARCH64_ADR_PREL_LO21, r.offset, - /*addend=*/0, rels[i - 1].sym}; - write32le(newData, aux.writes[i]); - baseTarget.relocate(newData, adrRel, aux.vals[i]); + /*addend=*/0, r.sym}; + write32le(newData + r.offset, aux.writes[i]); + baseTarget.relocate(newData + r.offset, adrRel, aux.vals[i]); + r.type = newType; break; } case R_AARCH64_ADR_PREL_PG_HI21: { - skip = 4; Relocation adrpSymRel = {R_AARCH64_PAGE_PC, R_AARCH64_ADR_PREL_PG_HI21, r.offset, /*addend=*/0, r.sym}; - write32le(newData, aux.writes[i]); - baseTarget.relocate(newData, adrpSymRel, aux.vals[i]); + write32le(newData + r.offset, aux.writes[i]); + baseTarget.relocate(newData + r.offset, adrpSymRel, aux.vals[i]); + r.type = newType; break; } case R_AARCH64_ADD_ABS_LO12_NC: { - skip = 4; - write32le(newData, aux.writes[i]); + write32le(newData + r.offset, aux.writes[i]); Relocation addRel = {R_ABS, R_AARCH64_ADD_ABS_LO12_NC, r.offset, /*addend=*/0, r.sym}; - baseTarget.relocate(newData, addRel, aux.vals[i]); + baseTarget.relocate(newData + r.offset, addRel, aux.vals[i]); + r.type = newType; break; } default: llvm_unreachable("unsupported type"); } - - newData += skip; - offset = r.offset + skip + remove; - } - memcpy(newData, old.data() + offset, old.size() - offset); - - // Update relocs. - delta = 0; - - for (size_t i = 0, e = rels.size(); i != e;) { - uint64_t cur = rels[i].offset; - do { - rels[i].offset -= delta; - if (aux.relocTypes[i] != R_AARCH64_RELAX_DUMMY) - rels[i].type = aux.relocTypes[i]; - } while (++i != e && rels[i].offset == cur); - - delta = aux.relocDeltas[i - 1]; } } } -- Gitee From 10540933cf65436f3a3d229fd7e419dd149bf794 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Sun, 3 Nov 2024 21:31:50 +0300 Subject: [PATCH 05/23] Fixes after rebase Signed-off-by: streshchukvitaly --- lld/ELF/InputSection.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 559b9a4fc331..6f923e1d4822 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -371,9 +371,9 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { RelType type = i >= relocs.size() ? rels[i].getType(config->isMips64EL) : relocs[i].type; - const SharedFileExtended *soExt = - elf::adlt::ctx->getSoExt(this->file); - Symbol &sym = soExt->getRelocTargetSym(rels[i]); + const ObjFile *file = config->adlt ? nullptr : getFile(); + Symbol &sym = + cast(this->file)->getRelocTargetSym(rels[i]); auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); @@ -428,14 +428,14 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { // // See the comment in maybeReportUndefined for PPC32 .got2 and PPC64 .toc auto *d = dyn_cast(&sym); - if (!d) { + if (!d && !config->adlt) { if (!isDebugSection(*sec) && sec->name != ".eh_frame" && sec->name != ".gcc_except_table" && sec->name != ".got2" && sec->name != ".toc") { uint32_t secIdx = cast(sym).discardedSecIdx; - Elf_Shdr_Impl sec = soExt->template getELFShdrs()[secIdx]; + Elf_Shdr_Impl sec = file->template getELFShdrs()[secIdx]; warn("relocation refers to a discarded section: " + - CHECK(soExt->getObj().getSectionName(sec), soExt) + + CHECK(file->getObj().getSectionName(sec), file) + "\n>>> referenced by " + getObjMsg(p->r_offset)); } p->setSymbolAndType(0, 0, false); -- Gitee From d047f505ea1b0a96aca72dbdc1456b3abddbc7a1 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Sun, 3 Nov 2024 23:33:51 +0300 Subject: [PATCH 06/23] Refactoring: relocChanged should always be up-to-date Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index b64c67732c16..9f01bfc4080f 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -199,8 +199,6 @@ void AArch64::initSymbolAnchors() const { std::make_unique(sec->relocations.size()); sec->relaxAuxAdlt->relocChanged = std::make_unique(sec->relocations.size()); - std::fill_n(sec->relaxAuxAdlt->relocChanged.get(), - sec->relocations.size(), false); sec->relaxAuxAdlt->writes = std::make_unique(sec->relocations.size()); sec->relaxAuxAdlt->vals = @@ -410,24 +408,25 @@ bool AArch64::relax(InputSection &sec) const { // Check if R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC // always appear in pairs. - size_t i = 0; - for (; i != relocs_size; ++i) { - if (relocs[i].type == R_AARCH64_ADR_GOT_PAGE) { - if (i + 1 < relocs_size && - relocs[i + 1].type == R_AARCH64_LD64_GOT_LO12_NC) { - ++i; + size_t j = 0; + for (; j != relocs_size; ++j) { + if (relocs[j].type == R_AARCH64_ADR_GOT_PAGE) { + if (j + 1 < relocs_size && + relocs[j + 1].type == R_AARCH64_LD64_GOT_LO12_NC) { + ++j; continue; } break; - } else if (relocs[i].type == R_AARCH64_LD64_GOT_LO12_NC) { + } else if (relocs[j].type == R_AARCH64_LD64_GOT_LO12_NC) { break; } } - safeToRelaxAdrpLdr = i == relocs_size; + safeToRelaxAdrpLdr = j == relocs_size; std::fill_n(aux.relocTypes.get(), relocs_size, R_AARCH64_RELAX_DUMMY); std::fill_n(aux.writes.get(), relocs_size, 0); + std::fill_n(aux.relocChanged.get(), relocs_size, false); for (size_t i = 0; i < relocs_size; ++i) { Relocation &r = relocs[i]; -- Gitee From 921f84d138ace4128dee1d30c7754f2990da3489 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Mon, 4 Nov 2024 18:24:46 +0300 Subject: [PATCH 07/23] Don't disable needsThunks Signed-off-by: streshchukvitaly --- lld/ELF/Arch/AArch64.cpp | 7 ------- lld/ELF/InputSection.cpp | 8 ++++++-- lld/ELF/Writer.cpp | 6 ++++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 2a41a5275262..3b3e276cae0a 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -88,13 +88,6 @@ AArch64::AArch64() { defaultImageBase = 0x200000; needsThunks = true; - - // OHOS_LOCAL begin - // We need to set 'false' for 'needsThunks' here - // in order for the 'relaxOnce' method to be called. - if (config->adlt && config->relax) - needsThunks = false; - // OHOS_LOCAL end } RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 6f923e1d4822..0461a1f70b92 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -368,8 +368,12 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { auto &relocs = sec->relocations; for (size_t i = 0; i < rels.size(); ++i) { - RelType type = i >= relocs.size() ? rels[i].getType(config->isMips64EL) - : relocs[i].type; + RelType type = rels[i].getType(config->isMips64EL); + + if (i < relocs.size() && sec->relaxAuxAdlt && + sec->relaxAuxAdlt->relocChanged[i]) { + type = relocs[i].type; + } const ObjFile *file = config->adlt ? nullptr : getFile(); Symbol &sym = diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index b3d5361be644..b4ff77bf6404 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1719,6 +1719,12 @@ template void Writer::finalizeAddressDependentContent() { for (;;) { bool changed = target->needsThunks ? tc.createThunks(pass, outputSections) : target->relaxOnce(pass); + + // OHOS_LOCAL begin + if (config->adlt && config->relax) + changed = changed || target->relaxOnce(pass); + // OHOS_LOCAL end + ++pass; // With Thunk Size much smaller than branch range we expect to -- Gitee From 9b33d3b49fea5bc720eb71db976bfe425cb7084e Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Mon, 4 Nov 2024 21:35:44 +0300 Subject: [PATCH 08/23] Refactoring Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 12 +++++----- lld/ELF/Adlt/{RelaxAuxAdlt.h => RelaxAux.h} | 25 ++++++++++++++++----- lld/ELF/InputSection.cpp | 8 +++---- lld/ELF/InputSection.h | 4 ++-- lld/ELF/Writer.cpp | 2 +- 5 files changed, 32 insertions(+), 19 deletions(-) rename lld/ELF/Adlt/{RelaxAuxAdlt.h => RelaxAux.h} (57%) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 9f01bfc4080f..653f774ac4b6 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -8,7 +8,7 @@ // OHOS_LOCAL begin #include "Adlt/Arch/AArch64.h" -#include "Adlt/RelaxAuxAdlt.h" +#include "Adlt/RelaxAux.h" #include "llvm/Support/Endian.h" #include "AArch64.h" @@ -105,7 +105,7 @@ void AArch64::finalizeRelax(int passes) const { if (!sec->relaxAuxAdlt) continue; - RelaxAuxAdlt &aux = *sec->relaxAuxAdlt; + RelaxAux &aux = *sec->relaxAuxAdlt; if (!aux.relocDeltas) continue; @@ -191,7 +191,7 @@ void AArch64::initSymbolAnchors() const { continue; for (InputSection *sec : getInputSections(*osec, storage)) { - sec->relaxAuxAdlt = make(); + sec->relaxAuxAdlt = make(); if (sec->relocations.size()) { sec->relaxAuxAdlt->relocDeltas = std::make_unique(sec->relocations.size()); @@ -399,7 +399,7 @@ bool AArch64::relax(InputSection &sec) const { bool changed = false; auto &aux = *sec.relaxAuxAdlt; const uint64_t secAddr = sec.getVA(); - ArrayRef sa = makeArrayRef(aux.anchors); + ArrayRef sa = makeArrayRef(aux.anchors); uint64_t delta = 0; bool safeToRelaxAdrpLdr = false; @@ -424,7 +424,7 @@ bool AArch64::relax(InputSection &sec) const { safeToRelaxAdrpLdr = j == relocs_size; - std::fill_n(aux.relocTypes.get(), relocs_size, R_AARCH64_RELAX_DUMMY); + std::fill_n(aux.relocTypes.get(), relocs_size, R_AARCH64_NONE); std::fill_n(aux.writes.get(), relocs_size, 0); std::fill_n(aux.relocChanged.get(), relocs_size, false); @@ -465,7 +465,7 @@ bool AArch64::relax(InputSection &sec) const { } } - for (const SymbolAnchorAdlt &a : sa) { + for (const SymbolAnchor &a : sa) { if (a.end) a.d->size = a.offset - delta - a.d->value; else diff --git a/lld/ELF/Adlt/RelaxAuxAdlt.h b/lld/ELF/Adlt/RelaxAux.h similarity index 57% rename from lld/ELF/Adlt/RelaxAuxAdlt.h rename to lld/ELF/Adlt/RelaxAux.h index 248635b1b287..aaa216859364 100644 --- a/lld/ELF/Adlt/RelaxAuxAdlt.h +++ b/lld/ELF/Adlt/RelaxAux.h @@ -1,5 +1,15 @@ -#ifndef RELAX_AUX_ADLT_H -#define RELAX_AUX_ADLT_H +//===- Adlt/RelaxAuxs.h ------------------------------------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// OHOS_LOCAL begin +#ifndef LLD_ELF_ADLT_RELAX_AUX_H +#define LLD_ELF_ADLT_RELAX_AUX_H #include "Relocations.h" #include "Symbols.h" @@ -7,16 +17,17 @@ namespace lld { namespace elf { -struct SymbolAnchorAdlt { +namespace adlt { +struct SymbolAnchor { uint64_t offset; Defined *d; bool end; // true for the anchor of st_value+st_size }; -struct RelaxAuxAdlt { +struct RelaxAux { // This records symbol start and end offsets which will be adjusted according // to the nearest relocDeltas element. - SmallVector anchors; + SmallVector anchors; // For relocations[i], the actual offset is // r_offset - (i ? relocDeltas[i-1] : 0). std::unique_ptr relocDeltas; @@ -29,7 +40,9 @@ struct RelaxAuxAdlt { // To store new values for relocations. std::unique_ptr vals; }; +} // namespace adlt } // namespace elf } // namespace lld -#endif +#endif // LLD_ELF_ADLT_RELAX_AUX_H +// OHOS_LOCAL end diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 0461a1f70b92..210331691bd0 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1452,21 +1452,21 @@ template void InputSection::writeTo(uint8_t *buf) { // may be a relocation section. if (LLVM_UNLIKELY(type == SHT_RELA)) { // OHOS_LOCAL begin - if (config->adlt && config->relax && !config->relocatable) + if (config->adlt) copyRelocationsAdlt( buf, getDataAs()); else - // OHOS_LOCAL end + // OHOS_LOCAL end copyRelocations(buf, getDataAs()); return; } if (LLVM_UNLIKELY(type == SHT_REL)) { // OHOS_LOCAL begin - if (config->adlt && config->relax && !config->relocatable) + if (config->adlt) copyRelocationsAdlt( buf, getDataAs()); else - // OHOS_LOCAL end + // OHOS_LOCAL end copyRelocations(buf, getDataAs()); return; } diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 102751db6e8d..ef25211760d8 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -20,7 +20,7 @@ // OHOS_LOCAL begin #include "Adlt/Context.h" -#include "Adlt/RelaxAuxAdlt.h" +#include "Adlt/RelaxAux.h" // OHOS_LOCAL end namespace lld { @@ -226,7 +226,7 @@ public: // OHOS_LOCAL begin // Auxiliary information for linker relaxation, when using ADLT. - RelaxAuxAdlt *relaxAuxAdlt; + adlt::RelaxAux *relaxAuxAdlt; // OHOS_LOCAL end }; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index b4ff77bf6404..fc3c7c11c5ed 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1721,7 +1721,7 @@ template void Writer::finalizeAddressDependentContent() { : target->relaxOnce(pass); // OHOS_LOCAL begin - if (config->adlt && config->relax) + if (config->adlt) changed = changed || target->relaxOnce(pass); // OHOS_LOCAL end -- Gitee From 8f73a75e4f011bb44a6c4271e49788bfe39dcd8b Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Mon, 4 Nov 2024 21:39:44 +0300 Subject: [PATCH 09/23] Fix header comment in RelaxAux.h Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/RelaxAux.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lld/ELF/Adlt/RelaxAux.h b/lld/ELF/Adlt/RelaxAux.h index aaa216859364..d703b9dbe18c 100644 --- a/lld/ELF/Adlt/RelaxAux.h +++ b/lld/ELF/Adlt/RelaxAux.h @@ -1,5 +1,4 @@ -//===- Adlt/RelaxAuxs.h ------------------------------------------*- C++ -//-*-===// +//===- Adlt/RelaxAux.h -------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. -- Gitee From 52d007450791b2d451db4bfddb900546204d2cd6 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Wed, 6 Nov 2024 15:50:00 +0300 Subject: [PATCH 10/23] Update RelaxAux creation order Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 78 ++++++++++++++--------------------- lld/ELF/Adlt/Arch/AArch64.h | 4 +- lld/ELF/Arch/AArch64.cpp | 12 ------ lld/ELF/Writer.cpp | 8 ++-- 4 files changed, 36 insertions(+), 66 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 653f774ac4b6..571215245004 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -93,7 +93,7 @@ bool AArch64::isErrata(uint64_t offset) { return (impl->errataOffset && impl->errataOffset == offset) ? true : false; } -void AArch64::finalizeRelax(int passes) const { +void AArch64::finalizeRelax() const { SmallVector storage; const TargetInfo &baseTarget = *elf::target; @@ -168,43 +168,34 @@ void AArch64::finalizeRelax(int passes) const { } } -bool AArch64::relaxOnce(int pass) const { - if (pass == 0) - initSymbolAnchors(); - +bool AArch64::relaxOnce() const { SmallVector storage; bool changed = false; for (OutputSection *osec : outputSections) { if (!(osec->flags & SHF_EXECINSTR)) continue; - for (InputSection *sec : getInputSections(*osec, storage)) + for (InputSection *sec : getInputSections(*osec, storage)) { + if (!sec->relaxAuxAdlt) + initSymbolAnchors(sec); changed |= relax(*sec); + } } return changed; } -void AArch64::initSymbolAnchors() const { - SmallVector storage; - - for (OutputSection *osec : outputSections) { - if (!(osec->flags & SHF_EXECINSTR)) - continue; - - for (InputSection *sec : getInputSections(*osec, storage)) { - sec->relaxAuxAdlt = make(); - if (sec->relocations.size()) { - sec->relaxAuxAdlt->relocDeltas = - std::make_unique(sec->relocations.size()); - sec->relaxAuxAdlt->relocTypes = - std::make_unique(sec->relocations.size()); - sec->relaxAuxAdlt->relocChanged = - std::make_unique(sec->relocations.size()); - sec->relaxAuxAdlt->writes = - std::make_unique(sec->relocations.size()); - sec->relaxAuxAdlt->vals = - std::make_unique(sec->relocations.size()); - } - } +void lld::elf::adlt::AArch64::initSymbolAnchors(InputSection *sec) const { + sec->relaxAuxAdlt = make(); + if (sec->relocations.size()) { + sec->relaxAuxAdlt->relocDeltas = + std::make_unique(sec->relocations.size()); + sec->relaxAuxAdlt->relocTypes = + std::make_unique(sec->relocations.size()); + sec->relaxAuxAdlt->relocChanged = + std::make_unique(sec->relocations.size()); + sec->relaxAuxAdlt->writes = + std::make_unique(sec->relocations.size()); + sec->relaxAuxAdlt->vals = + std::make_unique(sec->relocations.size()); } // Store anchors (st_value and st_value+st_size) for symbols relative to text @@ -214,28 +205,19 @@ void AArch64::initSymbolAnchors() const { auto *d = dyn_cast(sym); if (!d || d->file != file) continue; - if (auto *sec = dyn_cast_or_null(d->section)) - if (sec->flags & SHF_EXECINSTR && sec->relaxAuxAdlt) { - // If sec is discarded, relaxAuxAdlt will be nullptr. - sec->relaxAuxAdlt->anchors.push_back({d->value, d, false}); - sec->relaxAuxAdlt->anchors.push_back({d->value + d->size, d, true}); - } + if (auto *text_sec = dyn_cast_or_null(d->section)) + if (text_sec == sec) + if (text_sec->flags & SHF_EXECINSTR && text_sec->relaxAuxAdlt) { + // If sec is discarded, relaxAuxAdlt will be nullptr. + text_sec->relaxAuxAdlt->anchors.push_back({d->value, d, false}); + text_sec->relaxAuxAdlt->anchors.push_back( + {d->value + d->size, d, true}); + } } - // Sort anchors by offset so that we can find the closest relocation - // efficiently. For a zero size symbol, ensure that its start anchor precedes - // its end anchor. For two symbols with anchors at the same offset, their - // order does not matter. - for (OutputSection *osec : outputSections) { - if (!(osec->flags & SHF_EXECINSTR)) - continue; - for (InputSection *sec : getInputSections(*osec, storage)) { - llvm::sort(sec->relaxAuxAdlt->anchors, [](auto &a, auto &b) { - return std::make_pair(a.offset, a.end) < - std::make_pair(b.offset, b.end); - }); - } - } + llvm::sort(sec->relaxAuxAdlt->anchors, [](auto &a, auto &b) { + return std::make_pair(a.offset, a.end) < std::make_pair(b.offset, b.end); + }); } bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, diff --git a/lld/ELF/Adlt/Arch/AArch64.h b/lld/ELF/Adlt/Arch/AArch64.h index 1d888945af7f..63e5d8208e72 100644 --- a/lld/ELF/Adlt/Arch/AArch64.h +++ b/lld/ELF/Adlt/Arch/AArch64.h @@ -36,9 +36,9 @@ public: void setErrataOffset(uint64_t offset); bool isErrata(uint64_t offset); - void finalizeRelax(int passes) const; + void finalizeRelax() const; - bool relaxOnce(int pass) const; + bool relaxOnce() const; private: std::unique_ptr impl; diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 3b3e276cae0a..965298ccf4d7 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -58,9 +58,6 @@ public: uint64_t val) const override; void relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, uint64_t val) const override; - // OHOS_LOCAL begin - bool relaxOnce(int pass) const override; - // OHOS_LOCAL end }; } // namespace @@ -629,15 +626,6 @@ void AArch64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, llvm_unreachable("invalid relocation for TLS IE to LE relaxation"); } -// OHOS_LOCAL begin -bool AArch64::relaxOnce(int pass) const { - if (!config->adlt && config->relocatable) - return false; - - return adlt::ctx->adltInfo->relaxOnce(pass); -} -// OHOS_LOCAL end - AArch64Relaxer::AArch64Relaxer(ArrayRef relocs) { if (!config->relax || config->emachine != EM_AARCH64) { safeToRelaxAdrpLdr = false; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index fc3c7c11c5ed..3b21fdffed08 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1721,8 +1721,8 @@ template void Writer::finalizeAddressDependentContent() { : target->relaxOnce(pass); // OHOS_LOCAL begin - if (config->adlt) - changed = changed || target->relaxOnce(pass); + if (config->adlt && config->relax) + changed |= elf::adlt::ctx->adltInfo->relaxOnce(); // OHOS_LOCAL end ++pass; @@ -1774,8 +1774,8 @@ template void Writer::finalizeAddressDependentContent() { // OHOS_LOCAL begin // We need to finalize the relaxation: update types and output instructions. - if (config->adlt && !config->relocatable && config->emachine == EM_AARCH64) - elf::adlt::ctx->adltInfo->finalizeRelax(pass); + if (config->adlt && config->relax) + elf::adlt::ctx->adltInfo->finalizeRelax(); // OHOS LOCAL end if (config->relocatable) -- Gitee From 759c732680918f5f15d7eb6da4f3bfc2a00f78bf Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Wed, 6 Nov 2024 23:53:54 +0300 Subject: [PATCH 11/23] Review fixes --- lld/ELF/Adlt/Arch/AArch64.cpp | 79 ++++++++----------- lld/ELF/Adlt/RelaxAux.h | 12 +-- lld/ELF/InputSection.cpp | 137 ++++++++++++--------------------- lld/ELF/InputSection.h | 15 ++-- lld/test/ADLT/lit.local.cfg.py | 10 --- lld/test/ADLT/relax-adrp-add.s | 9 +-- lld/test/ADLT/relax-adrp-ldr.s | 15 ++-- 7 files changed, 100 insertions(+), 177 deletions(-) delete mode 100644 lld/test/ADLT/lit.local.cfg.py diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 571215245004..718bc012f20b 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -8,6 +8,7 @@ // OHOS_LOCAL begin #include "Adlt/Arch/AArch64.h" +#include "Adlt/Context.h" #include "Adlt/RelaxAux.h" #include "llvm/Support/Endian.h" @@ -176,14 +177,14 @@ bool AArch64::relaxOnce() const { continue; for (InputSection *sec : getInputSections(*osec, storage)) { if (!sec->relaxAuxAdlt) - initSymbolAnchors(sec); + initRelaxAux(sec); changed |= relax(*sec); } } return changed; } -void lld::elf::adlt::AArch64::initSymbolAnchors(InputSection *sec) const { +void lld::elf::adlt::AArch64::initRelaxAux(InputSection *sec) const { sec->relaxAuxAdlt = make(); if (sec->relocations.size()) { sec->relaxAuxAdlt->relocDeltas = @@ -197,27 +198,6 @@ void lld::elf::adlt::AArch64::initSymbolAnchors(InputSection *sec) const { sec->relaxAuxAdlt->vals = std::make_unique(sec->relocations.size()); } - - // Store anchors (st_value and st_value+st_size) for symbols relative to text - // sections. - for (InputFile *file : lld::elf::ctx->objectFiles) - for (Symbol *sym : file->getSymbols()) { - auto *d = dyn_cast(sym); - if (!d || d->file != file) - continue; - if (auto *text_sec = dyn_cast_or_null(d->section)) - if (text_sec == sec) - if (text_sec->flags & SHF_EXECINSTR && text_sec->relaxAuxAdlt) { - // If sec is discarded, relaxAuxAdlt will be nullptr. - text_sec->relaxAuxAdlt->anchors.push_back({d->value, d, false}); - text_sec->relaxAuxAdlt->anchors.push_back( - {d->value + d->size, d, true}); - } - } - - llvm::sort(sec->relaxAuxAdlt->anchors, [](auto &a, auto &b) { - return std::make_pair(a.offset, a.end) < std::make_pair(b.offset, b.end); - }); } bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, @@ -253,6 +233,8 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, uint32_t ldrInstr = read32le(sec.rawData.data() + ldrRel.offset); // Check if the first instruction is ADRP and the second instruction is LDR. + // ADRP: 0x90000000. + // LDR : 0x39000000. if ((adrpInstr & 0x9f000000) != 0x90000000 || (ldrInstr & 0x3b000000) != 0x39000000) return false; @@ -261,6 +243,10 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, if (!(ldrInstr >> 31)) return false; + // Extract register numbers from instructions. + // For example, if ADRP instruction: 0xf0ffffffe0, + // After operation: 0xf0ffffffe0 & 0x1f + // We get the result: 0x00000000 => 0. uint32_t adrpDestReg = adrpInstr & 0x1f; uint32_t ldrDestReg = ldrInstr & 0x1f; uint32_t ldrSrcReg = (ldrInstr >> 5) & 0x1f; @@ -287,7 +273,7 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, return false; sec.relaxAuxAdlt->relocTypes[i] = R_AARCH64_ADR_PREL_PG_HI21; - sec.relaxAuxAdlt->writes[i] = 0x90000000 | adrpDestReg; + sec.relaxAuxAdlt->writes[i] = 0x90000000 | adrpDestReg; // ADRP: 0x90000000. sec.relaxAuxAdlt->relocChanged[i] = true; sec.relaxAuxAdlt->vals[i] = SignExtend64( getAArch64Page(sym.getVA()) - getAArch64Page(secAddr + adrpRel.offset), @@ -295,7 +281,7 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, sec.relaxAuxAdlt->relocTypes[i + 1] = R_AARCH64_ADD_ABS_LO12_NC; sec.relaxAuxAdlt->writes[i + 1] = - 0x91000000 | adrpDestReg | (adrpDestReg << 5); + 0x91000000 | adrpDestReg | (adrpDestReg << 5); // ADD: 0x91000000. sec.relaxAuxAdlt->relocChanged[i + 1] = true; sec.relaxAuxAdlt->vals[i + 1] = SignExtend64(sym.getVA(), 64); @@ -339,6 +325,8 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, uint32_t addInstr = read32le(sec.rawData.data() + addRel.offset); // Check if the first instruction is ADRP and the second instruction is ADD. + // ADRP: 0x90000000. + // ADD : 0x91000000. if ((adrpInstr & 0x9f000000) != 0x90000000 || (addInstr & 0xffc00000) != 0x91000000) { // If the types do not match, @@ -349,6 +337,10 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, return false; } + // Extract register numbers from instructions. + // For example, if ADRP instruction: 0xf0ffffffe0, + // After operation: 0xf0ffffffe0 & 0x1f + // We get the result: 0x00000000 => 0. uint32_t adrpDestReg = adrpInstr & 0x1f; uint32_t addDestReg = addInstr & 0x1f; uint32_t addSrcReg = (addInstr >> 5) & 0x1f; @@ -370,7 +362,8 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, sec.relaxAuxAdlt->relocChanged[i] = true; sec.relaxAuxAdlt->relocTypes[i + 1] = R_AARCH64_ADR_PREL_LO21; - sec.relaxAuxAdlt->writes[i + 1] = 0x10000000 | adrpDestReg; + sec.relaxAuxAdlt->writes[i + 1] = + 0x10000000 | adrpDestReg; // ADR: 0x10000000. sec.relaxAuxAdlt->relocChanged[i + 1] = true; sec.relaxAuxAdlt->vals[i + 1] = val; @@ -381,7 +374,6 @@ bool AArch64::relax(InputSection &sec) const { bool changed = false; auto &aux = *sec.relaxAuxAdlt; const uint64_t secAddr = sec.getVA(); - ArrayRef sa = makeArrayRef(aux.anchors); uint64_t delta = 0; bool safeToRelaxAdrpLdr = false; @@ -406,14 +398,21 @@ bool AArch64::relax(InputSection &sec) const { safeToRelaxAdrpLdr = j == relocs_size; - std::fill_n(aux.relocTypes.get(), relocs_size, R_AARCH64_NONE); - std::fill_n(aux.writes.get(), relocs_size, 0); - std::fill_n(aux.relocChanged.get(), relocs_size, false); + // Set aux data to default values. + for (size_t i = 0; i < relocs_size; ++i) { + aux.relocTypes[i] = R_AARCH64_NONE; + aux.writes[i] = 0; + aux.relocChanged[i] = false; + } for (size_t i = 0; i < relocs_size; ++i) { Relocation &r = relocs[i]; const uint64_t loc = secAddr + r.offset - delta; uint32_t &cur = aux.relocDeltas[i]; + + // If size of instruction changes during relaxation: type + // will change or instruction will be deleted. It is necessary to save + // size of deleted/changed instruction in `remove` variable. uint32_t remove = 0; switch (r.expr) { @@ -429,16 +428,8 @@ bool AArch64::relax(InputSection &sec) const { break; } - // For all anchors whose offsets are <= r.offset, they are preceded by - // the previous relocation whose `relocDeltas` value equals `delta`. - // Decrease their st_value and update their st_size. - for (; sa.size() && sa[0].offset <= r.offset; sa = sa.slice(1)) { - if (sa[0].end) - sa[0].d->size = sa[0].offset - delta - sa[0].d->value; - else - sa[0].d->value = sa[0].offset - delta; - } - + // If any instruction has been deleted or its size has been changed, we need + // to update `delta`. delta += remove; if (delta != cur) { @@ -446,14 +437,6 @@ bool AArch64::relax(InputSection &sec) const { changed = true; } } - - for (const SymbolAnchor &a : sa) { - if (a.end) - a.d->size = a.offset - delta - a.d->value; - else - a.d->value = a.offset - delta; - } - // Inform assignAddresses that the size has changed. if (!isUInt<32>(delta)) fatal("section size decrease is too large: " + Twine(delta)); diff --git a/lld/ELF/Adlt/RelaxAux.h b/lld/ELF/Adlt/RelaxAux.h index d703b9dbe18c..bf895831851d 100644 --- a/lld/ELF/Adlt/RelaxAux.h +++ b/lld/ELF/Adlt/RelaxAux.h @@ -1,4 +1,5 @@ -//===- Adlt/RelaxAux.h -------------------------------------------*- C++ -*-===// +//===- Adlt/RelaxAux.h -------------------------------------------*- C++ +//-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -17,16 +18,7 @@ namespace lld { namespace elf { namespace adlt { -struct SymbolAnchor { - uint64_t offset; - Defined *d; - bool end; // true for the anchor of st_value+st_size -}; - struct RelaxAux { - // This records symbol start and end offsets which will be adjusted according - // to the nearest relocDeltas element. - SmallVector anchors; // For relocations[i], the actual offset is // r_offset - (i ? relocDeltas[i-1] : 0). std::unique_ptr relocDeltas; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 210331691bd0..2fcd0926af26 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -27,6 +27,7 @@ // OHOS_LOCAL begin #include "Adlt/Context.h" #include "Adlt/InputFiles.h" +#include "Adlt/RelaxAux.h" // OHOS_LOCAL end using namespace llvm; @@ -358,13 +359,16 @@ InputSectionBase *InputSection::getRelocatedSection() const { } // OHOS_LOCAL begin -// This method is a copy of the copyRelocations method, but modified to support -// correct relaxation of relocations when using ADLT. +namespace lld { +namespace elf { + +namespace adlt { +// This method is a copy of the copyRelocations method, but modified to +// support correct relaxation of relocations when using ADLT. template -void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { +void copyRelocations(uint8_t *buf, llvm::ArrayRef rels, InputFile *file, + InputSectionBase *sec) { const TargetInfo &target = *elf::target; - - InputSectionBase *sec = getRelocatedSection(); auto &relocs = sec->relocations; for (size_t i = 0; i < rels.size(); ++i) { @@ -375,9 +379,7 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { type = relocs[i].type; } - const ObjFile *file = config->adlt ? nullptr : getFile(); - Symbol &sym = - cast(this->file)->getRelocTargetSym(rels[i]); + Symbol &sym = cast(file)->getRelocTargetSym(rels[i]); auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); @@ -424,27 +426,15 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { // trivial for Elf_Rela, but for Elf_Rel we have to write to the // section data. We do that by adding to the Relocation vector. - // .eh_frame is horribly special and can reference discarded sections. To - // avoid having to parse and recreate .eh_frame, we just replace any + // .eh_frame is horribly special and can reference discarded sections. + // To avoid having to parse and recreate .eh_frame, we just replace any // relocation in it pointing to discarded sections with R_*_NONE, which - // hopefully creates a frame that is ignored at runtime. Also, don't warn - // on .gcc_except_table and debug sections. + // hopefully creates a frame that is ignored at runtime. Also, don't + // warn on .gcc_except_table and debug sections. // - // See the comment in maybeReportUndefined for PPC32 .got2 and PPC64 .toc + // See the comment in maybeReportUndefined for PPC32 .got2 and PPC64 + // .toc auto *d = dyn_cast(&sym); - if (!d && !config->adlt) { - if (!isDebugSection(*sec) && sec->name != ".eh_frame" && - sec->name != ".gcc_except_table" && sec->name != ".got2" && - sec->name != ".toc") { - uint32_t secIdx = cast(sym).discardedSecIdx; - Elf_Shdr_Impl sec = file->template getELFShdrs()[secIdx]; - warn("relocation refers to a discarded section: " + - CHECK(file->getObj().getSectionName(sec), file) + - "\n>>> referenced by " + getObjMsg(p->r_offset)); - } - p->setSymbolAndType(0, 0, false); - continue; - } SectionBase *section = d->section; if (!section->isLive()) { @@ -457,41 +447,14 @@ void InputSection::copyRelocationsAdlt(uint8_t *buf, ArrayRef rels) { if (!RelTy::IsRela) addend = target.getImplicitAddend(bufLoc, type); - if (config->emachine == EM_MIPS && - target.getRelExpr(type, sym, bufLoc) == R_MIPS_GOTREL) { - // Some MIPS relocations depend on "gp" value. By default, - // this value has 0x7ff0 offset from a .got section. But - // relocatable files produced by a compiler or a linker - // might redefine this default value and we must use it - // for a calculation of the relocation result. When we - // generate EXE or DSO it's trivial. Generating a relocatable - // output is more difficult case because the linker does - // not calculate relocations in this mode and loses - // individual "gp" values used by each input object file. - // As a workaround we add the "gp" value to the relocation - // addend and save it back to the file. - if (!config->adlt) - addend += sec->getFile()->mipsGp0; - } - if (RelTy::IsRela) p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr; - else if (config->relocatable && type != target.noneRel) - sec->relocations.push_back( - {R_ABS, type, rels[i].r_offset, addend, &sym}); - } else if (!config->adlt && config->emachine == EM_PPC && - type == R_PPC_PLTREL24 && p->r_addend >= 0x8000 && - sec->file->ppc32Got2) { - // Similar to R_MIPS_GPREL{16,32}. If the addend of R_PPC_PLTREL24 - // indicates that r30 is relative to the input section .got2 - // (r_addend>=0x8000), after linking, r30 should be relative to the output - // section .got2 . To compensate for the shift, adjust r_addend by - // ppc32Got->outSecOff. - if (!config->adlt) - p->r_addend += sec->file->ppc32Got2->outSecOff; } } } +} // namespace adlt +} // namespace elf +} // namespace lld // OHOS_LOCAL end // This is used for -r and --emit-relocs. We can't use memcpy to copy @@ -1225,37 +1188,35 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { break; case R_AARCH64_GOT_PAGE_PC: // OHOS_LOCAL begin - if (!(config->adlt && config->relax)) { - // OHOS_LOCAL end - if (i + 1 < size && aarch64relaxer.tryRelaxAdrpLdr( - rel, relocations[i + 1], secAddr, buf)) { - ++i; + if (config->adlt) { + if (config->relax && relaxAuxAdlt && relaxAuxAdlt->relocChanged[i]) continue; - } target.relocate(bufLoc, rel, targetVA); - // OHOS_LOCAL begin - } else { - if (relaxAuxAdlt && !relaxAuxAdlt->relocChanged[i]) - target.relocate(bufLoc, rel, targetVA); + break; } // OHOS_LOCAL end + if (i + 1 < size && aarch64relaxer.tryRelaxAdrpLdr( + rel, relocations[i + 1], secAddr, buf)) { + ++i; + continue; + } + target.relocate(bufLoc, rel, targetVA); break; case R_AARCH64_PAGE_PC: // OHOS_LOCAL begin - if (!(config->adlt && config->relax)) { - // OHOS_LOCAL end - if (i + 1 < size && aarch64relaxer.tryRelaxAdrpAdd( - rel, relocations[i + 1], secAddr, buf)) { - ++i; + if (config->adlt) { + if (config->relax && relaxAuxAdlt && relaxAuxAdlt->relocChanged[i]) continue; - } target.relocate(bufLoc, rel, targetVA); - // OHOS_LOCAL begin - } else { - if (relaxAuxAdlt && !relaxAuxAdlt->relocChanged[i]) - target.relocate(bufLoc, rel, targetVA); + break; } // OHOS_LOCAL end + if (i + 1 < size && aarch64relaxer.tryRelaxAdrpAdd( + rel, relocations[i + 1], secAddr, buf)) { + ++i; + continue; + } + target.relocate(bufLoc, rel, targetVA); break; case R_PPC64_RELAX_GOT_PC: { // The R_PPC64_PCREL_OPT relocation must appear immediately after @@ -1452,22 +1413,26 @@ template void InputSection::writeTo(uint8_t *buf) { // may be a relocation section. if (LLVM_UNLIKELY(type == SHT_RELA)) { // OHOS_LOCAL begin - if (config->adlt) - copyRelocationsAdlt( - buf, getDataAs()); - else + if (config->adlt) { + adlt::copyRelocations( + buf, getDataAs(), this->file, + getRelocatedSection()); + return; + } // OHOS_LOCAL end - copyRelocations(buf, getDataAs()); + copyRelocations(buf, getDataAs()); return; } if (LLVM_UNLIKELY(type == SHT_REL)) { // OHOS_LOCAL begin - if (config->adlt) - copyRelocationsAdlt( - buf, getDataAs()); - else + if (config->adlt) { + adlt::copyRelocations( + buf, getDataAs(), this->file, + getRelocatedSection()); + return; + } // OHOS_LOCAL end - copyRelocations(buf, getDataAs()); + copyRelocations(buf, getDataAs()); return; } diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index ef25211760d8..f8cdd152ccdc 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -18,11 +18,6 @@ #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Object/ELF.h" -// OHOS_LOCAL begin -#include "Adlt/Context.h" -#include "Adlt/RelaxAux.h" -// OHOS_LOCAL end - namespace lld { namespace elf { @@ -109,6 +104,11 @@ protected: }; struct RISCVRelaxAux; +// OHOS_LOCAL begin +namespace adlt { +struct RelaxAux; +} +// OHOS_LOCAL end // This corresponds to a section of an input file. class InputSectionBase : public SectionBase { @@ -401,11 +401,6 @@ private: template void copyRelocations(uint8_t *buf, llvm::ArrayRef rels); - // OHOS_LOCAL begin - template - void copyRelocationsAdlt(uint8_t *buf, ArrayRef rels); - // OHOS_LOCAL end - template void copyShtGroup(uint8_t *buf); }; diff --git a/lld/test/ADLT/lit.local.cfg.py b/lld/test/ADLT/lit.local.cfg.py deleted file mode 100644 index dc9862da84ee..000000000000 --- a/lld/test/ADLT/lit.local.cfg.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- Python -*- -# This script contains the necessary settings to run ADLT tests. - -import os - -# We need to know the path to the SDK in lit-tests to invoke required clang. -SDK_ROOT = os.getenv("SDK_ROOT", "") - -# We can then use the %SDK_ROOT variable in llvm-lit command descriptions. -config.substitutions.append(("%SDK_ROOT", SDK_ROOT)) diff --git a/lld/test/ADLT/relax-adrp-add.s b/lld/test/ADLT/relax-adrp-add.s index b66132af1f9b..9c60b694406e 100644 --- a/lld/test/ADLT/relax-adrp-add.s +++ b/lld/test/ADLT/relax-adrp-add.s @@ -1,9 +1,8 @@ // REQUIRES: aarch64 -# RUN: rm -f relax_adrp_add.c.o lib_relax_adrp_add.so libadlt_relax_adrp_add.so -# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot --target=aarch64-linux-ohos -fPIC -o relax_adrp_add.c.o -c %s -# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot -fPIC --target=aarch64-linux-ohos -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,lib_relax_adrp_add.so -o lib_relax_adrp_add.so relax_adrp_add.c.o -# RUN: ld.lld --adlt lib_relax_adrp_add.so -o libadlt_relax_adrp_add.so --emit-relocs --relax -# RUN: llvm-objdump -xd libadlt_relax_adrp_add.so | FileCheck %s +# RUN: clang --target=aarch64-linux-ohos -fPIC -o %t.c.o -c %s +# RUN: clang --target=aarch64-linux-ohos -fPIC -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,%t.so -o %t.so %t.c.o +# RUN: ld.lld --adlt %t.so -o %t.adlt.so --emit-relocs --relax +# RUN: llvm-objdump -xd %t.adlt.so | FileCheck %s # CHECK-LABEL: 0000000000001480 <_start>: # CHECK-NEXT: 1480: d503201f nop diff --git a/lld/test/ADLT/relax-adrp-ldr.s b/lld/test/ADLT/relax-adrp-ldr.s index 8a5d01e26e2d..01919dfebf81 100644 --- a/lld/test/ADLT/relax-adrp-ldr.s +++ b/lld/test/ADLT/relax-adrp-ldr.s @@ -1,22 +1,21 @@ // REQUIRES: aarch64 -# RUN: rm -f relax_adrp_ldr.c.o lib_relax_adrp_ldr.so libadlt_relax_adrp_ldr.so -# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot --target=aarch64-linux-ohos -fPIC -o relax_adrp_ldr.c.o -c %s -# RUN: %SDK_ROOT/prebuilts/clang/ohos/linux-x86_64/clang-15.0.4/bin/clang --sysroot=%SDK_ROOT/out/llvm-install/../sysroot -fPIC --target=aarch64-linux-ohos -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,lib_relax_adrp_ldr.so -o lib_relax_adrp_ldr.so relax_adrp_ldr.c.o -# RUN: ld.lld --adlt lib_relax_adrp_ldr.so -o libadlt_relax_adrp_ldr.so --emit-relocs --relax -# RUN: llvm-objdump -xd libadlt_relax_adrp_ldr.so | FileCheck %s +# RUN: clang --target=aarch64-linux-ohos -fPIC -o %t.c.o -c %s +# RUN: clang --target=aarch64-linux-ohos -fPIC -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,%t.so -o %t.so %t.c.o +# RUN: ld.lld --adlt %t.so -o %t.adlt.so --emit-relocs --relax +# RUN: llvm-objdump -xd %t.adlt.so | FileCheck %s # CHECK-LABEL: 0000000000001480 <_start>: # CHECK-NEXT: 1480: d503201f nop # CHECK-NEXT: 0000000000001480: R_AARCH64_NONE *ABS*+0x8 -# CHECK-NEXT: 1484: 10032ea0 adr x0, #26068 +# CHECK-NEXT: 1484: 100330a0 adr x0, #26132 # CHECK-NEXT: 0000000000001484: R_AARCH64_ADR_PREL_LO21 .data__0+0x8 # CHECK-NEXT: 1488: d503201f nop # CHECK-NEXT: 0000000000001488: R_AARCH64_NONE *ABS*+0x10 -# CHECK-NEXT: 148c: 10032ea1 adr x1, #26068 +# CHECK-NEXT: 148c: 100330a1 adr x1, #26132 # CHECK-NEXT: 000000000000148c: R_AARCH64_ADR_PREL_LO21 .data__0+0x10 # CHECK-NEXT: 1490: d503201f nop # CHECK-NEXT: 0000000000001490: R_AARCH64_NONE *ABS*+0x18 -# CHECK-NEXT: 1494: 10032ea2 adr x2, #26068 +# CHECK-NEXT: 1494: 100330a2 adr x2, #26132 # CHECK-NEXT: 0000000000001494: R_AARCH64_ADR_PREL_LO21 .data__0+0x18 # CHECK-EMPTY: -- Gitee From 09c7554c3e49818cbc6c7872ab47ab338fefc693 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Wed, 6 Nov 2024 23:59:05 +0300 Subject: [PATCH 12/23] Remove extra blank line Signed-off-by: streshchukvitaly --- lld/ELF/InputSection.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 2fcd0926af26..a944fe84ebc9 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -361,7 +361,6 @@ InputSectionBase *InputSection::getRelocatedSection() const { // OHOS_LOCAL begin namespace lld { namespace elf { - namespace adlt { // This method is a copy of the copyRelocations method, but modified to // support correct relaxation of relocations when using ADLT. -- Gitee From 53788744076cf9572b2093908f36c8bed8d54a41 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Fri, 8 Nov 2024 00:10:51 +0300 Subject: [PATCH 13/23] Refactoring after review Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 108 ++++++++++++++++++---------------- lld/ELF/Adlt/Arch/AArch64.h | 7 ++- lld/ELF/InputSection.cpp | 16 +++-- lld/ELF/InputSection.h | 10 ---- 4 files changed, 72 insertions(+), 69 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 718bc012f20b..0dc035a22413 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -94,7 +94,7 @@ bool AArch64::isErrata(uint64_t offset) { return (impl->errataOffset && impl->errataOffset == offset) ? true : false; } -void AArch64::finalizeRelax() const { +void AArch64::finalizeRelax() { SmallVector storage; const TargetInfo &baseTarget = *elf::target; @@ -103,10 +103,11 @@ void AArch64::finalizeRelax() const { continue; for (InputSection *sec : getInputSections(*osec, storage)) { - if (!sec->relaxAuxAdlt) + const uint64_t address = sec->inputAddress; + if (relaxAux.find(address) == relaxAux.end()) continue; - RelaxAux &aux = *sec->relaxAuxAdlt; + RelaxAux &aux = *relaxAux[address]; if (!aux.relocDeltas) continue; @@ -169,14 +170,14 @@ void AArch64::finalizeRelax() const { } } -bool AArch64::relaxOnce() const { +bool AArch64::relaxOnce() { SmallVector storage; bool changed = false; for (OutputSection *osec : outputSections) { if (!(osec->flags & SHF_EXECINSTR)) continue; for (InputSection *sec : getInputSections(*osec, storage)) { - if (!sec->relaxAuxAdlt) + if (relaxAux.find(sec->inputAddress) == relaxAux.end()) initRelaxAux(sec); changed |= relax(*sec); } @@ -184,25 +185,32 @@ bool AArch64::relaxOnce() const { return changed; } -void lld::elf::adlt::AArch64::initRelaxAux(InputSection *sec) const { - sec->relaxAuxAdlt = make(); - if (sec->relocations.size()) { - sec->relaxAuxAdlt->relocDeltas = - std::make_unique(sec->relocations.size()); - sec->relaxAuxAdlt->relocTypes = - std::make_unique(sec->relocations.size()); - sec->relaxAuxAdlt->relocChanged = - std::make_unique(sec->relocations.size()); - sec->relaxAuxAdlt->writes = - std::make_unique(sec->relocations.size()); - sec->relaxAuxAdlt->vals = - std::make_unique(sec->relocations.size()); +bool AArch64::isRelocChanged(const uint64_t address, const size_t i) { + if (relaxAux.find(address) == relaxAux.end()) + return false; + + return relaxAux[address]->relocChanged[i]; +} + +void AArch64::initRelaxAux(InputSection *sec) { + const size_t size = sec->relocations.size(); + const uint64_t address = sec->inputAddress; + + relaxAux.insert({address, make()}); + + if (size) { + RelaxAux &aux = *relaxAux[address]; + aux.relocDeltas = std::make_unique(size); + aux.relocTypes = std::make_unique(size); + aux.relocChanged = std::make_unique(size); + aux.writes = std::make_unique(size); + aux.vals = std::make_unique(size); } } bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, Relocation &adrpRel, Relocation &ldrRel, - uint32_t &remove) const { + uint32_t &remove) { // When the definition of sym is not preemptible then we may // be able to relax // ADRP xn, :got: sym @@ -233,10 +241,7 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, uint32_t ldrInstr = read32le(sec.rawData.data() + ldrRel.offset); // Check if the first instruction is ADRP and the second instruction is LDR. - // ADRP: 0x90000000. - // LDR : 0x39000000. - if ((adrpInstr & 0x9f000000) != 0x90000000 || - (ldrInstr & 0x3b000000) != 0x39000000) + if (!(isADRP(adrpInstr) || isLDR(ldrInstr))) return false; // Check the value of the sf bit. @@ -272,18 +277,20 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, if (val != llvm::SignExtend64(val, 33)) return false; - sec.relaxAuxAdlt->relocTypes[i] = R_AARCH64_ADR_PREL_PG_HI21; - sec.relaxAuxAdlt->writes[i] = 0x90000000 | adrpDestReg; // ADRP: 0x90000000. - sec.relaxAuxAdlt->relocChanged[i] = true; - sec.relaxAuxAdlt->vals[i] = SignExtend64( - getAArch64Page(sym.getVA()) - getAArch64Page(secAddr + adrpRel.offset), - 64); + const uint64_t address = sec.inputAddress; + RelaxAux &aux = *relaxAux[address]; - sec.relaxAuxAdlt->relocTypes[i + 1] = R_AARCH64_ADD_ABS_LO12_NC; - sec.relaxAuxAdlt->writes[i + 1] = - 0x91000000 | adrpDestReg | (adrpDestReg << 5); // ADD: 0x91000000. - sec.relaxAuxAdlt->relocChanged[i + 1] = true; - sec.relaxAuxAdlt->vals[i + 1] = SignExtend64(sym.getVA(), 64); + aux.relocTypes[i] = R_AARCH64_ADR_PREL_PG_HI21; + aux.writes[i] = 0x90000000 /*ADRP*/ | adrpDestReg; + aux.relocChanged[i] = true; + aux.vals[i] = SignExtend64(getAArch64Page(sym.getVA()) - + getAArch64Page(secAddr + adrpRel.offset), + 64); + + aux.relocTypes[i + 1] = R_AARCH64_ADD_ABS_LO12_NC; + aux.writes[i + 1] = 0x91000000 /*ADD*/ | adrpDestReg | (adrpDestReg << 5); + aux.relocChanged[i + 1] = true; + aux.vals[i + 1] = SignExtend64(sym.getVA(), 64); Relocation adrpSymRel = {R_AARCH64_PAGE_PC, R_AARCH64_ADR_PREL_PG_HI21, adrpRel.offset, /*addend=*/0, adrpRel.sym}; @@ -298,7 +305,7 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, Relocation &adrpRel, Relocation &addRel, - uint32_t &remove) const { + uint32_t &remove) { // When the address of sym is within the range of ADR then // we may relax // ADRP xn, sym @@ -324,16 +331,16 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, uint32_t adrpInstr = read32le(sec.rawData.data() + adrpRel.offset); uint32_t addInstr = read32le(sec.rawData.data() + addRel.offset); + const uint64_t address = sec.inputAddress; + RelaxAux &aux = *relaxAux[address]; + // Check if the first instruction is ADRP and the second instruction is ADD. - // ADRP: 0x90000000. - // ADD : 0x91000000. - if ((adrpInstr & 0x9f000000) != 0x90000000 || - (addInstr & 0xffc00000) != 0x91000000) { + if (!(isADRP(adrpInstr) || isADD(addInstr))) { // If the types do not match, // but an adrp + ldr relaxation has been performed before, // it is worth considering this case. - if (!(sec.relaxAuxAdlt->relocTypes[i] == R_AARCH64_ADR_PREL_PG_HI21 && - sec.relaxAuxAdlt->relocTypes[i + 1] == R_AARCH64_ADD_ABS_LO12_NC)) + if (!(aux.relocTypes[i] == R_AARCH64_ADR_PREL_PG_HI21 && + aux.relocTypes[i + 1] == R_AARCH64_ADD_ABS_LO12_NC)) return false; } @@ -357,22 +364,21 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, if (val < -1024 * 1024 || val >= 1024 * 1024) return false; - sec.relaxAuxAdlt->relocTypes[i] = R_AARCH64_NONE; - sec.relaxAuxAdlt->writes[i] = 0xd503201f; // nop. - sec.relaxAuxAdlt->relocChanged[i] = true; + aux.relocTypes[i] = R_AARCH64_NONE; + aux.writes[i] = 0xd503201f /*NOP*/; + aux.relocChanged[i] = true; - sec.relaxAuxAdlt->relocTypes[i + 1] = R_AARCH64_ADR_PREL_LO21; - sec.relaxAuxAdlt->writes[i + 1] = - 0x10000000 | adrpDestReg; // ADR: 0x10000000. - sec.relaxAuxAdlt->relocChanged[i + 1] = true; - sec.relaxAuxAdlt->vals[i + 1] = val; + aux.relocTypes[i + 1] = R_AARCH64_ADR_PREL_LO21; + aux.writes[i + 1] = 0x10000000 /*ADR*/ | adrpDestReg; + aux.relocChanged[i + 1] = true; + aux.vals[i + 1] = val; return true; } -bool AArch64::relax(InputSection &sec) const { +bool AArch64::relax(InputSection &sec) { bool changed = false; - auto &aux = *sec.relaxAuxAdlt; + RelaxAux &aux = *relaxAux[sec.inputAddress]; const uint64_t secAddr = sec.getVA(); uint64_t delta = 0; bool safeToRelaxAdrpLdr = false; diff --git a/lld/ELF/Adlt/Arch/AArch64.h b/lld/ELF/Adlt/Arch/AArch64.h index 63e5d8208e72..c0664dff7dd7 100644 --- a/lld/ELF/Adlt/Arch/AArch64.h +++ b/lld/ELF/Adlt/Arch/AArch64.h @@ -23,6 +23,7 @@ class InputSection; class TargetInfo; namespace adlt { +struct RelaxAux; struct AArch64Impl; // hidden implementation @@ -36,9 +37,11 @@ public: void setErrataOffset(uint64_t offset); bool isErrata(uint64_t offset); - void finalizeRelax() const; + void finalizeRelax(); - bool relaxOnce() const; + bool relaxOnce(); + + bool isRelocChanged(const uint64_t address, const size_t i); private: std::unique_ptr impl; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index a944fe84ebc9..0d8bd5200145 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -373,8 +373,8 @@ void copyRelocations(uint8_t *buf, llvm::ArrayRef rels, InputFile *file, for (size_t i = 0; i < rels.size(); ++i) { RelType type = rels[i].getType(config->isMips64EL); - if (i < relocs.size() && sec->relaxAuxAdlt && - sec->relaxAuxAdlt->relocChanged[i]) { + if (i < relocs.size() && + adlt::ctx->adltInfo->isRelocChanged(sec->inputAddress, i)) { type = relocs[i].type; } @@ -1188,7 +1188,8 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { case R_AARCH64_GOT_PAGE_PC: // OHOS_LOCAL begin if (config->adlt) { - if (config->relax && relaxAuxAdlt && relaxAuxAdlt->relocChanged[i]) + if (config->relax && + adlt::ctx->adltInfo->isRelocChanged(inputAddress, i)) continue; target.relocate(bufLoc, rel, targetVA); break; @@ -1204,7 +1205,8 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { case R_AARCH64_PAGE_PC: // OHOS_LOCAL begin if (config->adlt) { - if (config->relax && relaxAuxAdlt && relaxAuxAdlt->relocChanged[i]) + if (config->relax && + adlt::ctx->adltInfo->isRelocChanged(inputAddress, i)) continue; target.relocate(bufLoc, rel, targetVA); break; @@ -1287,8 +1289,10 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { default: // OHOS_LOCAL begin // If the relocation has been changed, then it has been relocated - if (config->adlt && relaxAuxAdlt && relaxAuxAdlt->relocChanged[i]) - break; + if (config->adlt) + if (config->relax && + adlt::ctx->adltInfo->isRelocChanged(inputAddress, i)) + break; // OHOS_LOCAL end target.relocate(bufLoc, rel, targetVA); break; diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index f8cdd152ccdc..74400ada2ff8 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -104,11 +104,6 @@ protected: }; struct RISCVRelaxAux; -// OHOS_LOCAL begin -namespace adlt { -struct RelaxAux; -} -// OHOS_LOCAL end // This corresponds to a section of an input file. class InputSectionBase : public SectionBase { @@ -223,11 +218,6 @@ public: // Auxiliary information for RISC-V linker relaxation. RISC-V does not use // jumpInstrMod. RISCVRelaxAux *relaxAux; - - // OHOS_LOCAL begin - // Auxiliary information for linker relaxation, when using ADLT. - adlt::RelaxAux *relaxAuxAdlt; - // OHOS_LOCAL end }; // A function compiled with -fsplit-stack calling a function -- Gitee From b9797148e3c8c17358305f453d680d61328f752b Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Fri, 8 Nov 2024 00:33:00 +0300 Subject: [PATCH 14/23] Fix after rebase Signed-off-by: streshchukvitaly --- lld/ELF/InputSection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 0d8bd5200145..16172fac0b30 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -378,7 +378,7 @@ void copyRelocations(uint8_t *buf, llvm::ArrayRef rels, InputFile *file, type = relocs[i].type; } - Symbol &sym = cast(file)->getRelocTargetSym(rels[i]); + Symbol &sym = cast(file)->getRelocTargetSym(rels[i]); auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); -- Gitee From 92f0c90ccccb50b139f520d5a785b4f9252bd08b Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Fri, 8 Nov 2024 22:25:25 +0300 Subject: [PATCH 15/23] Review fixes Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 52 ++++++++++++++++++++++++----------- lld/ELF/Adlt/Arch/AArch64.h | 4 +-- lld/ELF/InputSection.cpp | 8 +++--- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 0dc035a22413..4ae285d8be10 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -34,6 +34,19 @@ struct lld::elf::adlt::AArch64Impl { uint64_t errataOffset = 0; }; +namespace { +// ADRP +// | 1 | immlo (2) | 1 | 0 0 0 0 | immhi (19) | Rd (5) | +bool isADRP(uint32_t instr) { return (instr & 0x9f000000) == 0x90000000; } + +// Load/store register (unsigned immediate) +// | size (2) 11 | 1 V 01 | opc (2) | imm12 | Rn (5) | Rt (5) | +bool isLDR(uint32_t instr) { return (instr & 0x3b000000) == 0x39000000; } + +// ADD (immediate), ADD X0, X0, #0x0 +// | 1 | op | S | 1 0 0 0 1 0 | sh(1) | imm12 | Rn (5) | Rd (5) | +bool isADD(uint32_t instr) { return (instr & 0xffc00000) == 0x91000000; } +} // namespace void Impl::deRelocate(uint8_t *loc, const Relocation &rel, uint64_t *val) const { @@ -103,11 +116,11 @@ void AArch64::finalizeRelax() { continue; for (InputSection *sec : getInputSections(*osec, storage)) { - const uint64_t address = sec->inputAddress; - if (relaxAux.find(address) == relaxAux.end()) + const char *secName = sec->name.data(); + if (relaxAux.find(secName) == relaxAux.end()) continue; - RelaxAux &aux = *relaxAux[address]; + RelaxAux &aux = *relaxAux[secName]; if (!aux.relocDeltas) continue; @@ -177,29 +190,30 @@ bool AArch64::relaxOnce() { if (!(osec->flags & SHF_EXECINSTR)) continue; for (InputSection *sec : getInputSections(*osec, storage)) { - if (relaxAux.find(sec->inputAddress) == relaxAux.end()) - initRelaxAux(sec); changed |= relax(*sec); } } return changed; } -bool AArch64::isRelocChanged(const uint64_t address, const size_t i) { - if (relaxAux.find(address) == relaxAux.end()) +bool AArch64::isRelocChanged(const char *secName, const size_t i) { + if (relaxAux.find(secName) == relaxAux.end()) + return false; + + if (!relaxAux[secName]->relocChanged) return false; - return relaxAux[address]->relocChanged[i]; + return relaxAux[secName]->relocChanged[i]; } void AArch64::initRelaxAux(InputSection *sec) { const size_t size = sec->relocations.size(); - const uint64_t address = sec->inputAddress; + const char *secName = sec->name.data(); - relaxAux.insert({address, make()}); + relaxAux.insert({secName, make()}); if (size) { - RelaxAux &aux = *relaxAux[address]; + RelaxAux &aux = *relaxAux[secName]; aux.relocDeltas = std::make_unique(size); aux.relocTypes = std::make_unique(size); aux.relocChanged = std::make_unique(size); @@ -277,8 +291,8 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, if (val != llvm::SignExtend64(val, 33)) return false; - const uint64_t address = sec.inputAddress; - RelaxAux &aux = *relaxAux[address]; + const char *secName = sec.name.data(); + RelaxAux &aux = *relaxAux[secName]; aux.relocTypes[i] = R_AARCH64_ADR_PREL_PG_HI21; aux.writes[i] = 0x90000000 /*ADRP*/ | adrpDestReg; @@ -331,8 +345,8 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, uint32_t adrpInstr = read32le(sec.rawData.data() + adrpRel.offset); uint32_t addInstr = read32le(sec.rawData.data() + addRel.offset); - const uint64_t address = sec.inputAddress; - RelaxAux &aux = *relaxAux[address]; + const char *secName = sec.name.data(); + RelaxAux &aux = *relaxAux[secName]; // Check if the first instruction is ADRP and the second instruction is ADD. if (!(isADRP(adrpInstr) || isADD(addInstr))) { @@ -378,7 +392,13 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, bool AArch64::relax(InputSection &sec) { bool changed = false; - RelaxAux &aux = *relaxAux[sec.inputAddress]; + + const char *secName = sec.name.data(); + + if (relaxAux.find(secName) == relaxAux.end()) + initRelaxAux(&sec); + + RelaxAux &aux = *relaxAux[secName]; const uint64_t secAddr = sec.getVA(); uint64_t delta = 0; bool safeToRelaxAdrpLdr = false; diff --git a/lld/ELF/Adlt/Arch/AArch64.h b/lld/ELF/Adlt/Arch/AArch64.h index c0664dff7dd7..0ab5dd62e573 100644 --- a/lld/ELF/Adlt/Arch/AArch64.h +++ b/lld/ELF/Adlt/Arch/AArch64.h @@ -38,10 +38,8 @@ public: bool isErrata(uint64_t offset); void finalizeRelax(); - bool relaxOnce(); - - bool isRelocChanged(const uint64_t address, const size_t i); + bool isRelocChanged(const char *name, const size_t i); private: std::unique_ptr impl; diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 16172fac0b30..67bc2ffffe57 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -374,7 +374,7 @@ void copyRelocations(uint8_t *buf, llvm::ArrayRef rels, InputFile *file, RelType type = rels[i].getType(config->isMips64EL); if (i < relocs.size() && - adlt::ctx->adltInfo->isRelocChanged(sec->inputAddress, i)) { + adlt::ctx->adltInfo->isRelocChanged(sec->name.data(), i)) { type = relocs[i].type; } @@ -1189,7 +1189,7 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { // OHOS_LOCAL begin if (config->adlt) { if (config->relax && - adlt::ctx->adltInfo->isRelocChanged(inputAddress, i)) + adlt::ctx->adltInfo->isRelocChanged(name.data(), i)) continue; target.relocate(bufLoc, rel, targetVA); break; @@ -1206,7 +1206,7 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { // OHOS_LOCAL begin if (config->adlt) { if (config->relax && - adlt::ctx->adltInfo->isRelocChanged(inputAddress, i)) + adlt::ctx->adltInfo->isRelocChanged(name.data(), i)) continue; target.relocate(bufLoc, rel, targetVA); break; @@ -1291,7 +1291,7 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { // If the relocation has been changed, then it has been relocated if (config->adlt) if (config->relax && - adlt::ctx->adltInfo->isRelocChanged(inputAddress, i)) + adlt::ctx->adltInfo->isRelocChanged(name.data(), i)) break; // OHOS_LOCAL end target.relocate(bufLoc, rel, targetVA); -- Gitee From 90a154b534a019ecdccd3ee0ddbd4a30e2a091a5 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Sat, 9 Nov 2024 00:04:57 +0300 Subject: [PATCH 16/23] Update after rebase Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 106 +++++++++++++++++++--------------- lld/ELF/Adlt/Context.cpp | 5 +- lld/ELF/InputSection.cpp | 22 +++---- 3 files changed, 74 insertions(+), 59 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 4ae285d8be10..34b00d4342dd 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -31,9 +31,21 @@ struct lld::elf::adlt::AArch64Impl { void deRelocate(uint8_t *loc, const Relocation &rel, uint64_t *val) const; void orClear32le(uint8_t *loc) const; void orClearAArch64Imm(uint8_t *loc) const; + void initRelaxAux(InputSection *sec); + void initSymbolAnchors(); + void finalizeRelax(); + bool relaxOnce(); + bool relax(InputSection &sec); + bool relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, + Relocation &adrpRel, Relocation &ldrRel, uint32_t &remove); + bool relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, + Relocation &adrpRel, Relocation &addRel, uint32_t &remove); uint64_t errataOffset = 0; + // Auxiliary information for linker relaxation. + std::unordered_map relaxAux; }; + namespace { // ADRP // | 1 | immlo (2) | 1 | 0 0 0 0 | immhi (19) | Rd (5) | @@ -93,21 +105,23 @@ void Impl::orClearAArch64Imm(uint8_t *loc) const { write32le(loc, read32le(loc) & ~(0xFFF << 10)); } -AArch64::AArch64() : impl(std::make_unique()) {} -AArch64::~AArch64() = default; - -void AArch64::deRelocate(uint8_t *loc, const Relocation &rel, - uint64_t *val) const { - impl->deRelocate(loc, rel, val); -} +void Impl::initRelaxAux(InputSection *sec) { + const size_t size = sec->relocations.size(); + const char *secName = sec->name.data(); -void AArch64::setErrataOffset(uint64_t offset) { impl->errataOffset = offset; } + relaxAux.insert({secName, make()}); -bool AArch64::isErrata(uint64_t offset) { - return (impl->errataOffset && impl->errataOffset == offset) ? true : false; + if (size) { + RelaxAux &aux = *relaxAux[secName]; + aux.relocDeltas = std::make_unique(size); + aux.relocTypes = std::make_unique(size); + aux.relocChanged = std::make_unique(size); + aux.writes = std::make_unique(size); + aux.vals = std::make_unique(size); + } } -void AArch64::finalizeRelax() { +void Impl::finalizeRelax() { SmallVector storage; const TargetInfo &baseTarget = *elf::target; @@ -183,7 +197,7 @@ void AArch64::finalizeRelax() { } } -bool AArch64::relaxOnce() { +bool Impl::relaxOnce() { SmallVector storage; bool changed = false; for (OutputSection *osec : outputSections) { @@ -196,35 +210,9 @@ bool AArch64::relaxOnce() { return changed; } -bool AArch64::isRelocChanged(const char *secName, const size_t i) { - if (relaxAux.find(secName) == relaxAux.end()) - return false; - - if (!relaxAux[secName]->relocChanged) - return false; - - return relaxAux[secName]->relocChanged[i]; -} - -void AArch64::initRelaxAux(InputSection *sec) { - const size_t size = sec->relocations.size(); - const char *secName = sec->name.data(); - - relaxAux.insert({secName, make()}); - - if (size) { - RelaxAux &aux = *relaxAux[secName]; - aux.relocDeltas = std::make_unique(size); - aux.relocTypes = std::make_unique(size); - aux.relocChanged = std::make_unique(size); - aux.writes = std::make_unique(size); - aux.vals = std::make_unique(size); - } -} - -bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, - Relocation &adrpRel, Relocation &ldrRel, - uint32_t &remove) { +bool Impl::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, + Relocation &adrpRel, Relocation &ldrRel, + uint32_t &remove) { // When the definition of sym is not preemptible then we may // be able to relax // ADRP xn, :got: sym @@ -317,9 +305,9 @@ bool AArch64::relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, return true; } -bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, - Relocation &adrpRel, Relocation &addRel, - uint32_t &remove) { +bool Impl::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, + Relocation &adrpRel, Relocation &addRel, + uint32_t &remove) { // When the address of sym is within the range of ADR then // we may relax // ADRP xn, sym @@ -390,7 +378,7 @@ bool AArch64::relaxAdrpAdd(const InputSection &sec, size_t i, uint64_t loc, return true; } -bool AArch64::relax(InputSection &sec) { +bool Impl::relax(InputSection &sec) { bool changed = false; const char *secName = sec.name.data(); @@ -469,4 +457,32 @@ bool AArch64::relax(InputSection &sec) { sec.bytesDropped = delta; return changed; } + +AArch64::AArch64() : impl(std::make_unique()) {} +AArch64::~AArch64() = default; + +void AArch64::deRelocate(uint8_t *loc, const Relocation &rel, + uint64_t *val) const { + impl->deRelocate(loc, rel, val); +} + +void AArch64::setErrataOffset(uint64_t offset) { impl->errataOffset = offset; } + +bool AArch64::isErrata(uint64_t offset) { + return (impl->errataOffset && impl->errataOffset == offset) ? true : false; +} + +void AArch64::finalizeRelax() { impl->finalizeRelax(); } + +bool AArch64::relaxOnce() { return impl->relaxOnce(); } + +bool AArch64::isRelocChanged(const char *secName, const size_t i) { + if (impl->relaxAux.find(secName) == impl->relaxAux.end()) + return false; + + if (!impl->relaxAux[secName]->relocChanged) + return false; + + return impl->relaxAux[secName]->relocChanged[i]; +} // OHOS_LOCAL end diff --git a/lld/ELF/Adlt/Context.cpp b/lld/ELF/Adlt/Context.cpp index d36bad1088f9..21f9a283fc99 100644 --- a/lld/ELF/Adlt/Context.cpp +++ b/lld/ELF/Adlt/Context.cpp @@ -365,7 +365,10 @@ void Impl::copyRequiredLocalSymbols() { } } -Context::Context() : impl(std::make_unique()) {} +Context::Context() + : adltInfo(std::make_unique()), + impl(std::make_unique()) {} + Context::~Context() = default; llvm::SmallVector Context::getSharedFiles() { diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 67bc2ffffe57..3293b5cb2531 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -383,11 +383,6 @@ void copyRelocations(uint8_t *buf, llvm::ArrayRef rels, InputFile *file, auto *p = reinterpret_cast(buf); buf += sizeof(RelTy); - /*if (config->adlt) { - if (rel.r_offset == 0x111747c) // debug hint - asm("nop"); - }*/ - if (RelTy::IsRela) p->r_addend = getAddend(rels[i]); @@ -398,16 +393,17 @@ void copyRelocations(uint8_t *buf, llvm::ArrayRef rels, InputFile *file, size_t symbolIndex = in.symTab->getSymbolIndex(&sym); // Convert an absolute offsets to relative ones - if (sec->type == SHT_PROGBITS) - assert(sec->inputAddress && - "ADLT: copyRelocs: sec->inputAddress can't be zero!"); p->r_offset -= sec->inputAddress; - assert((int32_t)p->r_offset >= 0 && - "ADLT: copyRelocs: offset can't be negative!"); + bool isDebugSec = + (sec->flags & SHF_ALLOC) == 0 && sec->name.startswith(".debug_"); + if (sec->type == SHT_PROGBITS && !sec->inputAddress && !isDebugSec) + fatal("ADLT: copyRelocs: sec->inputAddress can't be zero!"); + if ((int32_t)p->r_offset < 0) + fatal("ADLT: copyRelocs: offset can't be negative!"); if (!(sym.exportDynamic || sym.dynsymIndex)) { // ignore .dynsym symbols - if (p->r_addend) - assert(symbolIndex && "ADLT: copyRelocs: wrong symbol index!" - "Is it not in the final symtab?"); + if (p->r_addend && !symbolIndex) + fatal("ADLT: copyRelocs: wrong symbol index!" + "Is it not in the final symtab?"); } if (type == R_AARCH64_NONE) { -- Gitee From cc763e09a692f857a61848de449c38e2aa393ed8 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Mon, 11 Nov 2024 13:38:41 +0300 Subject: [PATCH 17/23] Refactoring Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 22 ++++++++++------------ lld/ELF/Adlt/Arch/AArch64.h | 3 --- lld/ELF/Adlt/RelaxAux.h | 2 -- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 34b00d4342dd..0144b2298e87 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -34,6 +34,7 @@ struct lld::elf::adlt::AArch64Impl { void initRelaxAux(InputSection *sec); void initSymbolAnchors(); void finalizeRelax(); + bool relaxOnce(); bool relax(InputSection &sec); bool relaxAdrpLdr(const InputSection &sec, size_t i, uint64_t loc, @@ -389,29 +390,26 @@ bool Impl::relax(InputSection &sec) { RelaxAux &aux = *relaxAux[secName]; const uint64_t secAddr = sec.getVA(); uint64_t delta = 0; - bool safeToRelaxAdrpLdr = false; auto &relocs = sec.relocations; const size_t relocs_size = sec.relocations.size(); // Check if R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC // always appear in pairs. - size_t j = 0; - for (; j != relocs_size; ++j) { - if (relocs[j].type == R_AARCH64_ADR_GOT_PAGE) { - if (j + 1 < relocs_size && - relocs[j + 1].type == R_AARCH64_LD64_GOT_LO12_NC) { - ++j; + bool safeToRelaxAdrpLdr = true; + for (size_t i = 0; i != relocs_size; ++i) { + if (relocs[i].type == R_AARCH64_ADR_GOT_PAGE) { + if (i + 1 < relocs_size && + relocs[i + 1].type == R_AARCH64_LD64_GOT_LO12_NC) { + ++i; continue; } - break; - } else if (relocs[j].type == R_AARCH64_LD64_GOT_LO12_NC) { - break; + safeToRelaxAdrpLdr = false; + } else if (relocs[i].type == R_AARCH64_LD64_GOT_LO12_NC) { + safeToRelaxAdrpLdr = false; } } - safeToRelaxAdrpLdr = j == relocs_size; - // Set aux data to default values. for (size_t i = 0; i < relocs_size; ++i) { aux.relocTypes[i] = R_AARCH64_NONE; diff --git a/lld/ELF/Adlt/Arch/AArch64.h b/lld/ELF/Adlt/Arch/AArch64.h index 0ab5dd62e573..e9776eeb7c49 100644 --- a/lld/ELF/Adlt/Arch/AArch64.h +++ b/lld/ELF/Adlt/Arch/AArch64.h @@ -10,9 +10,6 @@ #ifndef LLD_ELF_ADLT_ARCH_AARCH64_H #define LLD_ELF_ADLT_ARCH_AARCH64_H -#include "llvm/ADT/ArrayRef.h" -#include -#include #include namespace lld { diff --git a/lld/ELF/Adlt/RelaxAux.h b/lld/ELF/Adlt/RelaxAux.h index bf895831851d..d28297a5b636 100644 --- a/lld/ELF/Adlt/RelaxAux.h +++ b/lld/ELF/Adlt/RelaxAux.h @@ -11,8 +11,6 @@ #ifndef LLD_ELF_ADLT_RELAX_AUX_H #define LLD_ELF_ADLT_RELAX_AUX_H -#include "Relocations.h" -#include "Symbols.h" #include namespace lld { -- Gitee From 814ca26e3cc9b784eab308e4de5ab3bd342e10dc Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Mon, 11 Nov 2024 13:40:45 +0300 Subject: [PATCH 18/23] Fix processing safeToRelaxAdrpLdr Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index 0144b2298e87..dccca5091f2a 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -405,8 +405,10 @@ bool Impl::relax(InputSection &sec) { continue; } safeToRelaxAdrpLdr = false; + break; } else if (relocs[i].type == R_AARCH64_LD64_GOT_LO12_NC) { safeToRelaxAdrpLdr = false; + break; } } -- Gitee From 02c2e367934dae494561d8559f4727e14169ecad Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Mon, 11 Nov 2024 22:47:18 +0300 Subject: [PATCH 19/23] Update loop processing for safeToRelaxAdrpLdr Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.cpp b/lld/ELF/Adlt/Arch/AArch64.cpp index dccca5091f2a..9a3310eac28f 100644 --- a/lld/ELF/Adlt/Arch/AArch64.cpp +++ b/lld/ELF/Adlt/Arch/AArch64.cpp @@ -398,18 +398,22 @@ bool Impl::relax(InputSection &sec) { // always appear in pairs. bool safeToRelaxAdrpLdr = true; for (size_t i = 0; i != relocs_size; ++i) { - if (relocs[i].type == R_AARCH64_ADR_GOT_PAGE) { + switch (relocs[i].type) { + case R_AARCH64_ADR_GOT_PAGE: { if (i + 1 < relocs_size && relocs[i + 1].type == R_AARCH64_LD64_GOT_LO12_NC) { ++i; continue; } - safeToRelaxAdrpLdr = false; break; - } else if (relocs[i].type == R_AARCH64_LD64_GOT_LO12_NC) { - safeToRelaxAdrpLdr = false; + } + case R_AARCH64_LD64_GOT_LO12_NC: break; + default: + continue; } + safeToRelaxAdrpLdr = false; + break; } // Set aux data to default values. -- Gitee From fd456128b8b9114d01a3ef7d7fb0fed1e0af6344 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Tue, 12 Nov 2024 17:32:43 +0300 Subject: [PATCH 20/23] Fix running lit-tests Signed-off-by: streshchukvitaly --- lld/test/ADLT/lit.local.cfg.py | 10 ++++++++++ lld/test/ADLT/relax-adrp-add.s | 4 ++-- lld/test/ADLT/relax-adrp-ldr.s | 4 ++-- lld/test/lit.site.cfg.py.in | 4 ++++ 4 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 lld/test/ADLT/lit.local.cfg.py diff --git a/lld/test/ADLT/lit.local.cfg.py b/lld/test/ADLT/lit.local.cfg.py new file mode 100644 index 000000000000..bb73042fed3c --- /dev/null +++ b/lld/test/ADLT/lit.local.cfg.py @@ -0,0 +1,10 @@ +# -*- Python -*- +# This script contains the necessary settings to run ADLT tests. + +import os + +ohos_llvm_install = config.llvm_install +ohos_sysroot_path = os.path.join(ohos_llvm_install, "../sysroot") + +config.substitutions.append(("%OHOS_SYSROOT", ohos_sysroot_path)) +config.substitutions.append(("%OHOS_LLVM_INSTALL", ohos_llvm_install)) diff --git a/lld/test/ADLT/relax-adrp-add.s b/lld/test/ADLT/relax-adrp-add.s index 9c60b694406e..0b355c1ba61b 100644 --- a/lld/test/ADLT/relax-adrp-add.s +++ b/lld/test/ADLT/relax-adrp-add.s @@ -1,6 +1,6 @@ // REQUIRES: aarch64 -# RUN: clang --target=aarch64-linux-ohos -fPIC -o %t.c.o -c %s -# RUN: clang --target=aarch64-linux-ohos -fPIC -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,%t.so -o %t.so %t.c.o +# RUN: %OHOS_LLVM_INSTALL/bin/clang --sysroot=%OHOS_SYSROOT --target=aarch64-linux-ohos -fPIC -o %t.c.o -c %s +# RUN: %OHOS_LLVM_INSTALL/bin/clang --sysroot=%OHOS_SYSROOT --target=aarch64-linux-ohos -fPIC -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,%t.so -o %t.so %t.c.o # RUN: ld.lld --adlt %t.so -o %t.adlt.so --emit-relocs --relax # RUN: llvm-objdump -xd %t.adlt.so | FileCheck %s diff --git a/lld/test/ADLT/relax-adrp-ldr.s b/lld/test/ADLT/relax-adrp-ldr.s index 01919dfebf81..29b39b0f0a7a 100644 --- a/lld/test/ADLT/relax-adrp-ldr.s +++ b/lld/test/ADLT/relax-adrp-ldr.s @@ -1,6 +1,6 @@ // REQUIRES: aarch64 -# RUN: clang --target=aarch64-linux-ohos -fPIC -o %t.c.o -c %s -# RUN: clang --target=aarch64-linux-ohos -fPIC -Wl,--emit-relocs,--no-relax -shared -Wl,-soname,%t.so -o %t.so %t.c.o +# RUN: %OHOS_LLVM_INSTALL/bin/clang --sysroot=%OHOS_SYSROOT --target=aarch64-linux-ohos -fPIC -o %t.c.o -c %s +# RUN: %OHOS_LLVM_INSTALL/bin/clang --sysroot=%OHOS_SYSROOT --target=aarch64-linux-ohos -fPIC -Wl,--sysroot=%OHOS_SYSROOT,--emit-relocs,--no-relax -shared -Wl,-soname,%t.so -o %t.so %t.c.o # RUN: ld.lld --adlt %t.so -o %t.adlt.so --emit-relocs --relax # RUN: llvm-objdump -xd %t.adlt.so | FileCheck %s diff --git a/lld/test/lit.site.cfg.py.in b/lld/test/lit.site.cfg.py.in index 0523762cf6c9..613bca2c69f9 100644 --- a/lld/test/lit.site.cfg.py.in +++ b/lld/test/lit.site.cfg.py.in @@ -26,6 +26,10 @@ config.build_examples = @LLVM_BUILD_EXAMPLES@ config.has_plugins = @LLVM_ENABLE_PLUGINS@ config.linked_bye_extension = @LLVM_BYE_LINK_INTO_TOOLS@ +# OHOS_LOCAL begin +config.llvm_install = "@CMAKE_INSTALL_PREFIX@" +# OHOS_LOCAL end + import lit.llvm lit.llvm.initialize(lit_config, config) -- Gitee From afde4d8380011422eea53d0ac9e69b77854ae2d7 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Tue, 12 Nov 2024 22:24:35 +0300 Subject: [PATCH 21/23] Update relax-adrp-ldr test Signed-off-by: streshchukvitaly --- lld/test/ADLT/relax-adrp-ldr.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lld/test/ADLT/relax-adrp-ldr.s b/lld/test/ADLT/relax-adrp-ldr.s index 29b39b0f0a7a..3e4541e62328 100644 --- a/lld/test/ADLT/relax-adrp-ldr.s +++ b/lld/test/ADLT/relax-adrp-ldr.s @@ -7,15 +7,15 @@ # CHECK-LABEL: 0000000000001480 <_start>: # CHECK-NEXT: 1480: d503201f nop # CHECK-NEXT: 0000000000001480: R_AARCH64_NONE *ABS*+0x8 -# CHECK-NEXT: 1484: 100330a0 adr x0, #26132 +# CHECK-NEXT: 1484: 100330a0 adr x0, #{{.*}} # CHECK-NEXT: 0000000000001484: R_AARCH64_ADR_PREL_LO21 .data__0+0x8 # CHECK-NEXT: 1488: d503201f nop # CHECK-NEXT: 0000000000001488: R_AARCH64_NONE *ABS*+0x10 -# CHECK-NEXT: 148c: 100330a1 adr x1, #26132 +# CHECK-NEXT: 148c: 100330a1 adr x1, #{{.*}} # CHECK-NEXT: 000000000000148c: R_AARCH64_ADR_PREL_LO21 .data__0+0x10 # CHECK-NEXT: 1490: d503201f nop # CHECK-NEXT: 0000000000001490: R_AARCH64_NONE *ABS*+0x18 -# CHECK-NEXT: 1494: 100330a2 adr x2, #26132 +# CHECK-NEXT: 1494: 100330a2 adr x2, #{{.*}} # CHECK-NEXT: 0000000000001494: R_AARCH64_ADR_PREL_LO21 .data__0+0x18 # CHECK-EMPTY: -- Gitee From 5180264ee0599c756aa1f3aa1150724c5935edfd Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Tue, 12 Nov 2024 23:42:08 +0300 Subject: [PATCH 22/23] Refactoring Signed-off-by: streshchukvitaly --- lld/test/ADLT/relax-adrp-ldr.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lld/test/ADLT/relax-adrp-ldr.s b/lld/test/ADLT/relax-adrp-ldr.s index 3e4541e62328..26afce83b368 100644 --- a/lld/test/ADLT/relax-adrp-ldr.s +++ b/lld/test/ADLT/relax-adrp-ldr.s @@ -7,15 +7,15 @@ # CHECK-LABEL: 0000000000001480 <_start>: # CHECK-NEXT: 1480: d503201f nop # CHECK-NEXT: 0000000000001480: R_AARCH64_NONE *ABS*+0x8 -# CHECK-NEXT: 1484: 100330a0 adr x0, #{{.*}} +# CHECK-NEXT: 1484: 100{{.*}} adr x0, #{{.*}} # CHECK-NEXT: 0000000000001484: R_AARCH64_ADR_PREL_LO21 .data__0+0x8 # CHECK-NEXT: 1488: d503201f nop # CHECK-NEXT: 0000000000001488: R_AARCH64_NONE *ABS*+0x10 -# CHECK-NEXT: 148c: 100330a1 adr x1, #{{.*}} +# CHECK-NEXT: 148c: 100{{.*}} adr x1, #{{.*}} # CHECK-NEXT: 000000000000148c: R_AARCH64_ADR_PREL_LO21 .data__0+0x10 # CHECK-NEXT: 1490: d503201f nop # CHECK-NEXT: 0000000000001490: R_AARCH64_NONE *ABS*+0x18 -# CHECK-NEXT: 1494: 100330a2 adr x2, #{{.*}} +# CHECK-NEXT: 1494: 100{{.*}} adr x2, #{{.*}} # CHECK-NEXT: 0000000000001494: R_AARCH64_ADR_PREL_LO21 .data__0+0x18 # CHECK-EMPTY: -- Gitee From 6d582d8f5f5f070f09dbb3c568ce2c23fad1ad42 Mon Sep 17 00:00:00 2001 From: streshchukvitaly Date: Wed, 13 Nov 2024 21:29:09 +0300 Subject: [PATCH 23/23] Refactoring Signed-off-by: streshchukvitaly --- lld/ELF/Adlt/Arch/AArch64.h | 3 --- lld/ELF/InputSection.cpp | 10 ++++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lld/ELF/Adlt/Arch/AArch64.h b/lld/ELF/Adlt/Arch/AArch64.h index e9776eeb7c49..909484309993 100644 --- a/lld/ELF/Adlt/Arch/AArch64.h +++ b/lld/ELF/Adlt/Arch/AArch64.h @@ -16,11 +16,8 @@ namespace lld { namespace elf { struct Relocation; -class InputSection; -class TargetInfo; namespace adlt { -struct RelaxAux; struct AArch64Impl; // hidden implementation diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 3293b5cb2531..32bddc76cc0f 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -1184,8 +1184,9 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { case R_AARCH64_GOT_PAGE_PC: // OHOS_LOCAL begin if (config->adlt) { - if (config->relax && - adlt::ctx->adltInfo->isRelocChanged(name.data(), i)) + bool isRelocChanged = + adlt::ctx->adltInfo->isRelocChanged(name.data(), i); + if (config->relax && isRelocChanged) continue; target.relocate(bufLoc, rel, targetVA); break; @@ -1201,8 +1202,9 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { case R_AARCH64_PAGE_PC: // OHOS_LOCAL begin if (config->adlt) { - if (config->relax && - adlt::ctx->adltInfo->isRelocChanged(name.data(), i)) + bool isRelocChanged = + adlt::ctx->adltInfo->isRelocChanged(name.data(), i); + if (config->relax && isRelocChanged) continue; target.relocate(bufLoc, rel, targetVA); break; -- Gitee