From cb1d6ea8cff7cbfc4218f91d1bd81544a44a61d4 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 20 Jun 2023 13:44:38 +0100 Subject: [PATCH] Reland: [ELFAttributeParser] Skip unknown vendor subsections. An .ARM.attributes section is divided into subsections, each labelled with a vendor name. There is one standardised vendor name, which must be used for all attributes that affect compatibility. Subsections labelled with other vendor names can be used for optimisation purposes, but it has to be safe for an object file consumer to ignore them if it doesn't recognise the vendor name. LLD currently terminates parsing of the whole attributes section as soon as it encounters a subsection with a vendor name it doesn't recognise (which is anything other than the standard one). This can prevent it from detecting compatibility issues, if a standard subsection followed the vendor-specific one. This patch modifies the attribute parser so that unrecognised vendor subsections are silently skipped, and the subsections beyond them are still processed. (Relanded with no change from the original commit 8f208edd44d0832. I reverted it in 949bb7e4de62cd0 due to widespread buildbot breakage, failing to notice that 975f71faa72aaaa had already fixed the failing unit test. Also, the *revert* caused at least one buildbot to fail, because I switched the affected lld test to making %t a directory, and then the reverted version tried to treat it as a file without cleaning the output directory first.) Differential Revision: https://reviews.llvm.org/D153335 --- lld/test/ELF/arm-tag-vfp-args-errs.s | 78 ++++++++++++++++++++++++++++----- llvm/lib/Support/ELFAttributeParser.cpp | 12 +++-- 2 files changed, 76 insertions(+), 14 deletions(-) diff --git a/lld/test/ELF/arm-tag-vfp-args-errs.s b/lld/test/ELF/arm-tag-vfp-args-errs.s index 622cea0..4fc152e 100644 --- a/lld/test/ELF/arm-tag-vfp-args-errs.s +++ b/lld/test/ELF/arm-tag-vfp-args-errs.s @@ -1,16 +1,25 @@ // REQUIRES:arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-base.s -o %tbase.o -// 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: 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: rm -rf %t +// RUN: split-file %s %t + +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-base.s -o %t/base.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-vfp.s -o %t/vfp.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-toolchain.s -o %t/toolchain.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %t/main.s -o %t/main.o +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %t/vendor.s -o %t/vendor.o +// RUN: not ld.lld %t/main.o %t/base.o %t/vfp.o -o%t/a.out 2>&1 | FileCheck %s +// RUN: not ld.lld %t/main.o %t/base.o %t/vendor.o -o%t/a.out 2>&1 | FileCheck %s +// RUN: not ld.lld %t/main.o %t/base.o %t/toolchain.o -o%t/a.out 2>&1 | FileCheck %s +// RUN: not ld.lld %t/main.o %t/vfp.o %t/base.o -o%t/a.out 2>&1 | FileCheck %s +// RUN: not ld.lld %t/main.o %t/vfp.o %t/toolchain.o -o%t/a.out 2>&1 | FileCheck %s +// RUN: not ld.lld %t/main.o %t/toolchain.o %t/base.o -o%t/a.out 2>&1 | FileCheck %s +// RUN: not ld.lld %t/main.o %t/toolchain.o %t/vfp.o -o%t/a.out 2>&1 | FileCheck %s // CHECK: incompatible Tag_ABI_VFP_args + +//--- main.s + .arch armv7-a .eabi_attribute 20, 1 .eabi_attribute 21, 1 @@ -27,3 +36,52 @@ .globl _start .type _start, %function _start: bx lr + +//--- vendor.s + + .syntax unified + + // Manually construct a custom .ARM.attributes section + .section .ARM.attributes,"",%0x70000003 // SHT_ARM_ATTRIBUTES + + // Initial byte giving the section format version + .byte 'A' + + // Subsection with a name that won't be recognised as a known vendor +vendor_subsect_start: + .word vendor_subsect_end - vendor_subsect_start // subsection length + .asciz "ShouldBeIgnored" // vendor name + .dcb.b 64, 0xff // dummy vendor section contents +vendor_subsect_end: + + // Subsection that should be identical to the attributes defined by + // Inputs/arm-vfp-arg-vfp.s +aeabi_subsect_start: + .word aeabi_subsect_end - aeabi_subsect_start + .asciz "aeabi" // vendor name indicating the standard subsection +file_subsubsect_start: + .byte 1 // introduce sub-subsection of attributes for the whole file + .word file_subsubsect_end - file_subsubsect_start // sub-subsection len + .byte 5 // CPU_name + .asciz "7-A" + .byte 6, 10 // CPU_arch = ARM v7 + .byte 7, 'A' // CPU_arch_profile = Application + .byte 8, 1 // ARM_ISA_use = Permitted + .byte 9, 2 // THUMB_ISA_use = Thumb-2 + .byte 18, 4 // ABI_PCS_wchar_t = 4-byte + .byte 20, 1 // ABI_FP_denormal = IEEE-754 + .byte 21, 1 // ABI_FP_exceptions = IEEE-754 + .byte 23, 3 // ABI_FP_number_model = IEEE-754 + .byte 24, 1 // ABI_align_needed = 8-byte alignment + .byte 25, 1 // ABI_align_preserved = 8-byte data alignment + .byte 26, 2 // ABI_enum_size = Int32 + .byte 28, 1 // ABI_VFP_args = AAPCS VFP + .byte 30, 6 // ABI_optimization_goals = Best Debugging + .byte 34, 1 // CPU_unaligned_access = v6-style +file_subsubsect_end: +aeabi_subsect_end: + + .text + .global f1 + .type f1, %function +f1: bx lr diff --git a/llvm/lib/Support/ELFAttributeParser.cpp b/llvm/lib/Support/ELFAttributeParser.cpp index a5a0676..2e90b70 100644 --- a/llvm/lib/Support/ELFAttributeParser.cpp +++ b/llvm/lib/Support/ELFAttributeParser.cpp @@ -127,10 +127,14 @@ Error ELFAttributeParser::parseSubsection(uint32_t length) { sw->printString("Vendor", vendorName); } - // Ignore unrecognized vendor-name. - if (vendorName.lower() != vendor) - return createStringError(errc::invalid_argument, - "unrecognized vendor-name: " + vendorName); + // Handle a subsection with an unrecognized vendor-name by skipping + // over it to the next subsection. ADDENDA32 in the Arm ABI defines + // that vendor attribute sections must not affect compatibility, so + // this should always be safe. + if (vendorName.lower() != vendor) { + cursor.seek(end); + return Error::success(); + } while (cursor.tell() < end) { /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size -- 2.7.4