mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 14:50:42 +08:00
[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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
33
lld/test/ELF/riscv-attributes.s
Normal file
33
lld/test/ELF/riscv-attributes.s
Normal 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"
|
||||
Reference in New Issue
Block a user