LoongArch: Update ELF e_flags handling according to specification.
authorliuzhensong <liuzhensong@loongson.cn>
Thu, 4 Aug 2022 06:30:39 +0000 (14:30 +0800)
committerliuzhensong <liuzhensong@loongson.cn>
Fri, 30 Sep 2022 06:00:47 +0000 (14:00 +0800)
  Update handling of e_flags according to the documentation
  update [1] (discussions [2][3]).

  Object file bitness is now represented in the EI_CLASS byte.
  The e_flags field is now interpreted as follows:

  e_flags[2:0]: Base ABI modifier

  - 0x1: soft-float
  - 0x2: single-precision hard-float
  - 0x3: double-precision hard-float

  e_flags[7:6]: ELF object ABI version

  - 0x0: v0
  - 0x1: v1

  [1]: https://github.com/loongson/LoongArch-Documentation/blob/main/docs/LoongArch-ELF-ABI-EN.adoc#e_flags-identifies-abi-type-and-version
  [2]: https://github.com/loongson/LoongArch-Documentation/pull/61
  [3]: https://github.com/loongson/LoongArch-Documentation/pull/47

bfd/elfnn-loongarch.c
binutils/readelf.c
gas/config/tc-loongarch.c
include/elf/loongarch.h

index 33c85e5207c79cb628226e327390df37fb300ef2..c040c5b4ec8e1bd48e475b246c8251311e46e153 100644 (file)
@@ -416,8 +416,22 @@ elfNN_loongarch_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
       elf_elfheader (obfd)->e_flags = in_flags;
       return true;
     }
+  else if (out_flags != in_flags)
+    {
+      if ((EF_LOONGARCH_IS_OBJ_V0 (out_flags)
+          && EF_LOONGARCH_IS_OBJ_V1 (in_flags))
+         || (EF_LOONGARCH_IS_OBJ_V0 (in_flags)
+             && EF_LOONGARCH_IS_OBJ_V1 (out_flags)))
+       {
+         elf_elfheader (obfd)->e_flags |= EF_LOONGARCH_OBJABI_V1;
+         out_flags = elf_elfheader (obfd)->e_flags;
+         in_flags = out_flags;
+       }
+    }
 
   /* Disallow linking different ABIs.  */
+  /* Only check relocation version.
+     The obj_v0 is compatible with obj_v1.  */
   if (EF_LOONGARCH_ABI(out_flags ^ in_flags) & EF_LOONGARCH_ABI_MASK)
     {
       _bfd_error_handler (_("%pB: can't link different ABI object."), ibfd);
@@ -1579,15 +1593,16 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
       if (bfd_link_executable (info) && !info->nointerp)
        {
          const char *interpreter;
-         flagword flags = elf_elfheader (output_bfd)->e_flags;
          s = bfd_get_linker_section (dynobj, ".interp");
          BFD_ASSERT (s != NULL);
-         if (EF_LOONGARCH_IS_ILP32 (flags))
+
+         if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS32)
            interpreter = "/lib32/ld.so.1";
-         else if (EF_LOONGARCH_IS_LP64 (flags))
+         else if (elf_elfheader (output_bfd)->e_ident[EI_CLASS] == ELFCLASS64)
            interpreter = "/lib64/ld.so.1";
          else
            interpreter = "/lib/ld.so.1";
+
          s->contents = (unsigned char *) interpreter;
          s->size = strlen (interpreter) + 1;
        }
index b1dbcad06f5306bf84e25d7e122d4cbe3aff2949..351571c8abbc4665a4fc0209b7e621feb74b0757 100644 (file)
@@ -4343,11 +4343,6 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine)
            }
          break;
        case EM_LOONGARCH:
-         if (EF_LOONGARCH_IS_LP64 (e_flags))
-           strcat (buf, ", LP64");
-         else if (EF_LOONGARCH_IS_ILP32 (e_flags))
-           strcat (buf, ", ILP32");
-
          if (EF_LOONGARCH_IS_SOFT_FLOAT (e_flags))
            strcat (buf, ", SOFT-FLOAT");
          else if (EF_LOONGARCH_IS_SINGLE_FLOAT (e_flags))
@@ -4355,6 +4350,11 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine)
          else if (EF_LOONGARCH_IS_DOUBLE_FLOAT (e_flags))
            strcat (buf, ", DOUBLE-FLOAT");
 
+         if (EF_LOONGARCH_IS_OBJ_V0 (e_flags))
+           strcat (buf, ", OBJ-v0");
+         else if (EF_LOONGARCH_IS_OBJ_V1 (e_flags))
+           strcat (buf, ", OBJ-v1");
+
          break;
        }
     }
index 5bb8d317c5a97f39c763de48e883ef652b4d9fb3..60149a6d8db1da732f5b0ff85b3a2fb73ee794a7 100644 (file)
@@ -143,13 +143,13 @@ md_parse_option (int c, const char *arg)
   char ilp32[256] = "";
   unsigned char *suf = (unsigned char *)arg;
 
-  lp64['s'] = lp64['S'] = EF_LOONGARCH_ABI_LP64_SOFT_FLOAT;
-  lp64['f'] = lp64['F'] = EF_LOONGARCH_ABI_LP64_SINGLE_FLOAT;
-  lp64['d'] = lp64['D'] = EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT;
+  lp64['s'] = lp64['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT;
+  lp64['f'] = lp64['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT;
+  lp64['d'] = lp64['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
 
-  ilp32['s'] = ilp32['S'] = EF_LOONGARCH_ABI_ILP32_SOFT_FLOAT;
-  ilp32['f'] = ilp32['F'] = EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT;
-  ilp32['d'] = ilp32['D'] = EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT;
+  ilp32['s'] = ilp32['S'] = EF_LOONGARCH_ABI_SOFT_FLOAT;
+  ilp32['f'] = ilp32['F'] = EF_LOONGARCH_ABI_SINGLE_FLOAT;
+  ilp32['d'] = ilp32['D'] = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
 
   switch (c)
     {
@@ -216,24 +216,24 @@ void
 loongarch_after_parse_args ()
 {
   /* Set default ABI/ISA LP64D.  */
-  if (!EF_LOONGARCH_IS_LP64(LARCH_opts.ase_abi)
-      && !EF_LOONGARCH_IS_ILP32(LARCH_opts.ase_abi))
+  if (!LARCH_opts.ase_ilp32)
     {
       if (strcmp (default_arch, "loongarch64") == 0)
        {
-         LARCH_opts.ase_abi = EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT;
+         LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
          LARCH_opts.ase_ilp32 = 1;
          LARCH_opts.ase_lp64 = 1;
        }
       else if (strcmp (default_arch, "loongarch32") == 0)
        {
-         LARCH_opts.ase_abi = EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT;
+         LARCH_opts.ase_abi = EF_LOONGARCH_ABI_DOUBLE_FLOAT;
          LARCH_opts.ase_ilp32 = 1;
        }
       else
        as_bad ("unknown default architecture `%s'", default_arch);
     }
 
+  LARCH_opts.ase_abi |= EF_LOONGARCH_OBJABI_V1;
   /* Set default ISA double-float.  */
   if (!LARCH_opts.ase_nf
       && !LARCH_opts.ase_sf
index 74757b82ca8c05fc81240e96c601547fe0e45726..a6341b46791d3f820f6e120cdc82ca30020ca7ab 100644 (file)
@@ -232,36 +232,34 @@ RELOC_NUMBER (R_LARCH_RELAX, 100)
 END_RELOC_NUMBERS (R_LARCH_count)
 
 /* Processor specific flags for the ELF header e_flags field.  */
-/*The flag lp64s/lp64f/lp64d/ilp32s/ilp32f/ilp32d 3bits. */
-#define EF_LOONGARCH_ABI_LP64_SOFT_FLOAT       0x1
-#define EF_LOONGARCH_ABI_LP64_SINGLE_FLOAT     0x2
-#define EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT     0x3
+/* Base ABI modifier, 3bits.  */
+#define EF_LOONGARCH_ABI_SOFT_FLOAT    0x1
+#define EF_LOONGARCH_ABI_SINGLE_FLOAT  0x2
+#define EF_LOONGARCH_ABI_DOUBLE_FLOAT  0x3
+#define EF_LOONGARCH_ABI_MODIFIER_MASK 0x7
 
-#define EF_LOONGARCH_ABI_ILP32_SOFT_FLOAT      0x5
-#define EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT    0x6
-#define EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT    0x7
+#define EF_LOONGARCH_OBJABI_V1         0x40
+#define EF_LOONGARCH_OBJABI_MASK       0xC0
 
-#define EF_LOONGARCH_ABI_MASK                  0x7
-#define EF_LOONGARCH_ABI_ILP32_MASK            0x4
-#define EF_LOONGARCH_ABI_FLOAT_MASK            0x3
-#define EF_LOONGARCH_ABI_SOFT_FLOAT_MASK       0x1
-#define EF_LOONGARCH_ABI_SINGLE_FLOAT_MASK     0x2
-#define EF_LOONGARCH_ABI_DOUBLE_FLOAT_MASK     0x3
+#define EF_LOONGARCH_ABI_MASK \
+      (EF_LOONGARCH_OBJABI_MASK | EF_LOONGARCH_ABI_MODIFIER_MASK)
 
-#define EF_LOONGARCH_ABI(abi)  (EF_LOONGARCH_ABI_MASK & (abi))
+#define EF_LOONGARCH_ABI_MODIFIER(abi) \
+      (EF_LOONGARCH_ABI_MODIFIER_MASK & (abi))
+#define EF_LOONGARCH_OBJABI(abi) \
+      (EF_LOONGARCH_OBJABI_MASK & (abi))
 
-#define EF_LOONGARCH_IS_LP64(abi) \
-  (EF_LOONGARCH_ABI(abi) && (!(EF_LOONGARCH_ABI(abi) & EF_LOONGARCH_ABI_ILP32_MASK)))
-#define EF_LOONGARCH_IS_ILP32(abi) \
-  (EF_LOONGARCH_ABI(abi) && (EF_LOONGARCH_ABI(abi) & EF_LOONGARCH_ABI_ILP32_MASK))
+#define EF_LOONGARCH_ABI(abi) ((abi) & EF_LOONGARCH_ABI_MASK)
 
 #define EF_LOONGARCH_IS_SOFT_FLOAT(abi) \
-  (!((EF_LOONGARCH_ABI(abi) & EF_LOONGARCH_ABI_FLOAT_MASK) ^ EF_LOONGARCH_ABI_SOFT_FLOAT_MASK))
-
+  (EF_LOONGARCH_ABI_MODIFIER (abi) == EF_LOONGARCH_ABI_SOFT_FLOAT)
 #define EF_LOONGARCH_IS_SINGLE_FLOAT(abi) \
-  (!((EF_LOONGARCH_ABI(abi) & EF_LOONGARCH_ABI_FLOAT_MASK) ^ EF_LOONGARCH_ABI_SINGLE_FLOAT_MASK))
-
+  (EF_LOONGARCH_ABI_MODIFIER (abi) == EF_LOONGARCH_ABI_SINGLE_FLOAT)
 #define EF_LOONGARCH_IS_DOUBLE_FLOAT(abi) \
-  (!((EF_LOONGARCH_ABI(abi) & EF_LOONGARCH_ABI_FLOAT_MASK) ^ EF_LOONGARCH_ABI_DOUBLE_FLOAT_MASK))
+  (EF_LOONGARCH_ABI_MODIFIER (abi) == EF_LOONGARCH_ABI_DOUBLE_FLOAT)
+
+#define EF_LOONGARCH_IS_OBJ_V0(abi) (!EF_LOONGARCH_OBJABI (abi))
+#define EF_LOONGARCH_IS_OBJ_V1(abi) \
+      (EF_LOONGARCH_OBJABI (abi) == EF_LOONGARCH_OBJABI_V1)
 
 #endif /* _ELF_LOONGARCH_H */