X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fi386nbsd-tdep.c;h=be46b0ef8f6c456056340cec6ab0c8332b1faca9;hb=4ee62156d969867d3d3ffedf656a74643f77279e;hp=3f19608788f7750464fc9fa9c9674dffca4e57bd;hpb=9ea75c57ced878b09e627ce6c85c7254fd00c647;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/i386nbsd-tdep.c b/gdb/i386nbsd-tdep.c index 3f19608788..be46b0ef8f 100644 --- a/gdb/i386nbsd-tdep.c +++ b/gdb/i386nbsd-tdep.c @@ -1,14 +1,13 @@ /* Target-dependent code for NetBSD/i386. - Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002, - 2003, 2004 - Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002, 2003, + 2004, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,9 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "arch-utils.h" @@ -29,6 +26,8 @@ #include "regset.h" #include "osabi.h" #include "symtab.h" +#include "trad-frame.h" +#include "tramp-frame.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -59,163 +58,216 @@ static int i386nbsd_r_reg_offset[] = 15 * 4 /* %gs */ }; -static void -i386nbsd_aout_supply_regset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *regs, size_t len) +/* From . */ +int i386nbsd_sc_reg_offset[] = { - const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch); + 10 * 4, /* %eax */ + 9 * 4, /* %ecx */ + 8 * 4, /* %edx */ + 7 * 4, /* %ebx */ + 14 * 4, /* %esp */ + 6 * 4, /* %ebp */ + 5 * 4, /* %esi */ + 4 * 4, /* %edi */ + 11 * 4, /* %eip */ + 13 * 4, /* %eflags */ + 12 * 4, /* %cs */ + 15 * 4, /* %ss */ + 3 * 4, /* %ds */ + 2 * 4, /* %es */ + 1 * 4, /* %fs */ + 0 * 4 /* %gs */ +}; - gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE); +/* From . */ +int i386nbsd_mc_reg_offset[] = +{ + 11 * 4, /* %eax */ + 10 * 4, /* %ecx */ + 9 * 4, /* %edx */ + 8 * 4, /* %ebx */ + 7 * 4, /* %esp */ + 6 * 4, /* %ebp */ + 5 * 4, /* %esi */ + 4 * 4, /* %edi */ + 14 * 4, /* %eip */ + 16 * 4, /* %eflags */ + 15 * 4, /* %cs */ + 18 * 4, /* %ss */ + 3 * 4, /* %ds */ + 2 * 4, /* %es */ + 1 * 4, /* %fs */ + 0 * 4 /* %gs */ +}; - i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset); - i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset); -} +static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *, + struct frame_info *, + struct trad_frame_cache *, + CORE_ADDR); -static const struct regset * -i386nbsd_aout_regset_from_core_section (struct gdbarch *gdbarch, - const char *sect_name, - size_t sect_size) +static const struct tramp_frame i386nbsd_sigtramp_sc16 = { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + SIGTRAMP_FRAME, + 1, + { + { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x10, -1 }, + /* leal 0x10(%esp), %eax */ + { 0x50, -1 }, /* pushl %eax */ + { 0x50, -1 }, /* pushl %eax */ + { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x127, %eax # __sigreturn14 */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x1, %eax # exit */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init +}; - /* NetBSD a.out core dumps don't use seperate register sets for the - general-purpose and floating-point registers. */ +static const struct tramp_frame i386nbsd_sigtramp_sc2 = +{ + SIGTRAMP_FRAME, + 1, + { + { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x0c, -1 }, + /* leal 0x0c(%esp), %eax */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x127, %eax # __sigreturn14 */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x1, %eax */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init +}; - if (strcmp (sect_name, ".reg") == 0 - && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE) - { - if (tdep->gregset == NULL) - tdep->gregset = - regset_alloc (gdbarch, i386nbsd_aout_supply_regset, NULL); - return tdep->gregset; - } +static const struct tramp_frame i386nbsd_sigtramp_si2 = +{ + SIGTRAMP_FRAME, + 1, + { + { 0x8b, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x08, -1 }, + /* movl 8(%esp),%eax */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* movl $0x134, %eax # setcontext */ + { 0xcd, -1 }, { 0x80, -1 }, + /* int $0x80 */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* movl $0x1, %eax */ + { 0xcd, -1 }, { 0x80, -1 }, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init +}; - return NULL; -} +static const struct tramp_frame i386nbsd_sigtramp_si31 = +{ + SIGTRAMP_FRAME, + 1, + { + { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 }, + { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* leal 0x8c(%esp), %eax */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* movl $0x134, %eax # setcontext */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x1, %eax */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init +}; -/* Under NetBSD/i386, signal handler invocations can be identified by the - designated code sequence that is used to return from a signal handler. - In particular, the return address of a signal handler points to the - following code sequence: - - leal 0x10(%esp), %eax - pushl %eax - pushl %eax - movl $0x127, %eax # __sigreturn14 - int $0x80 - - Each instruction has a unique encoding, so we simply attempt to match - the instruction the PC is pointing to with any of the above instructions. - If there is a hit, we know the offset to the start of the designated - sequence and can then check whether we really are executing in the - signal trampoline. If not, -1 is returned, otherwise the offset from the - start of the return sequence is returned. */ -#define RETCODE_INSN1 0x8d -#define RETCODE_INSN2 0x50 -#define RETCODE_INSN3 0x50 -#define RETCODE_INSN4 0xb8 -#define RETCODE_INSN5 0xcd - -#define RETCODE_INSN2_OFF 4 -#define RETCODE_INSN3_OFF 5 -#define RETCODE_INSN4_OFF 6 -#define RETCODE_INSN5_OFF 11 - -static const unsigned char sigtramp_retcode[] = +static const struct tramp_frame i386nbsd_sigtramp_si4 = { - RETCODE_INSN1, 0x44, 0x24, 0x10, - RETCODE_INSN2, - RETCODE_INSN3, - RETCODE_INSN4, 0x27, 0x01, 0x00, 0x00, - RETCODE_INSN5, 0x80, + SIGTRAMP_FRAME, + 1, + { + { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 }, + { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* leal 0x8c(%esp), %eax */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* movl $0x134, %eax # setcontext */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { 0xc7, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, + /* movl $0xffffffff,0x4(%esp) */ + { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x1, %eax */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init }; -static LONGEST -i386nbsd_sigtramp_offset (CORE_ADDR pc) +static void +i386nbsd_sigtramp_cache_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) { - unsigned char ret[sizeof(sigtramp_retcode)], insn; - LONGEST off; + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM); + CORE_ADDR base; + int *reg_offset; + int num_regs; int i; - if (read_memory_nobpt (pc, &insn, 1) != 0) - return -1; - - switch (insn) + if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2) { - case RETCODE_INSN1: - off = 0; - break; - - case RETCODE_INSN2: - /* INSN2 and INSN3 are the same. Read at the location of PC+1 - to determine if we're actually looking at INSN2 or INSN3. */ - if (read_memory_nobpt (pc + 1, &insn, 1) != 0) - return -1; - - if (insn == RETCODE_INSN3) - off = RETCODE_INSN2_OFF; - else - off = RETCODE_INSN3_OFF; - break; - - case RETCODE_INSN4: - off = RETCODE_INSN4_OFF; - break; - - case RETCODE_INSN5: - off = RETCODE_INSN5_OFF; - break; - - default: - return -1; - } - - pc -= off; - - if (read_memory_nobpt (pc, (char *) ret, sizeof (ret)) != 0) - return -1; + reg_offset = i386nbsd_sc_reg_offset; + num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset); - if (memcmp (ret, sigtramp_retcode, sizeof (ret)) == 0) - return off; - - return -1; -} + /* Read in the sigcontext address */ + base = read_memory_unsigned_integer (sp + 8, 4, byte_order); + } + else + { + reg_offset = i386nbsd_mc_reg_offset; + num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset); -/* Return whether the frame preceding NEXT_FRAME corresponds to a - NetBSD sigtramp routine. */ + /* Read in the ucontext address */ + base = read_memory_unsigned_integer (sp + 8, 4, byte_order); + /* offsetof(ucontext_t, uc_mcontext) == 36 */ + base += 36; + } -static int -i386nbsd_sigtramp_p (struct frame_info *next_frame) -{ - CORE_ADDR pc = frame_pc_unwind (next_frame); - char *name; + for (i = 0; i < num_regs; i++) + if (reg_offset[i] != -1) + trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]); - find_pc_partial_function (pc, &name, NULL, NULL); - return (nbsd_pc_in_sigtramp (pc, name) - || i386nbsd_sigtramp_offset (pc) >= 0); + /* Construct the frame ID using the function start. */ + trad_frame_set_id (this_cache, frame_id_build (sp, func)); } - -/* From . */ -int i386nbsd_sc_reg_offset[] = -{ - 10 * 4, /* %eax */ - 9 * 4, /* %ecx */ - 8 * 4, /* %edx */ - 7 * 4, /* %ebx */ - 14 * 4, /* %esp */ - 6 * 4, /* %ebp */ - 5 * 4, /* %esi */ - 4 * 4, /* %edi */ - 11 * 4, /* %eip */ - 13 * 4, /* %eflags */ - 12 * 4, /* %cs */ - 15 * 4, /* %ss */ - 3 * 4, /* %ds */ - 2 * 4, /* %es */ - 1 * 4, /* %fs */ - 0 * 4 /* %gs */ -}; + static void i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) @@ -230,30 +282,22 @@ i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset); tdep->sizeof_gregset = 16 * 4; - /* NetBSD has different signal trampoline conventions. */ - tdep->sigtramp_start = 0; - tdep->sigtramp_end = 0; - tdep->sigtramp_p = i386nbsd_sigtramp_p; - /* NetBSD uses -freg-struct-return by default. */ tdep->struct_return = reg_struct_return; - /* NetBSD has a `struct sigcontext' that's different from the - original 4.3 BSD. */ - tdep->sc_reg_offset = i386nbsd_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset); -} - -/* NetBSD a.out. */ - -static void -i386nbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - i386nbsd_init_abi (info, gdbarch); - - /* NetBSD a.out has a single register set. */ - set_gdbarch_regset_from_core_section - (gdbarch, i386nbsd_aout_regset_from_core_section); + /* NetBSD uses tramp_frame sniffers for signal trampolines. */ + tdep->sigcontext_addr= 0; + tdep->sigtramp_start = 0; + tdep->sigtramp_end = 0; + tdep->sigtramp_p = 0; + tdep->sc_reg_offset = 0; + tdep->sc_num_regs = 0; + + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16); + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2); + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2); + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31); + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4); } /* NetBSD ELF. */ @@ -270,8 +314,6 @@ i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) i386_elf_init_abi (info, gdbarch); /* NetBSD ELF uses SVR4-style shared libraries. */ - set_gdbarch_in_solib_call_trampoline - (gdbarch, generic_in_solib_call_trampoline); set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_ilp32_fetch_link_map_offsets); @@ -279,11 +321,12 @@ i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->struct_return = pcc_struct_return; } +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_i386nbsd_tdep; + void _initialize_i386nbsd_tdep (void) { - 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, i386nbsdelf_init_abi); }