From 13b7c2d2a602c1830ad4a3f2a50a66e3c4f2f1a3 Mon Sep 17 00:00:00 2001
From: Robin Haberkorn <robin.haberkorn@googlemail.com>
Date: Thu, 12 Jul 2018 17:29:04 +0600
Subject: [PATCH] added support for handling core dumps on arm-none-eabi-gdb
 (Embedded ARM)

 * this is merely a hack and not yet upstreamable, as it modifies core-regset.c,
   corelow.c and gregset.h with definitions taken from here and there.
 * core-regset.c is missing the following definitions:
   supply_gregset(), GDB_GREGSET_T, GDB_FPREGSET_T
 * probably, they should be added as a new module, but I don't know where
   it should be put. This should be discussed on the GDB mailing list.
 * also floatin point register retrieval is still missing and has simply
   been commented out.
---
 gdb/configure.tgt |  2 +-
 gdb/core-regset.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/corelow.c     |  2 +-
 gdb/gregset.h     |  3 +++
 4 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 7f1aac3..438f35b 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -112,7 +112,7 @@ arm*-*-symbianelf*)
 	;;
 arm*-*-*)
 	# Target: ARM embedded system
-	gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o"
+	gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o core-regset.o"
 	gdb_sim=../sim/arm/libsim.a
 	;;
 
diff --git a/gdb/core-regset.c b/gdb/core-regset.c
index 278887b..2227f5a 100644
--- a/gdb/core-regset.c
+++ b/gdb/core-regset.c
@@ -39,9 +39,60 @@
 #include <sys/procfs.h>
 #endif
 
+#include "arch/arm.h"
+
 /* Prototypes for supply_gregset etc.  */
 #include "gregset.h"
 
+#define ARM_CPSR_GREGNUM 16
+extern int arm_apcs_32;
+
+#define ARM_LINUX_SIZEOF_GREGSET (18 * INT_REGISTER_SIZE)
+
+void
+arm_linux_supply_gregset (const struct regset *regset,
+			  struct regcache *regcache,
+			  int regnum, const void *gregs_buf, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  const gdb_byte *gregs = (const gdb_byte *) gregs_buf;
+  int regno;
+  CORE_ADDR reg_pc;
+  gdb_byte pc_buf[INT_REGISTER_SIZE];
+
+  for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
+    if (regnum == -1 || regnum == regno)
+      regcache_raw_supply (regcache, regno,
+			   gregs + INT_REGISTER_SIZE * regno);
+
+  if (regnum == ARM_PS_REGNUM || regnum == -1)
+    {
+      if (arm_apcs_32)
+	regcache_raw_supply (regcache, ARM_PS_REGNUM,
+			     gregs + INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
+      else
+	regcache_raw_supply (regcache, ARM_PS_REGNUM,
+			     gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
+    }
+
+  if (regnum == ARM_PC_REGNUM || regnum == -1)
+    {
+      reg_pc = extract_unsigned_integer (gregs
+					 + INT_REGISTER_SIZE * ARM_PC_REGNUM,
+					 INT_REGISTER_SIZE, byte_order);
+      reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc);
+      store_unsigned_integer (pc_buf, INT_REGISTER_SIZE, byte_order, reg_pc);
+      regcache_raw_supply (regcache, ARM_PC_REGNUM, pc_buf);
+    }
+}
+
+void
+supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
+{
+  arm_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0);
+}
+
 /* Provide registers to GDB from a core file.
 
    CORE_REG_SECT points to an array of bytes, which are the contents
@@ -84,9 +135,11 @@ fetch_core_registers (struct regcache *regcache,
       else
 	{
 	  memcpy (&fpregset, core_reg_sect, sizeof (fpregset));
+#if 0
 	  if (gdbarch_fp0_regnum (get_regcache_arch (regcache)) >= 0)
 	    supply_fpregset (regcache,
 			     (const gdb_fpregset_t *) fpregset_p);
+#endif
 	}
       break;
 
diff --git a/gdb/corelow.c b/gdb/corelow.c
index c46af0a..504fd26 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -541,7 +541,7 @@ get_core_register_section (struct regcache *regcache,
       warning (_("Section `%s' in core file too small."), section_name);
       return;
     }
-  if (size != min_size && !(regset->flags & REGSET_VARIABLE_SIZE))
+  if (size != min_size && regset && !(regset->flags & REGSET_VARIABLE_SIZE))
     {
       warning (_("Unexpected size of section `%s' in core file."),
 	       section_name);
diff --git a/gdb/gregset.h b/gdb/gregset.h
index 3101edc..ff85d46 100644
--- a/gdb/gregset.h
+++ b/gdb/gregset.h
@@ -23,6 +23,9 @@
 #include <sys/procfs.h>
 #endif
 
+#define GDB_GREGSET_T struct { uint32_t reg[18]; }
+#define GDB_FPREGSET_T struct { uint32_t reg[18]; }
+
 #ifndef GDB_GREGSET_T
 #define GDB_GREGSET_T gregset_t
 #endif
-- 
2.7.4

