GDB (API)
|
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 }