summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2005-07-26 20:29:56 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2005-07-26 20:29:56 +0000
commit542adc78ece1e7d364c8a6f826313ade86df441d (patch)
treee9d0f9be95f53bbc886d88c06e0ba9608f54f492 /gnu
parente9573ff577c65f15fb1f4382a9caaaf03cf66104 (diff)
Handle new signal trampoline on i386.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/binutils/gdb/i386obsd-tdep.c98
1 files changed, 46 insertions, 52 deletions
diff --git a/gnu/usr.bin/binutils/gdb/i386obsd-tdep.c b/gnu/usr.bin/binutils/gdb/i386obsd-tdep.c
index d8556ea460a..4dd78294785 100644
--- a/gnu/usr.bin/binutils/gdb/i386obsd-tdep.c
+++ b/gnu/usr.bin/binutils/gdb/i386obsd-tdep.c
@@ -23,9 +23,12 @@
#include "defs.h"
#include "arch-utils.h"
+#include "frame.h"
#include "gdbcore.h"
#include "regcache.h"
#include "regset.h"
+#include "symtab.h"
+#include "objfiles.h"
#include "osabi.h"
#include "target.h"
@@ -48,11 +51,21 @@
/* Default page size. */
static const int i386obsd_page_size = 4096;
-/* Return whether PC is in an OpenBSD sigtramp routine. */
+/* Offset for sigreturn(2). */
+static const int i386obsd_sigreturn_offset[] = {
+ 0x0a, /* OpenBSD 3.2 */
+ 0x14, /* OpenBSD 3.6 */
+ 0x3a, /* OpenBSD 3.8 */
+ -1
+};
+
+/* Return whether the frame preceding NEXT_FRAME corresponds to an
+ OpenBSD sigtramp routine. */
static int
-i386obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
+i386obsd_sigtramp_p (struct frame_info *next_frame)
{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
const char sigreturn[] =
{
@@ -60,52 +73,38 @@ i386obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */
0xcd, 0x80 /* int $0x80 */
};
- char *buf;
-
- /* Avoid reading memory from the target if possible. If we're in a
- named function, we're certainly not in a sigtramp routine
- provided by the kernel. Take synthetic function names into
- account though. */
- if (name && name[0] != '<')
+ size_t buflen = sizeof sigreturn;
+ const int *offset;
+ char *name, *buf;
+
+ /* If the function has a valid symbol name, it isn't a
+ trampoline. */
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ if (name != NULL)
return 0;
- /* If we can't read the instructions at START_PC, return zero. */
- buf = alloca (sizeof sigreturn);
- if (target_read_memory (start_pc + 0x14, buf, sizeof sigreturn))
+ /* If the function lives in a valid section (even without a starting
+ point) it isn't a trampoline. */
+ if (find_pc_section (pc) != NULL)
return 0;
- /* Check for sigreturn(2). */
- if (memcmp (buf, sigreturn, sizeof sigreturn) == 0)
- return 1;
-
- /* Check for a traditional BSD sigtramp routine. */
- return i386bsd_pc_in_sigtramp (pc, name);
-}
-
-/* Return the start address of the sigtramp routine. */
-
-static CORE_ADDR
-i386obsd_sigtramp_start (CORE_ADDR pc)
-{
- CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
-
- if (i386bsd_pc_in_sigtramp (pc, NULL))
- return i386bsd_sigtramp_start (pc);
-
- return start_pc;
-}
+ /* Allocate buffer. */
+ buf = alloca (buflen);
-/* Return the end address of the sigtramp routine. */
-
-static CORE_ADDR
-i386obsd_sigtramp_end (CORE_ADDR pc)
-{
- CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
-
- if (i386bsd_pc_in_sigtramp (pc, NULL))
- return i386bsd_sigtramp_end (pc);
+ /* Loop over all offsets. */
+ for (offset = i386obsd_sigreturn_offset; *offset != -1; offset++)
+ {
+ /* If we can't read the instructions, return zero. */
+ if (!safe_frame_unwind_memory (next_frame, start_pc + *offset,
+ buf, buflen))
+ return 0;
+
+ /* Check for sigreturn(2). */
+ if (memcmp (buf, sigreturn, buflen) == 0)
+ return 1;
+ }
- return start_pc + 0x22;
+ return 0;
}
/* Mapping between the general-purpose registers in `struct reg'
@@ -137,7 +136,7 @@ i386obsd_aout_supply_regset (const struct regset *regset,
struct regcache *regcache, int regnum,
const void *regs, size_t len)
{
- const struct gdbarch_tdep *tdep = regset->descr;
+ const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
@@ -159,11 +158,8 @@ i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
&& sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
{
if (tdep->gregset == NULL)
- {
- tdep->gregset = XMALLOC (struct regset);
- tdep->gregset->descr = tdep;
- tdep->gregset->supply_regset = i386obsd_aout_supply_regset;
- }
+ tdep->gregset =
+ regset_alloc (gdbarch, i386obsd_aout_supply_regset, NULL);
return tdep->gregset;
}
@@ -215,12 +211,10 @@ i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* OpenBSD uses a different memory layout. */
tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
- set_gdbarch_pc_in_sigtramp (gdbarch, i386obsd_pc_in_sigtramp);
- set_gdbarch_sigtramp_start (gdbarch, i386obsd_sigtramp_start);
- set_gdbarch_sigtramp_end (gdbarch, i386obsd_sigtramp_end);
+ tdep->sigtramp_p = i386obsd_sigtramp_p;
/* OpenBSD has a `struct sigcontext' that's different from the
- origional 4.3 BSD. */
+ original 4.3 BSD. */
tdep->sc_reg_offset = i386obsd_sc_reg_offset;
tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
}