diff options
author | mp <mp@FreeBSD.org> | 2002-10-21 21:36:36 +0000 |
---|---|---|
committer | mp <mp@FreeBSD.org> | 2002-10-21 21:36:36 +0000 |
commit | 87d8bcb4cec1d7592062e19a03884b7ccd18ce1c (patch) | |
tree | 5184b48f2a8269b9a5dece86c60fa56daef58e0c /gnu | |
parent | 07d5bdbde715fbdca6784137d3b29b870b8073ea (diff) | |
download | FreeBSD-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.c | 69 |
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__ */ |