diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- 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" @@ -865,10 +866,7 @@ 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 @@ -876,20 +874,45 @@ : support::big)) { auto *isec = make(*this, sec, name); warn(toString(isec) + ": " + llvm::toString(std::move(e))); - break; + } 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.attributes == nullptr) { + in.attributes = make(*this, sec, name); + return in.attributes; + } + return &InputSection::discarded; } - 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; + } + + 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; } - 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 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1200,7 +1200,7 @@ // 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 --- /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"