summaryrefslogtreecommitdiff
path: root/lld/ELF/InputFiles.cpp
diff options
context:
space:
mode:
authorPeter Smith <peter.smith@linaro.org>2018-07-31 13:41:59 +0000
committerPeter Smith <peter.smith@linaro.org>2018-07-31 13:41:59 +0000
commit70997f9a4e4064f5ce157c63313b6b9e09081ac3 (patch)
treed2f227d01d382bc1b4a3bc7a5375dd52eb65eb9e /lld/ELF/InputFiles.cpp
parent4aec86d37a65758b2975a93d5f9c406a4610f052 (diff)
[ELF][ARM] Implement support for Tag_ABI_VFP_args
The Tag_ABI_VFP_args build attribute controls the procedure call standard used for floating point parameters on ARM. The values are: 0 - Base AAPCS (FP Parameters passed in Core (Integer) registers 1 - VFP AAPCS (FP Parameters passed in FP registers) 2 - Toolchain specific (Neither Base or VFP) 3 - Compatible with all (No use of floating point parameters) If the Tag_ABI_VFP_args build attribute is missing it has an implicit value of 0. We use the attribute in two ways: - Detect a clash in calling convention between Base, VFP and Toolchain. we follow ld.bfd's lead and do not error if there is a clash between an implicit Base AAPCS caused by a missing attribute. Many projects including the hard-float (VFP AAPCS) version of glibc contain assembler files that do not use floating point but do not have Tag_ABI_VFP_args. - Set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD ELF header flag for Base or VFP AAPCS respectively. This flag is used by some ELF loaders. References: - Addenda to, and Errata in, the ABI for the ARM Architecture for Tag_ABI_VFP_args - Elf for the ARM Architecture for ELF header flags Fixes PR36009 Differential Revision: https://reviews.llvm.org/D49993 llvm-svn: 338377
Diffstat (limited to 'lld/ELF/InputFiles.cpp')
-rw-r--r--lld/ELF/InputFiles.cpp42
1 files changed, 42 insertions, 0 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 6da722f6f30e..0eb605a556ae 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -494,6 +494,46 @@ void ObjFile<ELFT>::initializeSections(
}
}
+// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD
+// flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how
+// the input objects have been compiled.
+static void updateARMVFPArgs(const ARMAttributeParser &Attributes,
+ const InputFile *F) {
+ if (!Attributes.hasAttribute(ARMBuildAttrs::ABI_VFP_args))
+ // If an ABI tag isn't present then it is implicitly given the value of 0
+ // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files,
+ // including some in glibc that don't use FP args (and should have value 3)
+ // don't have the attribute so we do not consider an implicit value of 0
+ // as a clash.
+ return;
+
+ unsigned VFPArgs = Attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args);
+ ARMVFPArgKind Arg;
+ switch (VFPArgs) {
+ case ARMBuildAttrs::BaseAAPCS:
+ Arg = ARMVFPArgKind::Base;
+ break;
+ case ARMBuildAttrs::HardFPAAPCS:
+ Arg = ARMVFPArgKind::VFP;
+ break;
+ case ARMBuildAttrs::ToolChainFPPCS:
+ // Tool chain specific convention that conforms to neither AAPCS variant.
+ Arg = ARMVFPArgKind::ToolChain;
+ break;
+ case ARMBuildAttrs::CompatibleFPAAPCS:
+ // Object compatible with all conventions.
+ return;
+ default:
+ error(toString(F) + ": unknown Tag_ABI_VFP_args value: " + Twine(VFPArgs));
+ return;
+ }
+ // Follow ld.bfd and error if there is a mix of calling conventions.
+ if (Config->ARMVFPArgs != Arg && Config->ARMVFPArgs != ARMVFPArgKind::Default)
+ error(toString(F) + ": incompatible Tag_ABI_VFP_args");
+ else
+ Config->ARMVFPArgs = Arg;
+}
+
// The ARM support in lld makes some use of instructions that are not available
// on all ARM architectures. Namely:
// - Use of BLX instruction for interworking between ARM and Thumb state.
@@ -573,6 +613,8 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec));
Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind);
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.