Add new target_read_raw_memory function, and consolidate comments.
[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
4 Copyright (C) 2009-2013 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 "elf/common.h"
25
26#include <signal.h>
27#include <sys/user.h>
28#include <sys/ptrace.h>
29#include <sys/uio.h>
30
31#include "gdb_proc_service.h"
32
33/* Defined in auto-generated files. */
34void init_registers_aarch64 (void);
3aee8918 35extern const struct target_desc *tdesc_aarch64;
176eb98c 36
176eb98c
MS
37#ifdef HAVE_SYS_REG_H
38#include <sys/reg.h>
39#endif
40
41#define AARCH64_X_REGS_NUM 31
42#define AARCH64_V_REGS_NUM 32
43#define AARCH64_X0_REGNO 0
44#define AARCH64_SP_REGNO 31
45#define AARCH64_PC_REGNO 32
46#define AARCH64_CPSR_REGNO 33
47#define AARCH64_V0_REGNO 34
48
49#define AARCH64_NUM_REGS (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM)
50
51static int
52aarch64_regmap [] =
53{
54 /* These offsets correspond to GET/SETREGSET */
55 /* x0... */
56 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
57 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8,
58 16*8, 17*8, 18*8, 19*8, 20*8, 21*8, 22*8, 23*8,
59 24*8, 25*8, 26*8, 27*8, 28*8,
60 29*8,
61 30*8, /* x30 lr */
62 31*8, /* x31 sp */
63 32*8, /* pc */
64 33*8, /* cpsr 4 bytes!*/
65
66 /* FP register offsets correspond to GET/SETFPREGSET */
67 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16,
68 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16,
69 16*16, 17*16, 18*16, 19*16, 20*16, 21*16, 22*16, 23*16,
70 24*16, 25*16, 26*16, 27*16, 28*16, 29*16, 30*16, 31*16
71};
72
73/* Here starts the macro definitions, data structures, and code for
74 the hardware breakpoint and hardware watchpoint support. The
75 following is the abbreviations that are used frequently in the code
76 and comment:
77
78 hw - hardware
79 bp - breakpoint
80 wp - watchpoint */
81
82/* Maximum number of hardware breakpoint and watchpoint registers.
83 Neither of these values may exceed the width of dr_changed_t
84 measured in bits. */
85
86#define AARCH64_HBP_MAX_NUM 16
87#define AARCH64_HWP_MAX_NUM 16
88
89/* Alignment requirement in bytes of hardware breakpoint and
90 watchpoint address. This is the requirement for the addresses that
91 can be written to the hardware breakpoint/watchpoint value
92 registers. The kernel currently does not do any alignment on
93 addresses when receiving a writing request (via ptrace call) to
94 these debug registers, and it will reject any address that is
95 unaligned.
96 Some limited support has been provided in this gdbserver port for
97 unaligned watchpoints, so that from a gdb user point of view, an
98 unaligned watchpoint can still be set. This is achieved by
99 minimally enlarging the watched area to meet the alignment
100 requirement, and if necessary, splitting the watchpoint over
101 several hardware watchpoint registers. */
102
103#define AARCH64_HBP_ALIGNMENT 4
104#define AARCH64_HWP_ALIGNMENT 8
105
106/* The maximum length of a memory region that can be watched by one
107 hardware watchpoint register. */
108
109#define AARCH64_HWP_MAX_LEN_PER_REG 8
110
111/* Each bit of a variable of this type is used to indicate whether a
112 hardware breakpoint or watchpoint setting has been changed since
113 the last updating. Bit N corresponds to the Nth hardware
114 breakpoint or watchpoint setting which is managed in
115 aarch64_debug_reg_state. Where N is valid between 0 and the total
116 number of the hardware breakpoint or watchpoint debug registers
117 minus 1. When the bit N is 1, it indicates the corresponding
118 breakpoint or watchpoint setting is changed, and thus the
119 corresponding hardware debug register needs to be updated via the
120 ptrace interface.
121
122 In the per-thread arch-specific data area, we define two such
123 variables for per-thread hardware breakpoint and watchpoint
124 settings respectively.
125
126 This type is part of the mechanism which helps reduce the number of
127 ptrace calls to the kernel, i.e. avoid asking the kernel to write
128 to the debug registers with unchanged values. */
129
130typedef unsigned long long dr_changed_t;
131
132/* Set each of the lower M bits of X to 1; assert X is wide enough. */
133
134#define DR_MARK_ALL_CHANGED(x, m) \
135 do \
136 { \
137 gdb_assert (sizeof ((x)) * 8 >= (m)); \
138 (x) = (((dr_changed_t)1 << (m)) - 1); \
139 } while (0)
140
141#define DR_MARK_N_CHANGED(x, n) \
142 do \
143 { \
144 (x) |= ((dr_changed_t)1 << (n)); \
145 } while (0)
146
147#define DR_CLEAR_CHANGED(x) \
148 do \
149 { \
150 (x) = 0; \
151 } while (0)
152
153#define DR_HAS_CHANGED(x) ((x) != 0)
154#define DR_N_HAS_CHANGED(x, n) ((x) & ((dr_changed_t)1 << (n)))
155
156/* Structure for managing the hardware breakpoint/watchpoint resources.
157 DR_ADDR_* stores the address, DR_CTRL_* stores the control register
158 content, and DR_REF_COUNT_* counts the numbers of references to the
159 corresponding bp/wp, by which way the limited hardware resources
160 are not wasted on duplicated bp/wp settings (though so far gdb has
161 done a good job by not sending duplicated bp/wp requests). */
162
163struct aarch64_debug_reg_state
164{
165 /* hardware breakpoint */
166 CORE_ADDR dr_addr_bp[AARCH64_HBP_MAX_NUM];
167 unsigned int dr_ctrl_bp[AARCH64_HBP_MAX_NUM];
168 unsigned int dr_ref_count_bp[AARCH64_HBP_MAX_NUM];
169
170 /* hardware watchpoint */
171 CORE_ADDR dr_addr_wp[AARCH64_HWP_MAX_NUM];
172 unsigned int dr_ctrl_wp[AARCH64_HWP_MAX_NUM];
173 unsigned int dr_ref_count_wp[AARCH64_HWP_MAX_NUM];
174};
175
176/* Per-process arch-specific data we want to keep. */
177
178struct arch_process_info
179{
180 /* Hardware breakpoint/watchpoint data.
181 The reason for them to be per-process rather than per-thread is
182 due to the lack of information in the gdbserver environment;
183 gdbserver is not told that whether a requested hardware
184 breakpoint/watchpoint is thread specific or not, so it has to set
185 each hw bp/wp for every thread in the current process. The
186 higher level bp/wp management in gdb will resume a thread if a hw
187 bp/wp trap is not expected for it. Since the hw bp/wp setting is
188 same for each thread, it is reasonable for the data to live here.
189 */
190 struct aarch64_debug_reg_state debug_reg_state;
191};
192
193/* Per-thread arch-specific data we want to keep. */
194
195struct arch_lwp_info
196{
197 /* When bit N is 1, it indicates the Nth hardware breakpoint or
198 watchpoint register pair needs to be updated when the thread is
199 resumed; see aarch64_linux_prepare_to_resume. */
200 dr_changed_t dr_changed_bp;
201 dr_changed_t dr_changed_wp;
202};
203
204/* Number of hardware breakpoints/watchpoints the target supports.
205 They are initialized with values obtained via the ptrace calls
206 with NT_ARM_HW_BREAK and NT_ARM_HW_WATCH respectively. */
207
208static int aarch64_num_bp_regs;
209static int aarch64_num_wp_regs;
210
211/* Hardware breakpoint/watchpoint types.
212 The values map to their encodings in the bit 4 and bit 3 of the
213 hardware breakpoint/watchpoint control registers. */
214
215enum target_point_type
216{
217 hw_execute = 0, /* Execute HW breakpoint */
218 hw_read = 1, /* Read HW watchpoint */
219 hw_write = 2, /* Common HW watchpoint */
220 hw_access = 3, /* Access HW watchpoint */
221 point_type_unsupported
222};
223
224#define Z_PACKET_SW_BP '0'
225#define Z_PACKET_HW_BP '1'
226#define Z_PACKET_WRITE_WP '2'
227#define Z_PACKET_READ_WP '3'
228#define Z_PACKET_ACCESS_WP '4'
229
230/* Map the protocol breakpoint/watchpoint type TYPE to
231 enum target_point_type. */
232
233static enum target_point_type
234Z_packet_to_point_type (char type)
235{
236 switch (type)
237 {
238 case Z_PACKET_SW_BP:
239 /* Leave the handling of the sw breakpoint with the gdb client. */
240 return point_type_unsupported;
241 case Z_PACKET_HW_BP:
242 return hw_execute;
243 case Z_PACKET_WRITE_WP:
244 return hw_write;
245 case Z_PACKET_READ_WP:
246 return hw_read;
247 case Z_PACKET_ACCESS_WP:
248 return hw_access;
249 default:
250 return point_type_unsupported;
251 }
252}
253
254static int
255aarch64_cannot_store_register (int regno)
256{
257 return regno >= AARCH64_NUM_REGS;
258}
259
260static int
261aarch64_cannot_fetch_register (int regno)
262{
263 return regno >= AARCH64_NUM_REGS;
264}
265
266static void
267aarch64_fill_gregset (struct regcache *regcache, void *buf)
268{
269 struct user_pt_regs *regset = buf;
270 int i;
271
272 for (i = 0; i < AARCH64_X_REGS_NUM; i++)
273 collect_register (regcache, AARCH64_X0_REGNO + i, &regset->regs[i]);
274 collect_register (regcache, AARCH64_SP_REGNO, &regset->sp);
275 collect_register (regcache, AARCH64_PC_REGNO, &regset->pc);
276 collect_register (regcache, AARCH64_CPSR_REGNO, &regset->pstate);
277}
278
279static void
280aarch64_store_gregset (struct regcache *regcache, const void *buf)
281{
282 const struct user_pt_regs *regset = buf;
283 int i;
284
285 for (i = 0; i < AARCH64_X_REGS_NUM; i++)
286 supply_register (regcache, AARCH64_X0_REGNO + i, &regset->regs[i]);
287 supply_register (regcache, AARCH64_SP_REGNO, &regset->sp);
288 supply_register (regcache, AARCH64_PC_REGNO, &regset->pc);
289 supply_register (regcache, AARCH64_CPSR_REGNO, &regset->pstate);
290}
291
292static void
293aarch64_fill_fpregset (struct regcache *regcache, void *buf)
294{
295 struct user_fpsimd_state *regset = buf;
296 int i;
297
298 for (i = 0; i < AARCH64_V_REGS_NUM; i++)
299 collect_register (regcache, AARCH64_V0_REGNO + i, &regset->vregs[i]);
300}
301
302static void
303aarch64_store_fpregset (struct regcache *regcache, const void *buf)
304{
305 const struct user_fpsimd_state *regset = buf;
306 int i;
307
308 for (i = 0; i < AARCH64_V_REGS_NUM; i++)
309 supply_register (regcache, AARCH64_V0_REGNO + i, &regset->vregs[i]);
310}
311
312/* Debugging of hardware breakpoint/watchpoint support. */
313extern int debug_hw_points;
314
315/* Enable miscellaneous debugging output. The name is historical - it
316 was originally used to debug LinuxThreads support. */
317extern int debug_threads;
318
319static CORE_ADDR
320aarch64_get_pc (struct regcache *regcache)
321{
322 unsigned long pc;
323
324 collect_register_by_name (regcache, "pc", &pc);
325 if (debug_threads)
326 fprintf (stderr, "stop pc is %08lx\n", pc);
327 return pc;
328}
329
330static void
331aarch64_set_pc (struct regcache *regcache, CORE_ADDR pc)
332{
333 unsigned long newpc = pc;
334 supply_register_by_name (regcache, "pc", &newpc);
335}
336
337/* Correct in either endianness. */
338
339#define aarch64_breakpoint_len 4
340
341static const unsigned long aarch64_breakpoint = 0x00800011;
342
343static int
344aarch64_breakpoint_at (CORE_ADDR where)
345{
346 unsigned long insn;
347
348 (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
349 if (insn == aarch64_breakpoint)
350 return 1;
351
352 return 0;
353}
354
355/* Print the values of the cached breakpoint/watchpoint registers.
356 This is enabled via the "set debug-hw-points" monitor command. */
357
358static void
359aarch64_show_debug_reg_state (struct aarch64_debug_reg_state *state,
360 const char *func, CORE_ADDR addr,
361 int len, enum target_point_type type)
362{
363 int i;
364
365 fprintf (stderr, "%s", func);
366 if (addr || len)
367 fprintf (stderr, " (addr=0x%08lx, len=%d, type=%s)",
368 (unsigned long) addr, len,
369 type == hw_write ? "hw-write-watchpoint"
370 : (type == hw_read ? "hw-read-watchpoint"
371 : (type == hw_access ? "hw-access-watchpoint"
372 : (type == hw_execute ? "hw-breakpoint"
373 : "??unknown??"))));
374 fprintf (stderr, ":\n");
375
376 fprintf (stderr, "\tBREAKPOINTs:\n");
377 for (i = 0; i < aarch64_num_bp_regs; i++)
378 fprintf (stderr, "\tBP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
379 i, paddress (state->dr_addr_bp[i]),
380 state->dr_ctrl_bp[i], state->dr_ref_count_bp[i]);
381
382 fprintf (stderr, "\tWATCHPOINTs:\n");
383 for (i = 0; i < aarch64_num_wp_regs; i++)
384 fprintf (stderr, "\tWP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
385 i, paddress (state->dr_addr_wp[i]),
386 state->dr_ctrl_wp[i], state->dr_ref_count_wp[i]);
387}
388
389static void
390aarch64_init_debug_reg_state (struct aarch64_debug_reg_state *state)
391{
392 int i;
393
394 for (i = 0; i < AARCH64_HBP_MAX_NUM; ++i)
395 {
396 state->dr_addr_bp[i] = 0;
397 state->dr_ctrl_bp[i] = 0;
398 state->dr_ref_count_bp[i] = 0;
399 }
400
401 for (i = 0; i < AARCH64_HWP_MAX_NUM; ++i)
402 {
403 state->dr_addr_wp[i] = 0;
404 state->dr_ctrl_wp[i] = 0;
405 state->dr_ref_count_wp[i] = 0;
406 }
407}
408
409/* ptrace expects control registers to be formatted as follows:
410
411 31 13 5 3 1 0
412 +--------------------------------+----------+------+------+----+
413 | RESERVED (SBZ) | LENGTH | TYPE | PRIV | EN |
414 +--------------------------------+----------+------+------+----+
415
416 The TYPE field is ignored for breakpoints. */
417
418#define DR_CONTROL_ENABLED(ctrl) (((ctrl) & 0x1) == 1)
419#define DR_CONTROL_LENGTH(ctrl) (((ctrl) >> 5) & 0xff)
420
421/* Utility function that returns the length in bytes of a watchpoint
422 according to the content of a hardware debug control register CTRL.
423 Note that the kernel currently only supports the following Byte
424 Address Select (BAS) values: 0x1, 0x3, 0xf and 0xff, which means
425 that for a hardware watchpoint, its valid length can only be 1
426 byte, 2 bytes, 4 bytes or 8 bytes. */
427
428static inline unsigned int
429aarch64_watchpoint_length (unsigned int ctrl)
430{
431 switch (DR_CONTROL_LENGTH (ctrl))
432 {
433 case 0x01:
434 return 1;
435 case 0x03:
436 return 2;
437 case 0x0f:
438 return 4;
439 case 0xff:
440 return 8;
441 default:
442 return 0;
443 }
444}
445
446/* Given the hardware breakpoint or watchpoint type TYPE and its
447 length LEN, return the expected encoding for a hardware
448 breakpoint/watchpoint control register. */
449
450static unsigned int
451aarch64_point_encode_ctrl_reg (enum target_point_type type, int len)
452{
453 unsigned int ctrl;
454
455 /* type */
456 ctrl = type << 3;
457 /* length bitmask */
458 ctrl |= ((1 << len) - 1) << 5;
459 /* enabled at el0 */
460 ctrl |= (2 << 1) | 1;
461
462 return ctrl;
463}
464
465/* Addresses to be written to the hardware breakpoint and watchpoint
466 value registers need to be aligned; the alignment is 4-byte and
467 8-type respectively. Linux kernel rejects any non-aligned address
468 it receives from the related ptrace call. Furthermore, the kernel
469 currently only supports the following Byte Address Select (BAS)
470 values: 0x1, 0x3, 0xf and 0xff, which means that for a hardware
471 watchpoint to be accepted by the kernel (via ptrace call), its
472 valid length can only be 1 byte, 2 bytes, 4 bytes or 8 bytes.
473 Despite these limitations, the unaligned watchpoint is supported in
474 this gdbserver port.
475
476 Return 0 for any non-compliant ADDR and/or LEN; return 1 otherwise. */
477
478static int
479aarch64_point_is_aligned (int is_watchpoint, CORE_ADDR addr, int len)
480{
481 unsigned int alignment = is_watchpoint ? AARCH64_HWP_ALIGNMENT
482 : AARCH64_HBP_ALIGNMENT;
483
484 if (addr & (alignment - 1))
485 return 0;
486
487 if (len != 8 && len != 4 && len != 2 && len != 1)
488 return 0;
489
490 return 1;
491}
492
493/* Given the (potentially unaligned) watchpoint address in ADDR and
494 length in LEN, return the aligned address and aligned length in
495 *ALIGNED_ADDR_P and *ALIGNED_LEN_P, respectively. The returned
496 aligned address and length will be valid to be written to the
497 hardware watchpoint value and control registers. See the comment
498 above aarch64_point_is_aligned for the information about the
499 alignment requirement. The given watchpoint may get truncated if
500 more than one hardware register is needed to cover the watched
501 region. *NEXT_ADDR_P and *NEXT_LEN_P, if non-NULL, will return the
502 address and length of the remaining part of the watchpoint (which
503 can be processed by calling this routine again to generate another
504 aligned address and length pair.
505
506 Essentially, unaligned watchpoint is achieved by minimally
507 enlarging the watched area to meet the alignment requirement, and
508 if necessary, splitting the watchpoint over several hardware
509 watchpoint registers. The trade-off is that there will be
510 false-positive hits for the read-type or the access-type hardware
511 watchpoints; for the write type, which is more commonly used, there
512 will be no such issues, as the higher-level breakpoint management
513 in gdb always examines the exact watched region for any content
514 change, and transparently resumes a thread from a watchpoint trap
515 if there is no change to the watched region.
516
517 Another limitation is that because the watched region is enlarged,
518 the watchpoint fault address returned by
519 aarch64_stopped_data_address may be outside of the original watched
520 region, especially when the triggering instruction is accessing a
521 larger region. When the fault address is not within any known
522 range, watchpoints_triggered in gdb will get confused, as the
523 higher-level watchpoint management is only aware of original
524 watched regions, and will think that some unknown watchpoint has
525 been triggered. In such a case, gdb may stop without displaying
526 any detailed information.
527
528 Once the kernel provides the full support for Byte Address Select
529 (BAS) in the hardware watchpoint control register, these
530 limitations can be largely relaxed with some further work. */
531
532static void
533aarch64_align_watchpoint (CORE_ADDR addr, int len, CORE_ADDR *aligned_addr_p,
534 int *aligned_len_p, CORE_ADDR *next_addr_p,
535 int *next_len_p)
536{
537 int aligned_len;
538 unsigned int offset;
539 CORE_ADDR aligned_addr;
540 const unsigned int alignment = AARCH64_HWP_ALIGNMENT;
541 const unsigned int max_wp_len = AARCH64_HWP_MAX_LEN_PER_REG;
542
543 /* As assumed by the algorithm. */
544 gdb_assert (alignment == max_wp_len);
545
546 if (len <= 0)
547 return;
548
549 /* Address to be put into the hardware watchpoint value register
550 must be aligned. */
551 offset = addr & (alignment - 1);
552 aligned_addr = addr - offset;
553
554 gdb_assert (offset >= 0 && offset < alignment);
555 gdb_assert (aligned_addr >= 0 && aligned_addr <= addr);
556 gdb_assert ((offset + len) > 0);
557
558 if (offset + len >= max_wp_len)
559 {
560 /* Need more than one watchpoint registers; truncate it at the
561 alignment boundary. */
562 aligned_len = max_wp_len;
563 len -= (max_wp_len - offset);
564 addr += (max_wp_len - offset);
565 gdb_assert ((addr & (alignment - 1)) == 0);
566 }
567 else
568 {
569 /* Find the smallest valid length that is large enough to
570 accommodate this watchpoint. */
571 static const unsigned char
572 aligned_len_array[AARCH64_HWP_MAX_LEN_PER_REG] =
573 { 1, 2, 4, 4, 8, 8, 8, 8 };
574
575 aligned_len = aligned_len_array[offset + len - 1];
576 addr += len;
577 len = 0;
578 }
579
580 if (aligned_addr_p != NULL)
581 *aligned_addr_p = aligned_addr;
582 if (aligned_len_p != NULL)
583 *aligned_len_p = aligned_len;
584 if (next_addr_p != NULL)
585 *next_addr_p = addr;
586 if (next_len_p != NULL)
587 *next_len_p = len;
588}
589
590/* Call ptrace to set the thread TID's hardware breakpoint/watchpoint
591 registers with data from *STATE. */
592
593static void
594aarch64_linux_set_debug_regs (const struct aarch64_debug_reg_state *state,
595 int tid, int watchpoint)
596{
597 int i, count;
598 struct iovec iov;
599 struct user_hwdebug_state regs;
600 const CORE_ADDR *addr;
601 const unsigned int *ctrl;
602
c623a6ef 603 memset (&regs, 0, sizeof (regs));
176eb98c
MS
604 iov.iov_base = &regs;
605 iov.iov_len = sizeof (regs);
606 count = watchpoint ? aarch64_num_wp_regs : aarch64_num_bp_regs;
607 addr = watchpoint ? state->dr_addr_wp : state->dr_addr_bp;
608 ctrl = watchpoint ? state->dr_ctrl_wp : state->dr_ctrl_bp;
609
610 for (i = 0; i < count; i++)
611 {
612 regs.dbg_regs[i].addr = addr[i];
613 regs.dbg_regs[i].ctrl = ctrl[i];
614 }
615
616 if (ptrace (PTRACE_SETREGSET, tid,
617 watchpoint ? NT_ARM_HW_WATCH : NT_ARM_HW_BREAK,
618 (void *) &iov))
619 error (_("Unexpected error setting hardware debug registers"));
620}
621
622struct aarch64_dr_update_callback_param
623{
624 int pid;
625 int is_watchpoint;
626 unsigned int idx;
627};
628
629/* Callback function which records the information about the change of
630 one hardware breakpoint/watchpoint setting for the thread ENTRY.
631 The information is passed in via PTR.
632 N.B. The actual updating of hardware debug registers is not
633 carried out until the moment the thread is resumed. */
634
635static int
636debug_reg_change_callback (struct inferior_list_entry *entry, void *ptr)
637{
638 struct lwp_info *lwp = (struct lwp_info *) entry;
639 struct aarch64_dr_update_callback_param *param_p
640 = (struct aarch64_dr_update_callback_param *) ptr;
641 int pid = param_p->pid;
642 int idx = param_p->idx;
643 int is_watchpoint = param_p->is_watchpoint;
644 struct arch_lwp_info *info = lwp->arch_private;
645 dr_changed_t *dr_changed_ptr;
646 dr_changed_t dr_changed;
647
648 if (debug_hw_points)
649 {
650 fprintf (stderr, "debug_reg_change_callback: \n\tOn entry:\n");
651 fprintf (stderr, "\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
652 "dr_changed_wp=0x%llx\n",
653 pid, lwpid_of (lwp), info->dr_changed_bp,
654 info->dr_changed_wp);
655 }
656
657 dr_changed_ptr = is_watchpoint ? &info->dr_changed_wp
658 : &info->dr_changed_bp;
659 dr_changed = *dr_changed_ptr;
660
661 /* Only update the threads of this process. */
662 if (pid_of (lwp) == pid)
663 {
664 gdb_assert (idx >= 0
665 && (idx <= (is_watchpoint ? aarch64_num_wp_regs
666 : aarch64_num_bp_regs)));
667
668 /* The following assertion is not right, as there can be changes
669 that have not been made to the hardware debug registers
670 before new changes overwrite the old ones. This can happen,
671 for instance, when the breakpoint/watchpoint hit one of the
672 threads and the user enters continue; then what happens is:
673 1) all breakpoints/watchpoints are removed for all threads;
674 2) a single step is carried out for the thread that was hit;
675 3) all of the points are inserted again for all threads;
676 4) all threads are resumed.
677 The 2nd step will only affect the one thread in which the
678 bp/wp was hit, which means only that one thread is resumed;
679 remember that the actual updating only happen in
680 aarch64_linux_prepare_to_resume, so other threads remain
681 stopped during the removal and insertion of bp/wp. Therefore
682 for those threads, the change of insertion of the bp/wp
683 overwrites that of the earlier removals. (The situation may
684 be different when bp/wp is steppable, or in the non-stop
685 mode.) */
686 /* gdb_assert (DR_N_HAS_CHANGED (dr_changed, idx) == 0); */
687
688 /* The actual update is done later just before resuming the lwp,
689 we just mark that one register pair needs updating. */
690 DR_MARK_N_CHANGED (dr_changed, idx);
691 *dr_changed_ptr = dr_changed;
692
693 /* If the lwp isn't stopped, force it to momentarily pause, so
694 we can update its debug registers. */
695 if (!lwp->stopped)
696 linux_stop_lwp (lwp);
697 }
698
699 if (debug_hw_points)
700 {
701 fprintf (stderr, "\tOn exit:\n\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
702 "dr_changed_wp=0x%llx\n",
703 pid, lwpid_of (lwp), info->dr_changed_bp, info->dr_changed_wp);
704 }
705
706 return 0;
707}
708
709/* Notify each thread that their IDXth breakpoint/watchpoint register
710 pair needs to be updated. The message will be recorded in each
711 thread's arch-specific data area, the actual updating will be done
712 when the thread is resumed. */
713
714void
715aarch64_notify_debug_reg_change (const struct aarch64_debug_reg_state *state,
716 int is_watchpoint, unsigned int idx)
717{
718 struct aarch64_dr_update_callback_param param;
719
720 /* Only update the threads of this process. */
721 param.pid = pid_of (get_thread_lwp (current_inferior));
722
723 param.is_watchpoint = is_watchpoint;
724 param.idx = idx;
725
726 find_inferior (&all_lwps, debug_reg_change_callback, (void *) &param);
727}
728
729
730/* Return the pointer to the debug register state structure in the
731 current process' arch-specific data area. */
732
733static struct aarch64_debug_reg_state *
734aarch64_get_debug_reg_state ()
735{
736 struct process_info *proc;
737
738 proc = current_process ();
739 return &proc->private->arch_private->debug_reg_state;
740}
741
742/* Record the insertion of one breakpoint/watchpoint, as represented
743 by ADDR and CTRL, in the process' arch-specific data area *STATE. */
744
745static int
746aarch64_dr_state_insert_one_point (struct aarch64_debug_reg_state *state,
747 enum target_point_type type,
748 CORE_ADDR addr, int len)
749{
750 int i, idx, num_regs, is_watchpoint;
751 unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
752 CORE_ADDR *dr_addr_p;
753
754 /* Set up state pointers. */
755 is_watchpoint = (type != hw_execute);
756 gdb_assert (aarch64_point_is_aligned (is_watchpoint, addr, len));
757 if (is_watchpoint)
758 {
759 num_regs = aarch64_num_wp_regs;
760 dr_addr_p = state->dr_addr_wp;
761 dr_ctrl_p = state->dr_ctrl_wp;
762 dr_ref_count = state->dr_ref_count_wp;
763 }
764 else
765 {
766 num_regs = aarch64_num_bp_regs;
767 dr_addr_p = state->dr_addr_bp;
768 dr_ctrl_p = state->dr_ctrl_bp;
769 dr_ref_count = state->dr_ref_count_bp;
770 }
771
772 ctrl = aarch64_point_encode_ctrl_reg (type, len);
773
774 /* Find an existing or free register in our cache. */
775 idx = -1;
776 for (i = 0; i < num_regs; ++i)
777 {
778 if ((dr_ctrl_p[i] & 1) == 0)
779 {
780 gdb_assert (dr_ref_count[i] == 0);
781 idx = i;
782 /* no break; continue hunting for an exising one. */
783 }
784 else if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
785 {
786 gdb_assert (dr_ref_count[i] != 0);
787 idx = i;
788 break;
789 }
790 }
791
792 /* No space. */
793 if (idx == -1)
794 return -1;
795
796 /* Update our cache. */
797 if ((dr_ctrl_p[idx] & 1) == 0)
798 {
799 /* new entry */
800 dr_addr_p[idx] = addr;
801 dr_ctrl_p[idx] = ctrl;
802 dr_ref_count[idx] = 1;
803 /* Notify the change. */
804 aarch64_notify_debug_reg_change (state, is_watchpoint, idx);
805 }
806 else
807 {
808 /* existing entry */
809 dr_ref_count[idx]++;
810 }
811
812 return 0;
813}
814
815/* Record the removal of one breakpoint/watchpoint, as represented by
816 ADDR and CTRL, in the process' arch-specific data area *STATE. */
817
818static int
819aarch64_dr_state_remove_one_point (struct aarch64_debug_reg_state *state,
820 enum target_point_type type,
821 CORE_ADDR addr, int len)
822{
823 int i, num_regs, is_watchpoint;
824 unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
825 CORE_ADDR *dr_addr_p;
826
827 /* Set up state pointers. */
828 is_watchpoint = (type != hw_execute);
829 gdb_assert (aarch64_point_is_aligned (is_watchpoint, addr, len));
830 if (is_watchpoint)
831 {
832 num_regs = aarch64_num_wp_regs;
833 dr_addr_p = state->dr_addr_wp;
834 dr_ctrl_p = state->dr_ctrl_wp;
835 dr_ref_count = state->dr_ref_count_wp;
836 }
837 else
838 {
839 num_regs = aarch64_num_bp_regs;
840 dr_addr_p = state->dr_addr_bp;
841 dr_ctrl_p = state->dr_ctrl_bp;
842 dr_ref_count = state->dr_ref_count_bp;
843 }
844
845 ctrl = aarch64_point_encode_ctrl_reg (type, len);
846
847 /* Find the entry that matches the ADDR and CTRL. */
848 for (i = 0; i < num_regs; ++i)
849 if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
850 {
851 gdb_assert (dr_ref_count[i] != 0);
852 break;
853 }
854
855 /* Not found. */
856 if (i == num_regs)
857 return -1;
858
859 /* Clear our cache. */
860 if (--dr_ref_count[i] == 0)
861 {
862 /* Clear the enable bit. */
863 ctrl &= ~1;
864 dr_addr_p[i] = 0;
865 dr_ctrl_p[i] = ctrl;
866 /* Notify the change. */
867 aarch64_notify_debug_reg_change (state, is_watchpoint, i);
868 }
869
870 return 0;
871}
872
873static int
874aarch64_handle_breakpoint (enum target_point_type type, CORE_ADDR addr,
875 int len, int is_insert)
876{
877 struct aarch64_debug_reg_state *state;
878
879 /* The hardware breakpoint on AArch64 should always be 4-byte
880 aligned. */
881 if (!aarch64_point_is_aligned (0 /* is_watchpoint */ , addr, len))
882 return -1;
883
884 state = aarch64_get_debug_reg_state ();
885
886 if (is_insert)
887 return aarch64_dr_state_insert_one_point (state, type, addr, len);
888 else
889 return aarch64_dr_state_remove_one_point (state, type, addr, len);
890}
891
892/* This is essentially the same as aarch64_handle_breakpoint, apart
893 from that it is an aligned watchpoint to be handled. */
894
895static int
896aarch64_handle_aligned_watchpoint (enum target_point_type type,
897 CORE_ADDR addr, int len, int is_insert)
898{
899 struct aarch64_debug_reg_state *state;
900
901 state = aarch64_get_debug_reg_state ();
902
903 if (is_insert)
904 return aarch64_dr_state_insert_one_point (state, type, addr, len);
905 else
906 return aarch64_dr_state_remove_one_point (state, type, addr, len);
907}
908
909/* Insert/remove unaligned watchpoint by calling
910 aarch64_align_watchpoint repeatedly until the whole watched region,
911 as represented by ADDR and LEN, has been properly aligned and ready
912 to be written to one or more hardware watchpoint registers.
913 IS_INSERT indicates whether this is an insertion or a deletion.
914 Return 0 if succeed. */
915
916static int
917aarch64_handle_unaligned_watchpoint (enum target_point_type type,
918 CORE_ADDR addr, int len, int is_insert)
919{
920 struct aarch64_debug_reg_state *state
921 = aarch64_get_debug_reg_state ();
922
923 while (len > 0)
924 {
925 CORE_ADDR aligned_addr;
926 int aligned_len, ret;
927
928 aarch64_align_watchpoint (addr, len, &aligned_addr, &aligned_len,
929 &addr, &len);
930
931 if (is_insert)
932 ret = aarch64_dr_state_insert_one_point (state, type, aligned_addr,
933 aligned_len);
934 else
935 ret = aarch64_dr_state_remove_one_point (state, type, aligned_addr,
936 aligned_len);
937
938 if (debug_hw_points)
939 fprintf (stderr,
940 "handle_unaligned_watchpoint: is_insert: %d\n"
941 " aligned_addr: 0x%s, aligned_len: %d\n"
942 " next_addr: 0x%s, next_len: %d\n",
943 is_insert, paddress (aligned_addr), aligned_len,
944 paddress (addr), len);
945
946 if (ret != 0)
947 return ret;
948 }
949
950 return 0;
951}
952
953static int
954aarch64_handle_watchpoint (enum target_point_type type, CORE_ADDR addr,
955 int len, int is_insert)
956{
957 if (aarch64_point_is_aligned (1 /* is_watchpoint */ , addr, len))
958 return aarch64_handle_aligned_watchpoint (type, addr, len, is_insert);
959 else
960 return aarch64_handle_unaligned_watchpoint (type, addr, len, is_insert);
961}
962
963/* Insert a hardware breakpoint/watchpoint.
964 It actually only records the info of the to-be-inserted bp/wp;
965 the actual insertion will happen when threads are resumed.
966
967 Return 0 if succeed;
968 Return 1 if TYPE is unsupported type;
969 Return -1 if an error occurs. */
970
971static int
972aarch64_insert_point (char type, CORE_ADDR addr, int len)
973{
974 int ret;
975 enum target_point_type targ_type;
976
977 if (debug_hw_points)
978 fprintf (stderr, "insert_point on entry (addr=0x%08lx, len=%d)\n",
979 (unsigned long) addr, len);
980
981 /* Determine the type from the packet. */
982 targ_type = Z_packet_to_point_type (type);
983 if (targ_type == point_type_unsupported)
984 return 1;
985
986 if (targ_type != hw_execute)
987 ret =
988 aarch64_handle_watchpoint (targ_type, addr, len, 1 /* is_insert */);
989 else
990 ret =
991 aarch64_handle_breakpoint (targ_type, addr, len, 1 /* is_insert */);
992
993 if (debug_hw_points > 1)
994 aarch64_show_debug_reg_state (aarch64_get_debug_reg_state (),
995 "insert_point", addr, len, targ_type);
996
997 return ret;
998}
999
1000/* Remove a hardware breakpoint/watchpoint.
1001 It actually only records the info of the to-be-removed bp/wp,
1002 the actual removal will be done when threads are resumed.
1003
1004 Return 0 if succeed;
1005 Return 1 if TYPE is an unsupported type;
1006 Return -1 if an error occurs. */
1007
1008static int
1009aarch64_remove_point (char type, CORE_ADDR addr, int len)
1010{
1011 int ret;
1012 enum target_point_type targ_type;
1013
1014 if (debug_hw_points)
1015 fprintf (stderr, "remove_point on entry (addr=0x%08lx, len=%d)\n",
1016 (unsigned long) addr, len);
1017
1018 /* Determine the type from the packet. */
1019 targ_type = Z_packet_to_point_type (type);
1020 if (targ_type == point_type_unsupported)
1021 return 1;
1022
1023 /* Set up state pointers. */
1024 if (targ_type != hw_execute)
1025 ret =
1026 aarch64_handle_watchpoint (targ_type, addr, len, 0 /* is_insert */);
1027 else
1028 ret =
1029 aarch64_handle_breakpoint (targ_type, addr, len, 0 /* is_insert */);
1030
1031 if (debug_hw_points > 1)
1032 aarch64_show_debug_reg_state (aarch64_get_debug_reg_state (),
1033 "remove_point", addr, len, targ_type);
1034
1035 return ret;
1036}
1037
1038/* Returns the address associated with the watchpoint that hit, if
1039 any; returns 0 otherwise. */
1040
1041static CORE_ADDR
1042aarch64_stopped_data_address (void)
1043{
1044 siginfo_t siginfo;
1045 int pid, i;
1046 struct aarch64_debug_reg_state *state;
1047
1048 pid = lwpid_of (get_thread_lwp (current_inferior));
1049
1050 /* Get the siginfo. */
1051 if (ptrace (PTRACE_GETSIGINFO, pid, NULL, &siginfo) != 0)
1052 return (CORE_ADDR) 0;
1053
1054 /* Need to be a hardware breakpoint/watchpoint trap. */
1055 if (siginfo.si_signo != SIGTRAP
1056 || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
1057 return (CORE_ADDR) 0;
1058
1059 /* Check if the address matches any watched address. */
1060 state = aarch64_get_debug_reg_state ();
1061 for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
1062 {
1063 const unsigned int len = aarch64_watchpoint_length (state->dr_ctrl_wp[i]);
1064 const CORE_ADDR addr_trap = (CORE_ADDR) siginfo.si_addr;
1065 const CORE_ADDR addr_watch = state->dr_addr_wp[i];
1066 if (state->dr_ref_count_wp[i]
1067 && DR_CONTROL_ENABLED (state->dr_ctrl_wp[i])
1068 && addr_trap >= addr_watch
1069 && addr_trap < addr_watch + len)
1070 return addr_trap;
1071 }
1072
1073 return (CORE_ADDR) 0;
1074}
1075
1076/* Returns 1 if target was stopped due to a watchpoint hit, 0
1077 otherwise. */
1078
1079static int
1080aarch64_stopped_by_watchpoint (void)
1081{
1082 if (aarch64_stopped_data_address () != 0)
1083 return 1;
1084 else
1085 return 0;
1086}
1087
1088/* Fetch the thread-local storage pointer for libthread_db. */
1089
1090ps_err_e
55fac6e0 1091ps_get_thread_area (const struct ps_prochandle *ph,
176eb98c
MS
1092 lwpid_t lwpid, int idx, void **base)
1093{
55fac6e0
MS
1094 struct iovec iovec;
1095 uint64_t reg;
1096
1097 iovec.iov_base = &reg;
1098 iovec.iov_len = sizeof (reg);
1099
1100 if (ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0)
176eb98c
MS
1101 return PS_ERR;
1102
1103 /* IDX is the bias from the thread pointer to the beginning of the
1104 thread descriptor. It has to be subtracted due to implementation
1105 quirks in libthread_db. */
55fac6e0 1106 *base = (void *) (reg - idx);
176eb98c
MS
1107
1108 return PS_OK;
1109}
1110
1111/* Called when a new process is created. */
1112
1113static struct arch_process_info *
1114aarch64_linux_new_process (void)
1115{
1116 struct arch_process_info *info = xcalloc (1, sizeof (*info));
1117
1118 aarch64_init_debug_reg_state (&info->debug_reg_state);
1119
1120 return info;
1121}
1122
1123/* Called when a new thread is detected. */
1124
1125static struct arch_lwp_info *
1126aarch64_linux_new_thread (void)
1127{
1128 struct arch_lwp_info *info = xcalloc (1, sizeof (*info));
1129
1130 /* Mark that all the hardware breakpoint/watchpoint register pairs
1131 for this thread need to be initialized (with data from
1132 aarch_process_info.debug_reg_state). */
1133 DR_MARK_ALL_CHANGED (info->dr_changed_bp, aarch64_num_bp_regs);
1134 DR_MARK_ALL_CHANGED (info->dr_changed_wp, aarch64_num_wp_regs);
1135
1136 return info;
1137}
1138
1139/* Called when resuming a thread.
1140 If the debug regs have changed, update the thread's copies. */
1141
1142static void
1143aarch64_linux_prepare_to_resume (struct lwp_info *lwp)
1144{
1145 ptid_t ptid = ptid_of (lwp);
1146 struct arch_lwp_info *info = lwp->arch_private;
1147
1148 if (DR_HAS_CHANGED (info->dr_changed_bp)
1149 || DR_HAS_CHANGED (info->dr_changed_wp))
1150 {
1151 int tid = ptid_get_lwp (ptid);
1152 struct process_info *proc = find_process_pid (ptid_get_pid (ptid));
1153 struct aarch64_debug_reg_state *state
1154 = &proc->private->arch_private->debug_reg_state;
1155
1156 if (debug_hw_points)
1157 fprintf (stderr, "prepare_to_resume thread %ld\n", lwpid_of (lwp));
1158
1159 /* Watchpoints. */
1160 if (DR_HAS_CHANGED (info->dr_changed_wp))
1161 {
1162 aarch64_linux_set_debug_regs (state, tid, 1);
1163 DR_CLEAR_CHANGED (info->dr_changed_wp);
1164 }
1165
1166 /* Breakpoints. */
1167 if (DR_HAS_CHANGED (info->dr_changed_bp))
1168 {
1169 aarch64_linux_set_debug_regs (state, tid, 0);
1170 DR_CLEAR_CHANGED (info->dr_changed_bp);
1171 }
1172 }
1173}
1174
1175/* ptrace hardware breakpoint resource info is formatted as follows:
1176
1177 31 24 16 8 0
1178 +---------------+--------------+---------------+---------------+
1179 | RESERVED | RESERVED | DEBUG_ARCH | NUM_SLOTS |
1180 +---------------+--------------+---------------+---------------+ */
1181
1182#define AARCH64_DEBUG_NUM_SLOTS(x) ((x) & 0xff)
1183#define AARCH64_DEBUG_ARCH(x) (((x) >> 8) & 0xff)
1184#define AARCH64_DEBUG_ARCH_V8 0x6
1185
1186static void
1187aarch64_arch_setup (void)
1188{
1189 int pid;
1190 struct iovec iov;
1191 struct user_hwdebug_state dreg_state;
1192
3aee8918 1193 current_process ()->tdesc = tdesc_aarch64;
176eb98c
MS
1194
1195 pid = lwpid_of (get_thread_lwp (current_inferior));
1196 iov.iov_base = &dreg_state;
1197 iov.iov_len = sizeof (dreg_state);
1198
1199 /* Get hardware watchpoint register info. */
1200 if (ptrace (PTRACE_GETREGSET, pid, NT_ARM_HW_WATCH, &iov) == 0
1201 && AARCH64_DEBUG_ARCH (dreg_state.dbg_info) == AARCH64_DEBUG_ARCH_V8)
1202 {
1203 aarch64_num_wp_regs = AARCH64_DEBUG_NUM_SLOTS (dreg_state.dbg_info);
148de6bb
MS
1204 if (aarch64_num_wp_regs > AARCH64_HWP_MAX_NUM)
1205 {
1206 warning ("Unexpected number of hardware watchpoint registers reported"
1207 " by ptrace, got %d, expected %d.",
1208 aarch64_num_wp_regs, AARCH64_HWP_MAX_NUM);
1209 aarch64_num_wp_regs = AARCH64_HWP_MAX_NUM;
1210 }
176eb98c
MS
1211 }
1212 else
1213 {
1214 warning ("Unable to determine the number of hardware watchpoints"
1215 " available.");
1216 aarch64_num_wp_regs = 0;
1217 }
1218
1219 /* Get hardware breakpoint register info. */
1220 if (ptrace (PTRACE_GETREGSET, pid, NT_ARM_HW_BREAK, &iov) == 0
1221 && AARCH64_DEBUG_ARCH (dreg_state.dbg_info) == AARCH64_DEBUG_ARCH_V8)
1222 {
1223 aarch64_num_bp_regs = AARCH64_DEBUG_NUM_SLOTS (dreg_state.dbg_info);
1224 if (aarch64_num_bp_regs > AARCH64_HBP_MAX_NUM)
148de6bb
MS
1225 {
1226 warning ("Unexpected number of hardware breakpoint registers reported"
1227 " by ptrace, got %d, expected %d.",
1228 aarch64_num_bp_regs, AARCH64_HBP_MAX_NUM);
1229 aarch64_num_bp_regs = AARCH64_HBP_MAX_NUM;
1230 }
176eb98c
MS
1231 }
1232 else
1233 {
1234 warning ("Unable to determine the number of hardware breakpoints"
1235 " available.");
1236 aarch64_num_bp_regs = 0;
1237 }
1238}
1239
3aee8918 1240static struct regset_info aarch64_regsets[] =
176eb98c
MS
1241{
1242 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
1243 sizeof (struct user_pt_regs), GENERAL_REGS,
1244 aarch64_fill_gregset, aarch64_store_gregset },
1245 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET,
1246 sizeof (struct user_fpsimd_state), FP_REGS,
1247 aarch64_fill_fpregset, aarch64_store_fpregset
1248 },
1249 { 0, 0, 0, -1, -1, NULL, NULL }
1250};
1251
3aee8918
PA
1252static struct regsets_info aarch64_regsets_info =
1253 {
1254 aarch64_regsets, /* regsets */
1255 0, /* num_regsets */
1256 NULL, /* disabled_regsets */
1257 };
1258
1259static struct usrregs_info aarch64_usrregs_info =
1260 {
1261 AARCH64_NUM_REGS,
1262 aarch64_regmap,
1263 };
1264
1265static struct regs_info regs_info =
1266 {
1267 NULL, /* regset_bitmap */
1268 &aarch64_usrregs_info,
1269 &aarch64_regsets_info,
1270 };
1271
1272static const struct regs_info *
1273aarch64_regs_info (void)
1274{
1275 return &regs_info;
1276}
1277
176eb98c
MS
1278struct linux_target_ops the_low_target =
1279{
1280 aarch64_arch_setup,
3aee8918 1281 aarch64_regs_info,
176eb98c
MS
1282 aarch64_cannot_fetch_register,
1283 aarch64_cannot_store_register,
1284 NULL,
1285 aarch64_get_pc,
1286 aarch64_set_pc,
1287 (const unsigned char *) &aarch64_breakpoint,
1288 aarch64_breakpoint_len,
1289 NULL,
1290 0,
1291 aarch64_breakpoint_at,
1292 aarch64_insert_point,
1293 aarch64_remove_point,
1294 aarch64_stopped_by_watchpoint,
1295 aarch64_stopped_data_address,
1296 NULL,
1297 NULL,
1298 NULL,
1299 aarch64_linux_new_process,
1300 aarch64_linux_new_thread,
1301 aarch64_linux_prepare_to_resume,
1302};
3aee8918
PA
1303
1304void
1305initialize_low_arch (void)
1306{
1307 init_registers_aarch64 ();
1308
1309 initialize_regsets_info (&aarch64_regsets_info);
1310}
This page took 0.145888 seconds and 4 git commands to generate.