[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
This commit is contained in:
Jessica Clarke
2020-08-20 18:10:18 +01:00
parent da6b3aa4c6
commit bef38e86b4
3 changed files with 72 additions and 16 deletions

View File

@@ -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 <class ELFT>
InputSectionBase *ObjFile<ELFT>::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<uint8_t> contents = check(this->getObj().getSectionContents(&sec));
if (Error e = attributes.parse(contents, config->ekind == ELF32LEKind
@@ -878,20 +876,45 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &sec) {
: support::big)) {
auto *isec = make<InputSection>(*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<InputSection>(*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<InputSection>(*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<uint8_t> contents = check(this->getObj().getSectionContents(&sec));
if (Error e = attributes.parse(contents, support::little)) {
auto *isec = make<InputSection>(*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<InputSection>(*this, sec, name);
return in.attributes;
}
return &InputSection::discarded;
}
}
switch (sec.sh_type) {
case SHT_LLVM_DEPENDENT_LIBRARIES: {
if (config->relocatable)
break;

View File

@@ -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;

View File

@@ -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"