X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Falpha-linux-tdep.c;h=27b2398fdbc32ea3ab56b72399f1c02e992c254c;hb=99a5596592eda72c5c60b45cdfabb47e426132d5;hp=15111c9efccddc08a550a2b9abca439e5fa699cc;hpb=7b6bb8daaceb9ecf3f42dea57ae82733d6a3b2f6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c index 15111c9efc..27b2398fdb 100644 --- a/gdb/alpha-linux-tdep.c +++ b/gdb/alpha-linux-tdep.c @@ -1,6 +1,5 @@ /* Target-dependent code for GNU/Linux on Alpha. - Copyright (C) 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002-2019 Free Software Foundation, Inc. This file is part of GDB. @@ -19,8 +18,6 @@ #include "defs.h" #include "frame.h" -#include "gdb_assert.h" -#include "gdb_string.h" #include "osabi.h" #include "solib-svr4.h" #include "symtab.h" @@ -28,6 +25,36 @@ #include "regcache.h" #include "linux-tdep.h" #include "alpha-tdep.h" +#include "gdbarch.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 @@ -41,8 +68,7 @@ (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 (struct gdbarch *gdbarch, CORE_ADDR pc) @@ -94,7 +120,7 @@ alpha_linux_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) static int alpha_linux_pc_in_sigtramp (struct gdbarch *gdbarch, - CORE_ADDR pc, char *func_name) + CORE_ADDR pc, const char *func_name) { return alpha_linux_sigtramp_offset (gdbarch, pc) >= 0; } @@ -120,8 +146,8 @@ alpha_linux_sigcontext_addr (struct frame_info *this_frame) struct ucontext uc; }; - offsetof (struct rt_sigframe, uc.uc_mcontext); - */ + offsetof (struct rt_sigframe, uc.uc_mcontext); */ + if (alpha_read_insn (gdbarch, pc - off + 4) == 0x201f015f) return sp + 176; @@ -138,22 +164,28 @@ alpha_linux_supply_gregset (const struct regset *regset, struct regcache *regcache, int regnum, const void *gregs, size_t len) { - const gdb_byte *regs = gregs; - int i; + const gdb_byte *regs = (const gdb_byte *) gregs; + gdb_assert (len >= 32 * 8); + alpha_supply_int_regs (regcache, regnum, regs, regs + 31 * 8, + len >= 33 * 8 ? regs + 32 * 8 : NULL); +} - for (i = 0; i < ALPHA_ZERO_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, regs + i * 8); - } +/* Collect register REGNUM from the register cache REGCACHE and store + it in the buffer specified by GREGS and LEN as described by the + general-purpose register set REGSET. If REGNUM is -1, do this for + all registers in REGSET. */ - if (regnum == ALPHA_PC_REGNUM || regnum == -1) - regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8); +static void +alpha_linux_collect_gregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *gregs, size_t len) +{ + gdb_byte *regs = (gdb_byte *) gregs; - if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1) - regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM, - len >= 33 * 8 ? regs + 32 * 8 : NULL); + gdb_assert (len >= 32 * 8); + alpha_fill_int_regs (regcache, regnum, regs, regs + 31 * 8, + len >= 33 * 8 ? regs + 32 * 8 : NULL); } /* Supply register REGNUM from the buffer specified by FPREGS and LEN @@ -165,46 +197,158 @@ alpha_linux_supply_fpregset (const struct regset *regset, struct regcache *regcache, int regnum, const void *fpregs, size_t len) { - const gdb_byte *regs = fpregs; - int i; + const gdb_byte *regs = (const gdb_byte *) fpregs; + gdb_assert (len >= 32 * 8); + alpha_supply_fp_regs (regcache, regnum, regs, regs + 31 * 8); +} - for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8); - } +/* Collect register REGNUM from the register cache REGCACHE and store + it in the buffer specified by FPREGS and LEN as described by the + general-purpose register set REGSET. If REGNUM is -1, do this for + all registers in REGSET. */ - if (regnum == ALPHA_FPCR_REGNUM || regnum == -1) - regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8); +static void +alpha_linux_collect_fpregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *fpregs, size_t len) +{ + gdb_byte *regs = (gdb_byte *) fpregs; + + gdb_assert (len >= 32 * 8); + alpha_fill_fp_regs (regcache, regnum, regs, regs + 31 * 8); } -static struct regset alpha_linux_gregset = +static const struct regset alpha_linux_gregset = { NULL, - alpha_linux_supply_gregset + alpha_linux_supply_gregset, alpha_linux_collect_gregset }; -static struct regset alpha_linux_fpregset = +static const struct regset alpha_linux_fpregset = { NULL, - alpha_linux_supply_fpregset + alpha_linux_supply_fpregset, alpha_linux_collect_fpregset }; -/* Return the appropriate register set for the core section identified - by SECT_NAME and SECT_SIZE. */ +/* Iterate over core file register note sections. */ + +static void +alpha_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", 32 * 8, 32 * 8, &alpha_linux_gregset, NULL, cb_data); + cb (".reg2", 32 * 8, 32 * 8, &alpha_linux_fpregset, NULL, cb_data); +} + +/* 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; -static const struct regset * -alpha_linux_regset_from_core_section (struct gdbarch *gdbarch, - const char *sect_name, size_t sect_size) + 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) { - if (strcmp (sect_name, ".reg") == 0 && sect_size >= 32 * 8) - return &alpha_linux_gregset; + switch (signal) + { + case GDB_SIGNAL_EMT: + return ALPHA_LINUX_SIGEMT; + + case GDB_SIGNAL_BUS: + return ALPHA_LINUX_SIGBUS; - if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 32 * 8) - return &alpha_linux_fpregset; + case GDB_SIGNAL_SYS: + return ALPHA_LINUX_SIGSYS; - return NULL; + 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 @@ -236,12 +380,14 @@ alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); - set_gdbarch_regset_from_core_section - (gdbarch, alpha_linux_regset_from_core_section); -} + set_gdbarch_iterate_over_regset_sections + (gdbarch, alpha_linux_iterate_over_regset_sections); -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_alpha_linux_tdep; + 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); +} void _initialize_alpha_linux_tdep (void)