public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Add native GNU/Linux support for ARC in GDB
@ 2020-11-12 13:48 Shahab Vahedi
  2020-11-12 13:48 ` [PATCH 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Shahab Vahedi @ 2020-11-12 13:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This patch series is mainly about adding a native GNU/Linux support for
ARC in GDB ("[PATCH 2/2] gdb: Add native support for ARC in GNU/Linux").

During the process of mulling over that change, I noticed that the ARC
target support could become more efficient in some of the target hooks
in "arc-linux-tdep.c"; namely the "arc_linux_supply_*()" and the
"arc_linux_collect_v2_regset()".  In those hooks, REGNUM is completely
ignored and every register is fetched/overwritten.  These hooks are
used by the "arc-linux-nat.c" (the second patch) and it relies on them:
Therefore, the first patch of this series: "[PATCH 1/2]: arc: Take into
account the REGNUM in supply/collect gdb hooks".

To summarize:
[PATCH 1/2] -> Respect REGNUM in hooks.
[PATCH 2/2] -> Add native ARC GNU/Linux support while using those hooks.

One last remark: The native GDB works correctly along with this
fix [1].  Therefore, if you want to give it a try, please also apply
that patch.

[1] [PATCH] arc: Write correct "eret" value during register collection
https://sourceware.org/pipermail/gdb-patches/2020-November/173202.html

How to build:
Get the "Linux/{glibc,uClibc} ARC HS" toolchain from:
https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases
and extract it somewhere.

Update the PATHs so you can find "arc-linux-gcc":
$ export PATH=/extracted/dir/bin:$PATH
$ export LD_LIBRARY_PATH=/extracted/dir/lib:$LD_LIBRARY_PATH

$ cd /to/gdb/src
$ host=arc-snps-linux-gnu            # or arc-snps-linux-uclibc
$ configure --prefix=/usr            \
            --host=$host             \
            --disable-build-with-cxx \
            --disable-gas            \
            --disable-ld             \
            --disable-binutils
$ make -j $(nproc)
$ arc-linux-strip ./gdb/gdb

Anton Kolesov (1):
  gdb: Add native support for ARC in GNU/Linux

Shahab Vahedi (1):
  arc: Take into account the REGNUM in supply/collect gdb hooks

 gdb/Makefile.in      |   1 +
 gdb/arc-linux-nat.c  | 321 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-linux-tdep.c |  41 ++++--
 gdb/configure.host   |   3 +
 gdb/configure.nat    |   4 +
 5 files changed, 361 insertions(+), 9 deletions(-)
 create mode 100644 gdb/arc-linux-nat.c

-- 
2.29.2


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

* [PATCH 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks
  2020-11-12 13:48 [PATCH 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
@ 2020-11-12 13:48 ` Shahab Vahedi
  2020-11-12 17:33   ` Tom Tromey
  2020-11-12 13:48 ` [PATCH 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Shahab Vahedi @ 2020-11-12 13:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

All the arc_linux_supply_*() target operations and the
arc_linux_collect_v2_regset() in arc-linux-tdep.c were
supplying/collecting all the registers in regcache as if the
REGNUM was set to -1.

The more efficient behavior is to examine the REGNUM and act
accordingly.  That is what this patch does.

gdb/ChangeLog:

	* arc-linux-tdep.c (supply_register): New.
	(arc_linux_supply_gregset, arc_linux_supply_v2_regset,
	arc_linux_collect_v2_regset): Consider REGNUM.
---
 gdb/arc-linux-tdep.c | 41 ++++++++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
index b8ea2194934..e8e5461bc34 100644
--- a/gdb/arc-linux-tdep.c
+++ b/gdb/arc-linux-tdep.c
@@ -460,6 +460,18 @@ arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
     }
 }
 
+/* Populate REGCACHE with register REGNUM from BUF.  */
+
+static void
+supply_register (struct regcache *regcache, int regnum, const gdb_byte *buf)
+{
+  /* Skip non-existing registers.  */
+  if ((arc_linux_core_reg_offsets[regnum] == ARC_OFFSET_NO_REGISTER))
+    return;
+
+  regcache->raw_supply (regnum, buf + arc_linux_core_reg_offsets[regnum]);
+}
+
 void
 arc_linux_supply_gregset (const struct regset *regset,
 			  struct regcache *regcache,
@@ -470,9 +482,14 @@ arc_linux_supply_gregset (const struct regset *regset,
 
   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]);
+  /* regnum == -1 means writing all the registers.  */
+  if (regnum == -1)
+    for (int reg = 0; reg <= ARC_LAST_REGNUM; reg++)
+      supply_register (regcache, reg, buf);
+  else if (regnum <= ARC_LAST_REGNUM)
+    supply_register (regcache, regnum, buf);
+  else
+    gdb_assert_not_reached ("Invalid regnum in arc_linux_supply_gregset.");
 }
 
 void
@@ -483,9 +500,12 @@ arc_linux_supply_v2_regset (const struct regset *regset,
   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));
+  if (regnum == -1 || regnum == ARC_R30_REGNUM)
+    regcache->raw_supply (ARC_R30_REGNUM, buf);
+  if (regnum == -1 || regnum == ARC_R58_REGNUM)
+    regcache->raw_supply (ARC_R58_REGNUM, buf + REGOFF (1));
+  if (regnum == -1 || regnum == ARC_R59_REGNUM)
+    regcache->raw_supply (ARC_R59_REGNUM, buf + REGOFF (2));
 }
 
 /* Populate BUF with register REGNUM from the REGCACHE.  */
@@ -539,9 +559,12 @@ arc_linux_collect_v2_regset (const struct regset *regset,
 {
   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));
+  if (regnum == -1 || regnum == ARC_R30_REGNUM)
+    regcache->raw_collect (ARC_R30_REGNUM, buf);
+  if (regnum == -1 || regnum == ARC_R58_REGNUM)
+    regcache->raw_collect (ARC_R58_REGNUM, buf + REGOFF (1));
+  if (regnum == -1 || regnum == ARC_R59_REGNUM)
+    regcache->raw_collect (ARC_R59_REGNUM, buf + REGOFF (2));
 }
 
 /* Linux regset definitions.  */
-- 
2.29.2


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

* [PATCH 2/2] gdb: Add native support for ARC in GNU/Linux
  2020-11-12 13:48 [PATCH 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
  2020-11-12 13:48 ` [PATCH 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
@ 2020-11-12 13:48 ` Shahab Vahedi
  2020-11-12 18:03   ` Tom Tromey
  2020-12-07 16:37 ` [PATCH v2 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
  2020-12-22 11:21 ` [PUSHED v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
  3 siblings, 1 reply; 14+ messages in thread
From: Shahab Vahedi @ 2020-11-12 13:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

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

With this patch in place it is possible to build a GDB that
can run on ARC (GNU/Linux) hosts for debugging ARC targets.

The "arc-linux-nat.c" is a rather small one that mostly deals
with registers and a few thread related hooks.

gdb/ChangeLog:

	* Makefile.in (ALLDEPFILES): Add arc-linux-nat.c.
	* configure.host (host to gdb names): Add arc*-*-linux*.
	* configure.nat (gdb_host_cpu): Add arc.
	* arc-linux-nat.c: New.
---
 gdb/Makefile.in     |   1 +
 gdb/arc-linux-nat.c | 321 ++++++++++++++++++++++++++++++++++++++++++++
 gdb/configure.host  |   3 +
 gdb/configure.nat   |   4 +
 4 files changed, 329 insertions(+)
 create mode 100644 gdb/arc-linux-nat.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c46935efafa..44ba2f04ac9 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -2144,6 +2144,7 @@ ALLDEPFILES = \
 	amd64-ravenscar-thread.c \
 	amd64-sol2-tdep.c \
 	amd64-tdep.c \
+	arc-linux-nat.c \
 	arc-tdep.c \
 	arm.c \
 	arm-bsd-tdep.c \
diff --git a/gdb/arc-linux-nat.c b/gdb/arc-linux-nat.c
new file mode 100644
index 00000000000..365cc88477b
--- /dev/null
+++ b/gdb/arc-linux-nat.c
@@ -0,0 +1,321 @@
+/* Native-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/>.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "regcache.h"
+#include "gdbsupport/gdb_assert.h"
+#include "target.h"
+#include "linux-nat.h"
+#include "nat/gdb_ptrace.h"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include "gdbsupport/gdb_wait.h"
+#include <fcntl.h>
+#include <sys/procfs.h>
+#include <linux/elf.h>
+
+#include "gregset.h"
+#include "arc-tdep.h"
+#include "arc-linux-tdep.h"
+#include "arch/arc.h"
+
+/* Defines ps_err_e, struct ps_prochandle.  */
+#include "gdb_proc_service.h"
+
+/* Linux starting with 4.12 supports NT_ARC_V2 note type, which adds R30,
+   R58 and R59 registers, which are specific to ARC HS and aren't
+   available in ARC 700.  */
+#if defined (NT_ARC_V2) && defined (__ARCHS__)
+#define ARC_HAS_V2_REGSET
+#endif
+
+class arc_linux_nat_target final : public linux_nat_target
+{
+public:
+  /* Add ARC register access methods.  */
+  void fetch_registers (struct regcache *, int) override;
+  void store_registers (struct regcache *, int) override;
+
+  const struct target_desc *read_description () override;
+
+  /* Handle threads  */
+  void low_prepare_to_resume (struct lwp_info *lp) override;
+};
+
+static arc_linux_nat_target the_arc_linux_nat_target;
+
+/* Read general registers from target process/thread (via ptrace)
+   into REGCACHE.  */
+
+static void
+fetch_gregs (struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  gdb_gregset_t regs;
+
+  iov.iov_base = &regs;
+  iov.iov_len = sizeof (gdb_gregset_t);
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get general registers"));
+  else
+    arc_linux_supply_gregset (NULL, regcache, regnum, &regs, 0);
+}
+
+#ifdef ARC_HAS_V2_REGSET
+/* Read ARC v2 registers from target process/thread (via ptrace)
+   into REGCACHE.  */
+
+static void
+fetch_v2_regs (struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
+
+  iov.iov_base = &v2_buffer;
+  iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get ARC HS registers"));
+  else
+    arc_linux_supply_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
+}
+#endif
+
+/* Store general registers from REGCACHE into the target process/thread.  */
+
+static void
+store_gregs (const struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  gdb_gregset_t regs;
+
+  iov.iov_base = &regs;
+  iov.iov_len = sizeof (gdb_gregset_t);
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get general registers"));
+  else
+    {
+      arc_linux_collect_gregset (NULL, regcache, regnum, regs, 0);
+
+      if (ptrace (PTRACE_SETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+	perror_with_name (_("Couldn't write general registers"));
+    }
+}
+
+#ifdef ARC_HAS_V2_REGSET
+/* Store ARC v2 registers from REGCACHE into the target process/thread.  */
+
+static void
+store_v2_regs (const struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
+
+  iov.iov_base = &v2_buffer;
+  iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get ARC HS registers"));
+  else
+    {
+      arc_linux_collect_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
+
+      if (ptrace (PTRACE_SETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+	perror_with_name (_("Couldn't write ARC HS registers"));
+    }
+}
+#endif
+
+/* Target operation: Read REGNUM register (all registers if REGNUM == -1)
+   from target process into REGCACHE.  */
+
+void
+arc_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
+{
+
+  if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
+    fetch_gregs (regcache, regnum);
+
+#ifdef ARC_HAS_V2_REGSET
+  if (regnum == -1
+      || regnum == ARC_R30_REGNUM
+      || regnum == ARC_R58_REGNUM
+      || regnum == ARC_R59_REGNUM)
+      fetch_v2_regs (regcache, regnum);
+#endif
+}
+
+/* Target operation: Store REGNUM register (all registers if REGNUM == -1)
+   to the target process from REGCACHE.  */
+
+void
+arc_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
+{
+  if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
+    store_gregs (regcache, regnum);
+
+#ifdef ARC_HAS_V2_REGSET
+  if (regnum == -1
+      || regnum == ARC_R30_REGNUM
+      || regnum == ARC_R58_REGNUM
+      || regnum == ARC_R59_REGNUM)
+    store_v2_regs (regcache, regnum);
+#endif
+}
+
+/* Copy general purpose register(s) from REGCACHE into regset GREGS.
+   This function is exported to proc-service.c  */
+
+void
+fill_gregset (const struct regcache *regcache,
+	      gdb_gregset_t *gregs, int regnum)
+{
+  arc_linux_collect_gregset (NULL, regcache, regnum, gregs, 0);
+}
+
+/* Copy all the general purpose registers from regset GREGS into REGCACHE.
+   This function is exported to proc-service.c.  */
+
+void
+supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
+{
+  arc_linux_supply_gregset (NULL, regcache, -1, gregs, 0);
+}
+
+/* ARC doesn't have separate FP registers.  This function is exported
+   to proc-service.c.  */
+
+void
+fill_fpregset (const struct regcache *regcache,
+	       gdb_fpregset_t *fpregsetp, int regnum)
+{
+  if (arc_debug)
+    debug_printf ("arc-linux-nat: fill_fpregset called.");
+  return;
+}
+
+/* ARC doesn't have separate FP registers.  This function is exported
+   to proc-service.c.  */
+
+void
+supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
+{
+  if (arc_debug)
+    debug_printf ("arc-linux-nat: supply_fpregset called.");
+  return;
+}
+
+/* Implement the "read_description" method of linux_nat_target.  */
+
+const struct target_desc *
+arc_linux_nat_target::read_description ()
+{
+  /* This is a native target, hence description is hardcoded.  */
+#ifdef __ARCHS__
+  arc_arch_features features (4, ARC_ISA_ARCV2);
+#else
+  arc_arch_features features (4, ARC_ISA_ARCV1);
+#endif
+  return arc_lookup_target_description (features);
+}
+
+/* As described in arc_linux_collect_gregset(), we need to write resume-PC
+   to ERET.  However by default GDB for native targets doesn't write
+   registers if they haven't been changed.  This is a callback called by
+   generic GDB, and in this callback we have to rewrite PC value so it
+   would force rewrite of register on target.  It seems that the only
+   other arch that utilizes this hook is x86/x86-64 for HW breakpoint
+   support.  But then, AFAIK no other arch has this stop_pc/eret
+   complexity.
+
+   No better way was found, other than this fake write of register value,
+   to force GDB into writing register to target.  Is there any?  */
+
+void
+arc_linux_nat_target::low_prepare_to_resume (struct lwp_info *lwp)
+{
+  /* When new processes and threads are created we do not have the address
+     space for them and calling get_thread_regcache will cause an internal
+     error in GDB.  It looks like that checking for last_resume_kind is the
+     sensible way to determine processes for which we cannot get regcache.
+     Ultimately, a better way would be removing the need for
+     low_prepare_to_resume in the first place.  */
+  if (lwp->last_resume_kind == resume_stop)
+    return;
+
+  struct regcache *regcache = get_thread_regcache (this, lwp->ptid);
+  struct gdbarch *gdbarch = regcache->arch ();
+
+  /* Read current PC value, then write it back.  It is required to call
+     invalidate(), otherwise GDB will note that new value is equal to old
+     value and will skip write.  */
+  ULONGEST new_pc;
+  regcache_cooked_read_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
+				 &new_pc);
+  regcache->invalidate (gdbarch_pc_regnum (gdbarch));
+  regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
+				  new_pc);
+}
+
+/* Fetch the thread-local storage pointer for libthread_db.  Note that
+   this function is not called from GDB, but is called from libthread_db.
+   This is required to debug multithreaded applications with NPTL.  */
+
+ps_err_e
+ps_get_thread_area (struct ps_prochandle *ph, lwpid_t lwpid, int idx,
+		    void **base)
+{
+  if (arc_debug >= 2)
+    debug_printf ("arc-linux-nat: ps_get_thread_area called");
+
+  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
+    return PS_ERR;
+
+  /* IDX is the bias from the thread pointer to the beginning of the
+     thread descriptor.  It has to be subtracted due to implementation
+     quirks in libthread_db.  */
+  *base = (void *) ((char *) *base - idx);
+
+  return PS_OK;
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+void _initialize_arc_linux_nat (void);
+
+void
+_initialize_arc_linux_nat (void)
+{
+  /* Register the target.  */
+  linux_target = &the_arc_linux_nat_target;
+  add_inf_child_target (&the_arc_linux_nat_target);
+}
diff --git a/gdb/configure.host b/gdb/configure.host
index ce528237291..e94a19b0332 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -60,6 +60,7 @@ case "${host_cpu}" in
 
 aarch64*)		gdb_host_cpu=aarch64 ;;
 alpha*)			gdb_host_cpu=alpha ;;
+arc*)			gdb_host_cpu=arc ;;
 arm*)			gdb_host_cpu=arm ;;
 hppa*)			gdb_host_cpu=pa ;;
 i[34567]86*)		gdb_host_cpu=i386 ;;
@@ -91,6 +92,8 @@ alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu)
 			gdb_host=nbsd ;;
 alpha*-*-openbsd*)	gdb_host=nbsd ;;
 
+arc*-*-linux*)		gdb_host=linux ;;
+
 arm*-*-freebsd*)	gdb_host=fbsd ;;
 arm*-*-linux*)		gdb_host=linux ;;
 arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu)
diff --git a/gdb/configure.nat b/gdb/configure.nat
index ef2218f0b8d..0e36e09b692 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -238,6 +238,10 @@ case ${gdb_host} in
 		nat/aarch64-linux.o \
 		nat/aarch64-sve-linux-ptrace.o"
 		;;
+	    arc)
+		# Host: ARC based machine running GNU/Linux
+		NATDEPFILES="${NATDEPFILES} arc-linux-nat.o"
+		;;
 	    arm)
 		# Host: ARM based machine running GNU/Linux
 		NATDEPFILES="${NATDEPFILES} arm-linux-nat.o \
-- 
2.29.2


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

* Re: [PATCH 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks
  2020-11-12 13:48 ` [PATCH 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
@ 2020-11-12 17:33   ` Tom Tromey
  2020-11-12 17:36     ` Tom Tromey
  0 siblings, 1 reply; 14+ messages in thread
From: Tom Tromey @ 2020-11-12 17:33 UTC (permalink / raw)
  To: Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

>>>>> "Shahab" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:

Shahab>  void
Shahab>  arc_linux_supply_gregset (const struct regset *regset,
Shahab>  			  struct regcache *regcache,

I was thrown off here.  I think I'd normally expect a "gregset" function
to work with an ELF "gregset" -- the entire suite of registers.
Instead this is just an ordinary register callback function.

The patch seems fine to me.

FWIW it seems to me that these functions could all be static.

Tom

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

* Re: [PATCH 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks
  2020-11-12 17:33   ` Tom Tromey
@ 2020-11-12 17:36     ` Tom Tromey
  0 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2020-11-12 17:36 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Shahab Vahedi via Gdb-patches, Shahab Vahedi, Shahab Vahedi,
	Anton Kolesov, Francois Bedard

Tom> FWIW it seems to me that these functions could all be static.

Ok, I see now that they are used in the next patch, so never mind that.

Tom

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

* Re: [PATCH 2/2] gdb: Add native support for ARC in GNU/Linux
  2020-11-12 13:48 ` [PATCH 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
@ 2020-11-12 18:03   ` Tom Tromey
  0 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2020-11-12 18:03 UTC (permalink / raw)
  To: Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Francois Bedard

>>>>> "Shahab" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:

Shahab> From: Anton Kolesov <anton.kolesov@synopsys.com>
Shahab> With this patch in place it is possible to build a GDB that
Shahab> can run on ARC (GNU/Linux) hosts for debugging ARC targets.

Shahab> The "arc-linux-nat.c" is a rather small one that mostly deals
Shahab> with registers and a few thread related hooks.

Thanks for the patch.  I read through it and have one nit.

Shahab> +/* Suppress warning from -Wmissing-prototypes.  */
Shahab> +void _initialize_arc_linux_nat (void);
Shahab> +
Shahab> +void
Shahab> +_initialize_arc_linux_nat (void)

You can remove the "void"s here, those are relics from the C days.

This is ok with that tweak.

Tom

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

* [PATCH v2 0/2] Add native GNU/Linux support for ARC in GDB
  2020-11-12 13:48 [PATCH 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
  2020-11-12 13:48 ` [PATCH 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
  2020-11-12 13:48 ` [PATCH 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
@ 2020-12-07 16:37 ` Shahab Vahedi
  2020-12-07 16:37   ` [PATCH v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
  2020-12-07 16:37   ` [PATCH v2 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
  2020-12-22 11:21 ` [PUSHED v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
  3 siblings, 2 replies; 14+ messages in thread
From: Shahab Vahedi @ 2020-12-07 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

This patch series is mainly about adding a native GNU/Linux support for
ARC in GDB ("[PATCH 2/2] gdb: Add native support for ARC in GNU/Linux").

During the process of mulling over that change, I noticed that the ARC
target support could become more efficient in some of the target hooks
in "arc-linux-tdep.c"; namely the "arc_linux_supply_*()" and the
"arc_linux_collect_v2_regset()".  In those hooks, REGNUM is completely
ignored and every register is fetched/overwritten.  These hooks are
used by the "arc-linux-nat.c" (the second patch) and it relies on them:
Therefore, the first patch of this series: "[PATCH 1/2]: arc: Take into
account the REGNUM in supply/collect gdb hooks".

To summarize:
[PATCH 1/2] -> Respect REGNUM in hooks.
[PATCH 2/2] -> Add native ARC GNU/Linux support while using those hooks.

One last remark: The native GDB works correctly along with this
fix [1].  Therefore, if you want to give it a try, please also apply
that patch.

[1] [PATCH] arc: Write correct "eret" value during register collection
https://sourceware.org/pipermail/gdb-patches/2020-November/173202.html

How to build:
Get the "Linux/{glibc,uClibc} ARC HS" toolchain from:
https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases
and extract it somewhere.

Update the PATHs so you can find "arc-linux-gcc":
$ export PATH=/extracted/dir/bin:$PATH
$ export LD_LIBRARY_PATH=/extracted/dir/lib:$LD_LIBRARY_PATH

$ cd /to/gdb/src
$ host=arc-snps-linux-gnu            # or arc-snps-linux-uclibc
$ configure --prefix=/usr            \
            --host=$host             \
            --disable-build-with-cxx \
            --disable-gas            \
            --disable-ld             \
            --disable-binutils
$ make -j $(nproc)
$ arc-linux-strip ./gdb/gdb

v2:
Because there was only some remarks about the second patch in this
series, that is the one that has been reworked. Look at its commit
message to see what has exactly changed.

Anton Kolesov (1):
  gdb: Add native support for ARC in GNU/Linux

Shahab Vahedi (1):
  arc: Take into account the REGNUM in supply/collect gdb hooks

 gdb/Makefile.in      |   1 +
 gdb/arc-linux-nat.c  | 320 +++++++++++++++++++++++++++++++++++++++++++
 gdb/arc-linux-tdep.c |  41 ++++--
 gdb/configure.host   |   3 +
 gdb/configure.nat    |   4 +
 5 files changed, 360 insertions(+), 9 deletions(-)
 create mode 100644 gdb/arc-linux-nat.c

-- 
2.29.2


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

* [PATCH v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks
  2020-12-07 16:37 ` [PATCH v2 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
@ 2020-12-07 16:37   ` Shahab Vahedi
  2020-12-10 19:11     ` Tom Tromey
  2020-12-07 16:37   ` [PATCH v2 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
  1 sibling, 1 reply; 14+ messages in thread
From: Shahab Vahedi @ 2020-12-07 16:37 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

All the arc_linux_supply_*() target operations and the
arc_linux_collect_v2_regset() in arc-linux-tdep.c were
supplying/collecting all the registers in regcache as if the
REGNUM was set to -1.

The more efficient behavior is to examine the REGNUM and act
accordingly.  That is what this patch does.

gdb/ChangeLog:

	* arc-linux-tdep.c (supply_register): New.
	(arc_linux_supply_gregset, arc_linux_supply_v2_regset,
	arc_linux_collect_v2_regset): Consider REGNUM.
---
 gdb/arc-linux-tdep.c | 41 ++++++++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
index ad68f494b3c..eca8d626084 100644
--- a/gdb/arc-linux-tdep.c
+++ b/gdb/arc-linux-tdep.c
@@ -460,6 +460,18 @@ arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
     }
 }
 
+/* Populate REGCACHE with register REGNUM from BUF.  */
+
+static void
+supply_register (struct regcache *regcache, int regnum, const gdb_byte *buf)
+{
+  /* Skip non-existing registers.  */
+  if ((arc_linux_core_reg_offsets[regnum] == ARC_OFFSET_NO_REGISTER))
+    return;
+
+  regcache->raw_supply (regnum, buf + arc_linux_core_reg_offsets[regnum]);
+}
+
 void
 arc_linux_supply_gregset (const struct regset *regset,
 			  struct regcache *regcache,
@@ -470,9 +482,14 @@ arc_linux_supply_gregset (const struct regset *regset,
 
   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]);
+  /* regnum == -1 means writing all the registers.  */
+  if (regnum == -1)
+    for (int reg = 0; reg <= ARC_LAST_REGNUM; reg++)
+      supply_register (regcache, reg, buf);
+  else if (regnum <= ARC_LAST_REGNUM)
+    supply_register (regcache, regnum, buf);
+  else
+    gdb_assert_not_reached ("Invalid regnum in arc_linux_supply_gregset.");
 }
 
 void
@@ -483,9 +500,12 @@ arc_linux_supply_v2_regset (const struct regset *regset,
   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));
+  if (regnum == -1 || regnum == ARC_R30_REGNUM)
+    regcache->raw_supply (ARC_R30_REGNUM, buf);
+  if (regnum == -1 || regnum == ARC_R58_REGNUM)
+    regcache->raw_supply (ARC_R58_REGNUM, buf + REGOFF (1));
+  if (regnum == -1 || regnum == ARC_R59_REGNUM)
+    regcache->raw_supply (ARC_R59_REGNUM, buf + REGOFF (2));
 }
 
 /* Populate BUF with register REGNUM from the REGCACHE.  */
@@ -543,9 +563,12 @@ arc_linux_collect_v2_regset (const struct regset *regset,
 {
   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));
+  if (regnum == -1 || regnum == ARC_R30_REGNUM)
+    regcache->raw_collect (ARC_R30_REGNUM, buf);
+  if (regnum == -1 || regnum == ARC_R58_REGNUM)
+    regcache->raw_collect (ARC_R58_REGNUM, buf + REGOFF (1));
+  if (regnum == -1 || regnum == ARC_R59_REGNUM)
+    regcache->raw_collect (ARC_R59_REGNUM, buf + REGOFF (2));
 }
 
 /* Linux regset definitions.  */
-- 
2.29.2


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

* [PATCH v2 2/2] gdb: Add native support for ARC in GNU/Linux
  2020-12-07 16:37 ` [PATCH v2 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
  2020-12-07 16:37   ` [PATCH v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
@ 2020-12-07 16:37   ` Shahab Vahedi
  2020-12-10 19:13     ` Tom Tromey
  1 sibling, 1 reply; 14+ messages in thread
From: Shahab Vahedi @ 2020-12-07 16:37 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Francois Bedard, Anton Kolesov

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

With this patch in place it is possible to build a GDB that
can run on ARC (GNU/Linux) hosts for debugging ARC targets.

The "arc-linux-nat.c" is a rather small one that mostly deals
with registers and a few thread related hooks.

v2 [1]:
- Remove "void" from the input of "_initialize_arc_linux_nat ()"

[1] Tom's remark after the first patch
https://sourceware.org/pipermail/gdb-patches/2020-November/173223.html

gdb/ChangeLog:

	* Makefile.in (ALLDEPFILES): Add arc-linux-nat.c.
	* configure.host (host to gdb names): Add arc*-*-linux*.
	* configure.nat (gdb_host_cpu): Add arc.
	* arc-linux-nat.c: New.
---
 gdb/Makefile.in     |   1 +
 gdb/arc-linux-nat.c | 320 ++++++++++++++++++++++++++++++++++++++++++++
 gdb/configure.host  |   3 +
 gdb/configure.nat   |   4 +
 4 files changed, 328 insertions(+)
 create mode 100644 gdb/arc-linux-nat.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c46935efafa..44ba2f04ac9 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -2144,6 +2144,7 @@ ALLDEPFILES = \
 	amd64-ravenscar-thread.c \
 	amd64-sol2-tdep.c \
 	amd64-tdep.c \
+	arc-linux-nat.c \
 	arc-tdep.c \
 	arm.c \
 	arm-bsd-tdep.c \
diff --git a/gdb/arc-linux-nat.c b/gdb/arc-linux-nat.c
new file mode 100644
index 00000000000..41301fd4fed
--- /dev/null
+++ b/gdb/arc-linux-nat.c
@@ -0,0 +1,320 @@
+/* Native-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/>.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "regcache.h"
+#include "gdbsupport/gdb_assert.h"
+#include "target.h"
+#include "linux-nat.h"
+#include "nat/gdb_ptrace.h"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include "gdbsupport/gdb_wait.h"
+#include <fcntl.h>
+#include <sys/procfs.h>
+#include <linux/elf.h>
+
+#include "gregset.h"
+#include "arc-tdep.h"
+#include "arc-linux-tdep.h"
+#include "arch/arc.h"
+
+/* Defines ps_err_e, struct ps_prochandle.  */
+#include "gdb_proc_service.h"
+
+/* Linux starting with 4.12 supports NT_ARC_V2 note type, which adds R30,
+   R58 and R59 registers, which are specific to ARC HS and aren't
+   available in ARC 700.  */
+#if defined (NT_ARC_V2) && defined (__ARCHS__)
+#define ARC_HAS_V2_REGSET
+#endif
+
+class arc_linux_nat_target final : public linux_nat_target
+{
+public:
+  /* Add ARC register access methods.  */
+  void fetch_registers (struct regcache *, int) override;
+  void store_registers (struct regcache *, int) override;
+
+  const struct target_desc *read_description () override;
+
+  /* Handle threads  */
+  void low_prepare_to_resume (struct lwp_info *lp) override;
+};
+
+static arc_linux_nat_target the_arc_linux_nat_target;
+
+/* Read general registers from target process/thread (via ptrace)
+   into REGCACHE.  */
+
+static void
+fetch_gregs (struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  gdb_gregset_t regs;
+
+  iov.iov_base = &regs;
+  iov.iov_len = sizeof (gdb_gregset_t);
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get general registers"));
+  else
+    arc_linux_supply_gregset (NULL, regcache, regnum, &regs, 0);
+}
+
+#ifdef ARC_HAS_V2_REGSET
+/* Read ARC v2 registers from target process/thread (via ptrace)
+   into REGCACHE.  */
+
+static void
+fetch_v2_regs (struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
+
+  iov.iov_base = &v2_buffer;
+  iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get ARC HS registers"));
+  else
+    arc_linux_supply_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
+}
+#endif
+
+/* Store general registers from REGCACHE into the target process/thread.  */
+
+static void
+store_gregs (const struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  gdb_gregset_t regs;
+
+  iov.iov_base = &regs;
+  iov.iov_len = sizeof (gdb_gregset_t);
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get general registers"));
+  else
+    {
+      arc_linux_collect_gregset (NULL, regcache, regnum, regs, 0);
+
+      if (ptrace (PTRACE_SETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+	perror_with_name (_("Couldn't write general registers"));
+    }
+}
+
+#ifdef ARC_HAS_V2_REGSET
+/* Store ARC v2 registers from REGCACHE into the target process/thread.  */
+
+static void
+store_v2_regs (const struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
+
+  iov.iov_base = &v2_buffer;
+  iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get ARC HS registers"));
+  else
+    {
+      arc_linux_collect_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
+
+      if (ptrace (PTRACE_SETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+	perror_with_name (_("Couldn't write ARC HS registers"));
+    }
+}
+#endif
+
+/* Target operation: Read REGNUM register (all registers if REGNUM == -1)
+   from target process into REGCACHE.  */
+
+void
+arc_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
+{
+
+  if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
+    fetch_gregs (regcache, regnum);
+
+#ifdef ARC_HAS_V2_REGSET
+  if (regnum == -1
+      || regnum == ARC_R30_REGNUM
+      || regnum == ARC_R58_REGNUM
+      || regnum == ARC_R59_REGNUM)
+      fetch_v2_regs (regcache, regnum);
+#endif
+}
+
+/* Target operation: Store REGNUM register (all registers if REGNUM == -1)
+   to the target process from REGCACHE.  */
+
+void
+arc_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
+{
+  if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
+    store_gregs (regcache, regnum);
+
+#ifdef ARC_HAS_V2_REGSET
+  if (regnum == -1
+      || regnum == ARC_R30_REGNUM
+      || regnum == ARC_R58_REGNUM
+      || regnum == ARC_R59_REGNUM)
+    store_v2_regs (regcache, regnum);
+#endif
+}
+
+/* Copy general purpose register(s) from REGCACHE into regset GREGS.
+   This function is exported to proc-service.c  */
+
+void
+fill_gregset (const struct regcache *regcache,
+	      gdb_gregset_t *gregs, int regnum)
+{
+  arc_linux_collect_gregset (NULL, regcache, regnum, gregs, 0);
+}
+
+/* Copy all the general purpose registers from regset GREGS into REGCACHE.
+   This function is exported to proc-service.c.  */
+
+void
+supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
+{
+  arc_linux_supply_gregset (NULL, regcache, -1, gregs, 0);
+}
+
+/* ARC doesn't have separate FP registers.  This function is exported
+   to proc-service.c.  */
+
+void
+fill_fpregset (const struct regcache *regcache,
+	       gdb_fpregset_t *fpregsetp, int regnum)
+{
+  if (arc_debug)
+    debug_printf ("arc-linux-nat: fill_fpregset called.");
+  return;
+}
+
+/* ARC doesn't have separate FP registers.  This function is exported
+   to proc-service.c.  */
+
+void
+supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
+{
+  if (arc_debug)
+    debug_printf ("arc-linux-nat: supply_fpregset called.");
+  return;
+}
+
+/* Implement the "read_description" method of linux_nat_target.  */
+
+const struct target_desc *
+arc_linux_nat_target::read_description ()
+{
+  /* This is a native target, hence description is hardcoded.  */
+#ifdef __ARCHS__
+  arc_arch_features features (4, ARC_ISA_ARCV2);
+#else
+  arc_arch_features features (4, ARC_ISA_ARCV1);
+#endif
+  return arc_lookup_target_description (features);
+}
+
+/* As described in arc_linux_collect_gregset(), we need to write resume-PC
+   to ERET.  However by default GDB for native targets doesn't write
+   registers if they haven't been changed.  This is a callback called by
+   generic GDB, and in this callback we have to rewrite PC value so it
+   would force rewrite of register on target.  It seems that the only
+   other arch that utilizes this hook is x86/x86-64 for HW breakpoint
+   support.  But then, AFAIK no other arch has this stop_pc/eret
+   complexity.
+
+   No better way was found, other than this fake write of register value,
+   to force GDB into writing register to target.  Is there any?  */
+
+void
+arc_linux_nat_target::low_prepare_to_resume (struct lwp_info *lwp)
+{
+  /* When new processes and threads are created we do not have the address
+     space for them and calling get_thread_regcache will cause an internal
+     error in GDB.  It looks like that checking for last_resume_kind is the
+     sensible way to determine processes for which we cannot get regcache.
+     Ultimately, a better way would be removing the need for
+     low_prepare_to_resume in the first place.  */
+  if (lwp->last_resume_kind == resume_stop)
+    return;
+
+  struct regcache *regcache = get_thread_regcache (this, lwp->ptid);
+  struct gdbarch *gdbarch = regcache->arch ();
+
+  /* Read current PC value, then write it back.  It is required to call
+     invalidate(), otherwise GDB will note that new value is equal to old
+     value and will skip write.  */
+  ULONGEST new_pc;
+  regcache_cooked_read_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
+				 &new_pc);
+  regcache->invalidate (gdbarch_pc_regnum (gdbarch));
+  regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
+				  new_pc);
+}
+
+/* Fetch the thread-local storage pointer for libthread_db.  Note that
+   this function is not called from GDB, but is called from libthread_db.
+   This is required to debug multithreaded applications with NPTL.  */
+
+ps_err_e
+ps_get_thread_area (struct ps_prochandle *ph, lwpid_t lwpid, int idx,
+		    void **base)
+{
+  if (arc_debug >= 2)
+    debug_printf ("arc-linux-nat: ps_get_thread_area called");
+
+  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
+    return PS_ERR;
+
+  /* IDX is the bias from the thread pointer to the beginning of the
+     thread descriptor.  It has to be subtracted due to implementation
+     quirks in libthread_db.  */
+  *base = (void *) ((char *) *base - idx);
+
+  return PS_OK;
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+void _initialize_arc_linux_nat ();
+void
+_initialize_arc_linux_nat ()
+{
+  /* Register the target.  */
+  linux_target = &the_arc_linux_nat_target;
+  add_inf_child_target (&the_arc_linux_nat_target);
+}
diff --git a/gdb/configure.host b/gdb/configure.host
index ce528237291..e94a19b0332 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -60,6 +60,7 @@ case "${host_cpu}" in
 
 aarch64*)		gdb_host_cpu=aarch64 ;;
 alpha*)			gdb_host_cpu=alpha ;;
+arc*)			gdb_host_cpu=arc ;;
 arm*)			gdb_host_cpu=arm ;;
 hppa*)			gdb_host_cpu=pa ;;
 i[34567]86*)		gdb_host_cpu=i386 ;;
@@ -91,6 +92,8 @@ alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu)
 			gdb_host=nbsd ;;
 alpha*-*-openbsd*)	gdb_host=nbsd ;;
 
+arc*-*-linux*)		gdb_host=linux ;;
+
 arm*-*-freebsd*)	gdb_host=fbsd ;;
 arm*-*-linux*)		gdb_host=linux ;;
 arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu)
diff --git a/gdb/configure.nat b/gdb/configure.nat
index ef2218f0b8d..0e36e09b692 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -238,6 +238,10 @@ case ${gdb_host} in
 		nat/aarch64-linux.o \
 		nat/aarch64-sve-linux-ptrace.o"
 		;;
+	    arc)
+		# Host: ARC based machine running GNU/Linux
+		NATDEPFILES="${NATDEPFILES} arc-linux-nat.o"
+		;;
 	    arm)
 		# Host: ARM based machine running GNU/Linux
 		NATDEPFILES="${NATDEPFILES} arm-linux-nat.o \
-- 
2.29.2


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

* Re: [PATCH v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks
  2020-12-07 16:37   ` [PATCH v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
@ 2020-12-10 19:11     ` Tom Tromey
  0 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2020-12-10 19:11 UTC (permalink / raw)
  To: Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Francois Bedard

>>>>> "Shahab" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:

Shahab> From: Shahab Vahedi <shahab@synopsys.com>
Shahab> All the arc_linux_supply_*() target operations and the
Shahab> arc_linux_collect_v2_regset() in arc-linux-tdep.c were
Shahab> supplying/collecting all the registers in regcache as if the
Shahab> REGNUM was set to -1.

Thanks for the patch.

Shahab> +  /* regnum == -1 means writing all the registers.  */

In the gdb style, "REGNUM" should be all-caps in that comment, as it
refers to the value of a variable.

This patch is ok with that nit fixed.

Tom

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

* Re: [PATCH v2 2/2] gdb: Add native support for ARC in GNU/Linux
  2020-12-07 16:37   ` [PATCH v2 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
@ 2020-12-10 19:13     ` Tom Tromey
  2020-12-10 19:33       ` Shahab Vahedi
  0 siblings, 1 reply; 14+ messages in thread
From: Tom Tromey @ 2020-12-10 19:13 UTC (permalink / raw)
  To: Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Anton Kolesov, Tom Tromey, Francois Bedard

>>>>> "Shahab" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:

Shahab> From: Anton Kolesov <anton.kolesov@synopsys.com>
Shahab> With this patch in place it is possible to build a GDB that
Shahab> can run on ARC (GNU/Linux) hosts for debugging ARC targets.

Shahab> The "arc-linux-nat.c" is a rather small one that mostly deals
Shahab> with registers and a few thread related hooks.

Shahab> v2 [1]:
Shahab> - Remove "void" from the input of "_initialize_arc_linux_nat ()"

Shahab> [1] Tom's remark after the first patch
Shahab> https://sourceware.org/pipermail/gdb-patches/2020-November/173223.html

In there I said it was ok with a nit fixed -- sorry if that was not
clear, in gdb that means you can fix up the nit and check it in without
further review.  FAOD this patch is ok.  Thank you.

Tom

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

* Re: [PATCH v2 2/2] gdb: Add native support for ARC in GNU/Linux
  2020-12-10 19:13     ` Tom Tromey
@ 2020-12-10 19:33       ` Shahab Vahedi
  0 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2020-12-10 19:33 UTC (permalink / raw)
  To: Tom Tromey, Shahab Vahedi via Gdb-patches
  Cc: Shahab Vahedi, Anton Kolesov, Francois Bedard

Hi Tom,

On 12/10/20 8:13 PM, Tom Tromey wrote:
>>>>>> "Shahab" == Shahab Vahedi via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
> Shahab> [1] Tom's remark after the first patch
> Shahab> https://sourceware.org/pipermail/gdb-patches/2020-November/173223.html
> 
> In there I said it was ok with a nit fixed -- sorry if that was not
> clear, in gdb that means you can fix up the nit and check it in without
> further review.  FAOD this patch is ok.  Thank you.

You were clear.  It was just my OCD kicking in.  I will do as suggested from now on.


-- 
Shahab

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

* [PUSHED v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks
  2020-11-12 13:48 [PATCH 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
                   ` (2 preceding siblings ...)
  2020-12-07 16:37 ` [PATCH v2 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
@ 2020-12-22 11:21 ` Shahab Vahedi
  2020-12-22 11:21   ` [PUSHED v2 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
  3 siblings, 1 reply; 14+ messages in thread
From: Shahab Vahedi @ 2020-12-22 11:21 UTC (permalink / raw)
  To: gdb-patches; +Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Francois Bedard

From: Shahab Vahedi <shahab@synopsys.com>

All the arc_linux_supply_*() target operations and the
arc_linux_collect_v2_regset() in arc-linux-tdep.c were
supplying/collecting all the registers in regcache as if the
REGNUM was set to -1.

The more efficient behavior is to examine the REGNUM and act
accordingly.  That is what this patch does.

gdb/ChangeLog:

	* arc-linux-tdep.c (supply_register): New.
	(arc_linux_supply_gregset, arc_linux_supply_v2_regset,
	arc_linux_collect_v2_regset): Consider REGNUM.
---
 gdb/arc-linux-tdep.c | 41 ++++++++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c
index ad68f494b3c..eca8d626084 100644
--- a/gdb/arc-linux-tdep.c
+++ b/gdb/arc-linux-tdep.c
@@ -460,6 +460,18 @@ arc_linux_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
     }
 }
 
+/* Populate REGCACHE with register REGNUM from BUF.  */
+
+static void
+supply_register (struct regcache *regcache, int regnum, const gdb_byte *buf)
+{
+  /* Skip non-existing registers.  */
+  if ((arc_linux_core_reg_offsets[regnum] == ARC_OFFSET_NO_REGISTER))
+    return;
+
+  regcache->raw_supply (regnum, buf + arc_linux_core_reg_offsets[regnum]);
+}
+
 void
 arc_linux_supply_gregset (const struct regset *regset,
 			  struct regcache *regcache,
@@ -470,9 +482,14 @@ arc_linux_supply_gregset (const struct regset *regset,
 
   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]);
+  /* regnum == -1 means writing all the registers.  */
+  if (regnum == -1)
+    for (int reg = 0; reg <= ARC_LAST_REGNUM; reg++)
+      supply_register (regcache, reg, buf);
+  else if (regnum <= ARC_LAST_REGNUM)
+    supply_register (regcache, regnum, buf);
+  else
+    gdb_assert_not_reached ("Invalid regnum in arc_linux_supply_gregset.");
 }
 
 void
@@ -483,9 +500,12 @@ arc_linux_supply_v2_regset (const struct regset *regset,
   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));
+  if (regnum == -1 || regnum == ARC_R30_REGNUM)
+    regcache->raw_supply (ARC_R30_REGNUM, buf);
+  if (regnum == -1 || regnum == ARC_R58_REGNUM)
+    regcache->raw_supply (ARC_R58_REGNUM, buf + REGOFF (1));
+  if (regnum == -1 || regnum == ARC_R59_REGNUM)
+    regcache->raw_supply (ARC_R59_REGNUM, buf + REGOFF (2));
 }
 
 /* Populate BUF with register REGNUM from the REGCACHE.  */
@@ -543,9 +563,12 @@ arc_linux_collect_v2_regset (const struct regset *regset,
 {
   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));
+  if (regnum == -1 || regnum == ARC_R30_REGNUM)
+    regcache->raw_collect (ARC_R30_REGNUM, buf);
+  if (regnum == -1 || regnum == ARC_R58_REGNUM)
+    regcache->raw_collect (ARC_R58_REGNUM, buf + REGOFF (1));
+  if (regnum == -1 || regnum == ARC_R59_REGNUM)
+    regcache->raw_collect (ARC_R59_REGNUM, buf + REGOFF (2));
 }
 
 /* Linux regset definitions.  */
-- 
2.29.2


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

* [PUSHED v2 2/2] gdb: Add native support for ARC in GNU/Linux
  2020-12-22 11:21 ` [PUSHED v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
@ 2020-12-22 11:21   ` Shahab Vahedi
  0 siblings, 0 replies; 14+ messages in thread
From: Shahab Vahedi @ 2020-12-22 11:21 UTC (permalink / raw)
  To: gdb-patches
  Cc: Shahab Vahedi, Shahab Vahedi, Tom Tromey, Francois Bedard, Anton Kolesov

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

With this patch in place it is possible to build a GDB that
can run on ARC (GNU/Linux) hosts for debugging ARC targets.

The "arc-linux-nat.c" is a rather small one that mostly deals
with registers and a few thread related hooks.

v2 [1]:
- Remove "void" from the input of "_initialize_arc_linux_nat ()"

[1] Tom's remark after the first patch
https://sourceware.org/pipermail/gdb-patches/2020-November/173223.html

gdb/ChangeLog:

	* Makefile.in (ALLDEPFILES): Add arc-linux-nat.c.
	* configure.host (host to gdb names): Add arc*-*-linux*.
	* configure.nat (gdb_host_cpu): Add arc.
	* arc-linux-nat.c: New.
---
 gdb/Makefile.in     |   1 +
 gdb/arc-linux-nat.c | 320 ++++++++++++++++++++++++++++++++++++++++++++
 gdb/configure.host  |   3 +
 gdb/configure.nat   |   4 +
 4 files changed, 328 insertions(+)
 create mode 100644 gdb/arc-linux-nat.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c46935efafa..44ba2f04ac9 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -2144,6 +2144,7 @@ ALLDEPFILES = \
 	amd64-ravenscar-thread.c \
 	amd64-sol2-tdep.c \
 	amd64-tdep.c \
+	arc-linux-nat.c \
 	arc-tdep.c \
 	arm.c \
 	arm-bsd-tdep.c \
diff --git a/gdb/arc-linux-nat.c b/gdb/arc-linux-nat.c
new file mode 100644
index 00000000000..41301fd4fed
--- /dev/null
+++ b/gdb/arc-linux-nat.c
@@ -0,0 +1,320 @@
+/* Native-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/>.  */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "regcache.h"
+#include "gdbsupport/gdb_assert.h"
+#include "target.h"
+#include "linux-nat.h"
+#include "nat/gdb_ptrace.h"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include "gdbsupport/gdb_wait.h"
+#include <fcntl.h>
+#include <sys/procfs.h>
+#include <linux/elf.h>
+
+#include "gregset.h"
+#include "arc-tdep.h"
+#include "arc-linux-tdep.h"
+#include "arch/arc.h"
+
+/* Defines ps_err_e, struct ps_prochandle.  */
+#include "gdb_proc_service.h"
+
+/* Linux starting with 4.12 supports NT_ARC_V2 note type, which adds R30,
+   R58 and R59 registers, which are specific to ARC HS and aren't
+   available in ARC 700.  */
+#if defined (NT_ARC_V2) && defined (__ARCHS__)
+#define ARC_HAS_V2_REGSET
+#endif
+
+class arc_linux_nat_target final : public linux_nat_target
+{
+public:
+  /* Add ARC register access methods.  */
+  void fetch_registers (struct regcache *, int) override;
+  void store_registers (struct regcache *, int) override;
+
+  const struct target_desc *read_description () override;
+
+  /* Handle threads  */
+  void low_prepare_to_resume (struct lwp_info *lp) override;
+};
+
+static arc_linux_nat_target the_arc_linux_nat_target;
+
+/* Read general registers from target process/thread (via ptrace)
+   into REGCACHE.  */
+
+static void
+fetch_gregs (struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  gdb_gregset_t regs;
+
+  iov.iov_base = &regs;
+  iov.iov_len = sizeof (gdb_gregset_t);
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get general registers"));
+  else
+    arc_linux_supply_gregset (NULL, regcache, regnum, &regs, 0);
+}
+
+#ifdef ARC_HAS_V2_REGSET
+/* Read ARC v2 registers from target process/thread (via ptrace)
+   into REGCACHE.  */
+
+static void
+fetch_v2_regs (struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
+
+  iov.iov_base = &v2_buffer;
+  iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get ARC HS registers"));
+  else
+    arc_linux_supply_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
+}
+#endif
+
+/* Store general registers from REGCACHE into the target process/thread.  */
+
+static void
+store_gregs (const struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  gdb_gregset_t regs;
+
+  iov.iov_base = &regs;
+  iov.iov_len = sizeof (gdb_gregset_t);
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get general registers"));
+  else
+    {
+      arc_linux_collect_gregset (NULL, regcache, regnum, regs, 0);
+
+      if (ptrace (PTRACE_SETREGSET, tid, NT_PRSTATUS, (void *) &iov) < 0)
+	perror_with_name (_("Couldn't write general registers"));
+    }
+}
+
+#ifdef ARC_HAS_V2_REGSET
+/* Store ARC v2 registers from REGCACHE into the target process/thread.  */
+
+static void
+store_v2_regs (const struct regcache *regcache, int regnum)
+{
+  const int tid = get_ptrace_pid (regcache->ptid ());
+  struct iovec iov;
+  bfd_byte v2_buffer[ARC_LINUX_SIZEOF_V2_REGSET];
+
+  iov.iov_base = &v2_buffer;
+  iov.iov_len = ARC_LINUX_SIZEOF_V2_REGSET;
+
+  if (ptrace (PTRACE_GETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+    perror_with_name (_("Couldn't get ARC HS registers"));
+  else
+    {
+      arc_linux_collect_v2_regset (NULL, regcache, regnum, v2_buffer, 0);
+
+      if (ptrace (PTRACE_SETREGSET, tid, NT_ARC_V2, (void *) &iov) < 0)
+	perror_with_name (_("Couldn't write ARC HS registers"));
+    }
+}
+#endif
+
+/* Target operation: Read REGNUM register (all registers if REGNUM == -1)
+   from target process into REGCACHE.  */
+
+void
+arc_linux_nat_target::fetch_registers (struct regcache *regcache, int regnum)
+{
+
+  if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
+    fetch_gregs (regcache, regnum);
+
+#ifdef ARC_HAS_V2_REGSET
+  if (regnum == -1
+      || regnum == ARC_R30_REGNUM
+      || regnum == ARC_R58_REGNUM
+      || regnum == ARC_R59_REGNUM)
+      fetch_v2_regs (regcache, regnum);
+#endif
+}
+
+/* Target operation: Store REGNUM register (all registers if REGNUM == -1)
+   to the target process from REGCACHE.  */
+
+void
+arc_linux_nat_target::store_registers (struct regcache *regcache, int regnum)
+{
+  if (regnum == -1 || regnum <= ARC_LAST_REGNUM)
+    store_gregs (regcache, regnum);
+
+#ifdef ARC_HAS_V2_REGSET
+  if (regnum == -1
+      || regnum == ARC_R30_REGNUM
+      || regnum == ARC_R58_REGNUM
+      || regnum == ARC_R59_REGNUM)
+    store_v2_regs (regcache, regnum);
+#endif
+}
+
+/* Copy general purpose register(s) from REGCACHE into regset GREGS.
+   This function is exported to proc-service.c  */
+
+void
+fill_gregset (const struct regcache *regcache,
+	      gdb_gregset_t *gregs, int regnum)
+{
+  arc_linux_collect_gregset (NULL, regcache, regnum, gregs, 0);
+}
+
+/* Copy all the general purpose registers from regset GREGS into REGCACHE.
+   This function is exported to proc-service.c.  */
+
+void
+supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregs)
+{
+  arc_linux_supply_gregset (NULL, regcache, -1, gregs, 0);
+}
+
+/* ARC doesn't have separate FP registers.  This function is exported
+   to proc-service.c.  */
+
+void
+fill_fpregset (const struct regcache *regcache,
+	       gdb_fpregset_t *fpregsetp, int regnum)
+{
+  if (arc_debug)
+    debug_printf ("arc-linux-nat: fill_fpregset called.");
+  return;
+}
+
+/* ARC doesn't have separate FP registers.  This function is exported
+   to proc-service.c.  */
+
+void
+supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
+{
+  if (arc_debug)
+    debug_printf ("arc-linux-nat: supply_fpregset called.");
+  return;
+}
+
+/* Implement the "read_description" method of linux_nat_target.  */
+
+const struct target_desc *
+arc_linux_nat_target::read_description ()
+{
+  /* This is a native target, hence description is hardcoded.  */
+#ifdef __ARCHS__
+  arc_arch_features features (4, ARC_ISA_ARCV2);
+#else
+  arc_arch_features features (4, ARC_ISA_ARCV1);
+#endif
+  return arc_lookup_target_description (features);
+}
+
+/* As described in arc_linux_collect_gregset(), we need to write resume-PC
+   to ERET.  However by default GDB for native targets doesn't write
+   registers if they haven't been changed.  This is a callback called by
+   generic GDB, and in this callback we have to rewrite PC value so it
+   would force rewrite of register on target.  It seems that the only
+   other arch that utilizes this hook is x86/x86-64 for HW breakpoint
+   support.  But then, AFAIK no other arch has this stop_pc/eret
+   complexity.
+
+   No better way was found, other than this fake write of register value,
+   to force GDB into writing register to target.  Is there any?  */
+
+void
+arc_linux_nat_target::low_prepare_to_resume (struct lwp_info *lwp)
+{
+  /* When new processes and threads are created we do not have the address
+     space for them and calling get_thread_regcache will cause an internal
+     error in GDB.  It looks like that checking for last_resume_kind is the
+     sensible way to determine processes for which we cannot get regcache.
+     Ultimately, a better way would be removing the need for
+     low_prepare_to_resume in the first place.  */
+  if (lwp->last_resume_kind == resume_stop)
+    return;
+
+  struct regcache *regcache = get_thread_regcache (this, lwp->ptid);
+  struct gdbarch *gdbarch = regcache->arch ();
+
+  /* Read current PC value, then write it back.  It is required to call
+     invalidate(), otherwise GDB will note that new value is equal to old
+     value and will skip write.  */
+  ULONGEST new_pc;
+  regcache_cooked_read_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
+				 &new_pc);
+  regcache->invalidate (gdbarch_pc_regnum (gdbarch));
+  regcache_cooked_write_unsigned (regcache, gdbarch_pc_regnum (gdbarch),
+				  new_pc);
+}
+
+/* Fetch the thread-local storage pointer for libthread_db.  Note that
+   this function is not called from GDB, but is called from libthread_db.
+   This is required to debug multithreaded applications with NPTL.  */
+
+ps_err_e
+ps_get_thread_area (struct ps_prochandle *ph, lwpid_t lwpid, int idx,
+		    void **base)
+{
+  if (arc_debug >= 2)
+    debug_printf ("arc-linux-nat: ps_get_thread_area called");
+
+  if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
+    return PS_ERR;
+
+  /* IDX is the bias from the thread pointer to the beginning of the
+     thread descriptor.  It has to be subtracted due to implementation
+     quirks in libthread_db.  */
+  *base = (void *) ((char *) *base - idx);
+
+  return PS_OK;
+}
+
+/* Suppress warning from -Wmissing-prototypes.  */
+void _initialize_arc_linux_nat ();
+void
+_initialize_arc_linux_nat ()
+{
+  /* Register the target.  */
+  linux_target = &the_arc_linux_nat_target;
+  add_inf_child_target (&the_arc_linux_nat_target);
+}
diff --git a/gdb/configure.host b/gdb/configure.host
index ce528237291..e94a19b0332 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -60,6 +60,7 @@ case "${host_cpu}" in
 
 aarch64*)		gdb_host_cpu=aarch64 ;;
 alpha*)			gdb_host_cpu=alpha ;;
+arc*)			gdb_host_cpu=arc ;;
 arm*)			gdb_host_cpu=arm ;;
 hppa*)			gdb_host_cpu=pa ;;
 i[34567]86*)		gdb_host_cpu=i386 ;;
@@ -91,6 +92,8 @@ alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu)
 			gdb_host=nbsd ;;
 alpha*-*-openbsd*)	gdb_host=nbsd ;;
 
+arc*-*-linux*)		gdb_host=linux ;;
+
 arm*-*-freebsd*)	gdb_host=fbsd ;;
 arm*-*-linux*)		gdb_host=linux ;;
 arm*-*-netbsdelf* | arm*-*-knetbsd*-gnu)
diff --git a/gdb/configure.nat b/gdb/configure.nat
index ef2218f0b8d..0e36e09b692 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -238,6 +238,10 @@ case ${gdb_host} in
 		nat/aarch64-linux.o \
 		nat/aarch64-sve-linux-ptrace.o"
 		;;
+	    arc)
+		# Host: ARC based machine running GNU/Linux
+		NATDEPFILES="${NATDEPFILES} arc-linux-nat.o"
+		;;
 	    arm)
 		# Host: ARM based machine running GNU/Linux
 		NATDEPFILES="${NATDEPFILES} arm-linux-nat.o \
-- 
2.29.2


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

end of thread, other threads:[~2020-12-22 11:21 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-12 13:48 [PATCH 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
2020-11-12 13:48 ` [PATCH 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
2020-11-12 17:33   ` Tom Tromey
2020-11-12 17:36     ` Tom Tromey
2020-11-12 13:48 ` [PATCH 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
2020-11-12 18:03   ` Tom Tromey
2020-12-07 16:37 ` [PATCH v2 0/2] Add native GNU/Linux support for ARC in GDB Shahab Vahedi
2020-12-07 16:37   ` [PATCH v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
2020-12-10 19:11     ` Tom Tromey
2020-12-07 16:37   ` [PATCH v2 2/2] gdb: Add native support for ARC in GNU/Linux Shahab Vahedi
2020-12-10 19:13     ` Tom Tromey
2020-12-10 19:33       ` Shahab Vahedi
2020-12-22 11:21 ` [PUSHED v2 1/2] arc: Take into account the REGNUM in supply/collect gdb hooks Shahab Vahedi
2020-12-22 11:21   ` [PUSHED v2 2/2] gdb: Add native support for ARC in GNU/Linux 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).