[1/5] backends: Add abi_cfi and register_info callbacks for LoongArch

Message ID 1680836368-5373-2-git-send-email-tangyouling@loongson.cn
State Committed
Headers
Series Improve LoongArch support |

Commit Message

Youling Tang April 7, 2023, 2:59 a.m. UTC
  LoongArch Reference Manual - Volume 1:
https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html

LoongArch ELF ABI:
https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html

Signed-off-by: Liwei Ge <geliwei@openanolis.org>
Signed-off-by: Youling Tang <tangyouling@loongson.cn>
---
 backends/ChangeLog        |   9 ++-
 backends/Makefile.am      |   3 +-
 backends/loongarch_cfi.c  |  83 ++++++++++++++++++++++
 backends/loongarch_init.c |   4 ++
 backends/loongarch_regs.c | 141 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 238 insertions(+), 2 deletions(-)
 create mode 100644 backends/loongarch_cfi.c
 create mode 100644 backends/loongarch_regs.c
  

Comments

Mark Wielaard May 8, 2023, 7:48 p.m. UTC | #1
On Fri, Apr 07, 2023 at 10:59:24AM +0800, Youling Tang wrote:
> LoongArch Reference Manual - Volume 1:
> https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
> 
> LoongArch ELF ABI:
> https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html

Looks good. Thanks for the references.

Cheers,

Mark
  

Patch

diff --git a/backends/ChangeLog b/backends/ChangeLog
index 7bde2919..926c76ed 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,4 +1,11 @@ 
-2023-04-01  Youling Tang <tangyouling@loongson.cn>
+2023-04-07  Youling Tang  <tangyouling@loongson.cn>
+
+	* Makefile.am (loongarch_SRCS): Add loongarch_cfi.c and loongarch_regs.c.
+	* loongarch_cfi.c: New file.
+	* loongarch_regs.c: Likewise.
+	* loongarch_init.c (loongarch_init): Hook register_info and abi_cfi.
+
+2023-04-01  Youling Tang  <tangyouling@loongson.cn>
 
 	* loongarch_init.c (loongarch_init): Hook check_special_symbol.
 	* loongarch_symbol.c (loongarch_check_special_symbol): New function.
diff --git a/backends/Makefile.am b/backends/Makefile.am
index f373e5fb..2b6f08ce 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -96,7 +96,8 @@  riscv_SRCS = riscv_init.c riscv_symbol.c riscv_cfi.c riscv_regs.c \
 csky_SRCS = csky_attrs.c csky_init.c csky_symbol.c csky_cfi.c \
 	    csky_regs.c csky_initreg.c csky_corenote.c
 
-loongarch_SRCS = loongarch_init.c loongarch_symbol.c
+loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
+	    loongarch_regs.c
 
 arc_SRCS = arc_init.c arc_symbol.c
 
diff --git a/backends/loongarch_cfi.c b/backends/loongarch_cfi.c
new file mode 100644
index 00000000..5f3cd2c7
--- /dev/null
+++ b/backends/loongarch_cfi.c
@@ -0,0 +1,83 @@ 
+/* LoongArch ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2023 OpenAnolis community LoongArch SIG.
+   Copyright (C) 2023 Loongson Technology Corporation Limted.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND loongarch_
+#include "libebl_CPU.h"
+
+/* LoongArch ELF ABI specification:
+https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_register_convention
+*/
+int
+loongarch_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* The initial Canonical Frame Address is the value of the
+         Stack Pointer ($r3) as setup in the previous frame. */
+      DW_CFA_def_cfa, ULEB128_7 (3), ULEB128_7 (0),
+
+      /* The Stack Pointer ($r3) is restored from CFA address by default.  */
+      DW_CFA_val_offset, ULEB128_7 (3), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* The return address register contains the return address setup by
+	 caller.  */
+      SV (1),
+
+      /* Callee-saved registers $s0-$s7.  */
+      SV (23), SV (24), SV (25), SV (26), SV (27), SV (28),
+      SV (29), SV (30), SV (31),
+
+      /* The Frame Pointer ($fp, $r22) */
+      SV(22),
+
+      /* Callee-saved registers $fs0-$fs7.  */
+      SV (56), SV (57), SV (58), SV (59), SV (60), SV (61),
+      SV (62), SV (63),
+#undef SV
+
+      /* XXX Note: registers intentionally unused by the program,
+	 for example as a consequence of the procedure call standard
+	 should be initialized as if by DW_CFA_same_value.  */
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = -4;
+
+  abi_info->return_address_register = 1; /* ra.  */
+
+  return 0;
+}
diff --git a/backends/loongarch_init.c b/backends/loongarch_init.c
index b641b07f..7bfaaa7f 100644
--- a/backends/loongarch_init.c
+++ b/backends/loongarch_init.c
@@ -46,6 +46,10 @@  loongarch_init (Elf *elf __attribute__ ((unused)),
   loongarch_init_reloc (eh);
   HOOK (eh, reloc_simple_type);
   HOOK (eh, machine_flag_check);
+  HOOK (eh, register_info);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = 74;
   HOOK (eh, check_special_symbol);
 
   return eh;
diff --git a/backends/loongarch_regs.c b/backends/loongarch_regs.c
new file mode 100644
index 00000000..4a4b2052
--- /dev/null
+++ b/backends/loongarch_regs.c
@@ -0,0 +1,141 @@ 
+/* Register names and numbers for LoongArch DWARF.
+   Copyright (C) 2023 OpenAnolis community LoongArch SIG.
+   Copyright (C) 2023 Loongson Technology Corporation Limted.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND loongarch_
+#include "libebl_CPU.h"
+
+ssize_t
+loongarch_register_info (Ebl *ebl, int regno, char *name, size_t namelen,
+		     const char **prefix, const char **setname,
+		     int *bits, int *type)
+{
+  if (name == NULL)
+    return 64;
+
+  *prefix = "";
+
+  if (regno < 32)
+    {
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = ebl->class == ELFCLASS64 ? 64 : 32;
+    }
+  else
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+      *bits = 64;
+    }
+
+  switch (regno)
+    {
+    case 0:
+      return stpcpy (name, "zero") + 1 - name;
+
+    case 1:
+      *type = DW_ATE_address;
+      return stpcpy (name, "ra") + 1 - name;
+
+    case 2:
+      *type = DW_ATE_address;
+      return stpcpy (name, "tp") + 1 - name;
+
+    case 3:
+      *type = DW_ATE_address;
+      return stpcpy (name, "sp") + 1 - name;
+
+    case 4 ... 11:
+      name[0] = 'a';
+      name[1] = regno - 4 + '0';
+      namelen = 2;
+      break;
+
+    case 12 ... 20:
+      name[0] = 't';
+      name[1] = regno - 12 + '0';
+      namelen = 2;
+      break;
+
+    case 21:
+      return stpcpy (name, "u0") + 1 - name;
+
+    case 22:
+      *type = DW_ATE_address;
+      return stpcpy (name, "fp") + 1 - name;
+
+    case 23 ... 31:
+      name[0] = 's';
+      name[1] = regno - 23 + '0';
+      namelen = 2;
+      break;
+
+    case 32 ... 39:
+      name[0] = 'f';
+      name[1] = 'a';
+      name[2] = regno - 32 + '0';
+      namelen = 3;
+      break;
+
+    case 40 ... 49:
+      name[0] = 'f';
+      name[1] = 't';
+      name[2] = regno - 40 + '0';
+      namelen = 3;
+      break;
+
+    case 50 ... 55:
+      name[0] = 'f';
+      name[1] = 't';
+      name[2] = '1';
+      name[3] = regno - 50 + '0';
+      namelen = 4;
+      break;
+
+    case 56 ... 63:
+      name[0] = 'f';
+      name[1] = 's';
+      name[2] = regno - 56 + '0';
+      namelen = 3;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}