From: Nelson Chu Date: Fri, 22 Jan 2021 02:16:12 +0000 (-0800) Subject: RISC-V: PR27200, allow the first input non-ABI binary to be linked with any one. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0d6aab77761274e479ca443f8bcb35a0eee3a4c4;p=binutils-gdb.git RISC-V: PR27200, allow the first input non-ABI binary to be linked with any one. RISC-V only defines two float ABIs, soft-float and double-float, and the value of soft-float is 0x0. But 0x0 usually means unknown/default setting for many targets, and the non-ABI binary, which is generated by "ld/objcopy -b binary", also has the 0x0 elf header flags, this may be confused. We probably can define a new unknown/default ABI value to make them more clear, but that will need more bits in the elf header flags, and also need to discuss in the riscv psabi spec. Training linker have a default ABI setting, and can be changed by ld options or configure options is another solution, like what assemblr usually do. So all objects, including the binary files, will have explicit ABI setting. But the binary files will no longer be linked with any object, users need to recompile them with the exactly ABI they want. It may be inconvenience sometimes. Besides, I think linker doesn't need to know the default arch/abi so far, just set them according to the linked objects should be enough. Therefore, without changing the riscv psabi, and keep the non-ABI binary can be linked with any object, we don't check the ABI flags if no code section in the PR24389. Just that we find the first input non-ABI binary still cannot be linked with others in the PR27200. This patch fixs the problem by delaying the elf_flags_init(obfd) check, since the flags of non-ABI object with no code cannot be copyed to output BFD, we should skip it, even if it is the first linked object. However, there is a strange "break" at the end of loop in the PR24389. The "break" cause the ld testcase "Link with zlib-gabi compressed debug output 1" fails for rv64gc-linux toolchain, after applying the above change. The root cause is that - the "break" make linker only checks the "first" section of input BFD rather than the entire sections. I have checked that AARCH64 and ARM both have the "break" at the end of loop, but ARC doesn't. I suppose we should remove the "break" like what ARC do, or use a pair of braces for the if statement. I have passed the elf/linux toolchain regressions, so the change should be fine. bfd/ PR 27200 * elfnn-riscv.c (_bfd_riscv_elf_merge_private_bfd_data): Delay copying the elf flags from input BFD to output BFD, until we have checked if the input BFD has no code section or not. Also fix the problem that we only check the first section rather than the entire sections for input BFD. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index e2e9256086a..b7c35c79ce2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2021-02-17 Nelson Chu + + PR 27200 + * elfnn-riscv.c (_bfd_riscv_elf_merge_private_bfd_data): Delay + copying the elf flags from input BFD to output BFD, until we have + checked if the input BFD has no code section or not. Also fix the + problem that we only check the first section rather than the entire + sections for input BFD. + 2021-02-16 Alan Modra * libbfd.c (_bfd_read_unsigned_leb128): Avoid excessive shift. diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index b2ec6a29fbf..66272f5c661 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -3801,16 +3801,6 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) if (!riscv_merge_attributes (ibfd, info)) return FALSE; - new_flags = elf_elfheader (ibfd)->e_flags; - old_flags = elf_elfheader (obfd)->e_flags; - - if (! elf_flags_init (obfd)) - { - elf_flags_init (obfd) = TRUE; - elf_elfheader (obfd)->e_flags = new_flags; - return TRUE; - } - /* Check to see if the input BFD actually contains any sections. If not, its flags may not have been initialized either, but it cannot actually cause any incompatibility. Do not short-circuit dynamic objects; their @@ -3826,19 +3816,31 @@ _bfd_riscv_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) for (sec = ibfd->sections; sec != NULL; sec = sec->next) { + null_input_bfd = FALSE; + if ((bfd_section_flags (sec) & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)) == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)) - only_data_sections = FALSE; - - null_input_bfd = FALSE; - break; + { + only_data_sections = FALSE; + break; + } } if (null_input_bfd || only_data_sections) return TRUE; } + new_flags = elf_elfheader (ibfd)->e_flags; + old_flags = elf_elfheader (obfd)->e_flags; + + if (!elf_flags_init (obfd)) + { + elf_flags_init (obfd) = TRUE; + elf_elfheader (obfd)->e_flags = new_flags; + return TRUE; + } + /* Disallow linking different float ABIs. */ if ((old_flags ^ new_flags) & EF_RISCV_FLOAT_ABI) {