Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions lld/ELF/Arch/Hexagon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop braces for this single-line single-statement body. We can remove && r.first->second != *i.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

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)); }
1 change: 1 addition & 0 deletions lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ struct UndefinedDiag {
// a partition.
struct InStruct {
std::unique_ptr<InputSection> attributes;
std::unique_ptr<SyntheticSection> hexagonAttributes;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move before riscvAttributes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

std::unique_ptr<SyntheticSection> riscvAttributes;
std::unique_ptr<BssSection> bss;
std::unique_ptr<BssSection> bssRelRo;
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3446,6 +3446,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
if (!ctx.arg.relocatable)
combineEhSections(ctx);

// Merge .hexagon.attributes sections.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move before RISCV

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

if (ctx.arg.emachine == EM_HEXAGON)
mergeHexagonAttributesSections(ctx);

// Merge .riscv.attributes sections.
if (ctx.arg.emachine == EM_RISCV)
mergeRISCVAttributesSections(ctx);
Expand Down
1 change: 1 addition & 0 deletions lld/ELF/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 &);
Expand Down
150 changes: 150 additions & 0 deletions lld/test/ELF/hexagon-attributes.s
Original file line number Diff line number Diff line change
@@ -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,"",@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,"",@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,"",@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,"",@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: