- add kernel frame unwinding support (copied from i386obsd-tdep.c)
- add a nasty hack to recognize elf kernels which do not have a PT_NOTE as NetBSD binaries.
This commit is contained in:
parent
437f8cc149
commit
3254d721de
147
gnu/dist/gdb6/gdb/i386nbsd-tdep.c
vendored
147
gnu/dist/gdb6/gdb/i386nbsd-tdep.c
vendored
@ -37,6 +37,9 @@
|
||||
#include "i387-tdep.h"
|
||||
#include "nbsd-tdep.h"
|
||||
#include "solib-svr4.h"
|
||||
#include "elf-bfd.h" /* for header hack */
|
||||
#include "trad-frame.h" /* kernel frame support */
|
||||
#include "frame-unwind.h" /* kernel frame support */
|
||||
|
||||
/* From <machine/reg.h>. */
|
||||
static int i386nbsd_r_reg_offset[] =
|
||||
@ -218,6 +221,132 @@ int i386nbsd_sc_reg_offset[] =
|
||||
0 * 4 /* %gs */
|
||||
};
|
||||
|
||||
/* Kernel debugging support */
|
||||
|
||||
/* From <machine/frame.h>. Note that %esp and %ess are only saved in
|
||||
a trap frame when entering the kernel from user space. */
|
||||
static int i386nbsd_tf_reg_offset[] =
|
||||
{
|
||||
10 * 4, /* %eax */
|
||||
9 * 4, /* %ecx */
|
||||
8 * 4, /* %edx */
|
||||
7 * 4, /* %ebx */
|
||||
-1, /* %esp */
|
||||
6 * 4, /* %ebp */
|
||||
5 * 4, /* %esi */
|
||||
4 * 4, /* %edi */
|
||||
13 * 4, /* %eip */
|
||||
15 * 4, /* %eflags */
|
||||
14 * 4, /* %cs */
|
||||
-1, /* %ss */
|
||||
3 * 4, /* %ds */
|
||||
2 * 4, /* %es */
|
||||
1 * 4, /* %fs */
|
||||
0 * 4 /* %gs */
|
||||
};
|
||||
|
||||
static struct trad_frame_cache *
|
||||
i386nbsd_trapframe_cache(struct frame_info *next_frame, void **this_cache)
|
||||
{
|
||||
struct trad_frame_cache *cache;
|
||||
CORE_ADDR func, sp, addr;
|
||||
ULONGEST cs;
|
||||
char *name;
|
||||
int i;
|
||||
|
||||
if (*this_cache)
|
||||
return *this_cache;
|
||||
|
||||
cache = trad_frame_cache_zalloc (next_frame);
|
||||
*this_cache = cache;
|
||||
|
||||
func = frame_func_unwind (next_frame);
|
||||
sp = frame_unwind_register_unsigned (next_frame, I386_ESP_REGNUM);
|
||||
|
||||
find_pc_partial_function (func, &name, NULL, NULL);
|
||||
if (name && strncmp (name, "Xintr", 5) == 0)
|
||||
addr = sp + 8; /* It's an interrupt frame. */
|
||||
else
|
||||
addr = sp + 4;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (i386nbsd_tf_reg_offset); i++)
|
||||
if (i386nbsd_tf_reg_offset[i] != -1)
|
||||
trad_frame_set_reg_addr (cache, i, addr + i386nbsd_tf_reg_offset[i]);
|
||||
|
||||
/* Read %cs from trap frame. */
|
||||
addr += i386nbsd_tf_reg_offset[I386_CS_REGNUM];
|
||||
cs = read_memory_unsigned_integer (addr, 4);
|
||||
if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
|
||||
{
|
||||
/* Trap from user space; terminate backtrace. */
|
||||
trad_frame_set_id (cache, null_frame_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Construct the frame ID using the function start. */
|
||||
trad_frame_set_id (cache, frame_id_build (sp + 8, func));
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
static void
|
||||
i386nbsd_trapframe_this_id (struct frame_info *next_frame,
|
||||
void **this_cache, struct frame_id *this_id)
|
||||
{
|
||||
struct trad_frame_cache *cache =
|
||||
i386nbsd_trapframe_cache (next_frame, this_cache);
|
||||
|
||||
trad_frame_get_id (cache, this_id);
|
||||
}
|
||||
|
||||
static void
|
||||
i386nbsd_trapframe_prev_register (struct frame_info *next_frame,
|
||||
void **this_cache, int regnum,
|
||||
int *optimizedp, enum lval_type *lvalp,
|
||||
CORE_ADDR *addrp, int *realnump,
|
||||
gdb_byte *valuep)
|
||||
{
|
||||
struct trad_frame_cache *cache =
|
||||
i386nbsd_trapframe_cache (next_frame, this_cache);
|
||||
|
||||
trad_frame_get_register (cache, next_frame, regnum,
|
||||
optimizedp, lvalp, addrp, realnump, valuep);
|
||||
}
|
||||
|
||||
static int
|
||||
i386nbsd_trapframe_sniffer (const struct frame_unwind *self,
|
||||
struct frame_info *next_frame,
|
||||
void **this_prologue_cache)
|
||||
{
|
||||
ULONGEST cs;
|
||||
char *name;
|
||||
|
||||
/* Check Current Privilege Level and bail out if we're not executing
|
||||
in kernel space. */
|
||||
cs = frame_unwind_register_unsigned (next_frame, I386_CS_REGNUM);
|
||||
if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
|
||||
return 0;
|
||||
|
||||
|
||||
find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL);
|
||||
return (name && (strcmp (name, "calltrap") == 0
|
||||
|| strcmp (name, "syscall1") == 0
|
||||
|| strncmp (name, "Xintr", 5) == 0
|
||||
|| strncmp (name, "Xsoft", 5) == 0));
|
||||
}
|
||||
|
||||
const struct frame_unwind i386nbsd_trapframe_unwind = {
|
||||
/* FIXME: kettenis/20051219: This really is more like an interrupt
|
||||
frame, but SIGTRAMP_FRAME would print <signal handler called>,
|
||||
which really is not what we want here. */
|
||||
NORMAL_FRAME,
|
||||
i386nbsd_trapframe_this_id,
|
||||
i386nbsd_trapframe_prev_register,
|
||||
NULL,
|
||||
i386nbsd_trapframe_sniffer
|
||||
};
|
||||
|
||||
static void
|
||||
i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
{
|
||||
@ -243,6 +372,9 @@ i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
original 4.3 BSD. */
|
||||
tdep->sc_reg_offset = i386nbsd_sc_reg_offset;
|
||||
tdep->sc_num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset);
|
||||
|
||||
/* Unwind kernel trap frames correctly. */
|
||||
frame_unwind_prepend_unwinder (gdbarch, &i386nbsd_trapframe_unwind);
|
||||
}
|
||||
|
||||
/* NetBSD a.out. */
|
||||
@ -278,9 +410,24 @@ i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
tdep->struct_return = pcc_struct_return;
|
||||
}
|
||||
|
||||
static enum gdb_osabi
|
||||
i386nbsd_elf_osabi_sniffer (bfd *abfd)
|
||||
{
|
||||
if (strcmp (bfd_get_target (abfd), "elf32-i386") != 0)
|
||||
return GDB_OSABI_UNKNOWN;
|
||||
/* disgusting hack since kernels don't have a PT_NOTE section */
|
||||
if ((unsigned long)elf_elfheader (abfd)->e_entry != (unsigned long)0xc0100000)
|
||||
return GDB_OSABI_UNKNOWN;
|
||||
|
||||
return GDB_OSABI_NETBSD_ELF;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_initialize_i386nbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
|
||||
i386nbsd_elf_osabi_sniffer);
|
||||
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_AOUT,
|
||||
i386nbsdaout_init_abi);
|
||||
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_ELF,
|
||||
|
Loading…
Reference in New Issue
Block a user