GDB (API)
/home/stan/gdb/src/gdb/alpha-linux-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for GNU/Linux on Alpha.
00002    Copyright (C) 2002-2013 Free Software Foundation, Inc.
00003 
00004    This file is part of GDB.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 3 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00018 
00019 #include "defs.h"
00020 #include "frame.h"
00021 #include "gdb_assert.h"
00022 #include "gdb_string.h"
00023 #include "osabi.h"
00024 #include "solib-svr4.h"
00025 #include "symtab.h"
00026 #include "regset.h"
00027 #include "regcache.h"
00028 #include "linux-tdep.h"
00029 #include "alpha-tdep.h"
00030 
00031 /* This enum represents the signals' numbers on the Alpha
00032    architecture.  It just contains the signal definitions which are
00033    different from the generic implementation.
00034 
00035    It is derived from the file <arch/alpha/include/uapi/asm/signal.h>,
00036    from the Linux kernel tree.  */
00037 
00038 enum
00039   {
00040     /* SIGABRT is the same as in the generic implementation, but is
00041        defined here because SIGIOT depends on it.  */
00042     ALPHA_LINUX_SIGABRT = 6,
00043     ALPHA_LINUX_SIGEMT = 7,
00044     ALPHA_LINUX_SIGBUS = 10,
00045     ALPHA_LINUX_SIGSYS = 12,
00046     ALPHA_LINUX_SIGURG = 16,
00047     ALPHA_LINUX_SIGSTOP = 17,
00048     ALPHA_LINUX_SIGTSTP = 18,
00049     ALPHA_LINUX_SIGCONT = 19,
00050     ALPHA_LINUX_SIGCHLD = 20,
00051     ALPHA_LINUX_SIGIO = 23,
00052     ALPHA_LINUX_SIGINFO = 29,
00053     ALPHA_LINUX_SIGUSR1 = 30,
00054     ALPHA_LINUX_SIGUSR2 = 31,
00055     ALPHA_LINUX_SIGPOLL = ALPHA_LINUX_SIGIO,
00056     ALPHA_LINUX_SIGPWR = ALPHA_LINUX_SIGINFO,
00057     ALPHA_LINUX_SIGIOT = ALPHA_LINUX_SIGABRT,
00058   };
00059 
00060 /* Under GNU/Linux, signal handler invocations can be identified by
00061    the designated code sequence that is used to return from a signal
00062    handler.  In particular, the return address of a signal handler
00063    points to a sequence that copies $sp to $16, loads $0 with the
00064    appropriate syscall number, and finally enters the kernel.
00065 
00066    This is somewhat complicated in that:
00067      (1) the expansion of the "mov" assembler macro has changed over
00068          time, from "bis src,src,dst" to "bis zero,src,dst",
00069      (2) the kernel has changed from using "addq" to "lda" to load the
00070          syscall number,
00071      (3) there is a "normal" sigreturn and an "rt" sigreturn which
00072          has a different stack layout.  */
00073 
00074 static long
00075 alpha_linux_sigtramp_offset_1 (struct gdbarch *gdbarch, CORE_ADDR pc)
00076 {
00077   switch (alpha_read_insn (gdbarch, pc))
00078     {
00079     case 0x47de0410:            /* bis $30,$30,$16 */
00080     case 0x47fe0410:            /* bis $31,$30,$16 */
00081       return 0;
00082 
00083     case 0x43ecf400:            /* addq $31,103,$0 */
00084     case 0x201f0067:            /* lda $0,103($31) */
00085     case 0x201f015f:            /* lda $0,351($31) */
00086       return 4;
00087 
00088     case 0x00000083:            /* call_pal callsys */
00089       return 8;
00090 
00091     default:
00092       return -1;
00093     }
00094 }
00095 
00096 static LONGEST
00097 alpha_linux_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc)
00098 {
00099   long i, off;
00100 
00101   if (pc & 3)
00102     return -1;
00103 
00104   /* Guess where we might be in the sequence.  */
00105   off = alpha_linux_sigtramp_offset_1 (gdbarch, pc);
00106   if (off < 0)
00107     return -1;
00108 
00109   /* Verify that the other two insns of the sequence are as we expect.  */
00110   pc -= off;
00111   for (i = 0; i < 12; i += 4)
00112     {
00113       if (i == off)
00114         continue;
00115       if (alpha_linux_sigtramp_offset_1 (gdbarch, pc + i) != i)
00116         return -1;
00117     }
00118 
00119   return off;
00120 }
00121 
00122 static int
00123 alpha_linux_pc_in_sigtramp (struct gdbarch *gdbarch,
00124                             CORE_ADDR pc, const char *func_name)
00125 {
00126   return alpha_linux_sigtramp_offset (gdbarch, pc) >= 0;
00127 }
00128 
00129 static CORE_ADDR
00130 alpha_linux_sigcontext_addr (struct frame_info *this_frame)
00131 {
00132   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00133   CORE_ADDR pc;
00134   ULONGEST sp;
00135   long off;
00136 
00137   pc = get_frame_pc (this_frame);
00138   sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM);
00139 
00140   off = alpha_linux_sigtramp_offset (gdbarch, pc);
00141   gdb_assert (off >= 0);
00142 
00143   /* __NR_rt_sigreturn has a couple of structures on the stack.  This is:
00144 
00145         struct rt_sigframe {
00146           struct siginfo info;
00147           struct ucontext uc;
00148         };
00149 
00150         offsetof (struct rt_sigframe, uc.uc_mcontext);  */
00151 
00152   if (alpha_read_insn (gdbarch, pc - off + 4) == 0x201f015f)
00153     return sp + 176;
00154 
00155   /* __NR_sigreturn has the sigcontext structure at the top of the stack.  */
00156   return sp;
00157 }
00158 
00159 /* Supply register REGNUM from the buffer specified by GREGS and LEN
00160    in the general-purpose register set REGSET to register cache
00161    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
00162 
00163 static void
00164 alpha_linux_supply_gregset (const struct regset *regset,
00165                             struct regcache *regcache,
00166                             int regnum, const void *gregs, size_t len)
00167 {
00168   const gdb_byte *regs = gregs;
00169   int i;
00170   gdb_assert (len >= 32 * 8);
00171 
00172   for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
00173     {
00174       if (regnum == i || regnum == -1)
00175         regcache_raw_supply (regcache, i, regs + i * 8);
00176     }
00177 
00178   if (regnum == ALPHA_PC_REGNUM || regnum == -1)
00179     regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
00180 
00181   if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1)
00182     regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM,
00183                          len >= 33 * 8 ? regs + 32 * 8 : NULL);
00184 }
00185 
00186 /* Supply register REGNUM from the buffer specified by FPREGS and LEN
00187    in the floating-point register set REGSET to register cache
00188    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */
00189 
00190 static void
00191 alpha_linux_supply_fpregset (const struct regset *regset,
00192                              struct regcache *regcache,
00193                              int regnum, const void *fpregs, size_t len)
00194 {
00195   const gdb_byte *regs = fpregs;
00196   int i;
00197   gdb_assert (len >= 32 * 8);
00198 
00199   for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
00200     {
00201       if (regnum == i || regnum == -1)
00202         regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
00203     }
00204 
00205   if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
00206     regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8);
00207 }
00208 
00209 static struct regset alpha_linux_gregset =
00210 {
00211   NULL,
00212   alpha_linux_supply_gregset
00213 };
00214 
00215 static struct regset alpha_linux_fpregset =
00216 {
00217   NULL,
00218   alpha_linux_supply_fpregset
00219 };
00220 
00221 /* Return the appropriate register set for the core section identified
00222    by SECT_NAME and SECT_SIZE.  */
00223 
00224 static const struct regset *
00225 alpha_linux_regset_from_core_section (struct gdbarch *gdbarch,
00226                                       const char *sect_name, size_t sect_size)
00227 {
00228   if (strcmp (sect_name, ".reg") == 0 && sect_size >= 32 * 8)
00229     return &alpha_linux_gregset;
00230 
00231   if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 32 * 8)
00232     return &alpha_linux_fpregset;
00233 
00234   return NULL;
00235 }
00236 
00237 /* Implementation of `gdbarch_gdb_signal_from_target', as defined in
00238    gdbarch.h.  */
00239 
00240 static enum gdb_signal
00241 alpha_linux_gdb_signal_from_target (struct gdbarch *gdbarch,
00242                                     int signal)
00243 {
00244   switch (signal)
00245     {
00246     case ALPHA_LINUX_SIGEMT:
00247       return GDB_SIGNAL_EMT;
00248 
00249     case ALPHA_LINUX_SIGBUS:
00250       return GDB_SIGNAL_BUS;
00251 
00252     case ALPHA_LINUX_SIGSYS:
00253       return GDB_SIGNAL_SYS;
00254 
00255     case ALPHA_LINUX_SIGURG:
00256       return GDB_SIGNAL_URG;
00257 
00258     case ALPHA_LINUX_SIGSTOP:
00259       return GDB_SIGNAL_STOP;
00260 
00261     case ALPHA_LINUX_SIGTSTP:
00262       return GDB_SIGNAL_TSTP;
00263 
00264     case ALPHA_LINUX_SIGCONT:
00265       return GDB_SIGNAL_CONT;
00266 
00267     case ALPHA_LINUX_SIGCHLD:
00268       return GDB_SIGNAL_CHLD;
00269 
00270     /* No way to differentiate between SIGIO and SIGPOLL.
00271        Therefore, we just handle the first one.  */
00272     case ALPHA_LINUX_SIGIO:
00273       return GDB_SIGNAL_IO;
00274 
00275     /* No way to differentiate between SIGINFO and SIGPWR.
00276        Therefore, we just handle the first one.  */
00277     case ALPHA_LINUX_SIGINFO:
00278       return GDB_SIGNAL_INFO;
00279 
00280     case ALPHA_LINUX_SIGUSR1:
00281       return GDB_SIGNAL_USR1;
00282 
00283     case ALPHA_LINUX_SIGUSR2:
00284       return GDB_SIGNAL_USR2;
00285     }
00286 
00287   return linux_gdb_signal_from_target (gdbarch, signal);
00288 }
00289 
00290 /* Implementation of `gdbarch_gdb_signal_to_target', as defined in
00291    gdbarch.h.  */
00292 
00293 static int
00294 alpha_linux_gdb_signal_to_target (struct gdbarch *gdbarch,
00295                                   enum gdb_signal signal)
00296 {
00297   switch (signal)
00298     {
00299     case GDB_SIGNAL_EMT:
00300       return ALPHA_LINUX_SIGEMT;
00301 
00302     case GDB_SIGNAL_BUS:
00303       return ALPHA_LINUX_SIGBUS;
00304 
00305     case GDB_SIGNAL_SYS:
00306       return ALPHA_LINUX_SIGSYS;
00307 
00308     case GDB_SIGNAL_URG:
00309       return ALPHA_LINUX_SIGURG;
00310 
00311     case GDB_SIGNAL_STOP:
00312       return ALPHA_LINUX_SIGSTOP;
00313 
00314     case GDB_SIGNAL_TSTP:
00315       return ALPHA_LINUX_SIGTSTP;
00316 
00317     case GDB_SIGNAL_CONT:
00318       return ALPHA_LINUX_SIGCONT;
00319 
00320     case GDB_SIGNAL_CHLD:
00321       return ALPHA_LINUX_SIGCHLD;
00322 
00323     case GDB_SIGNAL_IO:
00324       return ALPHA_LINUX_SIGIO;
00325 
00326     case GDB_SIGNAL_INFO:
00327       return ALPHA_LINUX_SIGINFO;
00328 
00329     case GDB_SIGNAL_USR1:
00330       return ALPHA_LINUX_SIGUSR1;
00331 
00332     case GDB_SIGNAL_USR2:
00333       return ALPHA_LINUX_SIGUSR2;
00334 
00335     case GDB_SIGNAL_POLL:
00336       return ALPHA_LINUX_SIGPOLL;
00337 
00338     case GDB_SIGNAL_PWR:
00339       return ALPHA_LINUX_SIGPWR;
00340     }
00341 
00342   return linux_gdb_signal_to_target (gdbarch, signal);
00343 }
00344 
00345 static void
00346 alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00347 {
00348   struct gdbarch_tdep *tdep;
00349 
00350   linux_init_abi (info, gdbarch);
00351 
00352   /* Hook into the DWARF CFI frame unwinder.  */
00353   alpha_dwarf2_init_abi (info, gdbarch);
00354 
00355   /* Hook into the MDEBUG frame unwinder.  */
00356   alpha_mdebug_init_abi (info, gdbarch);
00357 
00358   tdep = gdbarch_tdep (gdbarch);
00359   tdep->dynamic_sigtramp_offset = alpha_linux_sigtramp_offset;
00360   tdep->sigcontext_addr = alpha_linux_sigcontext_addr;
00361   tdep->pc_in_sigtramp = alpha_linux_pc_in_sigtramp;
00362   tdep->jb_pc = 2;
00363   tdep->jb_elt_size = 8;
00364 
00365   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
00366 
00367   set_solib_svr4_fetch_link_map_offsets
00368     (gdbarch, svr4_lp64_fetch_link_map_offsets);
00369 
00370   /* Enable TLS support.  */
00371   set_gdbarch_fetch_tls_load_module_address (gdbarch,
00372                                              svr4_fetch_objfile_link_map);
00373 
00374   set_gdbarch_regset_from_core_section
00375     (gdbarch, alpha_linux_regset_from_core_section);
00376 
00377   set_gdbarch_gdb_signal_from_target (gdbarch,
00378                                       alpha_linux_gdb_signal_from_target);
00379   set_gdbarch_gdb_signal_to_target (gdbarch,
00380                                     alpha_linux_gdb_signal_to_target);
00381 }
00382 
00383 /* Provide a prototype to silence -Wmissing-prototypes.  */
00384 extern initialize_file_ftype _initialize_alpha_linux_tdep;
00385 
00386 void
00387 _initialize_alpha_linux_tdep (void)
00388 {
00389   gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_LINUX,
00390                           alpha_linux_init_abi);
00391 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines