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.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index b460ea4764965da3b770ff6528730b4248377b16..1a65e6e5a64e115a99be8a707651ea1786b3fcdc 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -8715,7 +8715,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. */ @@ -8736,6 +8736,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 @@ -8746,7 +8748,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) @@ -8770,11 +8771,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 c40eba959421ac6d5e97f11d95a5900fa8e5b2bf..9168a810fc57783dd122ce40b6385dddc6888042 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 0000000000000000000000000000000000000000..83a7291c911f83f5ae611a3db7afbf95e2f0b10d --- /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 0000000000000000000000000000000000000000..a9be82acddbb258ca8a27ea4b16adb62c786411d --- /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 0000000000000000000000000000000000000000..ddb44c59764c71a5ea23a381ae02615f52a8e571 --- /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.*
gnu-morello@op-lists.linaro.org