public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] arc: Add support for Linux coredump files
@ 2020-08-27 11:27 Shahab Vahedi
  2020-09-07  9:14 ` Shahab Vahedi
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Shahab Vahedi @ 2020-08-27 11:27 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Francois Bedard, Anton Kolesov

From: Anton Kolesov <Anton.Kolesov@synopsys.com>

With the implemenations in this patch, ARC gdb can handle
coredump related matters.  The binutils counter part of
this patch has already been pushed [1].

[1] arc: Add support for ARC HS extra registers in core files
https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=2745674244d6aecddcf636475034bdb9c0a6b4a0

gdb/ChangeLog:

Anton Kolesov  <anton.kolesov@synopsys.com>

	* arc-linux-tdep.h: New file.
	* arc-linux-tdep.c (arc_linux_core_reg_offsets,
	arc_linux_supply_gregset, arc_linux_supply_v2_regset,
	arc_linux_collect_gregset, arc_linux_collect_v2_regset,
	arc_linux_gregset, arc_linux_v2_regset,
	arc_linux_iterate_over_regset_sections,
	arc_linux_core_read_description): Implement.
	(arc_linux_init_osabi): Set iterate_over_regset_sections.
	* arc-tdep.c (ARC_OFFSET_NO_REGISTER): Declare.
---
 gdb/arc-linux-tdep.c | 193 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-linux-tdep.h |  52 ++++++++++++
 gdb/arc-tdep.c       |   5 +-
 gdb/arc-tdep.h       |   8 ++
 4 files changed, 255 insertions(+), 3 deletions(-)
 create mode 100644 gdb/arc-linux-tdep.h

diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
index 36f32459bbe..8dcd9785458 100644
--- a/gdb/arc-linux-tdep.c
+++ b/gdb/arc-linux-tdep.c
@@ -27,7 +27,61 @@
 
 /* ARC header files.  */
 #include "opcodes/arc-dis.h"
+#include "arc-linux-tdep.h"
 #include "arc-tdep.h"
+#include "arch/arc.h"
+
+#define REGOFF(offset) (offset * ARC_REGISTER_SIZE)
+
+/* arc_linux_core_reg_offsets[i] is the offset in the .reg section of GDB
+   regnum i.  Array index is an internal GDB register number, as defined in
+   arc-tdep.h:arc_regnum.
+
+   From include/uapi/asm/ptrace.h in the ARC Linux sources.  */
+
+static const int arc_linux_core_reg_offsets[] = {
+  /* R0 - R12.  */
+  REGOFF (22), REGOFF (21), REGOFF (20), REGOFF (19),
+  REGOFF (18), REGOFF (17), REGOFF (16), REGOFF (15),
+  REGOFF (14), REGOFF (13), REGOFF (12), REGOFF (11),
+  REGOFF (10),
+
+  /* R13 - R25.  */
+  REGOFF (37), REGOFF (36), REGOFF (35), REGOFF (34),
+  REGOFF (33), REGOFF (32), REGOFF (31), REGOFF (30),
+  REGOFF (29), REGOFF (28), REGOFF (27), REGOFF (26),
+  REGOFF (25),
+
+  REGOFF (9),			/* R26 (GP) */
+  REGOFF (8),			/* FP */
+  REGOFF (23),			/* SP */
+  ARC_OFFSET_NO_REGISTER,	/* ILINK */
+  ARC_OFFSET_NO_REGISTER,	/* R30 */
+  REGOFF (7),			/* BLINK */
+
+  /* R32 - R59.  */
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER, ARC_OFFSET_NO_REGISTER,
+  ARC_OFFSET_NO_REGISTER,
+
+  REGOFF (4),			/* LP_COUNT */
+  ARC_OFFSET_NO_REGISTER,	/* RESERVED */
+  ARC_OFFSET_NO_REGISTER,	/* LIMM */
+  ARC_OFFSET_NO_REGISTER,	/* PCL */
+
+  REGOFF (39),			/* PC  */
+  REGOFF (5),			/* STATUS32 */
+  REGOFF (2),			/* LP_START */
+  REGOFF (3),			/* LP_END */
+  REGOFF (1),			/* BTA */
+};
 
 /* Implement the "cannot_fetch_register" gdbarch method.  */
 
@@ -227,6 +281,142 @@ arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
     }
 }
 
+void
+arc_linux_supply_gregset (const struct regset *regset,
+			  struct regcache *regcache,
+			  int regnum, const void *gregs, size_t size)
+{
+  gdb_static_assert (ARC_LAST_REGNUM
+		     <= ARRAY_SIZE (arc_linux_core_reg_offsets));
+
+  const bfd_byte *buf = (const bfd_byte *) gregs;
+
+  for (int reg = 0; reg <= ARC_LAST_REGNUM; reg++)
+    {
+      if (arc_linux_core_reg_offsets[reg] != ARC_OFFSET_NO_REGISTER)
+	regcache->raw_supply (reg, buf + arc_linux_core_reg_offsets[reg]);
+    }
+}
+
+void
+arc_linux_supply_v2_regset (const struct regset *regset,
+			    struct regcache *regcache, int regnum,
+			    const void *v2_regs, size_t size)
+{
+  const bfd_byte *buf = (const bfd_byte *) v2_regs;
+
+  /* user_regs_arcv2 is defined in linux arch/arc/include/uapi/asm/ptrace.h.  */
+  regcache->raw_supply (ARC_R30_REGNUM, buf);
+  regcache->raw_supply (ARC_R58_REGNUM, buf + REGOFF (1));
+  regcache->raw_supply (ARC_R59_REGNUM, buf + REGOFF (2));
+}
+
+/* Populate BUF with register REGNUM from the REGCACHE.  */
+
+static void
+collect_register(const struct regcache *regcache, struct gdbarch *gdbarch,
+		 int regnum, gdb_byte *buf)
+{
+  /* Skip non-existing registers.  */
+  if ((arc_linux_core_reg_offsets[regnum] == ARC_OFFSET_NO_REGISTER))
+    return;
+
+  /* The Address where the execution has stopped is in pseudo-register
+     STOP_PC.  However, when kernel code is returning from the exception,
+     it uses the value from ERET register.  Since, TRAP_S (the breakpoint
+     instruction) commits, the ERET points to the next instruction.  In
+     other words: ERET != STOP_PC.  To jump back from the kernel code to
+     the correct address, ERET must be overwritten by GDB's STOP_PC.  Else,
+     the program will continue at the address after the current instruction.
+     */
+  if (regnum == gdbarch_pc_regnum (gdbarch))
+    {
+      int eret_offset = REGOFF (6);
+      regcache->raw_collect (regnum, buf + eret_offset);
+    }
+  else
+    regcache->raw_collect (regnum, buf + arc_linux_core_reg_offsets[regnum]);
+}
+
+void
+arc_linux_collect_gregset (const struct regset *regset,
+			   const struct regcache *regcache,
+			   int regnum, void *gregs, size_t size)
+{
+  gdb_static_assert (ARC_LAST_REGNUM
+		     <= ARRAY_SIZE (arc_linux_core_reg_offsets));
+
+  gdb_byte *buf = (gdb_byte *) gregs;
+  struct gdbarch *gdbarch = regcache->arch ();
+
+  /* regnum == -1 means writing all the registers.  */
+  if (regnum == -1)
+    for (int reg = 0; reg < ARC_LAST_REGNUM; reg++)
+      collect_register (regcache, gdbarch, reg, buf);
+  else if (regnum < ARC_LAST_REGNUM)
+    collect_register (regcache, gdbarch, regnum, buf);
+  else
+    gdb_assert (!"Invalid regnum in arc_linux_collect_gregset.");
+}
+
+void
+arc_linux_collect_v2_regset (const struct regset *regset,
+			     const struct regcache *regcache, int regnum,
+			     void *v2_regs, size_t size)
+{
+  bfd_byte *buf = (bfd_byte *) v2_regs;
+
+  regcache->raw_collect (ARC_R30_REGNUM, buf);
+  regcache->raw_collect (ARC_R58_REGNUM, buf + REGOFF (1));
+  regcache->raw_collect (ARC_R59_REGNUM, buf + REGOFF (2));
+}
+
+/* Linux regset definitions.  */
+
+static const struct regset arc_linux_gregset = {
+  arc_linux_core_reg_offsets,
+  arc_linux_supply_gregset,
+  arc_linux_collect_gregset,
+};
+
+static const struct regset arc_linux_v2_regset = {
+  NULL,
+  arc_linux_supply_v2_regset,
+  arc_linux_collect_v2_regset,
+};
+
+/* Implement the `iterate_over_regset_sections` gdbarch method.  */
+
+static void
+arc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
+					iterate_over_regset_sections_cb *cb,
+					void *cb_data,
+					const struct regcache *regcache)
+{
+  /* There are 40 registers in Linux user_regs_struct, although some of
+     them are now just a mere paddings, kept to maintain binary
+     compatibility with older tools.  */
+  const int sizeof_gregset = 40 * ARC_REGISTER_SIZE;
+
+  cb (".reg", sizeof_gregset, sizeof_gregset, &arc_linux_gregset, NULL,
+      cb_data);
+  cb (".reg-arc-v2", ARC_LINUX_SIZEOF_V2_REGSET, ARC_LINUX_SIZEOF_V2_REGSET,
+      &arc_linux_v2_regset, NULL, cb_data);
+}
+
+/* Implement the `core_read_description` gdbarch method.  */
+
+static const struct target_desc *
+arc_linux_core_read_description (struct gdbarch *gdbarch,
+				 struct target_ops *target,
+				 bfd *abfd)
+{
+  arc_gdbarch_features features
+    = arc_gdbarch_features_create (abfd,
+			           gdbarch_bfd_arch_info (gdbarch)->mach);
+  return arc_lookup_target_description (features);
+}
+
 /* Initialization specific to Linux environment.  */
 
 static void
@@ -260,6 +450,9 @@ arc_linux_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_software_single_step (gdbarch, arc_linux_software_single_step);
   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
   set_gdbarch_skip_solib_resolver (gdbarch, arc_linux_skip_solib_resolver);
+  set_gdbarch_iterate_over_regset_sections
+    (gdbarch, arc_linux_iterate_over_regset_sections);
+  set_gdbarch_core_read_description (gdbarch, arc_linux_core_read_description);
 
   /* GNU/Linux uses SVR4-style shared libraries, with 32-bit ints, longs
      and pointers (ILP32).  */
diff --git a/gdb/arc-linux-tdep.h b/gdb/arc-linux-tdep.h
new file mode 100644
index 00000000000..c26cacd7029
--- /dev/null
+++ b/gdb/arc-linux-tdep.h
@@ -0,0 +1,52 @@
+/* Target dependent code for GNU/Linux ARC.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef ARC_LINUX_TDEP_H
+#define ARC_LINUX_TDEP_H
+
+#include "gdbarch.h"
+#include "regset.h"
+
+#define ARC_LINUX_SIZEOF_V2_REGSET (3 * ARC_REGISTER_SIZE)
+
+/* Reads registers from the NT_PRSTATUS data array into the regcache.  */
+
+void arc_linux_supply_gregset (const struct regset *regset,
+			       struct regcache *regcache, int regnum,
+			       const void *gregs, size_t size);
+
+/* Reads regsiters from the NT_ARC_V2 data array into the regcache.  */
+
+void arc_linux_supply_v2_regset (const struct regset *regset,
+				 struct regcache *regcache, int regnum,
+				 const void *v2_regs, size_t size);
+
+/* Writes registers from the regcache into the NT_PRSTATUS data array.  */
+
+void arc_linux_collect_gregset (const struct regset *regset,
+				const struct regcache *regcache,
+				int regnum, void *gregs, size_t size);
+
+/* Writes registers from the regcache into the NT_ARC_V2 data array.  */
+
+void arc_linux_collect_v2_regset (const struct regset *regset,
+				  const struct regcache *regcache,
+				  int regnum, void *v2_regs, size_t size);
+
+#endif /* ARC_LINUX_TDEP_H */
diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c
index 6f544bff78d..91e106a0167 100644
--- a/gdb/arc-tdep.c
+++ b/gdb/arc-tdep.c
@@ -1883,10 +1883,9 @@ mach_type_to_arc_isa (const unsigned long mach)
     }
 }
 
-/* Common construction code for ARC_GDBARCH_FEATURES struct.  If there
-   is no ABFD, then a FEATURE with default values is returned.  */
+/* See arc-tdep.h.  */
 
-static arc_gdbarch_features
+arc_gdbarch_features
 arc_gdbarch_features_create (const bfd *abfd, const unsigned long mach)
 {
   /* Use 4 as a fallback value.  */
diff --git a/gdb/arc-tdep.h b/gdb/arc-tdep.h
index 6331d29f402..d8a0c42909d 100644
--- a/gdb/arc-tdep.h
+++ b/gdb/arc-tdep.h
@@ -105,6 +105,9 @@ enum arc_regnum
 /* STATUS32 register: current instruction is a delay slot.  */
 #define ARC_STATUS32_DE_MASK (1 << 6)
 
+/* Special value for register offset arrays.  */
+#define ARC_OFFSET_NO_REGISTER (-1)
+
 #define arc_print(fmt, args...) fprintf_unfiltered (gdb_stdlog, fmt, ##args)
 
 extern int arc_debug;
@@ -182,4 +185,9 @@ CORE_ADDR arc_insn_get_branch_target (const struct arc_instruction &insn);
 
 CORE_ADDR arc_insn_get_linear_next_pc (const struct arc_instruction &insn);
 
+/* Create an arc_gdbarch_features instance from the provided data.  */
+
+arc_gdbarch_features arc_gdbarch_features_create (const bfd *abfd,
+						  const unsigned long mach);
+
 #endif /* ARC_TDEP_H */
-- 
2.28.0


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2020-10-07 16:32 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-27 11:27 [PATCH] arc: Add support for Linux coredump files Shahab Vahedi
2020-09-07  9:14 ` Shahab Vahedi
2020-09-16  2:31 ` [PING^2][PATCH] " Shahab Vahedi
2020-09-16 20:21 ` [PATCH] " Simon Marchi
2020-09-17 11:55   ` Aktemur, Tankut Baris
2020-09-28 13:47     ` Shahab Vahedi
2020-09-28 14:08       ` Aktemur, Tankut Baris
2020-09-28 19:10         ` Simon Marchi
2020-09-29  8:24           ` Shahab Vahedi
2020-09-29  9:02             ` Shahab Vahedi
2020-09-29 14:22             ` Simon Marchi
2020-09-29 15:42               ` Shahab Vahedi
2020-10-01 13:30   ` Shahab Vahedi
2020-09-29 16:15 ` [PATCH v2] " Shahab Vahedi
2020-10-05  2:13   ` Simon Marchi
2020-10-07 16:11 ` [PUSHED master] " Shahab Vahedi
2020-10-07 16:32 ` [PUSHED gdb-10-branch] " Shahab Vahedi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).