x86: Move x86-specific linker options to elf_linker_x86_params
[deliverable/binutils-gdb.git] / gdb / alpha-linux-tdep.c
1 /* Target-dependent code for GNU/Linux on Alpha.
2 Copyright (C) 2002-2019 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
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.
10
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.
15
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/>. */
18
19 #include "defs.h"
20
21 /* Local non-gdb includes. */
22 #include "alpha-tdep.h"
23 #include "frame.h"
24 #include "linux-tdep.h"
25 #include "osabi.h"
26 #include "regcache.h"
27 #include "regset.h"
28 #include "solib-svr4.h"
29 #include "symtab.h"
30
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.
34
35 It is derived from the file <arch/alpha/include/uapi/asm/signal.h>,
36 from the Linux kernel tree. */
37
38 enum
39 {
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,
58 };
59
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.
65
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
70 syscall number,
71 (3) there is a "normal" sigreturn and an "rt" sigreturn which
72 has a different stack layout. */
73
74 static long
75 alpha_linux_sigtramp_offset_1 (struct gdbarch *gdbarch, CORE_ADDR pc)
76 {
77 switch (alpha_read_insn (gdbarch, pc))
78 {
79 case 0x47de0410: /* bis $30,$30,$16 */
80 case 0x47fe0410: /* bis $31,$30,$16 */
81 return 0;
82
83 case 0x43ecf400: /* addq $31,103,$0 */
84 case 0x201f0067: /* lda $0,103($31) */
85 case 0x201f015f: /* lda $0,351($31) */
86 return 4;
87
88 case 0x00000083: /* call_pal callsys */
89 return 8;
90
91 default:
92 return -1;
93 }
94 }
95
96 static LONGEST
97 alpha_linux_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc)
98 {
99 long i, off;
100
101 if (pc & 3)
102 return -1;
103
104 /* Guess where we might be in the sequence. */
105 off = alpha_linux_sigtramp_offset_1 (gdbarch, pc);
106 if (off < 0)
107 return -1;
108
109 /* Verify that the other two insns of the sequence are as we expect. */
110 pc -= off;
111 for (i = 0; i < 12; i += 4)
112 {
113 if (i == off)
114 continue;
115 if (alpha_linux_sigtramp_offset_1 (gdbarch, pc + i) != i)
116 return -1;
117 }
118
119 return off;
120 }
121
122 static int
123 alpha_linux_pc_in_sigtramp (struct gdbarch *gdbarch,
124 CORE_ADDR pc, const char *func_name)
125 {
126 return alpha_linux_sigtramp_offset (gdbarch, pc) >= 0;
127 }
128
129 static CORE_ADDR
130 alpha_linux_sigcontext_addr (struct frame_info *this_frame)
131 {
132 struct gdbarch *gdbarch = get_frame_arch (this_frame);
133 CORE_ADDR pc;
134 ULONGEST sp;
135 long off;
136
137 pc = get_frame_pc (this_frame);
138 sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM);
139
140 off = alpha_linux_sigtramp_offset (gdbarch, pc);
141 gdb_assert (off >= 0);
142
143 /* __NR_rt_sigreturn has a couple of structures on the stack. This is:
144
145 struct rt_sigframe {
146 struct siginfo info;
147 struct ucontext uc;
148 };
149
150 offsetof (struct rt_sigframe, uc.uc_mcontext); */
151
152 if (alpha_read_insn (gdbarch, pc - off + 4) == 0x201f015f)
153 return sp + 176;
154
155 /* __NR_sigreturn has the sigcontext structure at the top of the stack. */
156 return sp;
157 }
158
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. */
162
163 static void
164 alpha_linux_supply_gregset (const struct regset *regset,
165 struct regcache *regcache,
166 int regnum, const void *gregs, size_t len)
167 {
168 const gdb_byte *regs = (const gdb_byte *) gregs;
169
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);
173 }
174
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. */
179
180 static void
181 alpha_linux_collect_gregset (const struct regset *regset,
182 const struct regcache *regcache,
183 int regnum, void *gregs, size_t len)
184 {
185 gdb_byte *regs = (gdb_byte *) gregs;
186
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);
190 }
191
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. */
195
196 static void
197 alpha_linux_supply_fpregset (const struct regset *regset,
198 struct regcache *regcache,
199 int regnum, const void *fpregs, size_t len)
200 {
201 const gdb_byte *regs = (const gdb_byte *) fpregs;
202
203 gdb_assert (len >= 32 * 8);
204 alpha_supply_fp_regs (regcache, regnum, regs, regs + 31 * 8);
205 }
206
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. */
211
212 static void
213 alpha_linux_collect_fpregset (const struct regset *regset,
214 const struct regcache *regcache,
215 int regnum, void *fpregs, size_t len)
216 {
217 gdb_byte *regs = (gdb_byte *) fpregs;
218
219 gdb_assert (len >= 32 * 8);
220 alpha_fill_fp_regs (regcache, regnum, regs, regs + 31 * 8);
221 }
222
223 static const struct regset alpha_linux_gregset =
224 {
225 NULL,
226 alpha_linux_supply_gregset, alpha_linux_collect_gregset
227 };
228
229 static const struct regset alpha_linux_fpregset =
230 {
231 NULL,
232 alpha_linux_supply_fpregset, alpha_linux_collect_fpregset
233 };
234
235 /* Iterate over core file register note sections. */
236
237 static void
238 alpha_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
239 iterate_over_regset_sections_cb *cb,
240 void *cb_data,
241 const struct regcache *regcache)
242 {
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);
245 }
246
247 /* Implementation of `gdbarch_gdb_signal_from_target', as defined in
248 gdbarch.h. */
249
250 static enum gdb_signal
251 alpha_linux_gdb_signal_from_target (struct gdbarch *gdbarch,
252 int signal)
253 {
254 switch (signal)
255 {
256 case ALPHA_LINUX_SIGEMT:
257 return GDB_SIGNAL_EMT;
258
259 case ALPHA_LINUX_SIGBUS:
260 return GDB_SIGNAL_BUS;
261
262 case ALPHA_LINUX_SIGSYS:
263 return GDB_SIGNAL_SYS;
264
265 case ALPHA_LINUX_SIGURG:
266 return GDB_SIGNAL_URG;
267
268 case ALPHA_LINUX_SIGSTOP:
269 return GDB_SIGNAL_STOP;
270
271 case ALPHA_LINUX_SIGTSTP:
272 return GDB_SIGNAL_TSTP;
273
274 case ALPHA_LINUX_SIGCONT:
275 return GDB_SIGNAL_CONT;
276
277 case ALPHA_LINUX_SIGCHLD:
278 return GDB_SIGNAL_CHLD;
279
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;
284
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;
289
290 case ALPHA_LINUX_SIGUSR1:
291 return GDB_SIGNAL_USR1;
292
293 case ALPHA_LINUX_SIGUSR2:
294 return GDB_SIGNAL_USR2;
295 }
296
297 return linux_gdb_signal_from_target (gdbarch, signal);
298 }
299
300 /* Implementation of `gdbarch_gdb_signal_to_target', as defined in
301 gdbarch.h. */
302
303 static int
304 alpha_linux_gdb_signal_to_target (struct gdbarch *gdbarch,
305 enum gdb_signal signal)
306 {
307 switch (signal)
308 {
309 case GDB_SIGNAL_EMT:
310 return ALPHA_LINUX_SIGEMT;
311
312 case GDB_SIGNAL_BUS:
313 return ALPHA_LINUX_SIGBUS;
314
315 case GDB_SIGNAL_SYS:
316 return ALPHA_LINUX_SIGSYS;
317
318 case GDB_SIGNAL_URG:
319 return ALPHA_LINUX_SIGURG;
320
321 case GDB_SIGNAL_STOP:
322 return ALPHA_LINUX_SIGSTOP;
323
324 case GDB_SIGNAL_TSTP:
325 return ALPHA_LINUX_SIGTSTP;
326
327 case GDB_SIGNAL_CONT:
328 return ALPHA_LINUX_SIGCONT;
329
330 case GDB_SIGNAL_CHLD:
331 return ALPHA_LINUX_SIGCHLD;
332
333 case GDB_SIGNAL_IO:
334 return ALPHA_LINUX_SIGIO;
335
336 case GDB_SIGNAL_INFO:
337 return ALPHA_LINUX_SIGINFO;
338
339 case GDB_SIGNAL_USR1:
340 return ALPHA_LINUX_SIGUSR1;
341
342 case GDB_SIGNAL_USR2:
343 return ALPHA_LINUX_SIGUSR2;
344
345 case GDB_SIGNAL_POLL:
346 return ALPHA_LINUX_SIGPOLL;
347
348 case GDB_SIGNAL_PWR:
349 return ALPHA_LINUX_SIGPWR;
350 }
351
352 return linux_gdb_signal_to_target (gdbarch, signal);
353 }
354
355 static void
356 alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
357 {
358 struct gdbarch_tdep *tdep;
359
360 linux_init_abi (info, gdbarch);
361
362 /* Hook into the DWARF CFI frame unwinder. */
363 alpha_dwarf2_init_abi (info, gdbarch);
364
365 /* Hook into the MDEBUG frame unwinder. */
366 alpha_mdebug_init_abi (info, gdbarch);
367
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;
372 tdep->jb_pc = 2;
373 tdep->jb_elt_size = 8;
374
375 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
376
377 set_solib_svr4_fetch_link_map_offsets
378 (gdbarch, svr4_lp64_fetch_link_map_offsets);
379
380 /* Enable TLS support. */
381 set_gdbarch_fetch_tls_load_module_address (gdbarch,
382 svr4_fetch_objfile_link_map);
383
384 set_gdbarch_iterate_over_regset_sections
385 (gdbarch, alpha_linux_iterate_over_regset_sections);
386
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);
391 }
392
393 void
394 _initialize_alpha_linux_tdep (void)
395 {
396 gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_LINUX,
397 alpha_linux_init_abi);
398 }
This page took 0.05174 seconds and 5 git commands to generate.