/* Target-dependent code for OpenBSD/i386.
- Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002,
- 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GDB.
struct trad_frame_cache *cache;
CORE_ADDR func, sp, addr;
ULONGEST cs;
+ char *name;
int i;
if (*this_cache)
cache = trad_frame_cache_zalloc (next_frame);
*this_cache = cache;
- func = frame_func_unwind (next_frame);
+ /* NORMAL_FRAME matches the type in i386obsd_trapframe_unwind, but
+ SIGTRAMP_FRAME might be more appropriate. */
+ func = frame_func_unwind (next_frame, NORMAL_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;
+
for (i = 0; i < ARRAY_SIZE (i386obsd_tf_reg_offset); i++)
if (i386obsd_tf_reg_offset[i] != -1)
- trad_frame_set_reg_addr (cache, i, sp + i386obsd_tf_reg_offset[i]);
+ trad_frame_set_reg_addr (cache, i, addr + i386obsd_tf_reg_offset[i]);
/* Read %cs from trap frame. */
- addr = sp + i386obsd_tf_reg_offset[I386_CS_REGNUM];
+ addr += i386obsd_tf_reg_offset[I386_CS_REGNUM];
cs = read_memory_unsigned_integer (addr, 4);
if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
{
- /* Trap from use space; terminate backtrace. */
+ /* Trap from user space; terminate backtrace. */
trad_frame_set_id (cache, null_frame_id);
}
else
optimizedp, lvalp, addrp, realnump, valuep);
}
-static const struct frame_unwind i386obsd_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,
- i386obsd_trapframe_this_id,
- i386obsd_trapframe_prev_register
-};
-
-static const struct frame_unwind *
-i386obsd_trapframe_sniffer (struct frame_info *next_frame)
+static int
+i386obsd_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 NULL;
+ return 0;
find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL);
- if (name && ((strcmp ("calltrap", name) == 0)
- || (strcmp ("syscall1", name) == 0)))
- return &i386obsd_trapframe_unwind;
-
- return NULL;
+ return (name && (strcmp (name, "calltrap") == 0
+ || strcmp (name, "syscall1") == 0
+ || strncmp (name, "Xintr", 5) == 0
+ || strncmp (name, "Xsoft", 5) == 0));
}
+
+static const struct frame_unwind i386obsd_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,
+ i386obsd_trapframe_this_id,
+ i386obsd_trapframe_prev_register,
+ NULL,
+ i386obsd_trapframe_sniffer
+};
\f
static void
bsd_uthread_set_collect_uthread (gdbarch, i386obsd_collect_uthread);
/* Unwind kernel trap frames correctly. */
- frame_unwind_append_sniffer (gdbarch, i386obsd_trapframe_sniffer);
+ frame_unwind_prepend_unwinder (gdbarch, &i386obsd_trapframe_unwind);
}
/* OpenBSD a.out. */