From bef38e86b4e702a0c42e243d323fb7c09875e649 Mon Sep 17 00:00:00 2001 From: Jessica Clarke Date: Thu, 20 Aug 2020 18:10:18 +0100 Subject: [PATCH] [ELF] Handle SHT_RISCV_ATTRIBUTES similarly to SHT_ARM_ATTRIBUTES Currently we treat SHT_RISCV_ATTRIBUTES like a normal section and concatenate all such input sections, yielding invalid output unless only a single attributes section is present in the input. Instead, pick the first as with SHT_ARM_ATTRIBUTES. We do not currently need to condition our behaviour on the contents, unlike Arm. In future, we should both do stricter validation of the input and merge all sections together to ensure we have, for example, the full arch string requirement, but this rudimentary implementation is good enough for most common cases. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D86309 --- lld/ELF/InputFiles.cpp | 53 +++++++++++++++++++++++---------- lld/ELF/SyntheticSections.h | 2 +- lld/test/ELF/riscv-attributes.s | 33 ++++++++++++++++++++ 3 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 lld/test/ELF/riscv-attributes.s diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index bfc8e9c1e53b..acdb5c71efb9 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -27,6 +27,7 @@ #include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Path.h" +#include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/TarWriter.h" #include "llvm/Support/raw_ostream.h" @@ -867,10 +868,7 @@ template InputSectionBase *ObjFile::createInputSection(const Elf_Shdr &sec) { StringRef name = getSectionName(sec); - switch (sec.sh_type) { - case SHT_ARM_ATTRIBUTES: { - if (config->emachine != EM_ARM) - break; + if (config->emachine == EM_ARM && sec.sh_type == SHT_ARM_ATTRIBUTES) { ARMAttributeParser attributes; ArrayRef contents = check(this->getObj().getSectionContents(&sec)); if (Error e = attributes.parse(contents, config->ekind == ELF32LEKind @@ -878,20 +876,45 @@ InputSectionBase *ObjFile::createInputSection(const Elf_Shdr &sec) { : support::big)) { auto *isec = make(*this, sec, name); warn(toString(isec) + ": " + llvm::toString(std::move(e))); - break; - } - updateSupportedARMFeatures(attributes); - updateARMVFPArgs(attributes, this); + } else { + updateSupportedARMFeatures(attributes); + updateARMVFPArgs(attributes, this); - // FIXME: Retain the first attribute section we see. The eglibc ARM - // dynamic loaders require the presence of an attribute section for dlopen - // to work. In a full implementation we would merge all attribute sections. - if (in.armAttributes == nullptr) { - in.armAttributes = make(*this, sec, name); - return in.armAttributes; + // FIXME: Retain the first attribute section we see. The eglibc ARM + // dynamic loaders require the presence of an attribute section for dlopen + // to work. In a full implementation we would merge all attribute + // sections. + if (in.attributes == nullptr) { + in.attributes = make(*this, sec, name); + return in.attributes; + } + return &InputSection::discarded; } - return &InputSection::discarded; } + + if (config->emachine == EM_RISCV && sec.sh_type == SHT_RISCV_ATTRIBUTES) { + RISCVAttributeParser attributes; + ArrayRef contents = check(this->getObj().getSectionContents(&sec)); + if (Error e = attributes.parse(contents, support::little)) { + auto *isec = make(*this, sec, name); + warn(toString(isec) + ": " + llvm::toString(std::move(e))); + } else { + // FIXME: Validate arch tag contains C if and only if EF_RISCV_RVC is + // present. + + // FIXME: Retain the first attribute section we see. Tools such as + // llvm-objdump make use of the attribute section to determine which + // standard extensions to enable. In a full implementation we would merge + // all attribute sections. + if (in.attributes == nullptr) { + in.attributes = make(*this, sec, name); + return in.attributes; + } + return &InputSection::discarded; + } + } + + switch (sec.sh_type) { case SHT_LLVM_DEPENDENT_LIBRARIES: { if (config->relocatable) break; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index 7779efcd5fe5..8943596179c1 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1200,7 +1200,7 @@ inline Partition &SectionBase::getPartition() const { // Linker generated sections which can be used as inputs and are not specific to // a partition. struct InStruct { - InputSection *armAttributes; + InputSection *attributes; BssSection *bss; BssSection *bssRelRo; GotSection *got; diff --git a/lld/test/ELF/riscv-attributes.s b/lld/test/ELF/riscv-attributes.s new file mode 100644 index 000000000000..36e506a1df66 --- /dev/null +++ b/lld/test/ELF/riscv-attributes.s @@ -0,0 +1,33 @@ +# REQUIRES: riscv + +# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-readelf --arch-specific %t | FileCheck %s +# RUN: ld.lld %t.o %t.o -o %t2 +# RUN: llvm-readelf --arch-specific %t2 | FileCheck %s + +# CHECK: BuildAttributes { +# CHECK-NEXT: FormatVersion: 0x41 +# CHECK-NEXT: Section 1 { +# CHECK-NEXT: SectionLength: 52 +# CHECK-NEXT: Vendor: riscv +# CHECK-NEXT: Tag: Tag_File (0x1) +# CHECK-NEXT: Size: 42 +# CHECK-NEXT: FileAttributes { +# CHECK-NEXT: Attribute { +# CHECK-NEXT: Tag: 4 +# CHECK-NEXT: Value: 16 +# CHECK-NEXT: TagName: stack_align +# CHECK-NEXT: Description: Stack alignment is 16-bytes +# CHECK-NEXT: } +# CHECK-NEXT: Attribute { +# CHECK-NEXT: Tag: 5 +# CHECK-NEXT: TagName: arch +# CHECK-NEXT: Value: rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0 +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } +# CHECK-NEXT: } + +.attribute 4, 16 +.attribute 5, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"