summaryrefslogtreecommitdiff
path: root/lld/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/Arch/Hexagon.cpp119
-rw-r--r--lld/ELF/Arch/X86_64.cpp1
-rw-r--r--lld/ELF/BPSectionOrderer.cpp6
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp4
-rw-r--r--lld/ELF/Relocations.cpp5
-rw-r--r--lld/ELF/Target.h1
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> &sections) {
+ 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 &);