diff options
Diffstat (limited to 'lld/ELF')
| -rw-r--r-- | lld/ELF/Arch/Hexagon.cpp | 119 | ||||
| -rw-r--r-- | lld/ELF/Arch/X86_64.cpp | 1 | ||||
| -rw-r--r-- | lld/ELF/BPSectionOrderer.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/Config.h | 1 | ||||
| -rw-r--r-- | lld/ELF/Driver.cpp | 4 | ||||
| -rw-r--r-- | lld/ELF/Relocations.cpp | 5 | ||||
| -rw-r--r-- | lld/ELF/Target.h | 1 |
7 files changed, 132 insertions, 5 deletions
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index 726e425b36dc..479131a24dcf 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -7,11 +7,18 @@ //===----------------------------------------------------------------------===// #include "InputFiles.h" +#include "OutputSections.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" +#include "lld/Common/ErrorHandler.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/Support/ELFAttributes.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/HexagonAttributeParser.h" +#include "llvm/Support/HexagonAttributes.h" +#include "llvm/Support/LEB128.h" using namespace llvm; using namespace llvm::object; @@ -415,4 +422,116 @@ int64_t Hexagon::getImplicitAddend(const uint8_t *buf, RelType type) const { } } +namespace { +class HexagonAttributesSection final : public SyntheticSection { +public: + HexagonAttributesSection(Ctx &ctx) + : SyntheticSection(ctx, ".hexagon.attributes", SHT_HEXAGON_ATTRIBUTES, 0, + 1) {} + + size_t getSize() const override { return size; } + void writeTo(uint8_t *buf) override; + + static constexpr StringRef vendor = "hexagon"; + DenseMap<unsigned, unsigned> intAttr; + size_t size = 0; +}; +} // namespace + +static HexagonAttributesSection * +mergeAttributesSection(Ctx &ctx, + const SmallVector<InputSectionBase *, 0> §ions) { + ctx.in.hexagonAttributes = std::make_unique<HexagonAttributesSection>(ctx); + auto &merged = + static_cast<HexagonAttributesSection &>(*ctx.in.hexagonAttributes); + + // Collect all tags values from attributes section. + const auto &attributesTags = HexagonAttrs::getHexagonAttributeTags(); + for (const InputSectionBase *sec : sections) { + HexagonAttributeParser parser; + if (Error e = parser.parse(sec->content(), llvm::endianness::little)) + Warn(ctx) << sec << ": " << std::move(e); + for (const auto &tag : attributesTags) { + switch (HexagonAttrs::AttrType(tag.attr)) { + case HexagonAttrs::ARCH: + case HexagonAttrs::HVXARCH: + if (auto i = parser.getAttributeValue(tag.attr)) { + auto r = merged.intAttr.try_emplace(tag.attr, *i); + if (!r.second) + if (r.first->second < *i) + r.first->second = *i; + } + continue; + + case HexagonAttrs::HVXIEEEFP: + case HexagonAttrs::HVXQFLOAT: + case HexagonAttrs::ZREG: + case HexagonAttrs::AUDIO: + case HexagonAttrs::CABAC: + if (auto i = parser.getAttributeValue(tag.attr)) { + auto r = merged.intAttr.try_emplace(tag.attr, *i); + if (!r.second && r.first->second != *i) { + r.first->second |= *i; + } + } + continue; + } + } + } + + // The total size of headers: format-version [ <section-length> "vendor-name" + // [ <file-tag> <size>. + size_t size = 5 + merged.vendor.size() + 1 + 5; + for (auto &attr : merged.intAttr) + if (attr.second != 0) + size += getULEB128Size(attr.first) + getULEB128Size(attr.second); + merged.size = size; + return &merged; +} + +void HexagonAttributesSection::writeTo(uint8_t *buf) { + const size_t size = getSize(); + uint8_t *const end = buf + size; + *buf = ELFAttrs::Format_Version; + write32(ctx, buf + 1, size - 1); + buf += 5; + + memcpy(buf, vendor.data(), vendor.size()); + buf += vendor.size() + 1; + + *buf = ELFAttrs::File; + write32(ctx, buf + 1, end - buf); + buf += 5; + + for (auto &attr : intAttr) { + if (attr.second == 0) + continue; + buf += encodeULEB128(attr.first, buf); + buf += encodeULEB128(attr.second, buf); + } +} + +void elf::mergeHexagonAttributesSections(Ctx &ctx) { + // Find the first input SHT_HEXAGON_ATTRIBUTES; return if not found. + size_t place = + llvm::find_if(ctx.inputSections, + [](auto *s) { return s->type == SHT_HEXAGON_ATTRIBUTES; }) - + ctx.inputSections.begin(); + if (place == ctx.inputSections.size()) + return; + + // Extract all SHT_HEXAGON_ATTRIBUTES sections into `sections`. + SmallVector<InputSectionBase *, 0> sections; + llvm::erase_if(ctx.inputSections, [&](InputSectionBase *s) { + if (s->type != SHT_HEXAGON_ATTRIBUTES) + return false; + sections.push_back(s); + return true; + }); + + // Add the merged section. + ctx.inputSections.insert(ctx.inputSections.begin() + place, + mergeAttributesSection(ctx, sections)); +} + void elf::setHexagonTargetInfo(Ctx &ctx) { ctx.target.reset(new Hexagon(ctx)); } diff --git a/lld/ELF/Arch/X86_64.cpp b/lld/ELF/Arch/X86_64.cpp index 551123fd832d..4df776c92e98 100644 --- a/lld/ELF/Arch/X86_64.cpp +++ b/lld/ELF/Arch/X86_64.cpp @@ -447,6 +447,7 @@ void X86_64::relaxCFIJumpTables() const { // jump table where it is and keep the last entry. if (lastSec) { addSectionSlice(begin, cur, rbegin, rcur); + lastSec->retainAlignment = true; replacements.push_back(lastSec); sectionReplacements[sec] = {}; sectionReplacements[lastSec] = replacements; diff --git a/lld/ELF/BPSectionOrderer.cpp b/lld/ELF/BPSectionOrderer.cpp index f464b1d4518a..06152046d13d 100644 --- a/lld/ELF/BPSectionOrderer.cpp +++ b/lld/ELF/BPSectionOrderer.cpp @@ -76,10 +76,10 @@ DenseMap<const InputSectionBase *, int> elf::runBalancedPartitioning( if (!d) return; auto *sec = dyn_cast_or_null<InputSection>(d->section); - // Skip empty, discarded, ICF folded sections. Skipping ICF folded sections - // reduces duplicate detection work in BPSectionOrderer. + // Skip empty, discarded, ICF folded sections, .bss. Skipping ICF folded + // sections reduces duplicate detection work in BPSectionOrderer. if (!sec || sec->size == 0 || !sec->isLive() || sec->repl != sec || - !orderer.secToSym.try_emplace(sec, d).second) + !sec->content().data() || !orderer.secToSym.try_emplace(sec, d).second) return; rootSymbolToSectionIdxs[CachedHashStringRef( lld::utils::getRootSymbol(sym.getName()))] diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 2ccbadc4b2ca..26b75d7d7beb 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -569,6 +569,7 @@ struct UndefinedDiag { // a partition. struct InStruct { std::unique_ptr<InputSection> attributes; + std::unique_ptr<SyntheticSection> hexagonAttributes; std::unique_ptr<SyntheticSection> riscvAttributes; std::unique_ptr<BssSection> bss; std::unique_ptr<BssSection> bssRelRo; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index e88e5bf9162d..105b5d5a8460 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -3449,6 +3449,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) { if (!ctx.arg.relocatable) combineEhSections(ctx); + // Merge .hexagon.attributes sections. + if (ctx.arg.emachine == EM_HEXAGON) + mergeHexagonAttributesSections(ctx); + // Merge .riscv.attributes sections. if (ctx.arg.emachine == EM_RISCV) mergeRISCVAttributesSections(ctx); diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 87db32110e97..457137540ecc 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -1671,8 +1671,9 @@ void RelocationScanner::scan(Relocs<RelTy> rels) { } // Sort relocations by offset for more efficient searching for - // R_RISCV_PCREL_HI20, R_PPC64_ADDR64 and the branch-to-branch optimization. - if (ctx.arg.emachine == EM_RISCV || + // R_RISCV_PCREL_HI20, ALIGN relocations, R_PPC64_ADDR64 and the + // branch-to-branch optimization. + if (is_contained({EM_RISCV, EM_LOONGARCH}, ctx.arg.emachine) || (ctx.arg.emachine == EM_PPC64 && sec->name == ".toc") || ctx.arg.branchToBranch || sec->type == SHT_LLVM_CFI_JUMP_TABLE) llvm::stable_sort(sec->relocs(), diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index b8326f72e847..42ad5e9b1cf7 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -247,6 +247,7 @@ template <typename ELFT> void writeARMCmseImportLib(Ctx &); uint64_t getLoongArchPageDelta(uint64_t dest, uint64_t pc, RelType type); void riscvFinalizeRelax(int passes); void mergeRISCVAttributesSections(Ctx &); +void mergeHexagonAttributesSections(Ctx &); void addArmInputSectionMappingSymbols(Ctx &); void addArmSyntheticSectionMappingSymbol(Defined *); void sortArmMappingSymbols(Ctx &); |
