Skip to content

Commit d2bcc51

Browse files
authored
[LLD] Merge .hexagon.attributes sections (#148098)
Merge the attributes of object files being linked together. The `.hexagon.attributes` section can be used by loaders and analysis tools. This is similar to the .riscv.attributes, introduced in 8a900f2 / https://reviews.llvm.org/D138550.
1 parent 96148f9 commit d2bcc51

File tree

5 files changed

+275
-0
lines changed

5 files changed

+275
-0
lines changed

lld/ELF/Arch/Hexagon.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,18 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "InputFiles.h"
10+
#include "OutputSections.h"
1011
#include "Symbols.h"
1112
#include "SyntheticSections.h"
1213
#include "Target.h"
14+
#include "lld/Common/ErrorHandler.h"
15+
#include "llvm/ADT/SmallVector.h"
1316
#include "llvm/BinaryFormat/ELF.h"
17+
#include "llvm/Support/ELFAttributes.h"
1418
#include "llvm/Support/Endian.h"
19+
#include "llvm/Support/HexagonAttributeParser.h"
20+
#include "llvm/Support/HexagonAttributes.h"
21+
#include "llvm/Support/LEB128.h"
1522

1623
using namespace llvm;
1724
using namespace llvm::object;
@@ -415,4 +422,116 @@ int64_t Hexagon::getImplicitAddend(const uint8_t *buf, RelType type) const {
415422
}
416423
}
417424

425+
namespace {
426+
class HexagonAttributesSection final : public SyntheticSection {
427+
public:
428+
HexagonAttributesSection(Ctx &ctx)
429+
: SyntheticSection(ctx, ".hexagon.attributes", SHT_HEXAGON_ATTRIBUTES, 0,
430+
1) {}
431+
432+
size_t getSize() const override { return size; }
433+
void writeTo(uint8_t *buf) override;
434+
435+
static constexpr StringRef vendor = "hexagon";
436+
DenseMap<unsigned, unsigned> intAttr;
437+
size_t size = 0;
438+
};
439+
} // namespace
440+
441+
static HexagonAttributesSection *
442+
mergeAttributesSection(Ctx &ctx,
443+
const SmallVector<InputSectionBase *, 0> &sections) {
444+
ctx.in.hexagonAttributes = std::make_unique<HexagonAttributesSection>(ctx);
445+
auto &merged =
446+
static_cast<HexagonAttributesSection &>(*ctx.in.hexagonAttributes);
447+
448+
// Collect all tags values from attributes section.
449+
const auto &attributesTags = HexagonAttrs::getHexagonAttributeTags();
450+
for (const InputSectionBase *sec : sections) {
451+
HexagonAttributeParser parser;
452+
if (Error e = parser.parse(sec->content(), llvm::endianness::little))
453+
Warn(ctx) << sec << ": " << std::move(e);
454+
for (const auto &tag : attributesTags) {
455+
switch (HexagonAttrs::AttrType(tag.attr)) {
456+
case HexagonAttrs::ARCH:
457+
case HexagonAttrs::HVXARCH:
458+
if (auto i = parser.getAttributeValue(tag.attr)) {
459+
auto r = merged.intAttr.try_emplace(tag.attr, *i);
460+
if (!r.second)
461+
if (r.first->second < *i)
462+
r.first->second = *i;
463+
}
464+
continue;
465+
466+
case HexagonAttrs::HVXIEEEFP:
467+
case HexagonAttrs::HVXQFLOAT:
468+
case HexagonAttrs::ZREG:
469+
case HexagonAttrs::AUDIO:
470+
case HexagonAttrs::CABAC:
471+
if (auto i = parser.getAttributeValue(tag.attr)) {
472+
auto r = merged.intAttr.try_emplace(tag.attr, *i);
473+
if (!r.second && r.first->second != *i) {
474+
r.first->second |= *i;
475+
}
476+
}
477+
continue;
478+
}
479+
}
480+
}
481+
482+
// The total size of headers: format-version [ <section-length> "vendor-name"
483+
// [ <file-tag> <size>.
484+
size_t size = 5 + merged.vendor.size() + 1 + 5;
485+
for (auto &attr : merged.intAttr)
486+
if (attr.second != 0)
487+
size += getULEB128Size(attr.first) + getULEB128Size(attr.second);
488+
merged.size = size;
489+
return &merged;
490+
}
491+
492+
void HexagonAttributesSection::writeTo(uint8_t *buf) {
493+
const size_t size = getSize();
494+
uint8_t *const end = buf + size;
495+
*buf = ELFAttrs::Format_Version;
496+
write32(ctx, buf + 1, size - 1);
497+
buf += 5;
498+
499+
memcpy(buf, vendor.data(), vendor.size());
500+
buf += vendor.size() + 1;
501+
502+
*buf = ELFAttrs::File;
503+
write32(ctx, buf + 1, end - buf);
504+
buf += 5;
505+
506+
for (auto &attr : intAttr) {
507+
if (attr.second == 0)
508+
continue;
509+
buf += encodeULEB128(attr.first, buf);
510+
buf += encodeULEB128(attr.second, buf);
511+
}
512+
}
513+
514+
void elf::mergeHexagonAttributesSections(Ctx &ctx) {
515+
// Find the first input SHT_HEXAGON_ATTRIBUTES; return if not found.
516+
size_t place =
517+
llvm::find_if(ctx.inputSections,
518+
[](auto *s) { return s->type == SHT_HEXAGON_ATTRIBUTES; }) -
519+
ctx.inputSections.begin();
520+
if (place == ctx.inputSections.size())
521+
return;
522+
523+
// Extract all SHT_HEXAGON_ATTRIBUTES sections into `sections`.
524+
SmallVector<InputSectionBase *, 0> sections;
525+
llvm::erase_if(ctx.inputSections, [&](InputSectionBase *s) {
526+
if (s->type != SHT_HEXAGON_ATTRIBUTES)
527+
return false;
528+
sections.push_back(s);
529+
return true;
530+
});
531+
532+
// Add the merged section.
533+
ctx.inputSections.insert(ctx.inputSections.begin() + place,
534+
mergeAttributesSection(ctx, sections));
535+
}
536+
418537
void elf::setHexagonTargetInfo(Ctx &ctx) { ctx.target.reset(new Hexagon(ctx)); }

lld/ELF/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ struct UndefinedDiag {
568568
// a partition.
569569
struct InStruct {
570570
std::unique_ptr<InputSection> attributes;
571+
std::unique_ptr<SyntheticSection> hexagonAttributes;
571572
std::unique_ptr<SyntheticSection> riscvAttributes;
572573
std::unique_ptr<BssSection> bss;
573574
std::unique_ptr<BssSection> bssRelRo;

lld/ELF/Driver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3446,6 +3446,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
34463446
if (!ctx.arg.relocatable)
34473447
combineEhSections(ctx);
34483448

3449+
// Merge .hexagon.attributes sections.
3450+
if (ctx.arg.emachine == EM_HEXAGON)
3451+
mergeHexagonAttributesSections(ctx);
3452+
34493453
// Merge .riscv.attributes sections.
34503454
if (ctx.arg.emachine == EM_RISCV)
34513455
mergeRISCVAttributesSections(ctx);

lld/ELF/Target.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ template <typename ELFT> void writeARMCmseImportLib(Ctx &);
245245
uint64_t getLoongArchPageDelta(uint64_t dest, uint64_t pc, RelType type);
246246
void riscvFinalizeRelax(int passes);
247247
void mergeRISCVAttributesSections(Ctx &);
248+
void mergeHexagonAttributesSections(Ctx &);
248249
void addArmInputSectionMappingSymbols(Ctx &);
249250
void addArmSyntheticSectionMappingSymbol(Defined *);
250251
void sortArmMappingSymbols(Ctx &);

lld/test/ELF/hexagon-attributes.s

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# REQUIRES: hexagon
2+
3+
# RUN: rm -rf %t && split-file %s %t && cd %t
4+
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf a.s -o a.o
5+
# RUN: ld.lld -e 0 a.o -o out 2>&1 | count 0
6+
# RUN: llvm-readelf -S -l --arch-specific out | FileCheck %s --check-prefixes=HDR,CHECK
7+
# RUN: ld.lld -e 0 a.o a.o -o out1 2>&1 | count 0
8+
# RUN: llvm-readobj --arch-specific out1 | FileCheck %s
9+
# RUN: ld.lld -r a.o a.o -o out1 2>&1 | count 0
10+
# RUN: llvm-readobj --arch-specific out1 | FileCheck %s
11+
12+
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf b.s -o b.o
13+
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf c.s -o c.o
14+
# RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf d.s -o d.o
15+
# RUN: ld.lld a.o b.o c.o -o out2
16+
# RUN: llvm-readobj --arch-specific out2 | FileCheck %s --check-prefix=CHECK2
17+
# RUN: ld.lld a.o b.o c.o d.o -o out3
18+
# RUN: llvm-readobj --arch-specific out3 | FileCheck %s --check-prefix=CHECK3
19+
20+
# HDR: Name Type Address Off Size ES Flg Lk Inf Al
21+
# HDR: .hexagon.attributes HEXAGON_ATTRIBUTES 00000000 {{.*}} {{.*}} 00 0 0 1{{$}}
22+
23+
# HDR: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
24+
# HDR: LOAD {{.*}}
25+
# HDR-NEXT: GNU_STACK {{.*}}
26+
27+
# CHECK: BuildAttributes {
28+
# CHECK-NEXT: FormatVersion: 0x41
29+
# CHECK-NEXT: Section 1 {
30+
# CHECK-NEXT: SectionLength: 19
31+
# CHECK-NEXT: Vendor: hexagon
32+
# CHECK-NEXT: Tag: Tag_File (0x1)
33+
# CHECK-NEXT: Size: 7
34+
# CHECK-NEXT: FileAttributes {
35+
# CHECK-NEXT: Attribute {
36+
# CHECK-NEXT: Tag: 4
37+
# CHECK-NEXT: TagName: arch
38+
# CHECK-NEXT: Value: 68{{$}}
39+
# CHECK-NEXT: }
40+
# CHECK-NEXT: }
41+
# CHECK-NEXT: }
42+
# CHECK-NEXT: }
43+
44+
# CHECK2: BuildAttributes {
45+
# CHECK2-NEXT: FormatVersion: 0x41
46+
# CHECK2-NEXT: Section 1 {
47+
# CHECK2-NEXT: SectionLength: 21
48+
# CHECK2-NEXT: Vendor: hexagon
49+
# CHECK2-NEXT: Tag: Tag_File (0x1)
50+
# CHECK2-NEXT: Size: 9
51+
# CHECK2-NEXT: FileAttributes {
52+
# CHECK2-NEXT: Attribute {
53+
# CHECK2-NEXT: Tag: 4
54+
# CHECK2-NEXT: TagName: arch
55+
# CHECK2-NEXT: Value: 68{{$}}
56+
# CHECK2-NEXT: }
57+
# CHECK2-NEXT: Attribute {
58+
# CHECK2-NEXT: Tag: 5
59+
# CHECK2-NEXT: TagName: hvx_arch
60+
# CHECK2-NEXT: Value: 68{{$}}
61+
# CHECK2-NEXT: }
62+
# CHECK2-NEXT: }
63+
# CHECK2-NEXT: }
64+
# CHECK2-NEXT: }
65+
66+
# CHECK3: BuildAttributes {
67+
# CHECK3-NEXT: FormatVersion: 0x41
68+
# CHECK3-NEXT: Section 1 {
69+
# CHECK3-NEXT: SectionLength: 25
70+
# CHECK3-NEXT: Vendor: hexagon
71+
# CHECK3-NEXT: Tag: Tag_File (0x1)
72+
# CHECK3-NEXT: Size: 13
73+
# CHECK3-NEXT: FileAttributes {
74+
# CHECK3-NEXT: Attribute {
75+
# CHECK3-NEXT: Tag: 7
76+
# CHECK3-NEXT: TagName: hvx_qfloat
77+
# CHECK3-NEXT: Value: 68{{$}}
78+
# CHECK3-NEXT: }
79+
# CHECK3-NEXT: Attribute {
80+
# CHECK3-NEXT: Tag: 9
81+
# CHECK3-NEXT: TagName: audio
82+
# CHECK3-NEXT: Value: 68{{$}}
83+
# CHECK3-NEXT: }
84+
# CHECK3-NEXT: Attribute {
85+
# CHECK3-NEXT: Tag: 4
86+
# CHECK3-NEXT: TagName: arch
87+
# CHECK3-NEXT: Value: 68{{$}}
88+
# CHECK3-NEXT: }
89+
# CHECK3-NEXT: Attribute {
90+
# CHECK3-NEXT: Tag: 5
91+
# CHECK3-NEXT: TagName: hvx_arch
92+
# CHECK3-NEXT: Value: 68{{$}}
93+
# CHECK3-NEXT: }
94+
# CHECK3-NEXT: }
95+
# CHECK3-NEXT: }
96+
# CHECK3-NEXT: }
97+
98+
#--- a.s
99+
.section .hexagon.attributes,"",@0x70000003
100+
.byte 0x41
101+
.long .Lend-.hexagon.attributes-1
102+
.asciz "hexagon"
103+
.Lbegin:
104+
.byte 1
105+
.long .Lend-.Lbegin
106+
.byte 4
107+
.byte 68
108+
.Lend:
109+
110+
#--- b.s
111+
.section .hexagon.attributes,"",@0x70000003
112+
.byte 0x41
113+
.long .Lend1-.hexagon.attributes-1
114+
.asciz "hexagon"
115+
.Lbegin1:
116+
.byte 1
117+
.long .Lend1-.Lbegin1
118+
.byte 4
119+
.byte 68
120+
.Lend1:
121+
122+
#--- c.s
123+
.section .hexagon.attributes,"",@0x70000003
124+
.byte 0x41
125+
.long .Lend2-.hexagon.attributes-1
126+
.asciz "hexagon"
127+
.Lbegin2:
128+
.byte 1
129+
.long .Lend2-.Lbegin2
130+
.byte 4
131+
.byte 68
132+
.byte 5
133+
.byte 68
134+
.Lend2:
135+
136+
#--- d.s
137+
.section .hexagon.attributes,"",@0x70000003
138+
.byte 0x41
139+
.long .Lend3-.hexagon.attributes-1
140+
.asciz "hexagon"
141+
.Lbegin3:
142+
.byte 1
143+
.long .Lend3-.Lbegin3
144+
.byte 4
145+
.byte 68
146+
.byte 7
147+
.byte 68
148+
.byte 9
149+
.byte 68
150+
.Lend3:

0 commit comments

Comments
 (0)