diff --git a/gnu/usr.bin/gdb/kgdb/trgt_i386.c b/gnu/usr.bin/gdb/kgdb/trgt_i386.c index eb58df3e4baa..0522e2445384 100644 --- a/gnu/usr.bin/gdb/kgdb/trgt_i386.c +++ b/gnu/usr.bin/gdb/kgdb/trgt_i386.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -39,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include "kgdb.h" @@ -55,12 +57,12 @@ kgdb_trgt_fetch_registers(int regno __unused) warnx("kvm_read: %s", kvm_geterr(kvm)); memset(&pcb, 0, sizeof(pcb)); } - supply_register(3, (char *)&pcb.pcb_ebx); - supply_register(4, (char *)&pcb.pcb_esp); - supply_register(5, (char *)&pcb.pcb_ebp); - supply_register(6, (char *)&pcb.pcb_esi); - supply_register(7, (char *)&pcb.pcb_edi); - supply_register(8, (char *)&pcb.pcb_eip); + supply_register(I386_EBX_REGNUM, (char *)&pcb.pcb_ebx); + supply_register(I386_ESP_REGNUM, (char *)&pcb.pcb_esp); + supply_register(I386_EBP_REGNUM, (char *)&pcb.pcb_ebp); + supply_register(I386_ESI_REGNUM, (char *)&pcb.pcb_esi); + supply_register(I386_EDI_REGNUM, (char *)&pcb.pcb_edi); + supply_register(I386_EIP_REGNUM, (char *)&pcb.pcb_eip); } void @@ -69,10 +71,55 @@ 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[15] = { + offsetof(struct trapframe, tf_eax), + offsetof(struct trapframe, tf_ecx), + offsetof(struct trapframe, tf_edx), + offsetof(struct trapframe, tf_ebx), + offsetof(struct trapframe, tf_esp), + offsetof(struct trapframe, tf_ebp), + offsetof(struct trapframe, tf_esi), + offsetof(struct trapframe, tf_edi), + offsetof(struct trapframe, tf_eip), + offsetof(struct trapframe, tf_eflags), + offsetof(struct trapframe, tf_cs), + offsetof(struct trapframe, tf_ss), + offsetof(struct trapframe, tf_ds), + offsetof(struct trapframe, tf_es), + offsetof(struct trapframe, tf_fs) +}; + +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 @@ -80,6 +127,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 >= I386_EAX_REGNUM && regnum <= I386_FS_REGNUM) + ? kgdb_trgt_frame_offset[regnum] : -1; + if (ofs == -1) + return; + + cache = kgdb_trgt_frame_cache(next_frame, this_cache); + *addrp = cache->sp + ofs; + *lvalp = lval_memory; + target_read_memory(*addrp, valuep, regsz); } static const struct frame_unwind kgdb_trgt_trapframe_unwind = { @@ -91,6 +161,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; + pc = frame_pc_unwind(next_frame); + pname = NULL; + find_pc_partial_function(pc, &pname, NULL, NULL); + if (pname == NULL) + return (NULL); + if (strcmp(pname, "calltrap") == 0) + return (&kgdb_trgt_trapframe_unwind); + /* printf("%s: %llx =%s\n", __func__, pc, pname); */ return (NULL); }