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
);