windows-nat: Don't change current_event.dwThreadId in handle_output_debug_string()
[deliverable/binutils-gdb.git] / gdb / aarch64-linux-tdep.c
CommitLineData
1ae3db19
MS
1/* Target-dependent code for GNU/Linux AArch64.
2
32d0add0 3 Copyright (C) 2009-2015 Free Software Foundation, Inc.
1ae3db19
MS
4 Contributed by ARM Ltd.
5
6 This file is part of GDB.
7
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.
12
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.
17
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/>. */
20
21#include "defs.h"
22
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"
33
34#include "inferior.h"
35#include "regcache.h"
36#include "regset.h"
37
08248ca9
SDJ
38#include "cli/cli-utils.h"
39#include "stap-probe.h"
40#include "parser-defs.h"
41#include "user-regs.h"
f68f11b7 42#include "xml-syscall.h"
08248ca9
SDJ
43#include <ctype.h>
44
1ae3db19
MS
45/* Signal frame handling.
46
f2205de0
HZ
47 +------------+ ^
48 | saved lr | |
49 +->| saved fp |--+
50 | | |
51 | | |
52 | +------------+
53 | | saved lr |
54 +--| saved fp |
55 ^ | |
56 | | |
57 | +------------+
58 ^ | |
59 | | signal |
60 | | | SIGTRAMP_FRAME (struct rt_sigframe)
61 | | saved regs |
62 +--| saved sp |--> interrupted_sp
63 | | saved pc |--> interrupted_pc
64 | | |
65 | +------------+
66 | | saved lr |--> default_restorer (movz x8, NR_sys_rt_sigreturn; svc 0)
67 +--| saved fp |<- FP
68 | | NORMAL_FRAME
69 | |<- SP
70 +------------+
1ae3db19
MS
71
72 On signal delivery, the kernel will create a signal handler stack
73 frame and setup the return address in LR to point at restorer stub.
74 The signal stack frame is defined by:
75
76 struct rt_sigframe
77 {
78 siginfo_t info;
79 struct ucontext uc;
80 };
81
82 typedef struct
83 {
84 ... 128 bytes
85 } siginfo_t;
86
87 The ucontext has the following form:
88 struct ucontext
89 {
90 unsigned long uc_flags;
91 struct ucontext *uc_link;
92 stack_t uc_stack;
93 sigset_t uc_sigmask;
94 struct sigcontext uc_mcontext;
95 };
96
97 typedef struct sigaltstack
98 {
99 void *ss_sp;
100 int ss_flags;
101 size_t ss_size;
102 } stack_t;
103
104 struct sigcontext
105 {
106 unsigned long fault_address;
107 unsigned long regs[31];
108 unsigned long sp; / * 31 * /
109 unsigned long pc; / * 32 * /
110 unsigned long pstate; / * 33 * /
111 __u8 __reserved[4096]
112 };
113
114 The restorer stub will always have the form:
115
116 d28015a8 movz x8, #0xad
117 d4000001 svc #0x0
118
f2205de0
HZ
119 This is a system call sys_rt_sigreturn.
120
1ae3db19
MS
121 We detect signal frames by snooping the return code for the restorer
122 instruction sequence.
123
124 The handler then needs to recover the saved register set from
125 ucontext.uc_mcontext. */
126
127/* These magic numbers need to reflect the layout of the kernel
128 defined struct rt_sigframe and ucontext. */
129#define AARCH64_SIGCONTEXT_REG_SIZE 8
130#define AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET 128
131#define AARCH64_UCONTEXT_SIGCONTEXT_OFFSET 176
132#define AARCH64_SIGCONTEXT_XO_OFFSET 8
133
134/* Implement the "init" method of struct tramp_frame. */
135
136static void
137aarch64_linux_sigframe_init (const struct tramp_frame *self,
138 struct frame_info *this_frame,
139 struct trad_frame_cache *this_cache,
140 CORE_ADDR func)
141{
142 struct gdbarch *gdbarch = get_frame_arch (this_frame);
143 CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
1ae3db19
MS
144 CORE_ADDR sigcontext_addr =
145 sp
146 + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
147 + AARCH64_UCONTEXT_SIGCONTEXT_OFFSET;
148 int i;
149
150 for (i = 0; i < 31; i++)
151 {
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);
156 }
f2205de0
HZ
157 trad_frame_set_reg_addr (this_cache, AARCH64_SP_REGNUM,
158 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
159 + 31 * AARCH64_SIGCONTEXT_REG_SIZE);
160 trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM,
161 sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
162 + 32 * AARCH64_SIGCONTEXT_REG_SIZE);
163
164 trad_frame_set_id (this_cache, frame_id_build (sp, func));
1ae3db19
MS
165}
166
167static const struct tramp_frame aarch64_linux_rt_sigframe =
168{
169 SIGTRAMP_FRAME,
170 4,
171 {
172 /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8)
173 Soo1 0010 1hhi iiii iiii iiii iiir rrrr */
174 {0xd2801168, -1},
175
176 /* svc 0x0 (o=0, l=1)
177 1101 0100 oooi iiii iiii iiii iii0 00ll */
178 {0xd4000001, -1},
179 {TRAMP_SENTINEL_INSN, -1}
180 },
181 aarch64_linux_sigframe_init
182};
183
d4d793bf 184/* Register maps. */
1ae3db19 185
d4d793bf
AA
186static const struct regcache_map_entry aarch64_linux_gregmap[] =
187 {
188 { 31, AARCH64_X0_REGNUM, 8 }, /* x0 ... x30 */
189 { 1, AARCH64_SP_REGNUM, 8 },
190 { 1, AARCH64_PC_REGNUM, 8 },
191 { 1, AARCH64_CPSR_REGNUM, 8 },
192 { 0 }
193 };
1ae3db19 194
d4d793bf
AA
195static const struct regcache_map_entry aarch64_linux_fpregmap[] =
196 {
197 { 32, AARCH64_V0_REGNUM, 16 }, /* v0 ... v31 */
198 { 1, AARCH64_FPSR_REGNUM, 4 },
199 { 1, AARCH64_FPCR_REGNUM, 4 },
200 { 0 }
201 };
1ae3db19 202
d4d793bf 203/* Register set definitions. */
a069a2bd 204
d4d793bf 205const struct regset aarch64_linux_gregset =
a069a2bd 206 {
d4d793bf
AA
207 aarch64_linux_gregmap,
208 regcache_supply_regset, regcache_collect_regset
a069a2bd
AA
209 };
210
d4d793bf 211const struct regset aarch64_linux_fpregset =
a069a2bd 212 {
d4d793bf
AA
213 aarch64_linux_fpregmap,
214 regcache_supply_regset, regcache_collect_regset
a069a2bd
AA
215 };
216
1ae3db19
MS
217/* Implement the "regset_from_core_section" gdbarch method. */
218
4108500a
AA
219static void
220aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
221 iterate_over_regset_sections_cb *cb,
222 void *cb_data,
223 const struct regcache *regcache)
1ae3db19 224{
4108500a
AA
225 cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, &aarch64_linux_gregset,
226 NULL, cb_data);
227 cb (".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, &aarch64_linux_fpregset,
228 NULL, cb_data);
1ae3db19
MS
229}
230
08248ca9
SDJ
231/* Implementation of `gdbarch_stap_is_single_operand', as defined in
232 gdbarch.h. */
233
234static int
235aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
236{
237 return (*s == '#' || isdigit (*s) /* Literal number. */
238 || *s == '[' /* Register indirection. */
239 || isalpha (*s)); /* Register value. */
240}
241
242/* This routine is used to parse a special token in AArch64's assembly.
243
244 The special tokens parsed by it are:
245
246 - Register displacement (e.g, [fp, #-8])
247
248 It returns one if the special token has been parsed successfully,
249 or zero if the current token is not considered special. */
250
251static int
252aarch64_stap_parse_special_token (struct gdbarch *gdbarch,
253 struct stap_parse_info *p)
254{
255 if (*p->arg == '[')
256 {
257 /* Temporary holder for lookahead. */
258 const char *tmp = p->arg;
259 char *endp;
260 /* Used to save the register name. */
261 const char *start;
262 char *regname;
263 int len;
264 int got_minus = 0;
265 long displacement;
266 struct stoken str;
267
268 ++tmp;
269 start = tmp;
270
271 /* Register name. */
272 while (isalnum (*tmp))
273 ++tmp;
274
275 if (*tmp != ',')
276 return 0;
277
278 len = tmp - start;
279 regname = alloca (len + 2);
280
281 strncpy (regname, start, len);
282 regname[len] = '\0';
283
284 if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1)
285 error (_("Invalid register name `%s' on expression `%s'."),
286 regname, p->saved_arg);
287
288 ++tmp;
289 tmp = skip_spaces_const (tmp);
290 /* Now we expect a number. It can begin with '#' or simply
291 a digit. */
292 if (*tmp == '#')
293 ++tmp;
294
295 if (*tmp == '-')
296 {
297 ++tmp;
298 got_minus = 1;
299 }
300 else if (*tmp == '+')
301 ++tmp;
302
303 if (!isdigit (*tmp))
304 return 0;
305
306 displacement = strtol (tmp, &endp, 10);
307 tmp = endp;
308
309 /* Skipping last `]'. */
310 if (*tmp++ != ']')
311 return 0;
312
313 /* The displacement. */
410a0ff2
SDJ
314 write_exp_elt_opcode (&p->pstate, OP_LONG);
315 write_exp_elt_type (&p->pstate, builtin_type (gdbarch)->builtin_long);
316 write_exp_elt_longcst (&p->pstate, displacement);
317 write_exp_elt_opcode (&p->pstate, OP_LONG);
08248ca9 318 if (got_minus)
410a0ff2 319 write_exp_elt_opcode (&p->pstate, UNOP_NEG);
08248ca9
SDJ
320
321 /* The register name. */
410a0ff2 322 write_exp_elt_opcode (&p->pstate, OP_REGISTER);
08248ca9
SDJ
323 str.ptr = regname;
324 str.length = len;
410a0ff2
SDJ
325 write_exp_string (&p->pstate, str);
326 write_exp_elt_opcode (&p->pstate, OP_REGISTER);
08248ca9 327
410a0ff2 328 write_exp_elt_opcode (&p->pstate, BINOP_ADD);
08248ca9
SDJ
329
330 /* Casting to the expected type. */
410a0ff2
SDJ
331 write_exp_elt_opcode (&p->pstate, UNOP_CAST);
332 write_exp_elt_type (&p->pstate, lookup_pointer_type (p->arg_type));
333 write_exp_elt_opcode (&p->pstate, UNOP_CAST);
08248ca9 334
410a0ff2 335 write_exp_elt_opcode (&p->pstate, UNOP_IND);
08248ca9
SDJ
336
337 p->arg = tmp;
338 }
339 else
340 return 0;
341
342 return 1;
343}
344
f68f11b7
YQ
345/* Implement the "get_syscall_number" gdbarch method. */
346
347static LONGEST
348aarch64_linux_get_syscall_number (struct gdbarch *gdbarch,
349 ptid_t ptid)
350{
351 struct regcache *regs = get_thread_regcache (ptid);
352 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
353
354 /* The content of register x8. */
355 gdb_byte buf[X_REGISTER_SIZE];
356 /* The result. */
357 LONGEST ret;
358
359 /* Getting the system call number from the register x8. */
360 regcache_cooked_read (regs, AARCH64_DWARF_X0 + 8, buf);
361
362 ret = extract_signed_integer (buf, X_REGISTER_SIZE, byte_order);
363
364 return ret;
365}
366
1ae3db19
MS
367static void
368aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
369{
08248ca9
SDJ
370 static const char *const stap_integer_prefixes[] = { "#", "", NULL };
371 static const char *const stap_register_prefixes[] = { "", NULL };
372 static const char *const stap_register_indirection_prefixes[] = { "[",
373 NULL };
374 static const char *const stap_register_indirection_suffixes[] = { "]",
375 NULL };
1ae3db19
MS
376 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
377
378 tdep->lowest_pc = 0x8000;
379
05feb193
WN
380 linux_init_abi (info, gdbarch);
381
1ae3db19
MS
382 set_solib_svr4_fetch_link_map_offsets (gdbarch,
383 svr4_lp64_fetch_link_map_offsets);
384
45e25a36
MS
385 /* Enable TLS support. */
386 set_gdbarch_fetch_tls_load_module_address (gdbarch,
387 svr4_fetch_objfile_link_map);
388
1ae3db19
MS
389 /* Shared library handling. */
390 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
391
392 set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
393 tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
394
395 /* Enable longjmp. */
396 tdep->jb_pc = 11;
397
4108500a
AA
398 set_gdbarch_iterate_over_regset_sections
399 (gdbarch, aarch64_linux_iterate_over_regset_sections);
08248ca9
SDJ
400
401 /* SystemTap related. */
402 set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
403 set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
404 set_gdbarch_stap_register_indirection_prefixes (gdbarch,
405 stap_register_indirection_prefixes);
406 set_gdbarch_stap_register_indirection_suffixes (gdbarch,
407 stap_register_indirection_suffixes);
408 set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand);
409 set_gdbarch_stap_parse_special_token (gdbarch,
410 aarch64_stap_parse_special_token);
f68f11b7
YQ
411
412 /* `catch syscall' */
413 set_xml_syscall_file_name (gdbarch, "syscalls/aarch64-linux.xml");
414 set_gdbarch_get_syscall_number (gdbarch, aarch64_linux_get_syscall_number);
1ae3db19
MS
415}
416
417/* Provide a prototype to silence -Wmissing-prototypes. */
418extern initialize_file_ftype _initialize_aarch64_linux_tdep;
419
420void
421_initialize_aarch64_linux_tdep (void)
422{
423 gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_LINUX,
424 aarch64_linux_init_abi);
425}
This page took 0.179918 seconds and 4 git commands to generate.