diff options
author | marcel <marcel@FreeBSD.org> | 2005-09-10 23:11:54 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2005-09-10 23:11:54 +0000 |
commit | 63c6575f860383f41a6fb197fe5bb43d76c06e75 (patch) | |
tree | 89b307a0cfa099f089e48944a466c8b712b245df /gnu | |
parent | 9d88c7f7b7004dffafb8e7e5d1d098ed506b015a (diff) | |
download | FreeBSD-src-63c6575f860383f41a6fb197fe5bb43d76c06e75.zip FreeBSD-src-63c6575f860383f41a6fb197fe5bb43d76c06e75.tar.gz |
Unwind across trapframes. All kernel entries are handled.
MFC after: 1 week
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/usr.bin/gdb/kgdb/trgt_alpha.c | 105 |
1 files changed, 94 insertions, 11 deletions
diff --git a/gnu/usr.bin/gdb/kgdb/trgt_alpha.c b/gnu/usr.bin/gdb/kgdb/trgt_alpha.c index c63c005..99e8df6 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_alpha.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_alpha.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <machine/pcb.h> +#include <machine/frame.h> #include <err.h> #include <kvm.h> #include <string.h> @@ -39,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <inferior.h> #include <regcache.h> #include <frame-unwind.h> +#include <alpha-tdep.h> #include "kgdb.h" @@ -55,16 +57,17 @@ kgdb_trgt_fetch_registers(int regno __unused) warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } - - supply_register(9, (char *)&pcb.pcb_context[0]); - supply_register(10, (char *)&pcb.pcb_context[1]); - supply_register(11, (char *)&pcb.pcb_context[2]); - supply_register(12, (char *)&pcb.pcb_context[3]); - supply_register(13, (char *)&pcb.pcb_context[4]); - supply_register(14, (char *)&pcb.pcb_context[5]); - supply_register(15, (char *)&pcb.pcb_context[6]); - supply_register(30, (char *)&pcb.pcb_hw.apcb_ksp); - supply_register(64, (char *)&pcb.pcb_context[7]); +#define ALPHA_S0_REGNUM ALPHA_T7_REGNUM + 1 + supply_register(ALPHA_S0_REGNUM + 0, (char *)&pcb.pcb_context[0]); + supply_register(ALPHA_S0_REGNUM + 1, (char *)&pcb.pcb_context[1]); + supply_register(ALPHA_S0_REGNUM + 2, (char *)&pcb.pcb_context[2]); + supply_register(ALPHA_S0_REGNUM + 3, (char *)&pcb.pcb_context[3]); + supply_register(ALPHA_S0_REGNUM + 4, (char *)&pcb.pcb_context[4]); + supply_register(ALPHA_S0_REGNUM + 5, (char *)&pcb.pcb_context[5]); + supply_register(ALPHA_S0_REGNUM + 6, (char *)&pcb.pcb_context[6]); + supply_register(ALPHA_SP_REGNUM, (char *)&pcb.pcb_hw.apcb_ksp); + supply_register(ALPHA_PC_REGNUM, (char *)&pcb.pcb_context[7]); +#undef ALPHA_S0_REGNUM } void @@ -73,10 +76,57 @@ kgdb_trgt_store_registers(int regno __unused) fprintf_unfiltered(gdb_stderr, "XXX: %s\n", __func__); } +struct kgdb_frame_cache { + CORE_ADDR pc; + CORE_ADDR sp; +}; + +static int kgdb_trgt_frame_offset[65] = { + FRAME_V0, FRAME_T0, FRAME_T1, FRAME_T2, + FRAME_T3, FRAME_T4, FRAME_T5, FRAME_T6, + FRAME_T7, FRAME_S0, FRAME_S1, FRAME_S2, + FRAME_S3, FRAME_S4, FRAME_S5, FRAME_S6, + FRAME_A0, FRAME_A1, FRAME_A2, FRAME_A3, + FRAME_A4, FRAME_A5, FRAME_T8, FRAME_T9, + FRAME_T10, FRAME_T11, FRAME_RA, FRAME_T12, + -1, FRAME_GP, FRAME_SP, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + -1, -1, -1, -1, + FRAME_PC +}; + +static struct kgdb_frame_cache * +kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache) +{ + char buf[MAX_REGISTER_SIZE]; + struct kgdb_frame_cache *cache; + + cache = *this_cache; + if (cache == NULL) { + cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache); + *this_cache = cache; + cache->pc = frame_func_unwind(next_frame); + frame_unwind_register(next_frame, SP_REGNUM, buf); + cache->sp = extract_unsigned_integer(buf, + register_size(current_gdbarch, SP_REGNUM)); + } + return (cache); +} + static void kgdb_trgt_trapframe_this_id(struct frame_info *next_frame, void **this_cache, struct frame_id *this_id) { + struct kgdb_frame_cache *cache; + + cache = kgdb_trgt_frame_cache(next_frame, this_cache); + *this_id = frame_id_build(cache->sp, cache->pc); } static void @@ -84,6 +134,29 @@ kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame, void **this_cache, int regnum, int *optimizedp, enum lval_type *lvalp, CORE_ADDR *addrp, int *realnump, void *valuep) { + char dummy_valuep[MAX_REGISTER_SIZE]; + struct kgdb_frame_cache *cache; + int ofs, regsz; + + regsz = register_size(current_gdbarch, regnum); + + if (valuep == NULL) + valuep = dummy_valuep; + memset(valuep, 0, regsz); + *optimizedp = 0; + *addrp = 0; + *lvalp = not_lval; + *realnump = -1; + + ofs = (regnum >= 0 && regnum <= ALPHA_PC_REGNUM) + ? kgdb_trgt_frame_offset[regnum] : -1; + if (ofs == -1) + return; + + cache = kgdb_trgt_frame_cache(next_frame, this_cache); + *addrp = cache->sp + ofs * 8; + *lvalp = lval_memory; + target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { @@ -95,6 +168,16 @@ static const struct frame_unwind kgdb_trgt_trapframe_unwind = { const struct frame_unwind * kgdb_trgt_trapframe_sniffer(struct frame_info *next_frame) { + char *pname; + CORE_ADDR pc; - return (NULL); + pc = frame_func_unwind(next_frame); + pname = NULL; + find_pc_partial_function(pc, &pname, NULL, NULL); + if (pname == NULL) + return (NULL); + if (strncmp(pname, "Xent", 4) == 0) + return (&kgdb_trgt_trapframe_unwind); + /* printf("%s: %lx =%s\n", __func__, pc, pname); */ + return (NULL); } |