C++: handle glibc's ptrace(enum __ptrace_request, ...)
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-aarch64-low.c
CommitLineData
176eb98c
MS
1/* GNU/Linux/AArch64 specific low level interface, for the remote server for
2 GDB.
3
32d0add0 4 Copyright (C) 2009-2015 Free Software Foundation, Inc.
176eb98c
MS
5 Contributed by ARM Ltd.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22#include "server.h"
23#include "linux-low.h"
554717a3 24#include "nat/aarch64-linux-hw-point.h"
176eb98c
MS
25#include "elf/common.h"
26
27#include <signal.h>
28#include <sys/user.h>
29#include <sys/ptrace.h>
e9dae05e 30#include <asm/ptrace.h>
176eb98c
MS
31#include <sys/uio.h>
32
33#include "gdb_proc_service.h"
34
35/* Defined in auto-generated files. */
36void init_registers_aarch64 (void);
3aee8918 37extern const struct target_desc *tdesc_aarch64;
176eb98c 38
176eb98c
MS
39#ifdef HAVE_SYS_REG_H
40#include <sys/reg.h>
41#endif
42
43#define AARCH64_X_REGS_NUM 31
44#define AARCH64_V_REGS_NUM 32
45#define AARCH64_X0_REGNO 0
46#define AARCH64_SP_REGNO 31
47#define AARCH64_PC_REGNO 32
48#define AARCH64_CPSR_REGNO 33
49#define AARCH64_V0_REGNO 34
bf330350
CU
50#define AARCH64_FPSR_REGNO (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM)
51#define AARCH64_FPCR_REGNO (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM + 1)
176eb98c 52
bf330350 53#define AARCH64_NUM_REGS (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM + 2)
176eb98c 54
176eb98c
MS
55/* Per-process arch-specific data we want to keep. */
56
57struct arch_process_info
58{
59 /* Hardware breakpoint/watchpoint data.
60 The reason for them to be per-process rather than per-thread is
61 due to the lack of information in the gdbserver environment;
62 gdbserver is not told that whether a requested hardware
63 breakpoint/watchpoint is thread specific or not, so it has to set
64 each hw bp/wp for every thread in the current process. The
65 higher level bp/wp management in gdb will resume a thread if a hw
66 bp/wp trap is not expected for it. Since the hw bp/wp setting is
67 same for each thread, it is reasonable for the data to live here.
68 */
69 struct aarch64_debug_reg_state debug_reg_state;
70};
71
421530db
PL
72/* Implementation of linux_target_ops method "cannot_store_register". */
73
176eb98c
MS
74static int
75aarch64_cannot_store_register (int regno)
76{
77 return regno >= AARCH64_NUM_REGS;
78}
79
421530db
PL
80/* Implementation of linux_target_ops method "cannot_fetch_register". */
81
176eb98c
MS
82static int
83aarch64_cannot_fetch_register (int regno)
84{
85 return regno >= AARCH64_NUM_REGS;
86}
87
88static void
89aarch64_fill_gregset (struct regcache *regcache, void *buf)
90{
91 struct user_pt_regs *regset = buf;
92 int i;
93
94 for (i = 0; i < AARCH64_X_REGS_NUM; i++)
95 collect_register (regcache, AARCH64_X0_REGNO + i, &regset->regs[i]);
96 collect_register (regcache, AARCH64_SP_REGNO, &regset->sp);
97 collect_register (regcache, AARCH64_PC_REGNO, &regset->pc);
98 collect_register (regcache, AARCH64_CPSR_REGNO, &regset->pstate);
99}
100
101static void
102aarch64_store_gregset (struct regcache *regcache, const void *buf)
103{
104 const struct user_pt_regs *regset = buf;
105 int i;
106
107 for (i = 0; i < AARCH64_X_REGS_NUM; i++)
108 supply_register (regcache, AARCH64_X0_REGNO + i, &regset->regs[i]);
109 supply_register (regcache, AARCH64_SP_REGNO, &regset->sp);
110 supply_register (regcache, AARCH64_PC_REGNO, &regset->pc);
111 supply_register (regcache, AARCH64_CPSR_REGNO, &regset->pstate);
112}
113
114static void
115aarch64_fill_fpregset (struct regcache *regcache, void *buf)
116{
117 struct user_fpsimd_state *regset = buf;
118 int i;
119
120 for (i = 0; i < AARCH64_V_REGS_NUM; i++)
121 collect_register (regcache, AARCH64_V0_REGNO + i, &regset->vregs[i]);
bf330350
CU
122 collect_register (regcache, AARCH64_FPSR_REGNO, &regset->fpsr);
123 collect_register (regcache, AARCH64_FPCR_REGNO, &regset->fpcr);
176eb98c
MS
124}
125
126static void
127aarch64_store_fpregset (struct regcache *regcache, const void *buf)
128{
129 const struct user_fpsimd_state *regset = buf;
130 int i;
131
132 for (i = 0; i < AARCH64_V_REGS_NUM; i++)
133 supply_register (regcache, AARCH64_V0_REGNO + i, &regset->vregs[i]);
bf330350
CU
134 supply_register (regcache, AARCH64_FPSR_REGNO, &regset->fpsr);
135 supply_register (regcache, AARCH64_FPCR_REGNO, &regset->fpcr);
176eb98c
MS
136}
137
176eb98c
MS
138/* Enable miscellaneous debugging output. The name is historical - it
139 was originally used to debug LinuxThreads support. */
140extern int debug_threads;
141
421530db
PL
142/* Implementation of linux_target_ops method "get_pc". */
143
176eb98c
MS
144static CORE_ADDR
145aarch64_get_pc (struct regcache *regcache)
146{
147 unsigned long pc;
148
149 collect_register_by_name (regcache, "pc", &pc);
150 if (debug_threads)
87ce2a04 151 debug_printf ("stop pc is %08lx\n", pc);
176eb98c
MS
152 return pc;
153}
154
421530db
PL
155/* Implementation of linux_target_ops method "set_pc". */
156
176eb98c
MS
157static void
158aarch64_set_pc (struct regcache *regcache, CORE_ADDR pc)
159{
160 unsigned long newpc = pc;
161 supply_register_by_name (regcache, "pc", &newpc);
162}
163
176eb98c
MS
164#define aarch64_breakpoint_len 4
165
37d66942
PL
166/* AArch64 BRK software debug mode instruction.
167 This instruction needs to match gdb/aarch64-tdep.c
168 (aarch64_default_breakpoint). */
169static const gdb_byte aarch64_breakpoint[] = {0x00, 0x00, 0x20, 0xd4};
176eb98c 170
421530db
PL
171/* Implementation of linux_target_ops method "breakpoint_at". */
172
176eb98c
MS
173static int
174aarch64_breakpoint_at (CORE_ADDR where)
175{
37d66942 176 gdb_byte insn[aarch64_breakpoint_len];
176eb98c 177
37d66942
PL
178 (*the_target->read_memory) (where, (unsigned char *) &insn,
179 aarch64_breakpoint_len);
180 if (memcmp (insn, aarch64_breakpoint, aarch64_breakpoint_len) == 0)
176eb98c
MS
181 return 1;
182
183 return 0;
184}
185
176eb98c
MS
186static void
187aarch64_init_debug_reg_state (struct aarch64_debug_reg_state *state)
188{
189 int i;
190
191 for (i = 0; i < AARCH64_HBP_MAX_NUM; ++i)
192 {
193 state->dr_addr_bp[i] = 0;
194 state->dr_ctrl_bp[i] = 0;
195 state->dr_ref_count_bp[i] = 0;
196 }
197
198 for (i = 0; i < AARCH64_HWP_MAX_NUM; ++i)
199 {
200 state->dr_addr_wp[i] = 0;
201 state->dr_ctrl_wp[i] = 0;
202 state->dr_ref_count_wp[i] = 0;
203 }
204}
205
176eb98c
MS
206struct aarch64_dr_update_callback_param
207{
208 int pid;
209 int is_watchpoint;
210 unsigned int idx;
211};
212
213/* Callback function which records the information about the change of
214 one hardware breakpoint/watchpoint setting for the thread ENTRY.
215 The information is passed in via PTR.
216 N.B. The actual updating of hardware debug registers is not
217 carried out until the moment the thread is resumed. */
218
219static int
220debug_reg_change_callback (struct inferior_list_entry *entry, void *ptr)
221{
d86d4aaf
DE
222 struct thread_info *thread = (struct thread_info *) entry;
223 struct lwp_info *lwp = get_thread_lwp (thread);
176eb98c
MS
224 struct aarch64_dr_update_callback_param *param_p
225 = (struct aarch64_dr_update_callback_param *) ptr;
226 int pid = param_p->pid;
227 int idx = param_p->idx;
228 int is_watchpoint = param_p->is_watchpoint;
229 struct arch_lwp_info *info = lwp->arch_private;
230 dr_changed_t *dr_changed_ptr;
231 dr_changed_t dr_changed;
232
c5e92cca 233 if (show_debug_regs)
176eb98c
MS
234 {
235 fprintf (stderr, "debug_reg_change_callback: \n\tOn entry:\n");
236 fprintf (stderr, "\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
237 "dr_changed_wp=0x%llx\n",
d86d4aaf 238 pid, lwpid_of (thread), info->dr_changed_bp,
176eb98c
MS
239 info->dr_changed_wp);
240 }
241
242 dr_changed_ptr = is_watchpoint ? &info->dr_changed_wp
243 : &info->dr_changed_bp;
244 dr_changed = *dr_changed_ptr;
245
246 /* Only update the threads of this process. */
d86d4aaf 247 if (pid_of (thread) == pid)
176eb98c
MS
248 {
249 gdb_assert (idx >= 0
250 && (idx <= (is_watchpoint ? aarch64_num_wp_regs
251 : aarch64_num_bp_regs)));
252
253 /* The following assertion is not right, as there can be changes
254 that have not been made to the hardware debug registers
255 before new changes overwrite the old ones. This can happen,
256 for instance, when the breakpoint/watchpoint hit one of the
257 threads and the user enters continue; then what happens is:
258 1) all breakpoints/watchpoints are removed for all threads;
259 2) a single step is carried out for the thread that was hit;
260 3) all of the points are inserted again for all threads;
261 4) all threads are resumed.
262 The 2nd step will only affect the one thread in which the
263 bp/wp was hit, which means only that one thread is resumed;
264 remember that the actual updating only happen in
265 aarch64_linux_prepare_to_resume, so other threads remain
266 stopped during the removal and insertion of bp/wp. Therefore
267 for those threads, the change of insertion of the bp/wp
268 overwrites that of the earlier removals. (The situation may
269 be different when bp/wp is steppable, or in the non-stop
270 mode.) */
271 /* gdb_assert (DR_N_HAS_CHANGED (dr_changed, idx) == 0); */
272
273 /* The actual update is done later just before resuming the lwp,
274 we just mark that one register pair needs updating. */
275 DR_MARK_N_CHANGED (dr_changed, idx);
276 *dr_changed_ptr = dr_changed;
277
278 /* If the lwp isn't stopped, force it to momentarily pause, so
279 we can update its debug registers. */
280 if (!lwp->stopped)
281 linux_stop_lwp (lwp);
282 }
283
c5e92cca 284 if (show_debug_regs)
176eb98c
MS
285 {
286 fprintf (stderr, "\tOn exit:\n\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
287 "dr_changed_wp=0x%llx\n",
d86d4aaf
DE
288 pid, lwpid_of (thread), info->dr_changed_bp,
289 info->dr_changed_wp);
176eb98c
MS
290 }
291
292 return 0;
293}
294
295/* Notify each thread that their IDXth breakpoint/watchpoint register
296 pair needs to be updated. The message will be recorded in each
297 thread's arch-specific data area, the actual updating will be done
298 when the thread is resumed. */
299
300void
301aarch64_notify_debug_reg_change (const struct aarch64_debug_reg_state *state,
302 int is_watchpoint, unsigned int idx)
303{
304 struct aarch64_dr_update_callback_param param;
305
306 /* Only update the threads of this process. */
0bfdf32f 307 param.pid = pid_of (current_thread);
176eb98c
MS
308
309 param.is_watchpoint = is_watchpoint;
310 param.idx = idx;
311
d86d4aaf 312 find_inferior (&all_threads, debug_reg_change_callback, (void *) &param);
176eb98c
MS
313}
314
315
316/* Return the pointer to the debug register state structure in the
317 current process' arch-specific data area. */
318
319static struct aarch64_debug_reg_state *
320aarch64_get_debug_reg_state ()
321{
322 struct process_info *proc;
323
324 proc = current_process ();
fe978cb0 325 return &proc->priv->arch_private->debug_reg_state;
176eb98c
MS
326}
327
421530db
PL
328/* Implementation of linux_target_ops method "supports_z_point_type". */
329
4ff0d3d8
PA
330static int
331aarch64_supports_z_point_type (char z_type)
332{
333 switch (z_type)
334 {
96c97461 335 case Z_PACKET_SW_BP:
4ff0d3d8
PA
336 case Z_PACKET_HW_BP:
337 case Z_PACKET_WRITE_WP:
338 case Z_PACKET_READ_WP:
339 case Z_PACKET_ACCESS_WP:
340 return 1;
341 default:
4ff0d3d8
PA
342 return 0;
343 }
344}
345
421530db 346/* Implementation of linux_target_ops method "insert_point".
176eb98c 347
421530db
PL
348 It actually only records the info of the to-be-inserted bp/wp;
349 the actual insertion will happen when threads are resumed. */
176eb98c
MS
350
351static int
802e8e6d
PA
352aarch64_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
353 int len, struct raw_breakpoint *bp)
176eb98c
MS
354{
355 int ret;
4ff0d3d8 356 enum target_hw_bp_type targ_type;
c67ca4de 357 struct aarch64_debug_reg_state *state = aarch64_get_debug_reg_state ();
4ff0d3d8 358
c5e92cca 359 if (show_debug_regs)
176eb98c
MS
360 fprintf (stderr, "insert_point on entry (addr=0x%08lx, len=%d)\n",
361 (unsigned long) addr, len);
362
802e8e6d
PA
363 /* Determine the type from the raw breakpoint type. */
364 targ_type = raw_bkpt_type_to_target_hw_bp_type (type);
176eb98c
MS
365
366 if (targ_type != hw_execute)
367 ret =
c67ca4de
YQ
368 aarch64_handle_watchpoint (targ_type, addr, len, 1 /* is_insert */,
369 state);
176eb98c
MS
370 else
371 ret =
c67ca4de
YQ
372 aarch64_handle_breakpoint (targ_type, addr, len, 1 /* is_insert */,
373 state);
176eb98c 374
60a191ed 375 if (show_debug_regs)
176eb98c
MS
376 aarch64_show_debug_reg_state (aarch64_get_debug_reg_state (),
377 "insert_point", addr, len, targ_type);
378
379 return ret;
380}
381
421530db 382/* Implementation of linux_target_ops method "remove_point".
176eb98c 383
421530db
PL
384 It actually only records the info of the to-be-removed bp/wp,
385 the actual removal will be done when threads are resumed. */
176eb98c
MS
386
387static int
802e8e6d
PA
388aarch64_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
389 int len, struct raw_breakpoint *bp)
176eb98c
MS
390{
391 int ret;
4ff0d3d8 392 enum target_hw_bp_type targ_type;
c67ca4de 393 struct aarch64_debug_reg_state *state = aarch64_get_debug_reg_state ();
4ff0d3d8 394
c5e92cca 395 if (show_debug_regs)
176eb98c
MS
396 fprintf (stderr, "remove_point on entry (addr=0x%08lx, len=%d)\n",
397 (unsigned long) addr, len);
398
802e8e6d
PA
399 /* Determine the type from the raw breakpoint type. */
400 targ_type = raw_bkpt_type_to_target_hw_bp_type (type);
176eb98c
MS
401
402 /* Set up state pointers. */
403 if (targ_type != hw_execute)
404 ret =
c67ca4de
YQ
405 aarch64_handle_watchpoint (targ_type, addr, len, 0 /* is_insert */,
406 state);
176eb98c
MS
407 else
408 ret =
c67ca4de
YQ
409 aarch64_handle_breakpoint (targ_type, addr, len, 0 /* is_insert */,
410 state);
176eb98c 411
60a191ed 412 if (show_debug_regs)
176eb98c
MS
413 aarch64_show_debug_reg_state (aarch64_get_debug_reg_state (),
414 "remove_point", addr, len, targ_type);
415
416 return ret;
417}
418
421530db 419/* Implementation of linux_target_ops method "stopped_data_address". */
176eb98c
MS
420
421static CORE_ADDR
422aarch64_stopped_data_address (void)
423{
424 siginfo_t siginfo;
425 int pid, i;
426 struct aarch64_debug_reg_state *state;
427
0bfdf32f 428 pid = lwpid_of (current_thread);
176eb98c
MS
429
430 /* Get the siginfo. */
431 if (ptrace (PTRACE_GETSIGINFO, pid, NULL, &siginfo) != 0)
432 return (CORE_ADDR) 0;
433
434 /* Need to be a hardware breakpoint/watchpoint trap. */
435 if (siginfo.si_signo != SIGTRAP
436 || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
437 return (CORE_ADDR) 0;
438
439 /* Check if the address matches any watched address. */
440 state = aarch64_get_debug_reg_state ();
441 for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
442 {
443 const unsigned int len = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
444 const CORE_ADDR addr_trap = (CORE_ADDR) siginfo.si_addr;
445 const CORE_ADDR addr_watch = state->dr_addr_wp[i];
446 if (state->dr_ref_count_wp[i]
447 && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])
448 && addr_trap >= addr_watch
449 && addr_trap < addr_watch + len)
450 return addr_trap;
451 }
452
453 return (CORE_ADDR) 0;
454}
455
421530db 456/* Implementation of linux_target_ops method "stopped_by_watchpoint". */
176eb98c
MS
457
458static int
459aarch64_stopped_by_watchpoint (void)
460{
461 if (aarch64_stopped_data_address () != 0)
462 return 1;
463 else
464 return 0;
465}
466
467/* Fetch the thread-local storage pointer for libthread_db. */
468
469ps_err_e
55fac6e0 470ps_get_thread_area (const struct ps_prochandle *ph,
176eb98c
MS
471 lwpid_t lwpid, int idx, void **base)
472{
55fac6e0
MS
473 struct iovec iovec;
474 uint64_t reg;
475
476 iovec.iov_base = &reg;
477 iovec.iov_len = sizeof (reg);
478
479 if (ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0)
176eb98c
MS
480 return PS_ERR;
481
482 /* IDX is the bias from the thread pointer to the beginning of the
483 thread descriptor. It has to be subtracted due to implementation
484 quirks in libthread_db. */
55fac6e0 485 *base = (void *) (reg - idx);
176eb98c
MS
486
487 return PS_OK;
488}
489
421530db 490/* Implementation of linux_target_ops method "linux_new_process". */
176eb98c
MS
491
492static struct arch_process_info *
493aarch64_linux_new_process (void)
494{
495 struct arch_process_info *info = xcalloc (1, sizeof (*info));
496
497 aarch64_init_debug_reg_state (&info->debug_reg_state);
498
499 return info;
500}
501
421530db 502/* Implementation of linux_target_ops method "linux_new_thread". */
176eb98c 503
34c703da
GB
504static void
505aarch64_linux_new_thread (struct lwp_info *lwp)
176eb98c
MS
506{
507 struct arch_lwp_info *info = xcalloc (1, sizeof (*info));
508
509 /* Mark that all the hardware breakpoint/watchpoint register pairs
510 for this thread need to be initialized (with data from
511 aarch_process_info.debug_reg_state). */
512 DR_MARK_ALL_CHANGED (info->dr_changed_bp, aarch64_num_bp_regs);
513 DR_MARK_ALL_CHANGED (info->dr_changed_wp, aarch64_num_wp_regs);
514
34c703da 515 lwp->arch_private = info;
176eb98c
MS
516}
517
421530db
PL
518/* Implementation of linux_target_ops method "linux_new_fork". */
519
3a8a0396
DB
520static void
521aarch64_linux_new_fork (struct process_info *parent,
522 struct process_info *child)
523{
524 /* These are allocated by linux_add_process. */
61a7418c
DB
525 gdb_assert (parent->priv != NULL
526 && parent->priv->arch_private != NULL);
527 gdb_assert (child->priv != NULL
528 && child->priv->arch_private != NULL);
3a8a0396
DB
529
530 /* Linux kernel before 2.6.33 commit
531 72f674d203cd230426437cdcf7dd6f681dad8b0d
532 will inherit hardware debug registers from parent
533 on fork/vfork/clone. Newer Linux kernels create such tasks with
534 zeroed debug registers.
535
536 GDB core assumes the child inherits the watchpoints/hw
537 breakpoints of the parent, and will remove them all from the
538 forked off process. Copy the debug registers mirrors into the
539 new process so that all breakpoints and watchpoints can be
540 removed together. The debug registers mirror will become zeroed
541 in the end before detaching the forked off process, thus making
542 this compatible with older Linux kernels too. */
543
61a7418c 544 *child->priv->arch_private = *parent->priv->arch_private;
3a8a0396
DB
545}
546
421530db
PL
547/* Implementation of linux_target_ops method "linux_prepare_to_resume".
548
176eb98c
MS
549 If the debug regs have changed, update the thread's copies. */
550
551static void
552aarch64_linux_prepare_to_resume (struct lwp_info *lwp)
553{
d86d4aaf
DE
554 struct thread_info *thread = get_lwp_thread (lwp);
555 ptid_t ptid = ptid_of (thread);
176eb98c
MS
556 struct arch_lwp_info *info = lwp->arch_private;
557
558 if (DR_HAS_CHANGED (info->dr_changed_bp)
559 || DR_HAS_CHANGED (info->dr_changed_wp))
560 {
561 int tid = ptid_get_lwp (ptid);
562 struct process_info *proc = find_process_pid (ptid_get_pid (ptid));
563 struct aarch64_debug_reg_state *state
fe978cb0 564 = &proc->priv->arch_private->debug_reg_state;
176eb98c 565
c5e92cca 566 if (show_debug_regs)
d86d4aaf 567 fprintf (stderr, "prepare_to_resume thread %ld\n", lwpid_of (thread));
176eb98c
MS
568
569 /* Watchpoints. */
570 if (DR_HAS_CHANGED (info->dr_changed_wp))
571 {
572 aarch64_linux_set_debug_regs (state, tid, 1);
573 DR_CLEAR_CHANGED (info->dr_changed_wp);
574 }
575
576 /* Breakpoints. */
577 if (DR_HAS_CHANGED (info->dr_changed_bp))
578 {
579 aarch64_linux_set_debug_regs (state, tid, 0);
580 DR_CLEAR_CHANGED (info->dr_changed_bp);
581 }
582 }
583}
584
421530db
PL
585/* Implementation of linux_target_ops method "arch_setup". */
586
176eb98c
MS
587static void
588aarch64_arch_setup (void)
589{
3aee8918 590 current_process ()->tdesc = tdesc_aarch64;
176eb98c 591
af1b22f3 592 aarch64_linux_get_debug_reg_capacity (lwpid_of (current_thread));
176eb98c
MS
593}
594
3aee8918 595static struct regset_info aarch64_regsets[] =
176eb98c
MS
596{
597 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
598 sizeof (struct user_pt_regs), GENERAL_REGS,
599 aarch64_fill_gregset, aarch64_store_gregset },
600 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET,
601 sizeof (struct user_fpsimd_state), FP_REGS,
602 aarch64_fill_fpregset, aarch64_store_fpregset
603 },
604 { 0, 0, 0, -1, -1, NULL, NULL }
605};
606
3aee8918
PA
607static struct regsets_info aarch64_regsets_info =
608 {
609 aarch64_regsets, /* regsets */
610 0, /* num_regsets */
611 NULL, /* disabled_regsets */
612 };
613
3aee8918
PA
614static struct regs_info regs_info =
615 {
616 NULL, /* regset_bitmap */
c2d65f38 617 NULL, /* usrregs */
3aee8918
PA
618 &aarch64_regsets_info,
619 };
620
421530db
PL
621/* Implementation of linux_target_ops method "regs_info". */
622
3aee8918
PA
623static const struct regs_info *
624aarch64_regs_info (void)
625{
626 return &regs_info;
627}
628
7671bf47
PL
629/* Implementation of linux_target_ops method "supports_tracepoints". */
630
631static int
632aarch64_supports_tracepoints (void)
633{
634 return 1;
635}
636
d1d0aea1
PL
637/* Implementation of linux_target_ops method "supports_range_stepping". */
638
639static int
640aarch64_supports_range_stepping (void)
641{
642 return 1;
643}
644
176eb98c
MS
645struct linux_target_ops the_low_target =
646{
647 aarch64_arch_setup,
3aee8918 648 aarch64_regs_info,
176eb98c
MS
649 aarch64_cannot_fetch_register,
650 aarch64_cannot_store_register,
421530db 651 NULL, /* fetch_register */
176eb98c
MS
652 aarch64_get_pc,
653 aarch64_set_pc,
654 (const unsigned char *) &aarch64_breakpoint,
655 aarch64_breakpoint_len,
421530db
PL
656 NULL, /* breakpoint_reinsert_addr */
657 0, /* decr_pc_after_break */
176eb98c 658 aarch64_breakpoint_at,
802e8e6d 659 aarch64_supports_z_point_type,
176eb98c
MS
660 aarch64_insert_point,
661 aarch64_remove_point,
662 aarch64_stopped_by_watchpoint,
663 aarch64_stopped_data_address,
421530db
PL
664 NULL, /* collect_ptrace_register */
665 NULL, /* supply_ptrace_register */
666 NULL, /* siginfo_fixup */
176eb98c
MS
667 aarch64_linux_new_process,
668 aarch64_linux_new_thread,
3a8a0396 669 aarch64_linux_new_fork,
176eb98c 670 aarch64_linux_prepare_to_resume,
421530db 671 NULL, /* process_qsupported */
7671bf47 672 aarch64_supports_tracepoints,
d1d0aea1
PL
673 NULL, /* get_thread_area */
674 NULL, /* install_fast_tracepoint_jump_pad */
675 NULL, /* emit_ops */
676 NULL, /* get_min_fast_tracepoint_insn_len */
677 aarch64_supports_range_stepping,
176eb98c 678};
3aee8918
PA
679
680void
681initialize_low_arch (void)
682{
683 init_registers_aarch64 ();
684
685 initialize_regsets_info (&aarch64_regsets_info);
686}
This page took 0.253962 seconds and 4 git commands to generate.