AARCH64: Migrate from 'regset_from_core_section' to 'iterate_over_regset_sections'
[binutils-gdb.git] / gdb / aarch64-linux-tdep.c
blob804e767f094fbc63671bc204f378478bee734f78
1 /* Target-dependent code for GNU/Linux AArch64.
3 Copyright (C) 2009-2014 Free Software Foundation, Inc.
4 Contributed by ARM Ltd.
6 This file is part of GDB.
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.
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.
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/>. */
21 #include "defs.h"
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"
34 #include "inferior.h"
35 #include "regcache.h"
36 #include "regset.h"
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>
44 /* Signal frame handling.
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 +------------+
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:
75 struct rt_sigframe
77 siginfo_t info;
78 struct ucontext uc;
81 typedef struct
83 ... 128 bytes
84 } siginfo_t;
86 The ucontext has the following form:
87 struct ucontext
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;
96 typedef struct sigaltstack
98 void *ss_sp;
99 int ss_flags;
100 size_t ss_size;
101 } stack_t;
103 struct sigcontext
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]
113 The restorer stub will always have the form:
115 d28015a8 movz x8, #0xad
116 d4000001 svc #0x0
118 This is a system call sys_rt_sigreturn.
120 We detect signal frames by snooping the return code for the restorer
121 instruction sequence.
123 The handler then needs to recover the saved register set from
124 ucontext.uc_mcontext. */
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
133 /* Implement the "init" method of struct tramp_frame. */
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)
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 =
145 + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
146 + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET;
147 int i;
149 for (i = 0; i < 31; i++)
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);
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);
163 trad_frame_set_id (this_cache, frame_id_build (sp, func));
166 static const struct tramp_frame aarch64_linux_rt_sigframe =
168 SIGTRAMP_FRAME,
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},
175 /* svc 0x0 (o=0, l=1)
176 1101 0100 oooi iiii iiii iiii iii0 00ll */
177 {0xd4000001, -1},
178 {TRAMP_SENTINEL_INSN, -1}
180 aarch64_linux_sigframe_init
183 /* Register maps. */
185 static const struct regcache_map_entry aarch64_linux_gregmap[] =
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 }
194 static const struct regcache_map_entry aarch64_linux_fpregmap[] =
196 { 32, AARCH64_V0_REGNUM, 16 }, /* v0 ... v31 */
197 { 1, AARCH64_FPSR_REGNUM, 4 },
198 { 1, AARCH64_FPCR_REGNUM, 4 },
199 { 0 }
202 /* Register set definitions. */
204 const struct regset aarch64_linux_gregset =
206 aarch64_linux_gregmap,
207 regcache_supply_regset, regcache_collect_regset
210 const struct regset aarch64_linux_fpregset =
212 aarch64_linux_fpregmap,
213 regcache_supply_regset, regcache_collect_regset
216 /* Implement the "regset_from_core_section" gdbarch method. */
218 static void
219 aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
220 iterate_over_regset_sections_cb *cb,
221 void *cb_data,
222 const struct regcache *regcache)
224 cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, &aarch64_linux_gregset,
225 NULL, cb_data);
226 cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, &aarch64_linux_fpregset,
227 NULL, cb_data);
230 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
231 gdbarch.h. */
233 static int
234 aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
236 return (*s == '#' || isdigit (*s) /* Literal number. */
237 || *s == '[' /* Register indirection. */
238 || isalpha (*s)); /* Register value. */
241 /* This routine is used to parse a special token in AArch64's assembly.
243 The special tokens parsed by it are:
245 - Register displacement (e.g, [fp, #-8])
247 It returns one if the special token has been parsed successfully,
248 or zero if the current token is not considered special. */
250 static int
251 aarch64_stap_parse_special_token (struct gdbarch *gdbarch,
252 struct stap_parse_info *p)
254 if (*p->arg == '[')
256 /* Temporary holder for lookahead. */
257 const char *tmp = p->arg;
258 char *endp;
259 /* Used to save the register name. */
260 const char *start;
261 char *regname;
262 int len;
263 int got_minus = 0;
264 long displacement;
265 struct stoken str;
267 ++tmp;
268 start = tmp;
270 /* Register name. */
271 while (isalnum (*tmp))
272 ++tmp;
274 if (*tmp != ',')
275 return 0;
277 len = tmp - start;
278 regname = alloca (len + 2);
280 strncpy (regname, start, len);
281 regname[len] = '\0';
283 if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1)
284 error (_("Invalid register name `%s' on expression `%s'."),
285 regname, p->saved_arg);
287 ++tmp;
288 tmp = skip_spaces_const (tmp);
289 /* Now we expect a number. It can begin with '#' or simply
290 a digit. */
291 if (*tmp == '#')
292 ++tmp;
294 if (*tmp == '-')
296 ++tmp;
297 got_minus = 1;
299 else if (*tmp == '+')
300 ++tmp;
302 if (!isdigit (*tmp))
303 return 0;
305 displacement = strtol (tmp, &endp, 10);
306 tmp = endp;
308 /* Skipping last `]'. */
309 if (*tmp++ != ']')
310 return 0;
312 /* The displacement. */
313 write_exp_elt_opcode (&p->pstate, OP_LONG);
314 write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long);
315 write_exp_elt_longcst (&p->pstate, displacement);
316 write_exp_elt_opcode (&p->pstate, OP_LONG);
317 if (got_minus)
318 write_exp_elt_opcode (&p->pstate, UNOP_NEG);
320 /* The register name. */
321 write_exp_elt_opcode (&p->pstate, OP_REGISTER);
322 str.ptr = regname;
323 str.length = len;
324 write_exp_string (&p->pstate, str);
325 write_exp_elt_opcode (&p->pstate, OP_REGISTER);
327 write_exp_elt_opcode (&p->pstate, BINOP_ADD);
329 /* Casting to the expected type. */
330 write_exp_elt_opcode (&p->pstate, UNOP_CAST);
331 write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type));
332 write_exp_elt_opcode (&p->pstate, UNOP_CAST);
334 write_exp_elt_opcode (&p->pstate, UNOP_IND);
336 p->arg = tmp;
338 else
339 return 0;
341 return 1;
344 static void
345 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
347 static const char *const stap_integer_prefixes[] = { "#", "", NULL };
348 static const char *const stap_register_prefixes[] = { "", NULL };
349 static const char *const stap_register_indirection_prefixes[] = { "[",
350 NULL };
351 static const char *const stap_register_indirection_suffixes[] = { "]",
352 NULL };
353 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
355 tdep->lowest_pc = 0x8000;
357 linux_init_abi (info, gdbarch);
359 set_solib_svr4_fetch_link_map_offsets (gdbarch,
360 svr4_lp64_fetch_link_map_offsets);
362 /* Enable TLS support. */
363 set_gdbarch_fetch_tls_load_module_address (gdbarch,
364 svr4_fetch_objfile_link_map);
366 /* Shared library handling. */
367 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
369 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
370 tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
372 /* Enable longjmp. */
373 tdep->jb_pc = 11;
375 set_gdbarch_iterate_over_regset_sections
376 (gdbarch, aarch64_linux_iterate_over_regset_sections);
378 /* SystemTap related. */
379 set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
380 set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
381 set_gdbarch_stap_register_indirection_prefixes (gdbarch,
382 stap_register_indirection_prefixes);
383 set_gdbarch_stap_register_indirection_suffixes (gdbarch,
384 stap_register_indirection_suffixes);
385 set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand);
386 set_gdbarch_stap_parse_special_token (gdbarch,
387 aarch64_stap_parse_special_token);
390 /* Provide a prototype to silence -Wmissing-prototypes. */
391 extern initialize_file_ftype _initialize_aarch64_linux_tdep;
393 void
394 _initialize_aarch64_linux_tdep (void)
396 gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
397 aarch64_linux_init_abi);