AARCH64 Linux: Fill 'collect_regset' in regset structures.
[external/binutils.git] / gdb / aarch64-linux-tdep.c
1 /* Target-dependent code for GNU/Linux AArch64.
2
3    Copyright (C) 2009-2014 Free Software Foundation, Inc.
4    Contributed by ARM Ltd.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22
23 #include "gdbarch.h"
24 #include "glibc-tdep.h"
25 #include "linux-tdep.h"
26 #include "aarch64-tdep.h"
27 #include "aarch64-linux-tdep.h"
28 #include "osabi.h"
29 #include "solib-svr4.h"
30 #include "symtab.h"
31 #include "tramp-frame.h"
32 #include "trad-frame.h"
33
34 #include "inferior.h"
35 #include "regcache.h"
36 #include "regset.h"
37
38 #include "cli/cli-utils.h"
39 #include "stap-probe.h"
40 #include "parser-defs.h"
41 #include "user-regs.h"
42 #include <ctype.h>
43
44 /* Signal frame handling.
45
46       +------------+  ^
47       | saved lr   |  |
48    +->| saved fp   |--+
49    |  |            |
50    |  |            |
51    |  +------------+
52    |  | saved lr   |
53    +--| saved fp   |
54    ^  |            |
55    |  |            |
56    |  +------------+
57    ^  |            |
58    |  | signal     |
59    |  |            |        SIGTRAMP_FRAME (struct rt_sigframe)
60    |  | saved regs |
61    +--| saved sp   |--> interrupted_sp
62    |  | saved pc   |--> interrupted_pc
63    |  |            |
64    |  +------------+
65    |  | saved lr   |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
66    +--| saved fp   |<- FP
67       |            |         NORMAL_FRAME
68       |            |<- SP
69       +------------+
70
71   On signal delivery, the kernel will create a signal handler stack
72   frame and setup the return address in LR to point at restorer stub.
73   The signal stack frame is defined by:
74
75   struct rt_sigframe
76   {
77     siginfo_t info;
78     struct ucontext uc;
79   };
80
81   typedef struct
82   {
83     ...                                    128 bytes
84   } siginfo_t;
85
86   The ucontext has the following form:
87   struct ucontext
88   {
89     unsigned long uc_flags;
90     struct ucontext *uc_link;
91     stack_t uc_stack;
92     sigset_t uc_sigmask;
93     struct sigcontext uc_mcontext;
94   };
95
96   typedef struct sigaltstack
97   {
98     void *ss_sp;
99     int ss_flags;
100     size_t ss_size;
101   } stack_t;
102
103   struct sigcontext
104   {
105     unsigned long fault_address;
106     unsigned long regs[31];
107     unsigned long sp;           / * 31 * /
108     unsigned long pc;           / * 32 * /
109     unsigned long pstate;       / * 33 * /
110     __u8 __reserved[4096]
111   };
112
113   The restorer stub will always have the form:
114
115   d28015a8        movz    x8, #0xad
116   d4000001        svc     #0x0
117
118   This is a system call sys_rt_sigreturn.
119
120   We detect signal frames by snooping the return code for the restorer
121   instruction sequence.
122
123   The handler then needs to recover the saved register set from
124   ucontext.uc_mcontext.  */
125
126 /* These magic numbers need to reflect the layout of the kernel
127    defined struct rt_sigframe and ucontext.  */
128 #define AARCH64_SIGCONTEXT_REG_SIZE             8
129 #define AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET     128
130 #define AARCH64_UCONTEXT_SIGCONTEXT_OFFSET      176
131 #define AARCH64_SIGCONTEXT_XO_OFFSET            8
132
133 /* Implement the "init" method of struct tramp_frame.  */
134
135 static void
136 aarch64_linux_sigframe_init (const struct tramp_frame *self,
137                              struct frame_info *this_frame,
138                              struct trad_frame_cache *this_cache,
139                              CORE_ADDR func)
140 {
141   struct gdbarch *gdbarch = get_frame_arch (this_frame);
142   CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
143   CORE_ADDR sigcontext_addr =
144     sp
145     + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
146     + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET;
147   int i;
148
149   for (i = 0; i < 31; i++)
150     {
151       trad_frame_set_reg_addr (this_cache,
152                                AARCH64_X0_REGNUM + i,
153                                sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
154                                + i * AARCH64_SIGCONTEXT_REG_SIZE);
155     }
156   trad_frame_set_reg_addr (this_cache, AARCH64_SP_REGNUM,
157                            sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
158                              + 31 * AARCH64_SIGCONTEXT_REG_SIZE);
159   trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM,
160                            sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
161                              + 32 * AARCH64_SIGCONTEXT_REG_SIZE);
162
163   trad_frame_set_id (this_cache, frame_id_build (sp, func));
164 }
165
166 static const struct tramp_frame aarch64_linux_rt_sigframe =
167 {
168   SIGTRAMP_FRAME,
169   4,
170   {
171     /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8)
172        Soo1 0010 1hhi iiii iiii iiii iiir rrrr  */
173     {0xd2801168, -1},
174
175     /* svc  0x0      (o=0, l=1)
176        1101 0100 oooi iiii iiii iiii iii0 00ll  */
177     {0xd4000001, -1},
178     {TRAMP_SENTINEL_INSN, -1}
179   },
180   aarch64_linux_sigframe_init
181 };
182
183 /* Register maps.  */
184
185 static const struct regcache_map_entry aarch64_linux_gregmap[] =
186   {
187     { 31, AARCH64_X0_REGNUM, 8 }, /* x0 ... x30 */
188     { 1, AARCH64_SP_REGNUM, 8 },
189     { 1, AARCH64_PC_REGNUM, 8 },
190     { 1, AARCH64_CPSR_REGNUM, 8 },
191     { 0 }
192   };
193
194 static const struct regcache_map_entry aarch64_linux_fpregmap[] =
195   {
196     { 32, AARCH64_V0_REGNUM, 16 }, /* v0 ... v31 */
197     { 1, AARCH64_FPSR_REGNUM, 4 },
198     { 1, AARCH64_FPCR_REGNUM, 4 },
199     { 0 }
200   };
201
202 /* Register set definitions.  */
203
204 const struct regset aarch64_linux_gregset =
205   {
206     aarch64_linux_gregmap,
207     regcache_supply_regset, regcache_collect_regset
208   };
209
210 const struct regset aarch64_linux_fpregset =
211   {
212     aarch64_linux_fpregmap,
213     regcache_supply_regset, regcache_collect_regset
214   };
215
216 /* Implement the "regset_from_core_section" gdbarch method.  */
217
218 static const struct regset *
219 aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch,
220                                         const char *sect_name,
221                                         size_t sect_size)
222 {
223   if (strcmp (sect_name, ".reg") == 0
224       && sect_size == AARCH64_LINUX_SIZEOF_GREGSET)
225     return &aarch64_linux_gregset;
226
227   if (strcmp (sect_name, ".reg2") == 0
228       && sect_size == AARCH64_LINUX_SIZEOF_FPREGSET)
229     return &aarch64_linux_fpregset;
230
231   return NULL;
232 }
233
234 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
235    gdbarch.h.  */
236
237 static int
238 aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
239 {
240   return (*s == '#' || isdigit (*s) /* Literal number.  */
241           || *s == '[' /* Register indirection.  */
242           || isalpha (*s)); /* Register value.  */
243 }
244
245 /* This routine is used to parse a special token in AArch64's assembly.
246
247    The special tokens parsed by it are:
248
249       - Register displacement (e.g, [fp, #-8])
250
251    It returns one if the special token has been parsed successfully,
252    or zero if the current token is not considered special.  */
253
254 static int
255 aarch64_stap_parse_special_token (struct gdbarch *gdbarch,
256                                   struct stap_parse_info *p)
257 {
258   if (*p->arg == '[')
259     {
260       /* Temporary holder for lookahead.  */
261       const char *tmp = p->arg;
262       char *endp;
263       /* Used to save the register name.  */
264       const char *start;
265       char *regname;
266       int len;
267       int got_minus = 0;
268       long displacement;
269       struct stoken str;
270
271       ++tmp;
272       start = tmp;
273
274       /* Register name.  */
275       while (isalnum (*tmp))
276         ++tmp;
277
278       if (*tmp != ',')
279         return 0;
280
281       len = tmp - start;
282       regname = alloca (len + 2);
283
284       strncpy (regname, start, len);
285       regname[len] = '\0';
286
287       if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1)
288         error (_("Invalid register name `%s' on expression `%s'."),
289                regname, p->saved_arg);
290
291       ++tmp;
292       tmp = skip_spaces_const (tmp);
293       /* Now we expect a number.  It can begin with '#' or simply
294          a digit.  */
295       if (*tmp == '#')
296         ++tmp;
297
298       if (*tmp == '-')
299         {
300           ++tmp;
301           got_minus = 1;
302         }
303       else if (*tmp == '+')
304         ++tmp;
305
306       if (!isdigit (*tmp))
307         return 0;
308
309       displacement = strtol (tmp, &endp, 10);
310       tmp = endp;
311
312       /* Skipping last `]'.  */
313       if (*tmp++ != ']')
314         return 0;
315
316       /* The displacement.  */
317       write_exp_elt_opcode (&p->pstate, OP_LONG);
318       write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long);
319       write_exp_elt_longcst (&p->pstate, displacement);
320       write_exp_elt_opcode (&p->pstate, OP_LONG);
321       if (got_minus)
322         write_exp_elt_opcode (&p->pstate, UNOP_NEG);
323
324       /* The register name.  */
325       write_exp_elt_opcode (&p->pstate, OP_REGISTER);
326       str.ptr = regname;
327       str.length = len;
328       write_exp_string (&p->pstate, str);
329       write_exp_elt_opcode (&p->pstate, OP_REGISTER);
330
331       write_exp_elt_opcode (&p->pstate, BINOP_ADD);
332
333       /* Casting to the expected type.  */
334       write_exp_elt_opcode (&p->pstate, UNOP_CAST);
335       write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type));
336       write_exp_elt_opcode (&p->pstate, UNOP_CAST);
337
338       write_exp_elt_opcode (&p->pstate, UNOP_IND);
339
340       p->arg = tmp;
341     }
342   else
343     return 0;
344
345   return 1;
346 }
347
348 static void
349 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
350 {
351   static const char *const stap_integer_prefixes[] = { "#", "", NULL };
352   static const char *const stap_register_prefixes[] = { "", NULL };
353   static const char *const stap_register_indirection_prefixes[] = { "[",
354                                                                     NULL };
355   static const char *const stap_register_indirection_suffixes[] = { "]",
356                                                                     NULL };
357   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
358
359   tdep->lowest_pc = 0x8000;
360
361   linux_init_abi (info, gdbarch);
362
363   set_solib_svr4_fetch_link_map_offsets (gdbarch,
364                                          svr4_lp64_fetch_link_map_offsets);
365
366   /* Enable TLS support.  */
367   set_gdbarch_fetch_tls_load_module_address (gdbarch,
368                                              svr4_fetch_objfile_link_map);
369
370   /* Shared library handling.  */
371   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
372
373   set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
374   tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
375
376   /* Enable longjmp.  */
377   tdep->jb_pc = 11;
378
379   set_gdbarch_regset_from_core_section (gdbarch,
380                                         aarch64_linux_regset_from_core_section);
381
382   /* SystemTap related.  */
383   set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
384   set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
385   set_gdbarch_stap_register_indirection_prefixes (gdbarch,
386                                             stap_register_indirection_prefixes);
387   set_gdbarch_stap_register_indirection_suffixes (gdbarch,
388                                             stap_register_indirection_suffixes);
389   set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand);
390   set_gdbarch_stap_parse_special_token (gdbarch,
391                                         aarch64_stap_parse_special_token);
392 }
393
394 /* Provide a prototype to silence -Wmissing-prototypes.  */
395 extern initialize_file_ftype _initialize_aarch64_linux_tdep;
396
397 void
398 _initialize_aarch64_linux_tdep (void)
399 {
400   gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
401                           aarch64_linux_init_abi);
402 }