1 /* Target-dependent code for GNU/Linux on Alpha.
2 Copyright (C) 2002-2019 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/>. */
21 /* Local non-gdb includes. */
22 #include "alpha-tdep.h"
24 #include "linux-tdep.h"
28 #include "solib-svr4.h"
31 /* This enum represents the signals' numbers on the Alpha
32 architecture. It just contains the signal definitions which are
33 different from the generic implementation.
35 It is derived from the file <arch/alpha/include/uapi/asm/signal.h>,
36 from the Linux kernel tree. */
40 /* SIGABRT is the same as in the generic implementation, but is
41 defined here because SIGIOT depends on it. */
42 ALPHA_LINUX_SIGABRT
= 6,
43 ALPHA_LINUX_SIGEMT
= 7,
44 ALPHA_LINUX_SIGBUS
= 10,
45 ALPHA_LINUX_SIGSYS
= 12,
46 ALPHA_LINUX_SIGURG
= 16,
47 ALPHA_LINUX_SIGSTOP
= 17,
48 ALPHA_LINUX_SIGTSTP
= 18,
49 ALPHA_LINUX_SIGCONT
= 19,
50 ALPHA_LINUX_SIGCHLD
= 20,
51 ALPHA_LINUX_SIGIO
= 23,
52 ALPHA_LINUX_SIGINFO
= 29,
53 ALPHA_LINUX_SIGUSR1
= 30,
54 ALPHA_LINUX_SIGUSR2
= 31,
55 ALPHA_LINUX_SIGPOLL
= ALPHA_LINUX_SIGIO
,
56 ALPHA_LINUX_SIGPWR
= ALPHA_LINUX_SIGINFO
,
57 ALPHA_LINUX_SIGIOT
= ALPHA_LINUX_SIGABRT
,
60 /* Under GNU/Linux, signal handler invocations can be identified by
61 the designated code sequence that is used to return from a signal
62 handler. In particular, the return address of a signal handler
63 points to a sequence that copies $sp to $16, loads $0 with the
64 appropriate syscall number, and finally enters the kernel.
66 This is somewhat complicated in that:
67 (1) the expansion of the "mov" assembler macro has changed over
68 time, from "bis src,src,dst" to "bis zero,src,dst",
69 (2) the kernel has changed from using "addq" to "lda" to load the
71 (3) there is a "normal" sigreturn and an "rt" sigreturn which
72 has a different stack layout. */
75 alpha_linux_sigtramp_offset_1 (struct gdbarch
*gdbarch
, CORE_ADDR pc
)
77 switch (alpha_read_insn (gdbarch
, pc
))
79 case 0x47de0410: /* bis $30,$30,$16 */
80 case 0x47fe0410: /* bis $31,$30,$16 */
83 case 0x43ecf400: /* addq $31,103,$0 */
84 case 0x201f0067: /* lda $0,103($31) */
85 case 0x201f015f: /* lda $0,351($31) */
88 case 0x00000083: /* call_pal callsys */
97 alpha_linux_sigtramp_offset (struct gdbarch
*gdbarch
, CORE_ADDR pc
)
104 /* Guess where we might be in the sequence. */
105 off
= alpha_linux_sigtramp_offset_1 (gdbarch
, pc
);
109 /* Verify that the other two insns of the sequence are as we expect. */
111 for (i
= 0; i
< 12; i
+= 4)
115 if (alpha_linux_sigtramp_offset_1 (gdbarch
, pc
+ i
) != i
)
123 alpha_linux_pc_in_sigtramp (struct gdbarch
*gdbarch
,
124 CORE_ADDR pc
, const char *func_name
)
126 return alpha_linux_sigtramp_offset (gdbarch
, pc
) >= 0;
130 alpha_linux_sigcontext_addr (struct frame_info
*this_frame
)
132 struct gdbarch
*gdbarch
= get_frame_arch (this_frame
);
137 pc
= get_frame_pc (this_frame
);
138 sp
= get_frame_register_unsigned (this_frame
, ALPHA_SP_REGNUM
);
140 off
= alpha_linux_sigtramp_offset (gdbarch
, pc
);
141 gdb_assert (off
>= 0);
143 /* __NR_rt_sigreturn has a couple of structures on the stack. This is:
150 offsetof (struct rt_sigframe, uc.uc_mcontext); */
152 if (alpha_read_insn (gdbarch
, pc
- off
+ 4) == 0x201f015f)
155 /* __NR_sigreturn has the sigcontext structure at the top of the stack. */
159 /* Supply register REGNUM from the buffer specified by GREGS and LEN
160 in the general-purpose register set REGSET to register cache
161 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
164 alpha_linux_supply_gregset (const struct regset
*regset
,
165 struct regcache
*regcache
,
166 int regnum
, const void *gregs
, size_t len
)
168 const gdb_byte
*regs
= (const gdb_byte
*) gregs
;
170 gdb_assert (len
>= 32 * 8);
171 alpha_supply_int_regs (regcache
, regnum
, regs
, regs
+ 31 * 8,
172 len
>= 33 * 8 ? regs
+ 32 * 8 : NULL
);
175 /* Collect register REGNUM from the register cache REGCACHE and store
176 it in the buffer specified by GREGS and LEN as described by the
177 general-purpose register set REGSET. If REGNUM is -1, do this for
178 all registers in REGSET. */
181 alpha_linux_collect_gregset (const struct regset
*regset
,
182 const struct regcache
*regcache
,
183 int regnum
, void *gregs
, size_t len
)
185 gdb_byte
*regs
= (gdb_byte
*) gregs
;
187 gdb_assert (len
>= 32 * 8);
188 alpha_fill_int_regs (regcache
, regnum
, regs
, regs
+ 31 * 8,
189 len
>= 33 * 8 ? regs
+ 32 * 8 : NULL
);
192 /* Supply register REGNUM from the buffer specified by FPREGS and LEN
193 in the floating-point register set REGSET to register cache
194 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
197 alpha_linux_supply_fpregset (const struct regset
*regset
,
198 struct regcache
*regcache
,
199 int regnum
, const void *fpregs
, size_t len
)
201 const gdb_byte
*regs
= (const gdb_byte
*) fpregs
;
203 gdb_assert (len
>= 32 * 8);
204 alpha_supply_fp_regs (regcache
, regnum
, regs
, regs
+ 31 * 8);
207 /* Collect register REGNUM from the register cache REGCACHE and store
208 it in the buffer specified by FPREGS and LEN as described by the
209 general-purpose register set REGSET. If REGNUM is -1, do this for
210 all registers in REGSET. */
213 alpha_linux_collect_fpregset (const struct regset
*regset
,
214 const struct regcache
*regcache
,
215 int regnum
, void *fpregs
, size_t len
)
217 gdb_byte
*regs
= (gdb_byte
*) fpregs
;
219 gdb_assert (len
>= 32 * 8);
220 alpha_fill_fp_regs (regcache
, regnum
, regs
, regs
+ 31 * 8);
223 static const struct regset alpha_linux_gregset
=
226 alpha_linux_supply_gregset
, alpha_linux_collect_gregset
229 static const struct regset alpha_linux_fpregset
=
232 alpha_linux_supply_fpregset
, alpha_linux_collect_fpregset
235 /* Iterate over core file register note sections. */
238 alpha_linux_iterate_over_regset_sections (struct gdbarch
*gdbarch
,
239 iterate_over_regset_sections_cb
*cb
,
241 const struct regcache
*regcache
)
243 cb (".reg", 32 * 8, 32 * 8, &alpha_linux_gregset
, NULL
, cb_data
);
244 cb (".reg2", 32 * 8, 32 * 8, &alpha_linux_fpregset
, NULL
, cb_data
);
247 /* Implementation of `gdbarch_gdb_signal_from_target', as defined in
250 static enum gdb_signal
251 alpha_linux_gdb_signal_from_target (struct gdbarch
*gdbarch
,
256 case ALPHA_LINUX_SIGEMT
:
257 return GDB_SIGNAL_EMT
;
259 case ALPHA_LINUX_SIGBUS
:
260 return GDB_SIGNAL_BUS
;
262 case ALPHA_LINUX_SIGSYS
:
263 return GDB_SIGNAL_SYS
;
265 case ALPHA_LINUX_SIGURG
:
266 return GDB_SIGNAL_URG
;
268 case ALPHA_LINUX_SIGSTOP
:
269 return GDB_SIGNAL_STOP
;
271 case ALPHA_LINUX_SIGTSTP
:
272 return GDB_SIGNAL_TSTP
;
274 case ALPHA_LINUX_SIGCONT
:
275 return GDB_SIGNAL_CONT
;
277 case ALPHA_LINUX_SIGCHLD
:
278 return GDB_SIGNAL_CHLD
;
280 /* No way to differentiate between SIGIO and SIGPOLL.
281 Therefore, we just handle the first one. */
282 case ALPHA_LINUX_SIGIO
:
283 return GDB_SIGNAL_IO
;
285 /* No way to differentiate between SIGINFO and SIGPWR.
286 Therefore, we just handle the first one. */
287 case ALPHA_LINUX_SIGINFO
:
288 return GDB_SIGNAL_INFO
;
290 case ALPHA_LINUX_SIGUSR1
:
291 return GDB_SIGNAL_USR1
;
293 case ALPHA_LINUX_SIGUSR2
:
294 return GDB_SIGNAL_USR2
;
297 return linux_gdb_signal_from_target (gdbarch
, signal
);
300 /* Implementation of `gdbarch_gdb_signal_to_target', as defined in
304 alpha_linux_gdb_signal_to_target (struct gdbarch
*gdbarch
,
305 enum gdb_signal signal
)
310 return ALPHA_LINUX_SIGEMT
;
313 return ALPHA_LINUX_SIGBUS
;
316 return ALPHA_LINUX_SIGSYS
;
319 return ALPHA_LINUX_SIGURG
;
321 case GDB_SIGNAL_STOP
:
322 return ALPHA_LINUX_SIGSTOP
;
324 case GDB_SIGNAL_TSTP
:
325 return ALPHA_LINUX_SIGTSTP
;
327 case GDB_SIGNAL_CONT
:
328 return ALPHA_LINUX_SIGCONT
;
330 case GDB_SIGNAL_CHLD
:
331 return ALPHA_LINUX_SIGCHLD
;
334 return ALPHA_LINUX_SIGIO
;
336 case GDB_SIGNAL_INFO
:
337 return ALPHA_LINUX_SIGINFO
;
339 case GDB_SIGNAL_USR1
:
340 return ALPHA_LINUX_SIGUSR1
;
342 case GDB_SIGNAL_USR2
:
343 return ALPHA_LINUX_SIGUSR2
;
345 case GDB_SIGNAL_POLL
:
346 return ALPHA_LINUX_SIGPOLL
;
349 return ALPHA_LINUX_SIGPWR
;
352 return linux_gdb_signal_to_target (gdbarch
, signal
);
356 alpha_linux_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
358 struct gdbarch_tdep
*tdep
;
360 linux_init_abi (info
, gdbarch
);
362 /* Hook into the DWARF CFI frame unwinder. */
363 alpha_dwarf2_init_abi (info
, gdbarch
);
365 /* Hook into the MDEBUG frame unwinder. */
366 alpha_mdebug_init_abi (info
, gdbarch
);
368 tdep
= gdbarch_tdep (gdbarch
);
369 tdep
->dynamic_sigtramp_offset
= alpha_linux_sigtramp_offset
;
370 tdep
->sigcontext_addr
= alpha_linux_sigcontext_addr
;
371 tdep
->pc_in_sigtramp
= alpha_linux_pc_in_sigtramp
;
373 tdep
->jb_elt_size
= 8;
375 set_gdbarch_skip_trampoline_code (gdbarch
, find_solib_trampoline_target
);
377 set_solib_svr4_fetch_link_map_offsets
378 (gdbarch
, svr4_lp64_fetch_link_map_offsets
);
380 /* Enable TLS support. */
381 set_gdbarch_fetch_tls_load_module_address (gdbarch
,
382 svr4_fetch_objfile_link_map
);
384 set_gdbarch_iterate_over_regset_sections
385 (gdbarch
, alpha_linux_iterate_over_regset_sections
);
387 set_gdbarch_gdb_signal_from_target (gdbarch
,
388 alpha_linux_gdb_signal_from_target
);
389 set_gdbarch_gdb_signal_to_target (gdbarch
,
390 alpha_linux_gdb_signal_to_target
);
394 _initialize_alpha_linux_tdep (void)
396 gdbarch_register_osabi (bfd_arch_alpha
, 0, GDB_OSABI_LINUX
,
397 alpha_linux_init_abi
);