Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -321,6 +321,7 @@ const Elf_Shdr *VersymSec = nullptr; const Elf_Shdr *VerdefSec = nullptr; + const Elf_Shdr *ARMAttributesSec = nullptr; public: std::vector Verdefs; Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -583,6 +583,16 @@ } } +template +static void processARMAttributesSection(const ELFFileBase *F, + const typename ELFT::Shdr &Sec) { + ARMAttributeParser Attributes; + ArrayRef Contents = check(F->getObj().getSectionContents(&Sec)); + Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind); + updateSupportedARMFeatures(Attributes); + updateARMVFPArgs(Attributes, F); +} + template InputSectionBase *ObjFile::getRelocTarget(const Elf_Shdr &Sec) { uint32_t Idx = Sec.sh_info; @@ -616,11 +626,7 @@ case SHT_ARM_ATTRIBUTES: { if (Config->EMachine != EM_ARM) break; - ARMAttributeParser Attributes; - ArrayRef Contents = check(this->getObj().getSectionContents(&Sec)); - Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind); - updateSupportedARMFeatures(Attributes); - updateARMVFPArgs(Attributes, this); + processARMAttributesSection(this, Sec); // FIXME: Retain the first attribute section we see. The eglibc ARM // dynamic loaders require the presence of an attribute section for dlopen @@ -880,6 +886,9 @@ case SHT_DYNSYM: this->initSymtab(Sections, &Sec); break; + case SHT_ARM_ATTRIBUTES: + this->ARMAttributesSec = &Sec; + break; case SHT_DYNAMIC: DynamicSec = &Sec; break; @@ -993,6 +1002,8 @@ // than necessary, but you can easily understand the code if you wrap your // head around the data structure described above. template void SharedFile::parseRest() { + if (this->ARMAttributesSec && Config->EMachine == EM_ARM) + processARMAttributesSection(this, *(this->ARMAttributesSec)); Verdefs = parseVerdefs(); // parse .gnu.version_d std::vector Versyms = parseVersyms(); // parse .gnu.version ArrayRef Sections = CHECK(this->getObj().sections(), this); Index: test/ELF/arm-tag-vfp-args-errs.s =================================================================== --- test/ELF/arm-tag-vfp-args-errs.s +++ test/ELF/arm-tag-vfp-args-errs.s @@ -3,12 +3,16 @@ // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-vfp.s -o %tvfp.o // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-toolchain.s -o %ttoolchain.o // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o +// RUN: ld.lld -shared %tbase.o -o %tbase.so +// RUN: ld.lld -shared %tvfp.o -o %tvfp.so // RUN: not ld.lld %t.o %tbase.o %tvfp.o -o%t 2>&1 | FileCheck %s // RUN: not ld.lld %t.o %tbase.o %ttoolchain.o -o%t 2>&1 | FileCheck %s // RUN: not ld.lld %t.o %tvfp.o %tbase.o -o%t 2>&1 | FileCheck %s // RUN: not ld.lld %t.o %tvfp.o %ttoolchain.o -o%t 2>&1 | FileCheck %s // RUN: not ld.lld %t.o %ttoolchain.o %tbase.o -o%t 2>&1 | FileCheck %s // RUN: not ld.lld %t.o %ttoolchain.o %tvfp.o -o%t 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %tbase.o %tvfp.so -o%t 2>&1 | FileCheck %s +// RUN: not ld.lld %t.o %tbase.so %tvfp.o -o%t 2>&1 | FileCheck %s // CHECK: incompatible Tag_ABI_VFP_args .arch armv7-a