1 /* Target-dependent code for GNU/Linux AArch64.
3 Copyright (C) 2009-2013 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 /* The general-purpose regset consists of 31 X registers, plus SP, PC,
39 and PSTATE registers, as defined in the AArch64 port of the Linux
41 #define AARCH64_LINUX_SIZEOF_GREGSET (34 * X_REGISTER_SIZE)
43 /* The fp regset consists of 32 V registers, plus FPCR and FPSR which
44 are 4 bytes wide each, and the whole structure is padded to 128 bit
46 #define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
48 /* Signal frame handling.
64 | | saved lr |-->interrupted_function_pc
67 | | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
73 On signal delivery, the kernel will create a signal handler stack
74 frame and setup the return address in LR to point at restorer stub.
75 The signal stack frame is defined by:
88 The ucontext has the following form:
91 unsigned long uc_flags;
92 struct ucontext *uc_link;
95 struct sigcontext uc_mcontext;
98 typedef struct sigaltstack
107 unsigned long fault_address;
108 unsigned long regs[31];
109 unsigned long sp; / * 31 * /
110 unsigned long pc; / * 32 * /
111 unsigned long pstate; / * 33 * /
112 __u8 __reserved[4096]
115 The restorer stub will always have the form:
117 d28015a8 movz x8, #0xad
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 fp = get_frame_register_unsigned (this_frame, AARCH64_FP_REGNUM);
144 CORE_ADDR sigcontext_addr =
146 + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
147 + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET;
150 for (i = 0; i < 31; i++)
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);
158 trad_frame_set_reg_addr (this_cache, AARCH64_FP_REGNUM, fp);
159 trad_frame_set_reg_addr (this_cache, AARCH64_LR_REGNUM, fp + 8);
160 trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM, fp + 8);
162 trad_frame_set_id (this_cache, frame_id_build (fp, func));
165 static const struct tramp_frame aarch64_linux_rt_sigframe =
170 /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8)
171 Soo1 0010 1hhi iiii iiii iiii iiir rrrr */
174 /* svc 0x0 (o=0, l=1)
175 1101 0100 oooi iiii iiii iiii iii0 00ll */
177 {TRAMP_SENTINEL_INSN, -1}
179 aarch64_linux_sigframe_init
182 /* Fill GDB's register array with the general-purpose register values
183 in the buffer pointed by GREGS_BUF. */
186 aarch64_linux_supply_gregset (struct regcache *regcache,
187 const gdb_byte *gregs_buf)
191 for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
192 regcache_raw_supply (regcache, regno,
193 gregs_buf + X_REGISTER_SIZE
194 * (regno - AARCH64_X0_REGNUM));
197 /* The "supply_regset" function for the general-purpose register set. */
200 supply_gregset_from_core (const struct regset *regset,
201 struct regcache *regcache,
202 int regnum, const void *regbuf, size_t len)
204 aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
207 /* Fill GDB's register array with the floating-point register values
208 in the buffer pointed by FPREGS_BUF. */
211 aarch64_linux_supply_fpregset (struct regcache *regcache,
212 const gdb_byte *fpregs_buf)
216 for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
217 regcache_raw_supply (regcache, regno,
218 fpregs_buf + V_REGISTER_SIZE
219 * (regno - AARCH64_V0_REGNUM));
221 regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
222 fpregs_buf + V_REGISTER_SIZE * 32);
223 regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
224 fpregs_buf + V_REGISTER_SIZE * 32 + 4);
227 /* The "supply_regset" function for the floating-point register set. */
230 supply_fpregset_from_core (const struct regset *regset,
231 struct regcache *regcache,
232 int regnum, const void *regbuf, size_t len)
234 aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
237 /* Implement the "regset_from_core_section" gdbarch method. */
239 static const struct regset *
240 aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch,
241 const char *sect_name,
244 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
246 if (strcmp (sect_name, ".reg") == 0
247 && sect_size == AARCH64_LINUX_SIZEOF_GREGSET)
249 if (tdep->gregset == NULL)
250 tdep->gregset = regset_alloc (gdbarch, supply_gregset_from_core,
252 return tdep->gregset;
255 if (strcmp (sect_name, ".reg2") == 0
256 && sect_size == AARCH64_LINUX_SIZEOF_FPREGSET)
258 if (tdep->fpregset == NULL)
259 tdep->fpregset = regset_alloc (gdbarch, supply_fpregset_from_core,
261 return tdep->fpregset;
267 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
269 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
271 tdep->lowest_pc = 0x8000;
273 set_solib_svr4_fetch_link_map_offsets (gdbarch,
274 svr4_lp64_fetch_link_map_offsets);
276 /* Enable TLS support. */
277 set_gdbarch_fetch_tls_load_module_address (gdbarch,
278 svr4_fetch_objfile_link_map);
280 /* Shared library handling. */
281 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
283 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
284 tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
286 /* Enable longjmp. */
289 set_gdbarch_regset_from_core_section (gdbarch,
290 aarch64_linux_regset_from_core_section);
293 /* Provide a prototype to silence -Wmissing-prototypes. */
294 extern initialize_file_ftype _initialize_aarch64_linux_tdep;
297 _initialize_aarch64_linux_tdep (void)
299 gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
300 aarch64_linux_init_abi);