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