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/>. */
24 #include "glibc-tdep.h"
25 #include "linux-tdep.h"
26 #include "aarch64-tdep.h"
27 #include "aarch64-linux-tdep.h"
29 #include "solib-svr4.h"
31 #include "tramp-frame.h"
32 #include "trad-frame.h"
38 #include "cli/cli-utils.h"
39 #include "stap-probe.h"
40 #include "parser-defs.h"
41 #include "user-regs.h"
44 /* Signal frame handling.
59 | | | SIGTRAMP_FRAME (struct rt_sigframe)
61 +--| saved sp |--> interrupted_sp
62 | | saved pc |--> interrupted_pc
65 | | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
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:
86 The ucontext has the following form:
89 unsigned long uc_flags;
90 struct ucontext *uc_link;
93 struct sigcontext uc_mcontext;
96 typedef struct sigaltstack
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
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. */
136 aarch64_linux_sigframe_init (const struct tramp_frame
*self
,
137 struct frame_info
*this_frame
,
138 struct trad_frame_cache
*this_cache
,
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
;
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
=
171 /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8)
172 Soo1 0010 1hhi iiii iiii iiii iiir rrrr */
175 /* svc 0x0 (o=0, l=1)
176 1101 0100 oooi iiii iiii iiii iii0 00ll */
178 {TRAMP_SENTINEL_INSN
, -1}
180 aarch64_linux_sigframe_init
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 },
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 },
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. */
219 aarch64_linux_iterate_over_regset_sections (struct gdbarch
*gdbarch
,
220 iterate_over_regset_sections_cb
*cb
,
222 const struct regcache
*regcache
)
224 cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET
, &aarch64_linux_gregset
,
226 cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET
, &aarch64_linux_fpregset
,
230 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
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. */
251 aarch64_stap_parse_special_token (struct gdbarch
*gdbarch
,
252 struct stap_parse_info
*p
)
256 /* Temporary holder for lookahead. */
257 const char *tmp
= p
->arg
;
259 /* Used to save the register name. */
271 while (isalnum (*tmp
))
278 regname
= alloca (len
+ 2);
280 strncpy (regname
, start
, len
);
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
);
288 tmp
= skip_spaces_const (tmp
);
289 /* Now we expect a number. It can begin with '#' or simply
299 else if (*tmp
== '+')
305 displacement
= strtol (tmp
, &endp
, 10);
308 /* Skipping last `]'. */
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
);
318 write_exp_elt_opcode (&p
->pstate
, UNOP_NEG
);
320 /* The register name. */
321 write_exp_elt_opcode (&p
->pstate
, OP_REGISTER
);
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
);
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
[] = { "[",
351 static const char *const stap_register_indirection_suffixes
[] = { "]",
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. */
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
;
394 _initialize_aarch64_linux_tdep (void)
396 gdbarch_register_osabi (bfd_arch_aarch64
, 0, GDB_OSABI_LINUX
,
397 aarch64_linux_init_abi
);