[RFC,5/6] Linux kernel thread awareness Arm target support

Message ID 1548738199-9403-6-git-send-email-omair.javaid@linaro.org
State New, archived
Headers

Commit Message

Omair Javaid Jan. 29, 2019, 5:03 a.m. UTC
  This patch adds support for linux kernel thread aware debugging on Arm targets.
It implements arm_linux_kernel_ops derived class to provide Arm targets
specific functionality to linux_kernel_ops class.

gdb/ChangeLog:

	* Makefile.in (ALL_TARGET_OBS): Add arm-lk-tdep.o.
	(ALLDEPFILES): Add arm-lk-tdep.c.
	* configure.tgt (arm*-*-linux*): Add arm-lk-tdep.o and lk_tobjs.
	* arm-lk-tdep.c: New file.
---
 gdb/Makefile.in   |   2 +
 gdb/arm-lk-tdep.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/configure.tgt |   3 +-
 3 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 gdb/arm-lk-tdep.c
  

Patch

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 74c9da2..f6dbfdd 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -677,6 +677,7 @@  ALL_TARGET_OBS = \
 	arm-bsd-tdep.o \
 	arm-fbsd-tdep.o \
 	arm-linux-tdep.o \
+	arm-lk-tdep.o \
 	arm-nbsd-tdep.o \
 	arm-obsd-tdep.o \
 	arm-pikeos-tdep.o \
@@ -2195,6 +2196,7 @@  ALLDEPFILES = \
 	arm-linux.c \
 	arm-linux-nat.c \
 	arm-linux-tdep.c \
+	arm-lk-tdep.c \
 	arm-nbsd-nat.c \
 	arm-nbsd-tdep.c \
 	arm-obsd-tdep.c \
diff --git a/gdb/arm-lk-tdep.c b/gdb/arm-lk-tdep.c
new file mode 100644
index 0000000..f046490
--- /dev/null
+++ b/gdb/arm-lk-tdep.c
@@ -0,0 +1,139 @@ 
+/* Target-dependent code of Linux kernel target for ARM architecture.
+   Copyright (C) 2019 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 "osabi.h"
+#include "regset.h"
+#include "gdbcore.h"
+
+#include "arch/arm.h"
+
+#include "lk-low.h"
+
+/* Define register map and set.  */
+
+/* Referring to Linux kernel source arch/arm/include/asm/thread_info.h
+   struct cpu_context_save.  */
+
+static const struct regcache_map_entry arm_gregmap_lk[] =
+  {
+    { 8, ARM_A4_REGNUM + 1 },
+    { 1, ARM_SP_REGNUM },
+    { 1, ARM_PC_REGNUM },
+    { -2, REGCACHE_MAP_SKIP, 4 },
+    { 0 }
+  };
+
+const struct regset arm_gregset_lk =
+  {
+    arm_gregmap_lk,
+    regcache_supply_regset,
+    regcache_collect_regset
+  };
+
+/* Arm specific implementation for linux_kernel_ops.  */
+
+class arm_linux_kernel_ops : public linux_kernel_ops
+{
+public:
+  arm_linux_kernel_ops ()
+  {}
+
+  void get_registers (CORE_ADDR task, struct regcache *regcache,
+                      int regnum) override;
+protected:
+  void arch_read_symbols () override;
+};
+
+/* Implement linux_kernel_ops->arch_read_symbols virtual method.  */
+
+void
+arm_linux_kernel_ops::arch_read_symbols ()
+{
+  declare_field ("task_struct->stack", LK_CONFIG_ALWAYS);
+  declare_field ("thread_info->cpu_context", LK_CONFIG_ALWAYS);
+}
+
+/* Implement linux_kernel_ops->get_registers virtual method.  */
+
+void
+arm_linux_kernel_ops::get_registers (CORE_ADDR task,
+                                     struct regcache *regcache, int regnum)
+{
+  CORE_ADDR cpu_context, thread_info;
+  gdb_byte buf[48];
+  size_t size;
+
+  /* Read thread_info address.  */
+  thread_info = lk_read_addr (task + offset ("task_struct->stack"));
+
+  /* Calculate cpu_context address from thread_info address.  */
+  cpu_context = thread_info + offset ("thread_info->cpu_context");
+
+  size = FIELD_SIZE (field ("thread_info->cpu_context"));
+
+  gdb_assert (size <= sizeof (buf));
+
+  read_memory (cpu_context, buf, size);
+
+  regcache->supply_regset (&arm_gregset_lk, -1, buf, size);
+}
+
+/* Implement gdbarch get_new_lk_ops hook.  */
+
+static linux_kernel_ops *
+arm_get_new_lk_ops (struct gdbarch *gdbarch)
+{
+  return new arm_linux_kernel_ops;
+}
+
+/* Initialize Linux kernel specific gdbarch hooks.  */
+
+static void
+arm_lk_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  /* Support linux kernel debugging.  */
+  set_gdbarch_get_new_lk_ops (gdbarch, arm_get_new_lk_ops);
+}
+
+/* From the ELF-headers point of view Linux kernel- and user-space binaries
+   are the same.  So we have to rely on some heuristics to distinguish them.
+
+   For the heuristic we check for __ksymtab section in the vmlinux and
+   modules .ko files.  */
+
+static enum gdb_osabi
+arm_lk_osabi_sniffer (bfd *abfd)
+{
+  if (bfd_get_section_by_name (abfd, "__ksymtab"))
+    return GDB_OSABI_LINUX_KERNEL;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+void
+_initialize_arm_lk_tdep (void)
+{
+  /* Hook us into the OSABI mechanism.  */
+  gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_LINUX_KERNEL,
+				  arm_lk_init_abi);
+
+  /* Add OSABI sniffer.  */
+  gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_elf_flavour,
+				  arm_lk_osabi_sniffer);
+}
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 3713b9b..fe5a653 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -167,7 +167,8 @@  arm*-wince-pe | arm*-*-mingw32ce*)
 arm*-*-linux*)
 	# Target: ARM based machine running GNU/Linux
 	gdb_target_obs="arch/arm-linux.o arm-linux-tdep.o glibc-tdep.o \
-			solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o"
+			solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o \
+			arm-lk-tdep.o ${lk_tobjs}"
 	build_gdbserver=yes
 	;;
 arm*-*-freebsd*)