[PATCH] RISCV/ld: allow the first input non-ABI binary to be linked with any one.

Nelson Chu nelson.chu@sifive.com
Fri Jan 22 07:43:33 GMT 2021


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/
    * 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.
---
 bfd/elfnn-riscv.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index b2ec6a2..66272f5 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)
     {
-- 
2.7.4



More information about the Binutils mailing list