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]

Re: [PATCH][SH] Implement core-file support for sh-linux


>> Then the code from shnbsd can be moved to sh-tdep.c and the only
>> remaining bit is to initialize the array appropriately in shbnsd-tdep
>> and sh-linux-tdep.
>
> I believe this patch should do what you suggest.

You definitely got the idea, but the implementation does not work
in the case of multi-arch debugging.  This is because you are
introducing a global variable.  The solution is to rely on the
gdbarch_tdep structure.  Here is a patch that should provide you
with a quick sketch of how you can implement this:
  - I created a gdbarch_tdep structure for SH, since it didn't need one
    before; I populated it with a simple regmap being an array of
    integers, but it appears that this may not be sufficient, since
    registers might not be stored in the same order as GDB register
    numbers.  So your slightly more complex structure might be required
  - Move the core-file support from shnbsd-tdep to sh-tdep, did some
    renaming - hopefully I didn't miss much
  - Initialized support for core-file in sh-tdep knowing that the
    routine that checks core file section names will only return
    non-NULL if such support is available (detected by looking at
    the gdbarch_tdep structure).

Hopefully, once this is in place, the only thing you should have left
to do is to create the offset maps in sh-linux-tdep and set the tdep
maps during the sh/linux gdbarch initialization.

Does this make sense to you?

-- 
Joel
diff --git a/gdb/sh-linux-tdep.c b/gdb/sh-linux-tdep.c
index 46aad1d..5eba796 100644
--- a/gdb/sh-linux-tdep.c
+++ b/gdb/sh-linux-tdep.c
@@ -28,6 +28,8 @@
 static void
 sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
   /* GNU/Linux uses SVR4-style shared libraries.  */
   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
   set_solib_svr4_fetch_link_map_offsets
@@ -36,6 +38,12 @@ sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
+
+  /* Core files are supported for 32-bit SH only, at present.  */
+  if (info.bfd_arch_info->mach != bfd_mach_sh5)
+    {
+      /* set tdep->core_regmap and tdep->core_fpregmap here.  */
+    }
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c
index 3e509bf..5d8d5a3 100644
--- a/gdb/sh-tdep.c
+++ b/gdb/sh-tdep.c
@@ -2740,6 +2740,102 @@ sh_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 }
 
 
+/* Supply register REGNUM from the buffer specified by GREGS and LEN
+   in the general-purpose register set REGSET to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+static void
+sh_supply_gregset (const struct regset *regset, struct regcache *regcache,
+		   int regnum, const void *gregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* Use the tdep data to fill in the regset.  */
+}
+
+/* Collect register REGNUM in the general-purpose register set
+   REGSET. from register cache REGCACHE into the buffer specified by
+   GREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+static void
+sh_collect_gregset (const struct regset *regset,
+		    const struct regcache *regcache,
+		    int regnum, void *gregs, size_t len)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int i;
+
+  /* Use the tdep data to fill in the regset.  */
+}
+
+/* SH register sets.  */
+
+static struct regset sh_gregset =
+{
+  NULL,
+  sh_supply_gregset,
+  sh_collect_gregset
+};
+
+/* Supply register REGNUM from the buffer specified by FPREGS and LEN
+   in the floating point register set REGSET to register cache
+   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
+
+static void
+sh_supply_fpregset (const struct regset *regset, struct regcache *regcache,
+		    int regnum, const void *fpregs, size_t len)
+{
+  /* Same as above.  */
+}
+
+/* Collect register REGNUM in the floating point register set
+   REGSET. from register cache REGCACHE into the buffer specified by
+   FPREGS and LEN.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+static void
+sh_collect_fpregset (const struct regset *regset,
+		     const struct regcache *regcache,
+		     int regnum, void *fpregs, size_t len)
+{
+  /* Same as above.  */
+}
+
+/* SH register sets.  */
+
+static struct regset sh_fpregset =
+{
+  NULL,
+  sh_supply_fpregset,
+  sh_collect_fpregset
+};
+
+/* Return the appropriate register set for the core section identified
+   by SECT_NAME and SECT_SIZE.  */
+
+static const struct regset *
+sh_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name,
+			     size_t sect_size)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->core_regmap == NULL)
+    return NULL;  /* core files not supported on this architecture.  */
+
+  if (strcmp (sect_name, ".reg") == 0 && sect_size >= SH_SIZEOF_GREGS)
+    return &sh_gregset;
+
+  if (tdep->core_fp_regmap
+      && strcmp (sect_name, ".reg2") == 0
+      && sect_size >= SH_SIZEOF_FP_GREGS)
+    return &sh_fpregset;
+
+  return NULL;
+}
+
 static struct gdbarch *
 sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -2803,7 +2899,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* None found, create a new architecture from the information
      provided. */
-  gdbarch = gdbarch_alloc (&info, NULL);
+  tdep = XZALLOC (struct gdbarch_tdep);
+  gdbarch = gdbarch_alloc (&info, tdep);
 
   set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
   set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
@@ -2847,6 +2944,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   dwarf2_frame_set_init_reg (gdbarch, sh_dwarf2_frame_init_reg);
 
+  set_gdbarch_regset_from_core_section (gdbarch, sh_regset_from_core_section);
+
   switch (info.bfd_arch_info->mach)
     {
     case bfd_mach_sh:
diff --git a/gdb/sh-tdep.h b/gdb/sh-tdep.h
index dfa928e..37a8f8c 100644
--- a/gdb/sh-tdep.h
+++ b/gdb/sh-tdep.h
@@ -82,6 +82,18 @@ enum
     FV_LAST_REGNUM = 79
   };
 
+struct gdbarch_tdep
+{
+  /* Non-NULL when debugging from a core file.  Provides the offset
+     where each general-purpose register is stored inside the associated
+     core file section.  */
+  int *core_regmap;
+  /* Non-NULL when debugging from a core file and when FP registers are
+     available.  Provides the offset where each FP register is stored
+     inside the associated core file section.  */
+  int *core_fp_regmap;
+};
+
 extern gdbarch_init_ftype sh64_gdbarch_init;
 extern void sh64_show_regs (struct frame_info *);
 
diff --git a/gdb/shnbsd-tdep.c b/gdb/shnbsd-tdep.c
index a0cddc5..633770d 100644
--- a/gdb/shnbsd-tdep.c
+++ b/gdb/shnbsd-tdep.c
@@ -59,105 +59,6 @@ static const int regmap[] =
 /* Sizeof `struct reg' in <machine/reg.h>.  */
 #define SHNBSD_SIZEOF_GREGS	(21 * 4)
 
-/* Supply register REGNUM from the buffer specified by GREGS and LEN
-   in the general-purpose register set REGSET to register cache
-   REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
-
-static void
-shnbsd_supply_gregset (const struct regset *regset,
-		       struct regcache *regcache,
-		       int regnum, const void *gregs, size_t len)
-{
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  const gdb_byte *regs = gregs;
-  int i;
-
-  gdb_assert (len >= SHNBSD_SIZEOF_GREGS);
-
-  if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
-    regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch),
-			 regs + (0 * 4));
-
-  if (regnum == SR_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, SR_REGNUM, regs + (1 * 4));
-
-  if (regnum == PR_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, PR_REGNUM, regs + (2 * 4));
-
-  if (regnum == MACH_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, MACH_REGNUM, regs + (3 * 4));
-
-  if (regnum == MACL_REGNUM || regnum == -1)
-    regcache_raw_supply (regcache, MACL_REGNUM, regs + (4 * 4));
-
-  for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
-    {
-      if (regnum == i || regnum == -1)
-	regcache_raw_supply (regcache, i, regs + regmap[i - R0_REGNUM]);
-    }
-}
-
-/* Collect register REGNUM in the general-purpose register set
-   REGSET. from register cache REGCACHE into the buffer specified by
-   GREGS and LEN.  If REGNUM is -1, do this for all registers in
-   REGSET.  */
-
-static void
-shnbsd_collect_gregset (const struct regset *regset,
-			const struct regcache *regcache,
-			int regnum, void *gregs, size_t len)
-{
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  gdb_byte *regs = gregs;
-  int i;
-
-  gdb_assert (len >= SHNBSD_SIZEOF_GREGS);
-
-  if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
-    regcache_raw_collect (regcache, gdbarch_pc_regnum (gdbarch),
-			  regs + (0 * 4));
-
-  if (regnum == SR_REGNUM || regnum == -1)
-    regcache_raw_collect (regcache, SR_REGNUM, regs + (1 * 4));
-
-  if (regnum == PR_REGNUM || regnum == -1)
-    regcache_raw_collect (regcache, PR_REGNUM, regs + (2 * 4));
-
-  if (regnum == MACH_REGNUM || regnum == -1)
-    regcache_raw_collect (regcache, MACH_REGNUM, regs + (3 * 4));
-
-  if (regnum == MACL_REGNUM || regnum == -1)
-    regcache_raw_collect (regcache, MACL_REGNUM, regs + (4 * 4));
-
-  for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
-    {
-      if (regnum == i || regnum == -1)
-	regcache_raw_collect (regcache, i, regs + regmap[i - R0_REGNUM]);
-    }
-}
-
-/* SH register sets.  */
-
-static struct regset shnbsd_gregset =
-{
-  NULL,
-  shnbsd_supply_gregset,
-  shnbsd_collect_gregset
-};
-
-/* Return the appropriate register set for the core section identified
-   by SECT_NAME and SECT_SIZE.  */
-
-static const struct regset *
-shnbsd_regset_from_core_section (struct gdbarch *gdbarch,
-				 const char *sect_name, size_t sect_size)
-{
-  if (strcmp (sect_name, ".reg") == 0 && sect_size >= SHNBSD_SIZEOF_GREGS)
-    return &shnbsd_gregset;
-
-  return NULL;
-}
-
 void
 shnbsd_supply_reg (struct regcache *regcache, const char *regs, int regnum)
 {
@@ -177,11 +78,12 @@ static void
 shnbsd_init_abi (struct gdbarch_info info,
                   struct gdbarch *gdbarch)
 {
-  set_gdbarch_regset_from_core_section
-    (gdbarch, shnbsd_regset_from_core_section);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+
+  /* Set tdep->core_regmap here.  */
 }
 
 

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