windows-nat: Don't change current_event.dwThreadId in handle_output_debug_string()
[deliverable/binutils-gdb.git] / gdb / aarch64-linux-tdep.c
1 /* Target-dependent code for GNU/Linux AArch64.
2
3 Copyright (C) 2009-2015 Free Software Foundation, Inc.
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
38 #include "cli/cli-utils.h"
39 #include "stap-probe.h"
40 #include "parser-defs.h"
41 #include "user-regs.h"
42 #include "xml-syscall.h"
43 #include <ctype.h>
44
45 /* Signal frame handling.
46
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 +------------+
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
119 This is a system call sys_rt_sigreturn.
120
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
136 static void
137 aarch64_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);
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 }
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));
165 }
166
167 static 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
184 /* Register maps. */
185
186 static 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 };
194
195 static 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 };
202
203 /* Register set definitions. */
204
205 const struct regset aarch64_linux_gregset =
206 {
207 aarch64_linux_gregmap,
208 regcache_supply_regset, regcache_collect_regset
209 };
210
211 const struct regset aarch64_linux_fpregset =
212 {
213 aarch64_linux_fpregmap,
214 regcache_supply_regset, regcache_collect_regset
215 };
216
217 /* Implement the "regset_from_core_section" gdbarch method. */
218
219 static void
220 aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
221 iterate_over_regset_sections_cb *cb,
222 void *cb_data,
223 const struct regcache *regcache)
224 {
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);
229 }
230
231 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
232 gdbarch.h. */
233
234 static int
235 aarch64_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
251 static int
252 aarch64_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. */
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);
318 if (got_minus)
319 write_exp_elt_opcode (&p->pstate, UNOP_NEG);
320
321 /* The register name. */
322 write_exp_elt_opcode (&p->pstate, OP_REGISTER);
323 str.ptr = regname;
324 str.length = len;
325 write_exp_string (&p->pstate, str);
326 write_exp_elt_opcode (&p->pstate, OP_REGISTER);
327
328 write_exp_elt_opcode (&p->pstate, BINOP_ADD);
329
330 /* Casting to the expected type. */
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);
334
335 write_exp_elt_opcode (&p->pstate, UNOP_IND);
336
337 p->arg = tmp;
338 }
339 else
340 return 0;
341
342 return 1;
343 }
344
345 /* Implement the "get_syscall_number" gdbarch method. */
346
347 static LONGEST
348 aarch64_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
367 static void
368 aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
369 {
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 };
376 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
377
378 tdep->lowest_pc = 0x8000;
379
380 linux_init_abi (info, gdbarch);
381
382 set_solib_svr4_fetch_link_map_offsets (gdbarch,
383 svr4_lp64_fetch_link_map_offsets);
384
385 /* Enable TLS support. */
386 set_gdbarch_fetch_tls_load_module_address (gdbarch,
387 svr4_fetch_objfile_link_map);
388
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
398 set_gdbarch_iterate_over_regset_sections
399 (gdbarch, aarch64_linux_iterate_over_regset_sections);
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);
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);
415 }
416
417 /* Provide a prototype to silence -Wmissing-prototypes. */
418 extern initialize_file_ftype _initialize_aarch64_linux_tdep;
419
420 void
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.038905 seconds and 4 git commands to generate.