[RFA/commit] (Ada) Add ravenscar tasking support on AArch64

Message ID 20180911140006.GA10972@adacore.com
State New, archived
Headers

Commit Message

Joel Brobecker Sept. 11, 2018, 2 p.m. UTC
  > > > gdb/ChangeLog:
> > > 
> > >         * aarch64-ravenscar-thread.h, aarch64-ravenscar-thread.c:
> > >         New files.
> > >         * aarch64-tdep.c: #include "aarch64-ravenscar-thread.h".
> > >         (aarch64_gdbarch_init): Add call to register_aarch64_ravenscar_ops.
> > >         * Makefile.in (ALL_64_TARGET_OBS): Add aarch64-ravenscar-thread.o.
> > >         (HFILES_NO_SRCDIR): Add aarch64-ravenscar-thread.h.
> > >         (ALLDEPFILES): Add aarch64-ravenscar-thread.c.
> > >         * configure.tgt (cpu_obs) [aarch64*-*-*]: Add ravenscar-thread.o
> > >         and aarch64-ravenscar-thread.o.
> > > 
> > > Tested on aarch64-elf using AdaCore's testsuite.
> > > OK to apply?
> > 
> > IMO this deserves a NEWS entry.
> 
> Yes, indeed. Thanks for catching that.
> Attached is a patch that does just that. OK to apply, Eli?

Actually - I thought that the patch for which the NEWS entry was
already in, but I immediately realized that it was not. So better
yet, here is a patch that merges the two:

gdb/ChangeLog:

        * aarch64-ravenscar-thread.h, aarch64-ravenscar-thread.c:
        New files.
        * aarch64-tdep.c: #include "aarch64-ravenscar-thread.h".
        (aarch64_gdbarch_init): Add call to register_aarch64_ravenscar_ops.
        * Makefile.in (ALL_64_TARGET_OBS): Add aarch64-ravenscar-thread.o.
        (HFILES_NO_SRCDIR): Add aarch64-ravenscar-thread.h.
        (ALLDEPFILES): Add aarch64-ravenscar-thread.c.
        * configure.tgt (cpu_obs) [aarch64*-*-*]: Add ravenscar-thread.o
        and aarch64-ravenscar-thread.o.
        * gdb/NEWS: Add entry documenting Ravenscar tasking support
        on AArch64 ELF.

No change compared to the last version, except for the addition of
the NEWS entry.

Thank you!
  

Comments

Joel Brobecker Nov. 2, 2018, 5:39 p.m. UTC | #1
Hello,

> gdb/ChangeLog:
> 
>         * aarch64-ravenscar-thread.h, aarch64-ravenscar-thread.c:
>         New files.
>         * aarch64-tdep.c: #include "aarch64-ravenscar-thread.h".
>         (aarch64_gdbarch_init): Add call to register_aarch64_ravenscar_ops.
>         * Makefile.in (ALL_64_TARGET_OBS): Add aarch64-ravenscar-thread.o.
>         (HFILES_NO_SRCDIR): Add aarch64-ravenscar-thread.h.
>         (ALLDEPFILES): Add aarch64-ravenscar-thread.c.
>         * configure.tgt (cpu_obs) [aarch64*-*-*]: Add ravenscar-thread.o
>         and aarch64-ravenscar-thread.o.
>         * gdb/NEWS: Add entry documenting Ravenscar tasking support
>         on AArch64 ELF.
> 
> No change compared to the last version, except for the addition of
> the NEWS entry.

For the record, I just pushed this patch to master.

Cheers,
  

Patch

From ce6f16cdf46a266db68aa4610fa5a1bef6323f23 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Fri, 7 Sep 2018 17:53:37 -0400
Subject: [PATCH] (Ada) Add ravenscar tasking support on AArch64

This patch adds support for debugging Ravenscar tasks, similar to what
is done for ppc and sparc.

gdb/ChangeLog:

        * aarch64-ravenscar-thread.h, aarch64-ravenscar-thread.c:
        New files.
        * aarch64-tdep.c: #include "aarch64-ravenscar-thread.h".
        (aarch64_gdbarch_init): Add call to register_aarch64_ravenscar_ops.
        * Makefile.in (ALL_64_TARGET_OBS): Add aarch64-ravenscar-thread.o.
        (HFILES_NO_SRCDIR): Add aarch64-ravenscar-thread.h.
        (ALLDEPFILES): Add aarch64-ravenscar-thread.c.
        * configure.tgt (cpu_obs) [aarch64*-*-*]: Add ravenscar-thread.o
        and aarch64-ravenscar-thread.o.
        * gdb/NEWS: Add entry documenting Ravenscar tasking support
        on AArch64 ELF.
---
 gdb/Makefile.in                |   3 +
 gdb/NEWS                       |   5 +
 gdb/aarch64-ravenscar-thread.c | 213 +++++++++++++++++++++++++++++++++++++++++
 gdb/aarch64-ravenscar-thread.h |  27 ++++++
 gdb/aarch64-tdep.c             |   3 +
 gdb/configure.tgt              |   3 +-
 6 files changed, 253 insertions(+), 1 deletion(-)
 create mode 100644 gdb/aarch64-ravenscar-thread.c
 create mode 100644 gdb/aarch64-ravenscar-thread.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index d49f3ee..e985dfc 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -627,6 +627,7 @@  ALL_64_TARGET_OBS = \
 	aarch64-fbsd-tdep.o \
 	aarch64-linux-tdep.o \
 	aarch64-newlib-tdep.o \
+	aarch64-ravenscar-thread.o \
 	aarch64-tdep.o \
 	alpha-bsd-tdep.o \
 	alpha-linux-tdep.o \
@@ -1165,6 +1166,7 @@  SFILES = \
 # right, it is probably easiest just to list .h files here directly.
 
 HFILES_NO_SRCDIR = \
+	aarch64-ravenscar-thread.h \
 	aarch64-tdep.h \
 	ada-lang.h \
 	addrmap.h \
@@ -2169,6 +2171,7 @@  ALLDEPFILES = \
 	aarch64-linux-nat.c \
 	aarch64-linux-tdep.c \
 	aarch64-newlib-tdep.c \
+	aarch64-ravenscar-thread.c \
 	aarch64-tdep.c \
 	aix-thread.c \
 	alpha-bsd-nat.c \
diff --git a/gdb/NEWS b/gdb/NEWS
index 75436b0..cba67c5 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -18,6 +18,11 @@ 
 * DWARF index cache: GDB can now automatically save indices of DWARF
   symbols on disk to speed up further loading of the same binaries.
 
+* Ada task switching is now supported on aarch64-elf targets when
+  debugging a program using the Ravenscar Profile.  For more information,
+  see the "Tasking Support when using the Ravenscar Profile" section
+  in the GDB user manual.
+
 * GDB in batch mode now exits with status 1 if the last command to be
   executed failed.
 
diff --git a/gdb/aarch64-ravenscar-thread.c b/gdb/aarch64-ravenscar-thread.c
new file mode 100644
index 0000000..88629e4
--- /dev/null
+++ b/gdb/aarch64-ravenscar-thread.c
@@ -0,0 +1,213 @@ 
+/* Ravenscar Aarch64 target support.
+
+   Copyright (C) 2017-2018 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 "gdbcore.h"
+#include "regcache.h"
+#include "aarch64-tdep.h"
+#include "inferior.h"
+#include "ravenscar-thread.h"
+#include "aarch64-ravenscar-thread.h"
+
+#define NO_OFFSET -1
+
+/* See aarch64-tdep.h for register numbers.  */
+
+static const int aarch64_context_offsets[] =
+{
+  /* X0 - X28 */
+  NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
+  NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
+  NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
+  NO_OFFSET, NO_OFFSET, NO_OFFSET, NO_OFFSET,
+  NO_OFFSET, NO_OFFSET, NO_OFFSET, 0,
+  8,         16,        24,        32,
+  40,        48,        56,        64,
+  72,
+
+  /* FP, LR, SP, PC, CPSR */
+  /* Note that as task switch is synchronous, PC is in fact the LR here */
+  80,        88,        96,        88,
+  NO_OFFSET,
+
+  /* Q0 - Q31 */
+  112,       128,       144,       160,
+  176,       192,       208,       224,
+  240,       256,       272,       288,
+  304,       320,       336,       352,
+  368,       384,       400,       416,
+  432,       448,       464,       480,
+  496,       512,       528,       544,
+  560,       576,       592,       608,
+
+  /* FPSR, FPCR */
+  104,       108,
+
+  /* FPU Saved field */
+  624
+};
+
+/* The register layout info.  */
+
+struct ravenscar_reg_info
+{
+  /* A table providing the offset relative to the context structure
+     where each register is saved.  */
+  const int *context_offsets;
+
+  /* The number of elements in the context_offsets table above.  */
+  int context_offsets_size;
+};
+
+/* supply register REGNUM, which has been saved on REGISTER_ADDR, to the
+   regcache.  */
+
+static void
+supply_register_at_address (struct regcache *regcache, int regnum,
+                            CORE_ADDR register_addr)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  int buf_size = register_size (gdbarch, regnum);
+  gdb_byte *buf;
+
+  buf = (gdb_byte *) alloca (buf_size);
+  read_memory (register_addr, buf, buf_size);
+  regcache->raw_supply (regnum, buf);
+}
+
+/* Return true if, for a non-running thread, REGNUM has been saved on the
+   Thread_Descriptor.  */
+
+static int
+register_in_thread_descriptor_p (const struct ravenscar_reg_info *reg_info,
+				 int regnum)
+{
+  /* Check FPU registers */
+  return (regnum < reg_info->context_offsets_size
+	  && reg_info->context_offsets[regnum] != NO_OFFSET);
+}
+
+/* to_fetch_registers when inferior_ptid is different from the running
+   thread.  */
+
+static void
+aarch64_ravenscar_generic_fetch_registers
+  (const struct ravenscar_reg_info *reg_info,
+   struct regcache *regcache, int regnum)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  const int num_regs = gdbarch_num_regs (gdbarch);
+  int current_regnum;
+  CORE_ADDR current_address;
+  CORE_ADDR thread_descriptor_address;
+
+  /* The tid is the thread_id field, which is a pointer to the thread.  */
+  thread_descriptor_address = (CORE_ADDR) inferior_ptid.tid ();
+
+  /* Read registers.  */
+  for (current_regnum = 0; current_regnum < num_regs; current_regnum++)
+    {
+      if (register_in_thread_descriptor_p (reg_info, current_regnum))
+        {
+          current_address = thread_descriptor_address
+            + reg_info->context_offsets[current_regnum];
+          supply_register_at_address (regcache, current_regnum,
+                                      current_address);
+        }
+    }
+}
+
+/* to_prepare_to_store when inferior_ptid is different from the running
+   thread.  */
+
+static void
+aarch64_ravenscar_generic_prepare_to_store (struct regcache *regcache)
+{
+  /* Nothing to do.  */
+}
+
+/* to_store_registers when inferior_ptid is different from the running
+   thread.  */
+
+static void
+aarch64_ravenscar_generic_store_registers
+  (const struct ravenscar_reg_info *reg_info,
+   struct regcache *regcache, int regnum)
+{
+  struct gdbarch *gdbarch = regcache->arch ();
+  int buf_size = register_size (gdbarch, regnum);
+  gdb_byte buf[buf_size];
+  ULONGEST register_address;
+
+  if (register_in_thread_descriptor_p (reg_info, regnum))
+    register_address
+      = inferior_ptid.tid () + reg_info->context_offsets [regnum];
+  else
+    return;
+
+  regcache->raw_collect (regnum, buf);
+  write_memory (register_address,
+                buf,
+                buf_size);
+}
+
+/* The ravenscar_reg_info for most Aarch64 targets.  */
+
+static const struct ravenscar_reg_info aarch64_reg_info =
+{
+  aarch64_context_offsets,
+  ARRAY_SIZE (aarch64_context_offsets),
+};
+
+/* Implement the to_fetch_registers ravenscar_arch_ops method
+   for most Aarch64 targets.  */
+
+static void
+aarch64_ravenscar_fetch_registers (struct regcache *regcache, int regnum)
+{
+  aarch64_ravenscar_generic_fetch_registers
+    (&aarch64_reg_info, regcache, regnum);
+}
+
+/* Implement the to_store_registers ravenscar_arch_ops method
+   for most Aarch64 targets.  */
+
+static void
+aarch64_ravenscar_store_registers (struct regcache *regcache, int regnum)
+{
+  aarch64_ravenscar_generic_store_registers
+    (&aarch64_reg_info, regcache, regnum);
+}
+
+/* The ravenscar_arch_ops vector for most Aarch64 targets.  */
+
+static struct ravenscar_arch_ops aarch64_ravenscar_ops =
+{
+  aarch64_ravenscar_fetch_registers,
+  aarch64_ravenscar_store_registers,
+  aarch64_ravenscar_generic_prepare_to_store
+};
+
+/* Register aarch64_ravenscar_ops in GDBARCH.  */
+
+void
+register_aarch64_ravenscar_ops (struct gdbarch *gdbarch)
+{
+  set_gdbarch_ravenscar_ops (gdbarch, &aarch64_ravenscar_ops);
+}
diff --git a/gdb/aarch64-ravenscar-thread.h b/gdb/aarch64-ravenscar-thread.h
new file mode 100644
index 0000000..e900233
--- /dev/null
+++ b/gdb/aarch64-ravenscar-thread.h
@@ -0,0 +1,27 @@ 
+/* Ravenscar Aarch64 target support.
+ 
+   Copyright (C) 2017-2018 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 AARCH64_RAVENSCAR_THREAD_H
+#define AARCH64_RAVENSCAR_THREAD_H
+
+struct gdbarch;
+
+extern void register_aarch64_ravenscar_ops (struct gdbarch *gdbarch);
+
+#endif
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index d2e6ac6..02d1f0f 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -46,6 +46,7 @@ 
 #include "selftest.h"
 
 #include "aarch64-tdep.h"
+#include "aarch64-ravenscar-thread.h"
 
 #include "elf-bfd.h"
 #include "elf/aarch64.h"
@@ -3175,6 +3176,8 @@  aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 		  value_of_aarch64_user_reg,
 		  &aarch64_register_aliases[i].regnum);
 
+  register_aarch64_ravenscar_ops (gdbarch);
+
   return gdbarch;
 }
 
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 6d1a4df..ebe7dff 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -48,7 +48,8 @@  amd64_tobjs="amd64-tdep.o arch/amd64.o ${x86_tobjs}"
 
 case "${targ}" in
 aarch64*-*-*)
-	cpu_obs="aarch64-tdep.o arch/aarch64-insn.o arch/aarch64.o";;
+	cpu_obs="aarch64-tdep.o arch/aarch64-insn.o arch/aarch64.o \
+		 ravenscar-thread.o aarch64-ravenscar-thread.o";;
 
 alpha*-*-*)
 	# Target: Alpha
-- 
2.1.4