X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Falpha-linux-tdep.c;h=0f3996869425559da04ae0e394142cf87fee9959;hb=749234e5402bddc054d77b4113ecd09eda7a872e;hp=9ef9d936696b3ff2bece8cc344cfd94bc64cd8bf;hpb=0fb0cc7590113e9b459dfcc48dc71c9d419d9580;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c index 9ef9d93669..0f39968694 100644 --- a/gdb/alpha-linux-tdep.c +++ b/gdb/alpha-linux-tdep.c @@ -1,5 +1,5 @@ /* Target-dependent code for GNU/Linux on Alpha. - Copyright (C) 2002, 2003, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2002-2014 Free Software Foundation, Inc. This file is part of GDB. @@ -19,15 +19,44 @@ #include "defs.h" #include "frame.h" #include "gdb_assert.h" -#include "gdb_string.h" +#include #include "osabi.h" #include "solib-svr4.h" #include "symtab.h" #include "regset.h" #include "regcache.h" - +#include "linux-tdep.h" #include "alpha-tdep.h" +/* This enum represents the signals' numbers on the Alpha + architecture. It just contains the signal definitions which are + different from the generic implementation. + + It is derived from the file , + from the Linux kernel tree. */ + +enum + { + /* SIGABRT is the same as in the generic implementation, but is + defined here because SIGIOT depends on it. */ + ALPHA_LINUX_SIGABRT = 6, + ALPHA_LINUX_SIGEMT = 7, + ALPHA_LINUX_SIGBUS = 10, + ALPHA_LINUX_SIGSYS = 12, + ALPHA_LINUX_SIGURG = 16, + ALPHA_LINUX_SIGSTOP = 17, + ALPHA_LINUX_SIGTSTP = 18, + ALPHA_LINUX_SIGCONT = 19, + ALPHA_LINUX_SIGCHLD = 20, + ALPHA_LINUX_SIGIO = 23, + ALPHA_LINUX_SIGINFO = 29, + ALPHA_LINUX_SIGUSR1 = 30, + ALPHA_LINUX_SIGUSR2 = 31, + ALPHA_LINUX_SIGPOLL = ALPHA_LINUX_SIGIO, + ALPHA_LINUX_SIGPWR = ALPHA_LINUX_SIGINFO, + ALPHA_LINUX_SIGIOT = ALPHA_LINUX_SIGABRT, + }; + /* Under GNU/Linux, 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 @@ -40,13 +69,12 @@ (2) the kernel has changed from using "addq" to "lda" to load the syscall number, (3) there is a "normal" sigreturn and an "rt" sigreturn which - has a different stack layout. -*/ + has a different stack layout. */ static long -alpha_linux_sigtramp_offset_1 (CORE_ADDR pc) +alpha_linux_sigtramp_offset_1 (struct gdbarch *gdbarch, CORE_ADDR pc) { - switch (alpha_read_insn (pc)) + switch (alpha_read_insn (gdbarch, pc)) { case 0x47de0410: /* bis $30,$30,$16 */ case 0x47fe0410: /* bis $31,$30,$16 */ @@ -66,7 +94,7 @@ alpha_linux_sigtramp_offset_1 (CORE_ADDR pc) } static LONGEST -alpha_linux_sigtramp_offset (CORE_ADDR pc) +alpha_linux_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) { long i, off; @@ -74,7 +102,7 @@ alpha_linux_sigtramp_offset (CORE_ADDR pc) return -1; /* Guess where we might be in the sequence. */ - off = alpha_linux_sigtramp_offset_1 (pc); + off = alpha_linux_sigtramp_offset_1 (gdbarch, pc); if (off < 0) return -1; @@ -84,7 +112,7 @@ alpha_linux_sigtramp_offset (CORE_ADDR pc) { if (i == off) continue; - if (alpha_linux_sigtramp_offset_1 (pc + i) != i) + if (alpha_linux_sigtramp_offset_1 (gdbarch, pc + i) != i) return -1; } @@ -92,14 +120,16 @@ alpha_linux_sigtramp_offset (CORE_ADDR pc) } static int -alpha_linux_pc_in_sigtramp (CORE_ADDR pc, char *func_name) +alpha_linux_pc_in_sigtramp (struct gdbarch *gdbarch, + CORE_ADDR pc, const char *func_name) { - return alpha_linux_sigtramp_offset (pc) >= 0; + return alpha_linux_sigtramp_offset (gdbarch, pc) >= 0; } static CORE_ADDR alpha_linux_sigcontext_addr (struct frame_info *this_frame) { + struct gdbarch *gdbarch = get_frame_arch (this_frame); CORE_ADDR pc; ULONGEST sp; long off; @@ -107,7 +137,7 @@ alpha_linux_sigcontext_addr (struct frame_info *this_frame) pc = get_frame_pc (this_frame); sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM); - off = alpha_linux_sigtramp_offset (pc); + off = alpha_linux_sigtramp_offset (gdbarch, pc); gdb_assert (off >= 0); /* __NR_rt_sigreturn has a couple of structures on the stack. This is: @@ -117,9 +147,9 @@ alpha_linux_sigcontext_addr (struct frame_info *this_frame) struct ucontext uc; }; - offsetof (struct rt_sigframe, uc.uc_mcontext); - */ - if (alpha_read_insn (pc - off + 4) == 0x201f015f) + offsetof (struct rt_sigframe, uc.uc_mcontext); */ + + if (alpha_read_insn (gdbarch, pc - off + 4) == 0x201f015f) return sp + 176; /* __NR_sigreturn has the sigcontext structure at the top of the stack. */ @@ -191,7 +221,7 @@ static struct regset alpha_linux_fpregset = /* Return the appropriate register set for the core section identified by SECT_NAME and SECT_SIZE. */ -const struct regset * +static const struct regset * alpha_linux_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size) { @@ -204,11 +234,121 @@ alpha_linux_regset_from_core_section (struct gdbarch *gdbarch, return NULL; } +/* Implementation of `gdbarch_gdb_signal_from_target', as defined in + gdbarch.h. */ + +static enum gdb_signal +alpha_linux_gdb_signal_from_target (struct gdbarch *gdbarch, + int signal) +{ + switch (signal) + { + case ALPHA_LINUX_SIGEMT: + return GDB_SIGNAL_EMT; + + case ALPHA_LINUX_SIGBUS: + return GDB_SIGNAL_BUS; + + case ALPHA_LINUX_SIGSYS: + return GDB_SIGNAL_SYS; + + case ALPHA_LINUX_SIGURG: + return GDB_SIGNAL_URG; + + case ALPHA_LINUX_SIGSTOP: + return GDB_SIGNAL_STOP; + + case ALPHA_LINUX_SIGTSTP: + return GDB_SIGNAL_TSTP; + + case ALPHA_LINUX_SIGCONT: + return GDB_SIGNAL_CONT; + + case ALPHA_LINUX_SIGCHLD: + return GDB_SIGNAL_CHLD; + + /* No way to differentiate between SIGIO and SIGPOLL. + Therefore, we just handle the first one. */ + case ALPHA_LINUX_SIGIO: + return GDB_SIGNAL_IO; + + /* No way to differentiate between SIGINFO and SIGPWR. + Therefore, we just handle the first one. */ + case ALPHA_LINUX_SIGINFO: + return GDB_SIGNAL_INFO; + + case ALPHA_LINUX_SIGUSR1: + return GDB_SIGNAL_USR1; + + case ALPHA_LINUX_SIGUSR2: + return GDB_SIGNAL_USR2; + } + + return linux_gdb_signal_from_target (gdbarch, signal); +} + +/* Implementation of `gdbarch_gdb_signal_to_target', as defined in + gdbarch.h. */ + +static int +alpha_linux_gdb_signal_to_target (struct gdbarch *gdbarch, + enum gdb_signal signal) +{ + switch (signal) + { + case GDB_SIGNAL_EMT: + return ALPHA_LINUX_SIGEMT; + + case GDB_SIGNAL_BUS: + return ALPHA_LINUX_SIGBUS; + + case GDB_SIGNAL_SYS: + return ALPHA_LINUX_SIGSYS; + + case GDB_SIGNAL_URG: + return ALPHA_LINUX_SIGURG; + + case GDB_SIGNAL_STOP: + return ALPHA_LINUX_SIGSTOP; + + case GDB_SIGNAL_TSTP: + return ALPHA_LINUX_SIGTSTP; + + case GDB_SIGNAL_CONT: + return ALPHA_LINUX_SIGCONT; + + case GDB_SIGNAL_CHLD: + return ALPHA_LINUX_SIGCHLD; + + case GDB_SIGNAL_IO: + return ALPHA_LINUX_SIGIO; + + case GDB_SIGNAL_INFO: + return ALPHA_LINUX_SIGINFO; + + case GDB_SIGNAL_USR1: + return ALPHA_LINUX_SIGUSR1; + + case GDB_SIGNAL_USR2: + return ALPHA_LINUX_SIGUSR2; + + case GDB_SIGNAL_POLL: + return ALPHA_LINUX_SIGPOLL; + + case GDB_SIGNAL_PWR: + return ALPHA_LINUX_SIGPWR; + } + + return linux_gdb_signal_to_target (gdbarch, signal); +} + static void alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep; + linux_init_abi (info, gdbarch); + /* Hook into the DWARF CFI frame unwinder. */ alpha_dwarf2_init_abi (info, gdbarch); @@ -233,8 +373,16 @@ alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_regset_from_core_section (gdbarch, alpha_linux_regset_from_core_section); + + set_gdbarch_gdb_signal_from_target (gdbarch, + alpha_linux_gdb_signal_from_target); + set_gdbarch_gdb_signal_to_target (gdbarch, + alpha_linux_gdb_signal_to_target); } +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_alpha_linux_tdep; + void _initialize_alpha_linux_tdep (void) {