summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
authormp <mp@FreeBSD.org>2002-10-21 21:36:36 +0000
committermp <mp@FreeBSD.org>2002-10-21 21:36:36 +0000
commit87d8bcb4cec1d7592062e19a03884b7ccd18ce1c (patch)
tree5184b48f2a8269b9a5dece86c60fa56daef58e0c /gnu
parent07d5bdbde715fbdca6784137d3b29b870b8073ea (diff)
downloadFreeBSD-src-87d8bcb4cec1d7592062e19a03884b7ccd18ce1c.zip
FreeBSD-src-87d8bcb4cec1d7592062e19a03884b7ccd18ce1c.tar.gz
Add support for sparc64 kernel debugging.
Submitted by: tmm
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/binutils/gdb/kvm-fbsd.c69
1 files changed, 64 insertions, 5 deletions
diff --git a/gnu/usr.bin/binutils/gdb/kvm-fbsd.c b/gnu/usr.bin/binutils/gdb/kvm-fbsd.c
index 634a6b6..23dbeaf 100644
--- a/gnu/usr.bin/binutils/gdb/kvm-fbsd.c
+++ b/gnu/usr.bin/binutils/gdb/kvm-fbsd.c
@@ -500,19 +500,78 @@ fetch_kcore_registers (struct pcb *pcb)
#ifdef __sparc64__
-/*
-#include "sparc/tm-sp64.h"
-*/
+#define SPARC_INTREG_SIZE 8
+static void
fetch_kcore_registers (struct pcb *pcbp)
{
-}
+ static struct frame top;
+ CORE_ADDR f_addr;
+ int i;
+ /* Get the register values out of the sys pcb and store them where
+ `read_register' will find them. */
+ /*
+ * XXX many registers aren't available.
+ * XXX for the non-core case, the registers are stale - they are for
+ * the last context switch to the debugger.
+ * XXX do something with the floating-point registers?
+ */
+ supply_register (SP_REGNUM, (char *)&pcbp->pcb_fp);
+ supply_register (PC_REGNUM, (char *)&pcbp->pcb_pc);
+ f_addr = extract_address (&pcbp->pcb_fp, SPARC_INTREG_SIZE);
+ /* Load the previous frame by hand (XXX) and supply it. */
+ read_memory (f_addr + SPOFF, (char *)&top, sizeof (top));
+ for (i = 0; i < 8; i++)
+ supply_register (i + L0_REGNUM, (char *)&top.fr_local[i]);
+ for (i = 0; i < 8; i++)
+ supply_register (i + I0_REGNUM, (char *)&top.fr_in[i]);
+}
CORE_ADDR
fbsd_kern_frame_saved_pc (struct frame_info *fi)
{
- return NULL;
+ struct minimal_symbol *sym;
+ CORE_ADDR frame, pc_addr, pc;
+ char *buf;
+
+ buf = alloca (MAX_REGISTER_RAW_SIZE);
+ /* XXX: duplicates fi->extra_info->bottom. */
+ frame = (fi->next != NULL) ? fi->next->frame : read_sp ();
+ pc_addr = frame + offsetof (struct frame, fr_in[7]);
+
+#define READ_PC(pc, a, b) do { \
+ read_memory (a, b, SPARC_INTREG_SIZE); \
+ pc = extract_address (b, SPARC_INTREG_SIZE); \
+} while (0)
+
+ READ_PC (pc, pc_addr, buf);
+
+ sym = lookup_minimal_symbol_by_pc (pc);
+ if (sym != NULL)
+ {
+ if (strncmp (SYMBOL_NAME (sym), "tl0_", 4) == 0 ||
+ strcmp (SYMBOL_NAME (sym), "btext") == 0 ||
+ strcmp (SYMBOL_NAME (sym), "mp_startup") == 0 ||
+ strcmp (SYMBOL_NAME (sym), "fork_trampoline") == 0)
+ {
+ /*
+ * Ugly kluge: user space addresses aren't separated from kernel
+ * ones by range; if encountering a trap from user space, just
+ * return a 0 to stop the trace.
+ * Do the same for entry points of kernel processes to avoid
+ * printing garbage.
+ */
+ pc = 0;
+ }
+ if (strncmp (SYMBOL_NAME (sym), "tl1_", 4) == 0)
+ {
+ pc_addr = fi->frame + sizeof (struct frame) +
+ offsetof (struct trapframe, tf_tpc);
+ READ_PC (pc, pc_addr, buf);
+ }
+ }
+ return (pc);
}
#endif /* __sparc64__ */
OpenPOWER on IntegriCloud