[lld] [LLD] Merge .hexagon.attributes sections (PR #148098)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 10 18:51:35 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf

@llvm/pr-subscribers-lld

Author: Brian Cain (androm3da)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/148098.diff


5 Files Affected:

- (modified) lld/ELF/Arch/Hexagon.cpp (+121) 
- (modified) lld/ELF/Config.h (+1) 
- (modified) lld/ELF/Driver.cpp (+4) 
- (modified) lld/ELF/Target.h (+1) 
- (added) lld/test/ELF/hexagon-attributes.s (+150) 


``````````diff
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp
index 726e425b36dc6..c449efa51c715 100644
--- a/lld/ELF/Arch/Hexagon.cpp
+++ b/lld/ELF/Arch/Hexagon.cpp
@@ -7,11 +7,19 @@
 //===----------------------------------------------------------------------===//
 
 #include "InputFiles.h"
+#include "OutputSections.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
+#include "Thunks.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 +423,117 @@ 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 && r.first->second != *i) {
+            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/Config.h b/lld/ELF/Config.h
index 4c771e47a0e72..8961c5141200e 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -569,6 +569,7 @@ struct UndefinedDiag {
 struct InStruct {
   std::unique_ptr<InputSection> attributes;
   std::unique_ptr<SyntheticSection> riscvAttributes;
+  std::unique_ptr<SyntheticSection> hexagonAttributes;
   std::unique_ptr<BssSection> bss;
   std::unique_ptr<BssSection> bssRelRo;
   std::unique_ptr<SyntheticSection> gnuProperty;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index a194ae71d559a..a18cc4d4e4dd0 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -3450,6 +3450,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
   if (ctx.arg.emachine == EM_RISCV)
     mergeRISCVAttributesSections(ctx);
 
+  // Merge .hexagon.attributes sections.
+  if (ctx.arg.emachine == EM_HEXAGON)
+    mergeHexagonAttributesSections(ctx);
+
   {
     llvm::TimeTraceScope timeScope("Assign sections");
 
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 6dd20b2f0cbaa..93f15920bfedb 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -245,6 +245,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 &);
diff --git a/lld/test/ELF/hexagon-attributes.s b/lld/test/ELF/hexagon-attributes.s
new file mode 100644
index 0000000000000..ff22e3a750e0d
--- /dev/null
+++ b/lld/test/ELF/hexagon-attributes.s
@@ -0,0 +1,150 @@
+# REQUIRES: hexagon
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf a.s -o a.o
+# RUN: ld.lld -e 0 a.o -o out 2>&1 | count 0
+# RUN: llvm-readelf -S -l --arch-specific out | FileCheck %s --check-prefixes=HDR,CHECK
+# RUN: ld.lld -e 0 a.o a.o -o out1 2>&1 | count 0
+# RUN: llvm-readobj --arch-specific out1 | FileCheck %s
+# RUN: ld.lld -r a.o a.o -o out1 2>&1 | count 0
+# RUN: llvm-readobj --arch-specific out1 | FileCheck %s
+
+# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf b.s -o b.o
+# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf c.s -o c.o
+# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf d.s -o d.o
+# RUN: ld.lld a.o b.o c.o -o out2
+# RUN: llvm-readobj --arch-specific out2 | FileCheck %s --check-prefix=CHECK2
+# RUN: ld.lld a.o b.o c.o d.o -o out3
+# RUN: llvm-readobj --arch-specific out3 | FileCheck %s --check-prefix=CHECK3
+
+# HDR:      Name              Type             Address          Off    Size   ES Flg Lk Inf Al
+# HDR:      .hexagon.attributes HEXAGON_ATTRIBUTES 00000000 {{.*}} {{.*}} 00      0   0  1{{$}}
+
+# HDR:      Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+# HDR:      LOAD           {{.*}}
+# HDR-NEXT: GNU_STACK      {{.*}}
+
+# CHECK:      BuildAttributes {
+# CHECK-NEXT:   FormatVersion: 0x41
+# CHECK-NEXT:   Section 1 {
+# CHECK-NEXT:     SectionLength: 19
+# CHECK-NEXT:     Vendor: hexagon
+# CHECK-NEXT:     Tag: Tag_File (0x1)
+# CHECK-NEXT:     Size: 7
+# CHECK-NEXT:     FileAttributes {
+# CHECK-NEXT:       Attribute {
+# CHECK-NEXT:         Tag: 4
+# CHECK-NEXT:         TagName: arch
+# CHECK-NEXT:         Value: 68{{$}}
+# CHECK-NEXT:       }
+# CHECK-NEXT:     }
+# CHECK-NEXT:   }
+# CHECK-NEXT: }
+
+# CHECK2:      BuildAttributes {
+# CHECK2-NEXT:   FormatVersion: 0x41
+# CHECK2-NEXT:   Section 1 {
+# CHECK2-NEXT:     SectionLength: 21
+# CHECK2-NEXT:     Vendor: hexagon
+# CHECK2-NEXT:     Tag: Tag_File (0x1)
+# CHECK2-NEXT:     Size: 9
+# CHECK2-NEXT:     FileAttributes {
+# CHECK2-NEXT:       Attribute {
+# CHECK2-NEXT:         Tag: 4
+# CHECK2-NEXT:         TagName: arch
+# CHECK2-NEXT:         Value: 68{{$}}
+# CHECK2-NEXT:       }
+# CHECK2-NEXT:       Attribute {
+# CHECK2-NEXT:         Tag: 5
+# CHECK2-NEXT:         TagName: hvx_arch
+# CHECK2-NEXT:         Value: 68{{$}}
+# CHECK2-NEXT:       }
+# CHECK2-NEXT:     }
+# CHECK2-NEXT:   }
+# CHECK2-NEXT: }
+
+# CHECK3:      BuildAttributes {
+# CHECK3-NEXT:   FormatVersion: 0x41
+# CHECK3-NEXT:   Section 1 {
+# CHECK3-NEXT:     SectionLength: 25
+# CHECK3-NEXT:     Vendor: hexagon
+# CHECK3-NEXT:     Tag: Tag_File (0x1)
+# CHECK3-NEXT:     Size: 13
+# CHECK3-NEXT:     FileAttributes {
+# CHECK3-NEXT:       Attribute {
+# CHECK3-NEXT:         Tag: 7
+# CHECK3-NEXT:         TagName: hvx_qfloat
+# CHECK3-NEXT:         Value: 68{{$}}
+# CHECK3-NEXT:       }
+# CHECK3-NEXT:       Attribute {
+# CHECK3-NEXT:         Tag: 9
+# CHECK3-NEXT:         TagName: audio
+# CHECK3-NEXT:         Value: 68{{$}}
+# CHECK3-NEXT:       }
+# CHECK3-NEXT:       Attribute {
+# CHECK3-NEXT:         Tag: 4
+# CHECK3-NEXT:         TagName: arch
+# CHECK3-NEXT:         Value: 68{{$}}
+# CHECK3-NEXT:       }
+# CHECK3-NEXT:       Attribute {
+# CHECK3-NEXT:         Tag: 5
+# CHECK3-NEXT:         TagName: hvx_arch
+# CHECK3-NEXT:         Value: 68{{$}}
+# CHECK3-NEXT:       }
+# CHECK3-NEXT:     }
+# CHECK3-NEXT:   }
+# CHECK3-NEXT: }
+
+#--- a.s
+.section .hexagon.attributes,"", at 0x70000003
+.byte 0x41
+.long .Lend-.hexagon.attributes-1
+.asciz "hexagon"
+.Lbegin:
+.byte 1
+.long .Lend-.Lbegin
+.byte 4
+.byte 68
+.Lend:
+
+#--- b.s
+.section .hexagon.attributes,"", at 0x70000003
+.byte 0x41
+.long .Lend1-.hexagon.attributes-1
+.asciz "hexagon"
+.Lbegin1:
+.byte 1
+.long .Lend1-.Lbegin1
+.byte 4
+.byte 68
+.Lend1:
+
+#--- c.s
+.section .hexagon.attributes,"", at 0x70000003
+.byte 0x41
+.long .Lend2-.hexagon.attributes-1
+.asciz "hexagon"
+.Lbegin2:
+.byte 1
+.long .Lend2-.Lbegin2
+.byte 4
+.byte 68
+.byte 5
+.byte 68
+.Lend2:
+
+#--- d.s
+.section .hexagon.attributes,"", at 0x70000003
+.byte 0x41
+.long .Lend3-.hexagon.attributes-1
+.asciz "hexagon"
+.Lbegin3:
+.byte 1
+.long .Lend3-.Lbegin3
+.byte 4
+.byte 68
+.byte 7
+.byte 68
+.byte 9
+.byte 68
+.Lend3:

``````````

</details>


https://github.com/llvm/llvm-project/pull/148098


More information about the llvm-commits mailing list