From: Matthew Malcomson Date: Mon, 7 Feb 2022 16:54:55 +0000 (+0000) Subject: Error linking binaries with differing e_flags. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f8180c200bf1a2d6ae42d4236f07edbe4520f500;p=thirdparty%2Fbinutils-gdb.git Error linking binaries with differing e_flags. This commit is partly changing two existing (believed buggy) behaviours in elfNN_aarch64_merge_private_bfd_data and partly accounting for a capability-specific requirement. The existing behaviours in elfNN_aarch64_merge_private_bfd_data were: 1) It returned `TRUE` by default. This effectively ignored the ELF flags on the binaries, despite there being code looking at them. 2) We do not mark the output BFD as initialised until we see flags with non-default architecture and flags. This can't tell the difference between linking default objects to non-default objects if the default objects are given first on the command line. The capability-specific requirement is: - This function originally returned early if the object file getting merged into the existing output object file is not dynamic and has no code sections. The code reasoned that differing ELF flags did not matter in this case since there was no code that would be expecting it. For capabilities the binary compatibility is still important. Data sections now contain capabilities as pointers, got sections now have a different got element size. Hence we avoid this short-circuit if any of the flags we're checking are the CHERI_PURECAP flag. --- diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 939fac197d5..8b69c03c4a2 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -8686,7 +8686,7 @@ elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) bfd *obfd = info->output_bfd; flagword out_flags; flagword in_flags; - bfd_boolean flags_compatible = TRUE; + bfd_boolean flags_compatible = FALSE; asection *sec; /* Check if we have the same endianess. */ @@ -8707,6 +8707,8 @@ elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) if (!elf_flags_init (obfd)) { + elf_flags_init (obfd) = TRUE; + /* If the input is the default architecture and had the default flags then do not bother setting the flags for the output architecture, instead allow future merges to do this. If no @@ -8717,7 +8719,6 @@ elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) && elf_elfheader (ibfd)->e_flags == 0) return TRUE; - elf_flags_init (obfd) = TRUE; elf_elfheader (obfd)->e_flags = in_flags; if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) @@ -8741,11 +8742,17 @@ elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) Also check to see if there are no code sections in the input. In this case there is no need to check for code specific flags. XXX - do we need to worry about floating-point format compatability - in data sections ? */ + in data sections ? + + We definitely need to check for data sections if one set of flags is + targetting the PURECAP abi and another is not. Pointers being + capabilities in data sections can not be glossed over. */ if (!(ibfd->flags & DYNAMIC)) { bfd_boolean null_input_bfd = TRUE; - bfd_boolean only_data_sections = TRUE; + bfd_boolean only_data_sections + = !(in_flags & EF_AARCH64_CHERI_PURECAP + || out_flags & EF_AARCH64_CHERI_PURECAP); for (sec = ibfd->sections; sec != NULL; sec = sec->next) { diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index c40eba95942..9168a810fc5 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -255,6 +255,7 @@ run_dump_test_lp64 "emit-morello-reloc-markers-3" run_dump_test_lp64 "morello-sizeless-local-syms" run_dump_test_lp64 "morello-sizeless-global-syms" run_dump_test_lp64 "morello-sizeless-got-syms" +run_dump_test_lp64 "morello-disallow-merged-binaries" run_dump_test_lp64 "morello-capinit" run_dump_test_lp64 "morello-stubs" diff --git a/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries-code.s b/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries-code.s new file mode 100644 index 00000000000..83a7291c911 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries-code.s @@ -0,0 +1,11 @@ + .file "very-basic-test.c" + .text + .align 2 + .global _start + .type _start, %function +_start: + adrp c0, :got:extobj + ldr c0, [c0, #:got_lo12:extobj] + ldr w0, [c0] + ret + .size _start, .-_start diff --git a/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries-data.s b/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries-data.s new file mode 100644 index 00000000000..a9be82acddb --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries-data.s @@ -0,0 +1,8 @@ + .text + .global extobj + .data + .align 2 + .type extobj, %object + .size extobj, 4 +extobj: + .word 1 diff --git a/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries.d b/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries.d new file mode 100644 index 00000000000..ddb44c59764 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-disallow-merged-binaries.d @@ -0,0 +1,4 @@ +#source: morello-disallow-merged-binaries-data.s -march=morello +#source: morello-disallow-merged-binaries-code.s -march=morello+c64 +#ld: -static +#error: .*failed to merge target specific data.*