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