Include gdb_assert.h in common-defs.h
[external/binutils.git] / gdb / alpha-linux-tdep.c
1 /* Target-dependent code for GNU/Linux on Alpha.
2    Copyright (C) 2002-2014 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 <string.h>
22 #include "osabi.h"
23 #include "solib-svr4.h"
24 #include "symtab.h"
25 #include "regset.h"
26 #include "regcache.h"
27 #include "linux-tdep.h"
28 #include "alpha-tdep.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 = gregs;
168   int i;
169   gdb_assert (len >= 32 * 8);
170
171   for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
172     {
173       if (regnum == i || regnum == -1)
174         regcache_raw_supply (regcache, i, regs + i * 8);
175     }
176
177   if (regnum == ALPHA_PC_REGNUM || regnum == -1)
178     regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
179
180   if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1)
181     regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM,
182                          len >= 33 * 8 ? regs + 32 * 8 : NULL);
183 }
184
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.  */
188
189 static void
190 alpha_linux_supply_fpregset (const struct regset *regset,
191                              struct regcache *regcache,
192                              int regnum, const void *fpregs, size_t len)
193 {
194   const gdb_byte *regs = fpregs;
195   int i;
196   gdb_assert (len >= 32 * 8);
197
198   for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
199     {
200       if (regnum == i || regnum == -1)
201         regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
202     }
203
204   if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
205     regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8);
206 }
207
208 static const struct regset alpha_linux_gregset =
209 {
210   NULL,
211   alpha_linux_supply_gregset
212 };
213
214 static const struct regset alpha_linux_fpregset =
215 {
216   NULL,
217   alpha_linux_supply_fpregset
218 };
219
220 /* Return the appropriate register set for the core section identified
221    by SECT_NAME and SECT_SIZE.  */
222
223 static const struct regset *
224 alpha_linux_regset_from_core_section (struct gdbarch *gdbarch,
225                                       const char *sect_name, size_t sect_size)
226 {
227   if (strcmp (sect_name, ".reg") == 0 && sect_size >= 32 * 8)
228     return &alpha_linux_gregset;
229
230   if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 32 * 8)
231     return &alpha_linux_fpregset;
232
233   return NULL;
234 }
235
236 /* Implementation of `gdbarch_gdb_signal_from_target', as defined in
237    gdbarch.h.  */
238
239 static enum gdb_signal
240 alpha_linux_gdb_signal_from_target (struct gdbarch *gdbarch,
241                                     int signal)
242 {
243   switch (signal)
244     {
245     case ALPHA_LINUX_SIGEMT:
246       return GDB_SIGNAL_EMT;
247
248     case ALPHA_LINUX_SIGBUS:
249       return GDB_SIGNAL_BUS;
250
251     case ALPHA_LINUX_SIGSYS:
252       return GDB_SIGNAL_SYS;
253
254     case ALPHA_LINUX_SIGURG:
255       return GDB_SIGNAL_URG;
256
257     case ALPHA_LINUX_SIGSTOP:
258       return GDB_SIGNAL_STOP;
259
260     case ALPHA_LINUX_SIGTSTP:
261       return GDB_SIGNAL_TSTP;
262
263     case ALPHA_LINUX_SIGCONT:
264       return GDB_SIGNAL_CONT;
265
266     case ALPHA_LINUX_SIGCHLD:
267       return GDB_SIGNAL_CHLD;
268
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;
273
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;
278
279     case ALPHA_LINUX_SIGUSR1:
280       return GDB_SIGNAL_USR1;
281
282     case ALPHA_LINUX_SIGUSR2:
283       return GDB_SIGNAL_USR2;
284     }
285
286   return linux_gdb_signal_from_target (gdbarch, signal);
287 }
288
289 /* Implementation of `gdbarch_gdb_signal_to_target', as defined in
290    gdbarch.h.  */
291
292 static int
293 alpha_linux_gdb_signal_to_target (struct gdbarch *gdbarch,
294                                   enum gdb_signal signal)
295 {
296   switch (signal)
297     {
298     case GDB_SIGNAL_EMT:
299       return ALPHA_LINUX_SIGEMT;
300
301     case GDB_SIGNAL_BUS:
302       return ALPHA_LINUX_SIGBUS;
303
304     case GDB_SIGNAL_SYS:
305       return ALPHA_LINUX_SIGSYS;
306
307     case GDB_SIGNAL_URG:
308       return ALPHA_LINUX_SIGURG;
309
310     case GDB_SIGNAL_STOP:
311       return ALPHA_LINUX_SIGSTOP;
312
313     case GDB_SIGNAL_TSTP:
314       return ALPHA_LINUX_SIGTSTP;
315
316     case GDB_SIGNAL_CONT:
317       return ALPHA_LINUX_SIGCONT;
318
319     case GDB_SIGNAL_CHLD:
320       return ALPHA_LINUX_SIGCHLD;
321
322     case GDB_SIGNAL_IO:
323       return ALPHA_LINUX_SIGIO;
324
325     case GDB_SIGNAL_INFO:
326       return ALPHA_LINUX_SIGINFO;
327
328     case GDB_SIGNAL_USR1:
329       return ALPHA_LINUX_SIGUSR1;
330
331     case GDB_SIGNAL_USR2:
332       return ALPHA_LINUX_SIGUSR2;
333
334     case GDB_SIGNAL_POLL:
335       return ALPHA_LINUX_SIGPOLL;
336
337     case GDB_SIGNAL_PWR:
338       return ALPHA_LINUX_SIGPWR;
339     }
340
341   return linux_gdb_signal_to_target (gdbarch, signal);
342 }
343
344 static void
345 alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
346 {
347   struct gdbarch_tdep *tdep;
348
349   linux_init_abi (info, gdbarch);
350
351   /* Hook into the DWARF CFI frame unwinder.  */
352   alpha_dwarf2_init_abi (info, gdbarch);
353
354   /* Hook into the MDEBUG frame unwinder.  */
355   alpha_mdebug_init_abi (info, gdbarch);
356
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;
361   tdep->jb_pc = 2;
362   tdep->jb_elt_size = 8;
363
364   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
365
366   set_solib_svr4_fetch_link_map_offsets
367     (gdbarch, svr4_lp64_fetch_link_map_offsets);
368
369   /* Enable TLS support.  */
370   set_gdbarch_fetch_tls_load_module_address (gdbarch,
371                                              svr4_fetch_objfile_link_map);
372
373   set_gdbarch_regset_from_core_section
374     (gdbarch, alpha_linux_regset_from_core_section);
375
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);
380 }
381
382 /* Provide a prototype to silence -Wmissing-prototypes.  */
383 extern initialize_file_ftype _initialize_alpha_linux_tdep;
384
385 void
386 _initialize_alpha_linux_tdep (void)
387 {
388   gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_LINUX,
389                           alpha_linux_init_abi);
390 }