This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] aarch64-linux-tdep support


Hi,

This is a re-spin of the AArch64 aarch64-linux-tdep patch addressing comments here:

http://www.sourceware.org/ml/gdb-patches/2013-01/msg00256.html

Can you explain why you added includes of "stap-probe.h", "user-regs.h"
and <ctype.h>? It doesn't look like the code changed much since the
previous version of the patch...

Sorry, my mistake, that code should have been excluded from this patch. It has been removed in this version.


Can you explain why you added includes of "stap-probe.h", "user-regs.h"
and <ctype.h>? It doesn't look like the code changed much since the
previous version of the patch...

This comment was just before aarch64_linux_sigframe_init, which
you moved.  I am wondering whether you wanted to move this comment
as well...

The comment in question discusses signal handling in general and is not specific to the function aarch64_linux_sigframe_init() therefore I think it makes more sense to leave this particular comment above the
signal related to code.



+  /* Note: We do not do anything with the two pseudo registers orig_X0
+     and syscallno (the 35th and 36th entries in the register buffer)
+     at the moment.  */

If you know why, it'd be interesting to document it here...

This comment is incorrect and has been removed.


Thanks
/Marcus

Proposed ChangeLog entry:

2013-01-22  Jim MacArthur  <jim.macarthur@arm.com>
	    Marcus Shawcroft  <marcus.shawcroft@arm.com>
	    Nigel Stephens  <nigel.stephens@arm.com>
	    Yufeng Zhang  <yufeng.zhang@arm.com>

	* Makefile.in (ALL_64_TARGET_OBS): Add aarch64-linux-tdep.o.
	(ALLDEPFILES): Add aarch64-linux-tdep.c.
	* aarch64-linux-tdep.c: New file.
	* aarch64-linux-tdep.h: New file.
	* aarch64-tdep.h (gdbarch_tdep): Define gregset and fpregset.
	* configure.tgt: Add aarch64-none-linux-gnu.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 8f5ec2d..a3fc2d3 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -519,7 +519,7 @@ TARGET_OBS = @TARGET_OBS@
 # All target-dependent objects files that require 64-bit CORE_ADDR
 # (used with --enable-targets=all --enable-64-bit-bfd).
 ALL_64_TARGET_OBS = \
-	aarch64-tdep.o \
+	aarch64-tdep.o aarch64-linux-tdep.o \
 	alphabsd-tdep.o alphafbsd-tdep.o alpha-linux-tdep.o alpha-mdebug-tdep.o \
 	alphanbsd-tdep.o alphaobsd-tdep.o alpha-osf1-tdep.o alpha-tdep.o \
 	amd64fbsd-tdep.o amd64-darwin-tdep.o amd64-dicos-tdep.o \
@@ -1417,7 +1417,7 @@ force_update:
 MAKEOVERRIDES=
 
 ALLDEPFILES = \
-	aarch64-tdep.c \
+	aarch64-tdep.c aarch64-linux-tdep.c \
 	aix-thread.c \
 	alpha-nat.c alphabsd-nat.c alpha-linux-nat.c \
 	alpha-tdep.c alpha-mdebug-tdep.c \
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
new file mode 100644
index 0000000..62c1096
--- /dev/null
+++ b/gdb/aarch64-linux-tdep.c
@@ -0,0 +1,293 @@
+/* Target-dependent code for GNU/Linux AArch64.
+
+   Copyright (C) 2009-2013 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   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 "gdbarch.h"
+#include "glibc-tdep.h"
+#include "linux-tdep.h"
+#include "aarch64-tdep.h"
+#include "aarch64-linux-tdep.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+#include "symtab.h"
+#include "tramp-frame.h"
+#include "trad-frame.h"
+
+#include "inferior.h"
+#include "regcache.h"
+#include "regset.h"
+
+/* The general-purpose regset consists of 31 X registers, plus SP, PC,
+   PSTATE and two extra pseudo 64-bit registers, as defined in the
+   AArch64 port of the Linux kernel.  */
+#define AARCH64_LINUX_SIZEOF_GREGSET  (36 * X_REGISTER_SIZE)
+
+/* The fp regset consists of 32 V registers, plus FPCR and FPSR which
+   are 4 bytes wide each, and the whole structure is padded to 128 bit
+   alignment.  */
+#define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
+
+/* Signal frame handling.
+
+      +----------+  ^
+      | saved lr |  |
+   +->| saved fp |--+
+   |  |          |
+   |  |          |
+   |  +----------+
+   |  | saved lr |
+   +--| saved fp |
+   ^  |          |
+   |  |          |
+   |  +----------+
+   ^  |          |
+   |  | signal   |
+   |  |          |
+   |  | saved lr |-->interrupted_function_pc
+   +--| saved fp |
+   |  +----------+
+   |  | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
+   +--| saved fp |<- FP
+      |          |
+      |          |<- SP
+      +----------+
+
+   On signal delivery, the kernel will create a signal handler stack
+   frame and setup the return address in LR to point at restorer
+   stub.  The signal stack frame is defined by:
+
+   struct rt_sigframe
+   {
+	siginfo_t info;
+	struct ucontext uc;
+   };
+
+   typeef struct
+   {
+     ...                                    128 bytes
+   } siginfo_t;
+
+   The ucontext has the following form:
+   struct ucontext {
+	unsigned long	  uc_flags;
+	struct ucontext  *uc_link;
+	stack_t		  uc_stack;
+	sigset_t	  uc_sigmask;
+	struct sigcontext uc_mcontext;
+  };
+
+  typedef struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+  } stack_t;
+
+  struct sigcontext {
+	unsigned long fault_address;
+	unsigned long regs[31];
+	unsigned long sp;	/ * 31 * /
+	unsigned long pc;	/ * 32 * /
+	unsigned long pstate;	/ * 33 * /
+	__u8 __reserved[4096]
+   };
+  The restorer stub will always have the form:
+
+  d28015a8        movz    x8, #0xad
+  d4000001        svc     #0x0
+
+  We detect signal frames by snooping the return code for the restorer
+  instruction sequence.
+
+  The handler then needs to recover the saved register set from
+  ucontext.uc_mcontext.  */
+
+/* These magic numbers need to reflect the layout of the kernel
+   defined struct rt_sigframe and ucontext.  */
+#define AARCH64_SIGCONTEXT_REG_SIZE             8
+#define AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET     128
+#define AARCH64_UCONTEXT_SIGCONTEXT_OFFSET      176
+#define AARCH64_SIGCONTEXT_XO_OFFSET            8
+
+/* Implement the "init" method of struct tramp_frame.  */
+
+static void
+aarch64_linux_sigframe_init (const struct tramp_frame *self,
+			     struct frame_info *this_frame,
+			     struct trad_frame_cache *this_cache,
+			     CORE_ADDR func)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
+  CORE_ADDR fp = get_frame_register_unsigned (this_frame, AARCH64_FP_REGNUM);
+  CORE_ADDR sigcontext_addr =
+    sp
+    + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
+    + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET;
+  int i;
+
+  for (i = 0; i < 31; i++)
+    {
+      trad_frame_set_reg_addr (this_cache,
+			       AARCH64_X0_REGNUM + i,
+			       sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
+			       + i * AARCH64_SIGCONTEXT_REG_SIZE);
+    }
+
+  trad_frame_set_reg_addr (this_cache, AARCH64_FP_REGNUM, fp);
+  trad_frame_set_reg_addr (this_cache, AARCH64_LR_REGNUM, fp + 8);
+  trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM, fp + 8);
+
+  trad_frame_set_id (this_cache, frame_id_build (fp, func));
+}
+
+static const struct tramp_frame aarch64_linux_rt_sigframe =
+{
+  SIGTRAMP_FRAME,
+  4,
+  {
+    /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8)
+       Soo1 0010 1hhi iiii iiii iiii iiir rrrr  */
+    {0xd2801168, -1},
+
+    /* svc  0x0      (o=0, l=1)
+       1101 0100 oooi iiii iiii iiii iii0 00ll  */
+    {0xd4000001, -1},
+    {TRAMP_SENTINEL_INSN, -1}
+  },
+  aarch64_linux_sigframe_init
+};
+
+/* Fill GDB's register array with the general-purpose register values
+   in the buffer pointed by GREGS_BUF.  */
+
+void
+aarch64_linux_supply_gregset (struct regcache *regcache,
+			      const gdb_byte *gregs_buf)
+{
+  int regno;
+
+  for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
+    regcache_raw_supply (regcache, regno,
+			 gregs_buf + X_REGISTER_SIZE
+			 * (regno - AARCH64_X0_REGNUM));
+}
+
+/* The "supply_regset" function for the general-purpose register set.  */
+
+static void
+supply_gregset_from_core (const struct regset *regset,
+			  struct regcache *regcache,
+			  int regnum, const void *regbuf, size_t len)
+{
+  aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
+}
+
+/* Fill GDB's register array with the floating-point register values
+   in the buffer pointed by FPREGS_BUF.  */
+
+void
+aarch64_linux_supply_fpregset (struct regcache *regcache,
+			       const gdb_byte *fpregs_buf)
+{
+  int regno;
+
+  for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
+    regcache_raw_supply (regcache, regno,
+			 fpregs_buf + V_REGISTER_SIZE
+			 * (regno - AARCH64_V0_REGNUM));
+
+  regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
+		       fpregs_buf + V_REGISTER_SIZE * 32);
+  regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
+		       fpregs_buf + V_REGISTER_SIZE * 32 + 4);
+}
+
+/* The "supply_regset" function for the floating-point register set.  */
+
+static void
+supply_fpregset_from_core (const struct regset *regset,
+			   struct regcache *regcache,
+			   int regnum, const void *regbuf, size_t len)
+{
+  aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
+}
+
+/* Implement the "regset_from_core_section" gdbarch method.  */
+
+static const struct regset *
+aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch,
+					const char *sect_name,
+					size_t sect_size)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (strcmp (sect_name, ".reg") == 0
+      && sect_size == AARCH64_LINUX_SIZEOF_GREGSET)
+    {
+      if (tdep->gregset == NULL)
+	tdep->gregset = regset_alloc (gdbarch, supply_gregset_from_core,
+				      NULL);
+      return tdep->gregset;
+    }
+
+  if (strcmp (sect_name, ".reg2") == 0
+      && sect_size == AARCH64_LINUX_SIZEOF_FPREGSET)
+    {
+      if (tdep->fpregset == NULL)
+	tdep->fpregset = regset_alloc (gdbarch, supply_fpregset_from_core,
+				       NULL);
+      return tdep->fpregset;
+    }
+  return NULL;
+}
+
+static void
+aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  tdep->lowest_pc = 0x8000;
+
+  set_solib_svr4_fetch_link_map_offsets (gdbarch,
+					 svr4_lp64_fetch_link_map_offsets);
+
+  /* Shared library handling.  */
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+
+  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
+  tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
+
+  /* Enable longjmp.  */
+  tdep->jb_pc = 11;
+
+  set_gdbarch_regset_from_core_section (gdbarch,
+					aarch64_linux_regset_from_core_section);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_aarch64_linux_tdep;
+
+void
+_initialize_aarch64_linux_tdep (void)
+{
+  gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
+			  aarch64_linux_init_abi);
+}
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
new file mode 100644
index 0000000..b1c3646
--- /dev/null
+++ b/gdb/aarch64-linux-tdep.h
@@ -0,0 +1,26 @@
+/* GNU/Linux on AArch64 target support, prototypes.
+
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by ARM Ltd.
+
+   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/>.  */
+
+struct regcache;
+
+extern void aarch64_linux_supply_gregset (struct regcache *regcache,
+					  const gdb_byte *gregs_buf);
+extern void aarch64_linux_supply_fpregset (struct regcache *regcache,
+					   const gdb_byte *fpregs_buf);
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index a2f3e36..0de3ba6 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -82,6 +82,10 @@ struct gdbarch_tdep
   /* And the size of each entry in the buf.  */
   size_t jb_elt_size;
 
+  /* Cached core file helpers.  */
+  struct regset *gregset;
+  struct regset *fpregset;
+
   /* Types for AdvSISD registers.  */
   struct type *vnq_type;
   struct type *vnd_type;
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 099f28f..10365c1 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -36,6 +36,12 @@ aarch64*-*-elf)
 	gdb_target_obs="aarch64-tdep.o"
 	;;
 
+aarch64*-*-linux*)
+	# Target: AArch64 linux
+	gdb_target_obs="aarch64-tdep.o aarch64-linux-tdep.o \
+			glibc-tdep.o linux-tdep.o solib-svr4.o \
+			symfile-mem.o"
+	;;
 
 alpha*-*-osf*)
 	# Target: Little-endian Alpha running OSF/1

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]