1 /* Target-dependent code for GNU/Linux on Alpha.
2 Copyright (C) 2002-2014 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "solib-svr4.h"
27 #include "linux-tdep.h"
28 #include "alpha-tdep.h"
30 /* This enum represents the signals' numbers on the Alpha
31 architecture. It just contains the signal definitions which are
32 different from the generic implementation.
34 It is derived from the file <arch/alpha/include/uapi/asm/signal.h>,
35 from the Linux kernel tree. */
39 /* SIGABRT is the same as in the generic implementation, but is
40 defined here because SIGIOT depends on it. */
41 ALPHA_LINUX_SIGABRT = 6,
42 ALPHA_LINUX_SIGEMT = 7,
43 ALPHA_LINUX_SIGBUS = 10,
44 ALPHA_LINUX_SIGSYS = 12,
45 ALPHA_LINUX_SIGURG = 16,
46 ALPHA_LINUX_SIGSTOP = 17,
47 ALPHA_LINUX_SIGTSTP = 18,
48 ALPHA_LINUX_SIGCONT = 19,
49 ALPHA_LINUX_SIGCHLD = 20,
50 ALPHA_LINUX_SIGIO = 23,
51 ALPHA_LINUX_SIGINFO = 29,
52 ALPHA_LINUX_SIGUSR1 = 30,
53 ALPHA_LINUX_SIGUSR2 = 31,
54 ALPHA_LINUX_SIGPOLL = ALPHA_LINUX_SIGIO,
55 ALPHA_LINUX_SIGPWR = ALPHA_LINUX_SIGINFO,
56 ALPHA_LINUX_SIGIOT = ALPHA_LINUX_SIGABRT,
59 /* Under GNU/Linux, signal handler invocations can be identified by
60 the designated code sequence that is used to return from a signal
61 handler. In particular, the return address of a signal handler
62 points to a sequence that copies $sp to $16, loads $0 with the
63 appropriate syscall number, and finally enters the kernel.
65 This is somewhat complicated in that:
66 (1) the expansion of the "mov" assembler macro has changed over
67 time, from "bis src,src,dst" to "bis zero,src,dst",
68 (2) the kernel has changed from using "addq" to "lda" to load the
70 (3) there is a "normal" sigreturn and an "rt" sigreturn which
71 has a different stack layout. */
74 alpha_linux_sigtramp_offset_1 (struct gdbarch *gdbarch, CORE_ADDR pc)
76 switch (alpha_read_insn (gdbarch, pc))
78 case 0x47de0410: /* bis $30,$30,$16 */
79 case 0x47fe0410: /* bis $31,$30,$16 */
82 case 0x43ecf400: /* addq $31,103,$0 */
83 case 0x201f0067: /* lda $0,103($31) */
84 case 0x201f015f: /* lda $0,351($31) */
87 case 0x00000083: /* call_pal callsys */
96 alpha_linux_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc)
103 /* Guess where we might be in the sequence. */
104 off = alpha_linux_sigtramp_offset_1 (gdbarch, pc);
108 /* Verify that the other two insns of the sequence are as we expect. */
110 for (i = 0; i < 12; i += 4)
114 if (alpha_linux_sigtramp_offset_1 (gdbarch, pc + i) != i)
122 alpha_linux_pc_in_sigtramp (struct gdbarch *gdbarch,
123 CORE_ADDR pc, const char *func_name)
125 return alpha_linux_sigtramp_offset (gdbarch, pc) >= 0;
129 alpha_linux_sigcontext_addr (struct frame_info *this_frame)
131 struct gdbarch *gdbarch = get_frame_arch (this_frame);
136 pc = get_frame_pc (this_frame);
137 sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM);
139 off = alpha_linux_sigtramp_offset (gdbarch, pc);
140 gdb_assert (off >= 0);
142 /* __NR_rt_sigreturn has a couple of structures on the stack. This is:
149 offsetof (struct rt_sigframe, uc.uc_mcontext); */
151 if (alpha_read_insn (gdbarch, pc - off + 4) == 0x201f015f)
154 /* __NR_sigreturn has the sigcontext structure at the top of the stack. */
158 /* Supply register REGNUM from the buffer specified by GREGS and LEN
159 in the general-purpose register set REGSET to register cache
160 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
163 alpha_linux_supply_gregset (const struct regset *regset,
164 struct regcache *regcache,
165 int regnum, const void *gregs, size_t len)
167 const gdb_byte *regs = gregs;
169 gdb_assert (len >= 32 * 8);
171 for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
173 if (regnum == i || regnum == -1)
174 regcache_raw_supply (regcache, i, regs + i * 8);
177 if (regnum == ALPHA_PC_REGNUM || regnum == -1)
178 regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
180 if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1)
181 regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM,
182 len >= 33 * 8 ? regs + 32 * 8 : NULL);
185 /* Supply register REGNUM from the buffer specified by FPREGS and LEN
186 in the floating-point register set REGSET to register cache
187 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
190 alpha_linux_supply_fpregset (const struct regset *regset,
191 struct regcache *regcache,
192 int regnum, const void *fpregs, size_t len)
194 const gdb_byte *regs = fpregs;
196 gdb_assert (len >= 32 * 8);
198 for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
200 if (regnum == i || regnum == -1)
201 regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
204 if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
205 regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8);
208 static const struct regset alpha_linux_gregset =
211 alpha_linux_supply_gregset
214 static const struct regset alpha_linux_fpregset =
217 alpha_linux_supply_fpregset
220 /* Return the appropriate register set for the core section identified
221 by SECT_NAME and SECT_SIZE. */
223 static const struct regset *
224 alpha_linux_regset_from_core_section (struct gdbarch *gdbarch,
225 const char *sect_name, size_t sect_size)
227 if (strcmp (sect_name, ".reg") == 0 && sect_size >= 32 * 8)
228 return &alpha_linux_gregset;
230 if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 32 * 8)
231 return &alpha_linux_fpregset;
236 /* Implementation of `gdbarch_gdb_signal_from_target', as defined in
239 static enum gdb_signal
240 alpha_linux_gdb_signal_from_target (struct gdbarch *gdbarch,
245 case ALPHA_LINUX_SIGEMT:
246 return GDB_SIGNAL_EMT;
248 case ALPHA_LINUX_SIGBUS:
249 return GDB_SIGNAL_BUS;
251 case ALPHA_LINUX_SIGSYS:
252 return GDB_SIGNAL_SYS;
254 case ALPHA_LINUX_SIGURG:
255 return GDB_SIGNAL_URG;
257 case ALPHA_LINUX_SIGSTOP:
258 return GDB_SIGNAL_STOP;
260 case ALPHA_LINUX_SIGTSTP:
261 return GDB_SIGNAL_TSTP;
263 case ALPHA_LINUX_SIGCONT:
264 return GDB_SIGNAL_CONT;
266 case ALPHA_LINUX_SIGCHLD:
267 return GDB_SIGNAL_CHLD;
269 /* No way to differentiate between SIGIO and SIGPOLL.
270 Therefore, we just handle the first one. */
271 case ALPHA_LINUX_SIGIO:
272 return GDB_SIGNAL_IO;
274 /* No way to differentiate between SIGINFO and SIGPWR.
275 Therefore, we just handle the first one. */
276 case ALPHA_LINUX_SIGINFO:
277 return GDB_SIGNAL_INFO;
279 case ALPHA_LINUX_SIGUSR1:
280 return GDB_SIGNAL_USR1;
282 case ALPHA_LINUX_SIGUSR2:
283 return GDB_SIGNAL_USR2;
286 return linux_gdb_signal_from_target (gdbarch, signal);
289 /* Implementation of `gdbarch_gdb_signal_to_target', as defined in
293 alpha_linux_gdb_signal_to_target (struct gdbarch *gdbarch,
294 enum gdb_signal signal)
299 return ALPHA_LINUX_SIGEMT;
302 return ALPHA_LINUX_SIGBUS;
305 return ALPHA_LINUX_SIGSYS;
308 return ALPHA_LINUX_SIGURG;
310 case GDB_SIGNAL_STOP:
311 return ALPHA_LINUX_SIGSTOP;
313 case GDB_SIGNAL_TSTP:
314 return ALPHA_LINUX_SIGTSTP;
316 case GDB_SIGNAL_CONT:
317 return ALPHA_LINUX_SIGCONT;
319 case GDB_SIGNAL_CHLD:
320 return ALPHA_LINUX_SIGCHLD;
323 return ALPHA_LINUX_SIGIO;
325 case GDB_SIGNAL_INFO:
326 return ALPHA_LINUX_SIGINFO;
328 case GDB_SIGNAL_USR1:
329 return ALPHA_LINUX_SIGUSR1;
331 case GDB_SIGNAL_USR2:
332 return ALPHA_LINUX_SIGUSR2;
334 case GDB_SIGNAL_POLL:
335 return ALPHA_LINUX_SIGPOLL;
338 return ALPHA_LINUX_SIGPWR;
341 return linux_gdb_signal_to_target (gdbarch, signal);
345 alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
347 struct gdbarch_tdep *tdep;
349 linux_init_abi (info, gdbarch);
351 /* Hook into the DWARF CFI frame unwinder. */
352 alpha_dwarf2_init_abi (info, gdbarch);
354 /* Hook into the MDEBUG frame unwinder. */
355 alpha_mdebug_init_abi (info, gdbarch);
357 tdep = gdbarch_tdep (gdbarch);
358 tdep->dynamic_sigtramp_offset = alpha_linux_sigtramp_offset;
359 tdep->sigcontext_addr = alpha_linux_sigcontext_addr;
360 tdep->pc_in_sigtramp = alpha_linux_pc_in_sigtramp;
362 tdep->jb_elt_size = 8;
364 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
366 set_solib_svr4_fetch_link_map_offsets
367 (gdbarch, svr4_lp64_fetch_link_map_offsets);
369 /* Enable TLS support. */
370 set_gdbarch_fetch_tls_load_module_address (gdbarch,
371 svr4_fetch_objfile_link_map);
373 set_gdbarch_regset_from_core_section
374 (gdbarch, alpha_linux_regset_from_core_section);
376 set_gdbarch_gdb_signal_from_target (gdbarch,
377 alpha_linux_gdb_signal_from_target);
378 set_gdbarch_gdb_signal_to_target (gdbarch,
379 alpha_linux_gdb_signal_to_target);
382 /* Provide a prototype to silence -Wmissing-prototypes. */
383 extern initialize_file_ftype _initialize_alpha_linux_tdep;
386 _initialize_alpha_linux_tdep (void)
388 gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_LINUX,
389 alpha_linux_init_abi);