diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 826deba07e2..d077e074e95 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,37 @@ 2004-02-22 Mark Kettenis + Fix OpenBSD/i386 sigtramp recognition. + * i386-tdep.h: Update copyright year. + (i386bsd_pc_in_sigtramp, i386bsd_sigtramp_start) + (i386bsd_sigtramp_end): New prototypes. + (i386fbsd_sigtramp_start_addr): Renamed from + i386fbsd_sigtramp_start. + (i386fbsd_sigtramp_end_addr): Renamed from i386fbsd_sigtramp_end. + (i386obsd_sigtramp_start_addr): Renamed from + i386obsd_sigtramp_start. + (i386obsd_sigtramp_end_addr): Renamed from i386obsd_sigtramp_end. + * i386bsd-tdep.c: Update copyright year. + (i386bsd_pc_in_sigtramp): Make public. + * i386fbsd-nat.c: Update copyright year. + (_initialize_i386fbsd_nat): Adjust for renamed variables. + * i386fbsd-tdep.c: Update copyright year. + (i386fbsd_sigtramp_start_addr): Renamed from + i386fbsd_sigtramp_start. + (i386fbsd_sigtramp_end_addr): Renamed from i386fbsd_sigtramp_end. + (i386fbsdaout_init_abi): Adjust for renamed variables. + * i386obsd-nat.c: Update copyright year. + (_initialize_i386obsd_nat): Adjust for renamed variables. + * i386obsd-tdep.c: Include "target.h". + (i386obsd_page_size): New variable. + (i386obsd_pc_in_sigtramp, i386obsd_sigtramp_start) + (i386obsd_sigtramp_end): New functions. + (i386obsd_sigtramp_start_addr): Renamed from + i386obsd_sigtramp_start. + (i386obsd_sigtramp_end_addr): Renamed from i386obsd_sigtramp_end. + (i386obsd_init_abi): Adjust for renamed variables. Set + pc_in_sigtramp, sigtramp_start and sigtramp_end. + * Makefile.in (i386obsd-tdep.o): Update dependencies. + * amd64obsd-tdep.c (amd64obsd_pc_in_sigtramp): Adjust for signal trampoline change in OpenBSD kernel. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 7e179a83d5e..b1e4e4c4a12 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1849,8 +1849,8 @@ i386-nto-tdep.o: i386-nto-tdep.c $(gdb_string_h) $(gdb_assert_h) $(defs_h) \ $(nto_tdep_h) $(osabi_h) $(i387_tdep_h) i386obsd-nat.o: i386obsd-nat.c $(defs_h) $(i386_tdep_h) i386obsd-tdep.o: i386obsd-tdep.c $(defs_h) $(arch_utils_h) $(gdbcore_h) \ - $(regcache_h) $(regset_h) $(osabi_h) $(gdb_assert_h) $(gdb_string_h) \ - $(i386_tdep_h) $(i387_tdep_h) $(solib_svr4_h) + $(regcache_h) $(regset_h) $(osabi_h) $(target_h) $(gdb_assert_h) \ + $(gdb_string_h) $(i386_tdep_h) $(i387_tdep_h) $(solib_svr4_h) i386-sol2-tdep.o: i386-sol2-tdep.c $(defs_h) $(value_h) $(osabi_h) \ $(i386_tdep_h) i386-stub.o: i386-stub.c diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index 70f6b8fec24..f164e9d849a 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -1,7 +1,6 @@ /* Target-dependent code for the i386. - Copyright 2001, 2002, 2003 - Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -214,10 +213,13 @@ extern void i386_svr4_init_abi (struct gdbarch_info, struct gdbarch *); /* Functions and variables exported from i386bsd-tdep.c. */ extern void i386bsd_init_abi (struct gdbarch_info, struct gdbarch *); -extern CORE_ADDR i386fbsd_sigtramp_start; -extern CORE_ADDR i386fbsd_sigtramp_end; -extern CORE_ADDR i386obsd_sigtramp_start; -extern CORE_ADDR i386obsd_sigtramp_end; +extern int i386bsd_pc_in_sigtramp (CORE_ADDR pc, char *name); +extern CORE_ADDR i386bsd_sigtramp_start (CORE_ADDR pc); +extern CORE_ADDR i386bsd_sigtramp_end (CORE_ADDR pc); +extern CORE_ADDR i386fbsd_sigtramp_start_addr; +extern CORE_ADDR i386fbsd_sigtramp_end_addr; +extern CORE_ADDR i386obsd_sigtramp_start_addr; +extern CORE_ADDR i386obsd_sigtramp_end_addr; extern int i386fbsd4_sc_reg_offset[]; extern int i386fbsd_sc_reg_offset[]; extern int i386nbsd_sc_reg_offset[]; diff --git a/gdb/i386bsd-tdep.c b/gdb/i386bsd-tdep.c index 67d09ee14d7..9276c32b3f7 100644 --- a/gdb/i386bsd-tdep.c +++ b/gdb/i386bsd-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for i386 BSD's. - Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -34,7 +34,7 @@ /* Return whether PC is in a BSD sigtramp routine. */ -static int +int i386bsd_pc_in_sigtramp (CORE_ADDR pc, char *name) { struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); diff --git a/gdb/i386fbsd-nat.c b/gdb/i386fbsd-nat.c index 7feb7b053e6..efc61b6cbbb 100644 --- a/gdb/i386fbsd-nat.c +++ b/gdb/i386fbsd-nat.c @@ -1,5 +1,6 @@ /* Native-dependent code for FreeBSD/i386. - Copyright 2001, 2002, 2003 Free Software Foundation, Inc. + + Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -98,8 +99,8 @@ _initialize_i386fbsd_nat (void) len = sizeof (ps_strings); if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0) { - i386fbsd_sigtramp_start = ps_strings - 128; - i386fbsd_sigtramp_end = ps_strings; + i386fbsd_sigtramp_start_addr = ps_strings - 128; + i386fbsd_sigtramp_end_addr = ps_strings; } } #endif diff --git a/gdb/i386fbsd-tdep.c b/gdb/i386fbsd-tdep.c index 786de7d1fc2..4cf8de8b45e 100644 --- a/gdb/i386fbsd-tdep.c +++ b/gdb/i386fbsd-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for FreeBSD/i386. - Copyright 2003 Free Software Foundation, Inc. + Copyright 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -39,8 +39,9 @@ static int i386fbsd_r_reg_offset[] = 1 * 4, 0 * 4, -1, -1 /* %ds, %es, %fs, %gs */ }; -CORE_ADDR i386fbsd_sigtramp_start = 0xbfbfdf20; -CORE_ADDR i386fbsd_sigtramp_end = 0xbfbfdff0; +/* Sigtramp routine location. */ +CORE_ADDR i386fbsd_sigtramp_start_addr = 0xbfbfdf20; +CORE_ADDR i386fbsd_sigtramp_end_addr = 0xbfbfdff0; /* From . */ static int i386fbsd_sc_reg_offset[] = @@ -82,8 +83,8 @@ i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->struct_return = reg_struct_return; /* FreeBSD uses a different memory layout. */ - tdep->sigtramp_start = i386fbsd_sigtramp_start; - tdep->sigtramp_end = i386fbsd_sigtramp_end; + tdep->sigtramp_start = i386fbsd_sigtramp_start_addr; + tdep->sigtramp_end = i386fbsd_sigtramp_end_addr; /* FreeBSD has a more complete `struct sigcontext'. */ tdep->sc_reg_offset = i386fbsd_sc_reg_offset; diff --git a/gdb/i386obsd-nat.c b/gdb/i386obsd-nat.c index b0d4e033b8d..68cc79044ec 100644 --- a/gdb/i386obsd-nat.c +++ b/gdb/i386obsd-nat.c @@ -1,5 +1,6 @@ /* Native-dependent code for OpenBSD/i386. - Copyright 2002, 2003 Free Software Foundation, Inc. + + Copyright 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -51,8 +52,8 @@ _initialize_i386obsd_nat (void) len = sizeof (_ps); if (sysctl (mib, 2, &_ps, &len, NULL, 0) == 0) { - i386obsd_sigtramp_start = (CORE_ADDR)_ps.val - 128; - i386obsd_sigtramp_end = (CORE_ADDR)_ps.val; + i386obsd_sigtramp_start_addr = (CORE_ADDR)_ps.val - 128; + i386obsd_sigtramp_end_addr = (CORE_ADDR)_ps.val; } } #endif diff --git a/gdb/i386obsd-tdep.c b/gdb/i386obsd-tdep.c index be9e735cb3c..d8556ea460a 100644 --- a/gdb/i386obsd-tdep.c +++ b/gdb/i386obsd-tdep.c @@ -27,6 +27,7 @@ #include "regcache.h" #include "regset.h" #include "osabi.h" +#include "target.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -35,6 +36,81 @@ #include "i387-tdep.h" #include "solib-svr4.h" +/* Support for signal handlers. */ + +/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page + in virtual memory. The randomness makes it somewhat tricky to + detect it, but fortunately we can rely on the fact that the start + of the sigtramp routine is page-aligned. By the way, the mapping + is read-only, so you cannot place a breakpoint in the signal + trampoline. */ + +/* Default page size. */ +static const int i386obsd_page_size = 4096; + +/* Return whether PC is in an OpenBSD sigtramp routine. */ + +static int +i386obsd_pc_in_sigtramp (CORE_ADDR pc, char *name) +{ + CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); + const char sigreturn[] = + { + 0xb8, + 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] != '<') + 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)) + 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; +} + +/* 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); + + return start_pc + 0x22; +} + +/* Mapping between the general-purpose registers in `struct reg' + format and GDB's register cache layout. */ + /* From . */ static int i386obsd_r_reg_offset[] = { @@ -95,8 +171,9 @@ i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch, } -CORE_ADDR i386obsd_sigtramp_start = 0xbfbfdf20; -CORE_ADDR i386obsd_sigtramp_end = 0xbfbfdff0; +/* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */ +CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20; +CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0; /* From . */ int i386obsd_sc_reg_offset[I386_NUM_GREGS] = @@ -136,8 +213,11 @@ i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->struct_return = reg_struct_return; /* OpenBSD uses a different memory layout. */ - tdep->sigtramp_start = i386obsd_sigtramp_start; - tdep->sigtramp_end = i386obsd_sigtramp_end; + 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); /* OpenBSD has a `struct sigcontext' that's different from the origional 4.3 BSD. */