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 /* The general-purpose regset consists of 31 X registers, plus SP, PC,
45 and PSTATE registers, as defined in the AArch64 port of the Linux
47 #define AARCH64_LINUX_SIZEOF_GREGSET (34 * X_REGISTER_SIZE)
49 /* The fp regset consists of 32 V registers, plus FPCR and FPSR which
50 are 4 bytes wide each, and the whole structure is padded to 128 bit
52 #define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
54 /* Signal frame handling.
69 | | | SIGTRAMP_FRAME (struct rt_sigframe)
71 +--| saved sp |--> interrupted_sp
72 | | saved pc |--> interrupted_pc
75 | | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
81 On signal delivery, the kernel will create a signal handler stack
82 frame and setup the return address in LR to point at restorer stub.
83 The signal stack frame is defined by:
96 The ucontext has the following form:
99 unsigned long uc_flags;
100 struct ucontext *uc_link;
103 struct sigcontext uc_mcontext;
106 typedef struct sigaltstack
115 unsigned long fault_address;
116 unsigned long regs[31];
117 unsigned long sp; / * 31 * /
118 unsigned long pc; / * 32 * /
119 unsigned long pstate; / * 33 * /
120 __u8 __reserved[4096]
123 The restorer stub will always have the form:
125 d28015a8 movz x8, #0xad
128 This is a system call sys_rt_sigreturn.
130 We detect signal frames by snooping the return code for the restorer
131 instruction sequence.
133 The handler then needs to recover the saved register set from
134 ucontext.uc_mcontext. */
136 /* These magic numbers need to reflect the layout of the kernel
137 defined struct rt_sigframe and ucontext. */
138 #define AARCH64_SIGCONTEXT_REG_SIZE 8
139 #define AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET 128
140 #define AARCH64_UCONTEXT_SIGCONTEXT_OFFSET 176
141 #define AARCH64_SIGCONTEXT_XO_OFFSET 8
143 /* Implement the "init" method of struct tramp_frame. */
146 aarch64_linux_sigframe_init (const struct tramp_frame *self,
147 struct frame_info *this_frame,
148 struct trad_frame_cache *this_cache,
151 struct gdbarch *gdbarch = get_frame_arch (this_frame);
152 CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
153 CORE_ADDR sigcontext_addr =
155 + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
156 + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET;
159 for (i = 0; i < 31; i++)
161 trad_frame_set_reg_addr (this_cache,
162 AARCH64_X0_REGNUM + i,
163 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
164 + i * AARCH64_SIGCONTEXT_REG_SIZE);
166 trad_frame_set_reg_addr (this_cache, AARCH64_SP_REGNUM,
167 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
168 + 31 * AARCH64_SIGCONTEXT_REG_SIZE);
169 trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM,
170 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
171 + 32 * AARCH64_SIGCONTEXT_REG_SIZE);
173 trad_frame_set_id (this_cache, frame_id_build (sp, func));
176 static const struct tramp_frame aarch64_linux_rt_sigframe =
181 /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8)
182 Soo1 0010 1hhi iiii iiii iiii iiir rrrr */
185 /* svc 0x0 (o=0, l=1)
186 1101 0100 oooi iiii iiii iiii iii0 00ll */
188 {TRAMP_SENTINEL_INSN, -1}
190 aarch64_linux_sigframe_init
193 /* Fill GDB's register array with the general-purpose register values
194 in the buffer pointed by GREGS_BUF. */
197 aarch64_linux_supply_gregset (struct regcache *regcache,
198 const gdb_byte *gregs_buf)
202 for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
203 regcache_raw_supply (regcache, regno,
204 gregs_buf + X_REGISTER_SIZE
205 * (regno - AARCH64_X0_REGNUM));
208 /* The "supply_regset" function for the general-purpose register set. */
211 supply_gregset_from_core (const struct regset *regset,
212 struct regcache *regcache,
213 int regnum, const void *regbuf, size_t len)
215 aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
218 /* Fill GDB's register array with the floating-point register values
219 in the buffer pointed by FPREGS_BUF. */
222 aarch64_linux_supply_fpregset (struct regcache *regcache,
223 const gdb_byte *fpregs_buf)
227 for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
228 regcache_raw_supply (regcache, regno,
229 fpregs_buf + V_REGISTER_SIZE
230 * (regno - AARCH64_V0_REGNUM));
232 regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
233 fpregs_buf + V_REGISTER_SIZE * 32);
234 regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
235 fpregs_buf + V_REGISTER_SIZE * 32 + 4);
238 /* The "supply_regset" function for the floating-point register set. */
241 supply_fpregset_from_core (const struct regset *regset,
242 struct regcache *regcache,
243 int regnum, const void *regbuf, size_t len)
245 aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
248 /* Register set definitions. */
250 static const struct regset aarch64_linux_gregset =
252 NULL, supply_gregset_from_core, NULL
255 static const struct regset aarch64_linux_fpregset =
257 NULL, supply_fpregset_from_core, NULL
260 /* Implement the "regset_from_core_section" gdbarch method. */
262 static const struct regset *
263 aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch,
264 const char *sect_name,
267 if (strcmp (sect_name, ".reg") == 0
268 && sect_size == AARCH64_LINUX_SIZEOF_GREGSET)
269 return &aarch64_linux_gregset;
271 if (strcmp (sect_name, ".reg2") == 0
272 && sect_size == AARCH64_LINUX_SIZEOF_FPREGSET)
273 return &aarch64_linux_fpregset;
278 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
282 aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
284 return (*s == '#' || isdigit (*s) /* Literal number. */
285 || *s == '[' /* Register indirection. */
286 || isalpha (*s)); /* Register value. */
289 /* This routine is used to parse a special token in AArch64's assembly.
291 The special tokens parsed by it are:
293 - Register displacement (e.g, [fp, #-8])
295 It returns one if the special token has been parsed successfully,
296 or zero if the current token is not considered special. */
299 aarch64_stap_parse_special_token (struct gdbarch *gdbarch,
300 struct stap_parse_info *p)
304 /* Temporary holder for lookahead. */
305 const char *tmp = p->arg;
307 /* Used to save the register name. */
319 while (isalnum (*tmp))
326 regname = alloca (len + 2);
328 strncpy (regname, start, len);
331 if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1)
332 error (_("Invalid register name `%s' on expression `%s'."),
333 regname, p->saved_arg);
336 tmp = skip_spaces_const (tmp);
337 /* Now we expect a number. It can begin with '#' or simply
347 else if (*tmp == '+')
353 displacement = strtol (tmp, &endp, 10);
356 /* Skipping last `]'. */
360 /* The displacement. */
361 write_exp_elt_opcode (&p->pstate, OP_LONG);
362 write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long);
363 write_exp_elt_longcst (&p->pstate, displacement);
364 write_exp_elt_opcode (&p->pstate, OP_LONG);
366 write_exp_elt_opcode (&p->pstate, UNOP_NEG);
368 /* The register name. */
369 write_exp_elt_opcode (&p->pstate, OP_REGISTER);
372 write_exp_string (&p->pstate, str);
373 write_exp_elt_opcode (&p->pstate, OP_REGISTER);
375 write_exp_elt_opcode (&p->pstate, BINOP_ADD);
377 /* Casting to the expected type. */
378 write_exp_elt_opcode (&p->pstate, UNOP_CAST);
379 write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type));
380 write_exp_elt_opcode (&p->pstate, UNOP_CAST);
382 write_exp_elt_opcode (&p->pstate, UNOP_IND);
393 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
395 static const char *const stap_integer_prefixes[] = { "#", "", NULL };
396 static const char *const stap_register_prefixes[] = { "", NULL };
397 static const char *const stap_register_indirection_prefixes[] = { "[",
399 static const char *const stap_register_indirection_suffixes[] = { "]",
401 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
403 tdep->lowest_pc = 0x8000;
405 linux_init_abi (info, gdbarch);
407 set_solib_svr4_fetch_link_map_offsets (gdbarch,
408 svr4_lp64_fetch_link_map_offsets);
410 /* Enable TLS support. */
411 set_gdbarch_fetch_tls_load_module_address (gdbarch,
412 svr4_fetch_objfile_link_map);
414 /* Shared library handling. */
415 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
417 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
418 tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
420 /* Enable longjmp. */
423 set_gdbarch_regset_from_core_section (gdbarch,
424 aarch64_linux_regset_from_core_section);
426 /* SystemTap related. */
427 set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
428 set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
429 set_gdbarch_stap_register_indirection_prefixes (gdbarch,
430 stap_register_indirection_prefixes);
431 set_gdbarch_stap_register_indirection_suffixes (gdbarch,
432 stap_register_indirection_suffixes);
433 set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand);
434 set_gdbarch_stap_parse_special_token (gdbarch,
435 aarch64_stap_parse_special_token);
438 /* Provide a prototype to silence -Wmissing-prototypes. */
439 extern initialize_file_ftype _initialize_aarch64_linux_tdep;
442 _initialize_aarch64_linux_tdep (void)
444 gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
445 aarch64_linux_init_abi);