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