24 #include "elf/common.h"
28 #include <sys/ptrace.h>
29 #include <asm/ptrace.h>
42 #define AARCH64_X_REGS_NUM 31
43 #define AARCH64_V_REGS_NUM 32
44 #define AARCH64_X0_REGNO 0
45 #define AARCH64_SP_REGNO 31
46 #define AARCH64_PC_REGNO 32
47 #define AARCH64_CPSR_REGNO 33
48 #define AARCH64_V0_REGNO 34
49 #define AARCH64_FPSR_REGNO (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM)
50 #define AARCH64_FPCR_REGNO (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM + 1)
52 #define AARCH64_NUM_REGS (AARCH64_V0_REGNO + AARCH64_V_REGS_NUM + 2)
59 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
60 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8,
61 16*8, 17*8, 18*8, 19*8, 20*8, 21*8, 22*8, 23*8,
62 24*8, 25*8, 26*8, 27*8, 28*8,
70 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16,
71 8*16, 9*16, 10*16, 11*16, 12*16, 13*16, 14*16, 15*16,
72 16*16, 17*16, 18*16, 19*16, 20*16, 21*16, 22*16, 23*16,
73 24*16, 25*16, 26*16, 27*16, 28*16, 29*16, 30*16, 31*16
89 #define AARCH64_HBP_MAX_NUM 16
90 #define AARCH64_HWP_MAX_NUM 16
106 #define AARCH64_HBP_ALIGNMENT 4
107 #define AARCH64_HWP_ALIGNMENT 8
112 #define AARCH64_HWP_MAX_LEN_PER_REG 8
137 #define DR_MARK_ALL_CHANGED(x, m) \
140 gdb_assert (sizeof ((x)) * 8 >= (m)); \
141 (x) = (((dr_changed_t)1 << (m)) - 1); \
144 #define DR_MARK_N_CHANGED(x, n) \
147 (x) |= ((dr_changed_t)1 << (n)); \
150 #define DR_CLEAR_CHANGED(x) \
156 #define DR_HAS_CHANGED(x) ((x) != 0)
157 #define DR_N_HAS_CHANGED(x, n) ((x) & ((dr_changed_t)1 << (n)))
229 struct user_pt_regs *regset = buf;
242 const struct user_pt_regs *regset = buf;
255 struct user_fpsimd_state *regset = buf;
267 const struct user_fpsimd_state *regset = buf;
294 unsigned long newpc = pc;
298 #define aarch64_breakpoint_len 4
328 fprintf (stderr,
"%s", func);
330 fprintf (stderr,
" (addr=0x%08lx, len=%d, type=%s)",
331 (
unsigned long) addr, len,
332 type ==
hw_write ?
"hw-write-watchpoint"
333 : (type ==
hw_read ?
"hw-read-watchpoint"
334 : (type ==
hw_access ?
"hw-access-watchpoint"
337 fprintf (stderr,
":\n");
339 fprintf (stderr,
"\tBREAKPOINTs:\n");
341 fprintf (stderr,
"\tBP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
345 fprintf (stderr,
"\tWATCHPOINTs:\n");
347 fprintf (stderr,
"\tWP%d: addr=0x%s, ctrl=0x%08x, ref.count=%d\n",
381 #define DR_CONTROL_ENABLED(ctrl) (((ctrl) & 0x1) == 1)
382 #define DR_CONTROL_LENGTH(ctrl) (((ctrl) >> 5) & 0xff)
391 static inline unsigned int
416 unsigned int ctrl, ttype;
440 ctrl |= ((1 << len) - 1) << 5;
442 ctrl |= (2 << 1) | 1;
466 if (addr & (alignment - 1))
469 if (len != 8 && len != 4 && len != 2 && len != 1)
516 int *aligned_len_p,
CORE_ADDR *next_addr_p,
533 offset = addr & (alignment - 1);
534 aligned_addr = addr -
offset;
536 gdb_assert (offset >= 0 && offset < alignment);
537 gdb_assert (aligned_addr >= 0 && aligned_addr <= addr);
540 if (offset + len >= max_wp_len)
544 aligned_len = max_wp_len;
545 len -= (max_wp_len -
offset);
546 addr += (max_wp_len -
offset);
553 static const unsigned char
555 { 1, 2, 4, 4, 8, 8, 8, 8 };
557 aligned_len = aligned_len_array[offset + len - 1];
562 if (aligned_addr_p != NULL)
563 *aligned_addr_p = aligned_addr;
564 if (aligned_len_p != NULL)
565 *aligned_len_p = aligned_len;
566 if (next_addr_p != NULL)
568 if (next_len_p != NULL)
577 int tid,
int watchpoint)
581 struct user_hwdebug_state regs;
583 const unsigned int *ctrl;
585 memset (®s, 0,
sizeof (regs));
586 iov.iov_base = ®s;
592 iov.iov_len = (offsetof (
struct user_hwdebug_state, dbg_regs[count - 1])
593 +
sizeof (regs.dbg_regs [count - 1]));
595 for (i = 0; i < count; i++)
597 regs.dbg_regs[i].addr = addr[i];
598 regs.dbg_regs[i].ctrl = ctrl[i];
601 if (ptrace (PTRACE_SETREGSET, tid,
602 watchpoint ? NT_ARM_HW_WATCH : NT_ARM_HW_BREAK,
604 error (
_(
"Unexpected error setting hardware debug registers"));
631 dr_changed_t *dr_changed_ptr;
632 dr_changed_t dr_changed;
636 fprintf (stderr,
"debug_reg_change_callback: \n\tOn entry:\n");
637 fprintf (stderr,
"\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
638 "dr_changed_wp=0x%llx\n",
645 dr_changed = *dr_changed_ptr;
648 if (
pid_of (thread) == pid)
651 && (idx <= (is_watchpoint ? aarch64_num_wp_regs
652 : aarch64_num_bp_regs)));
677 *dr_changed_ptr = dr_changed;
687 fprintf (stderr,
"\tOn exit:\n\tpid%d, tid: %ld, dr_changed_bp=0x%llx, "
688 "dr_changed_wp=0x%llx\n",
703 int is_watchpoint,
unsigned int idx)
737 int i, idx, num_regs, is_watchpoint;
738 unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
763 for (i = 0; i < num_regs; ++i)
765 if ((dr_ctrl_p[i] & 1) == 0)
771 else if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
784 if ((dr_ctrl_p[idx] & 1) == 0)
787 dr_addr_p[idx] = addr;
788 dr_ctrl_p[idx] = ctrl;
789 dr_ref_count[idx] = 1;
810 int i, num_regs, is_watchpoint;
811 unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
835 for (i = 0; i < num_regs; ++i)
836 if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
847 if (--dr_ref_count[i] == 0)
862 int len,
int is_insert)
913 int aligned_len, ret;
927 "handle_unaligned_watchpoint: is_insert: %d\n"
928 " aligned_addr: 0x%s, aligned_len: %d\n"
929 " next_addr: 0x%s, next_len: %d\n",
930 is_insert,
paddress (aligned_addr), aligned_len,
942 int len,
int is_insert)
982 fprintf (stderr,
"insert_point on entry (addr=0x%08lx, len=%d)\n",
983 (
unsigned long) addr, len);
997 "insert_point", addr, len, targ_type);
1018 fprintf (stderr,
"remove_point on entry (addr=0x%08lx, len=%d)\n",
1019 (
unsigned long) addr, len);
1034 "remove_point", addr, len, targ_type);
1056 if (siginfo.si_signo != SIGTRAP
1057 || (siginfo.si_code & 0xffff) != 0x0004 )
1062 for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
1069 && addr_trap >= addr_watch
1070 && addr_trap < addr_watch + len)
1093 lwpid_t lwpid,
int idx,
void **base)
1098 iovec.iov_base = ®
1099 iovec.iov_len =
sizeof (reg);
1107 *base = (
void *) (reg - idx);
1186 fprintf (stderr,
"prepare_to_resume thread %ld\n",
lwpid_of (thread));
1211 #define AARCH64_DEBUG_NUM_SLOTS(x) ((x) & 0xff)
1212 #define AARCH64_DEBUG_ARCH(x) (((x) >> 8) & 0xff)
1213 #define AARCH64_DEBUG_ARCH_V8 0x6
1220 struct user_hwdebug_state dreg_state;
1225 iov.iov_base = &dreg_state;
1226 iov.iov_len =
sizeof (dreg_state);
1235 warning (
"Unexpected number of hardware watchpoint registers reported"
1236 " by ptrace, got %d, expected %d.",
1243 warning (
"Unable to determine the number of hardware watchpoints"
1245 aarch64_num_wp_regs = 0;
1255 warning (
"Unexpected number of hardware breakpoint registers reported"
1256 " by ptrace, got %d, expected %d.",
1263 warning (
"Unable to determine the number of hardware breakpoints"
1265 aarch64_num_bp_regs = 0;
1272 sizeof (
struct user_pt_regs), GENERAL_REGS,
1273 aarch64_fill_gregset, aarch64_store_gregset },
1275 sizeof (
struct user_fpsimd_state), FP_REGS,
1276 aarch64_fill_fpregset, aarch64_store_fpregset
1278 { 0, 0, 0, -1, -1, NULL, NULL }
1281 static struct regsets_info aarch64_regsets_info =
1294 static struct regs_info regs_info =
1301 static const struct regs_info *
1316 (
const unsigned char *) &aarch64_breakpoint,
1340 initialize_regsets_info (&aarch64_regsets_info);
struct arch_lwp_info * arch_private
enum target_hw_bp_type raw_bkpt_type_to_target_hw_bp_type(enum raw_bkpt_type raw_type)
#define DR_MARK_ALL_CHANGED(x, m)
void initialize_low_arch(void)
struct thread_info * current_thread
void collect_register(struct regcache *regcache, int n, void *buf)
static int debug_reg_change_callback(struct inferior_list_entry *entry, void *ptr)
static void aarch64_linux_new_thread(struct lwp_info *lwp)
static void aarch64_store_gregset(struct regcache *regcache, const void *buf)
static void aarch64_fill_gregset(struct regcache *regcache, void *buf)
void supply_register_by_name(struct regcache *regcache, const char *name, const void *buf)
#define AARCH64_DEBUG_ARCH_V8
static void aarch64_linux_set_debug_regs(const struct aarch64_debug_reg_state *state, int tid, int watchpoint)
static int aarch64_cannot_fetch_register(int regno)
static CORE_ADDR aarch64_stopped_data_address(void)
struct aarch64_debug_reg_state debug_reg_state
void warning(const char *fmt,...)
unsigned int dr_ref_count_wp[AARCH64_HWP_MAX_NUM]
static struct aarch64_debug_reg_state * aarch64_get_debug_reg_state()
static int aarch64_handle_unaligned_watchpoint(enum target_hw_bp_type type, CORE_ADDR addr, int len, int is_insert)
struct process_info * find_process_pid(int pid)
static struct regs_info regs_info
char * paddress(CORE_ADDR addr)
static int aarch64_supports_z_point_type(char z_type)
#define AARCH64_FPCR_REGNO
#define AARCH64_CPSR_REGNO
static struct regset_info aarch64_regsets[]
static void aarch64_arch_setup(void)
#define AARCH64_X_REGS_NUM
static int aarch64_regmap[]
static struct arch_process_info * aarch64_linux_new_process(void)
#define get_thread_lwp(thr)
static int aarch64_breakpoint_at(CORE_ADDR where)
struct target_ops * the_target
const struct target_desc * tdesc
static int aarch64_handle_watchpoint(enum target_hw_bp_type type, CORE_ADDR addr, int len, int is_insert)
void init_registers_aarch64(void)
struct arch_process_info * arch_private
static CORE_ADDR aarch64_get_pc(struct regcache *regcache)
static const gdb_byte aarch64_breakpoint[]
static int aarch64_cannot_store_register(int regno)
void collect_register_by_name(struct regcache *regcache, const char *name, void *buf)
ps_err_e ps_get_thread_area(const struct ps_prochandle *ph, lwpid_t lwpid, int idx, void **base)
#define AARCH64_HWP_ALIGNMENT
static unsigned int aarch64_watchpoint_length(unsigned int ctrl)
#define aarch64_breakpoint_len
const struct target_desc * tdesc_aarch64
#define DR_HAS_CHANGED(x)
#define AARCH64_HBP_ALIGNMENT
#define AARCH64_HWP_MAX_LEN_PER_REG
#define AARCH64_DEBUG_NUM_SLOTS(x)
static int aarch64_dr_state_remove_one_point(struct aarch64_debug_reg_state *state, enum target_hw_bp_type type, CORE_ADDR addr, int len)
static void aarch64_linux_new_fork(struct process_info *parent, struct process_info *child)
#define AARCH64_HBP_MAX_NUM
#define get_lwp_thread(lwp)
static struct regsets_info aarch64_regsets_info
static int aarch64_num_bp_regs
static void aarch64_fill_fpregset(struct regcache *regcache, void *buf)
static unsigned int aarch64_point_encode_ctrl_reg(enum target_hw_bp_type type, int len)
#define DR_CLEAR_CHANGED(x)
struct process_info * current_process(void)
CORE_ADDR dr_addr_bp[AARCH64_HBP_MAX_NUM]
static int aarch64_point_is_aligned(int is_watchpoint, CORE_ADDR addr, int len)
struct process_info_private * priv
struct inferior_list all_threads
static void aarch64_set_pc(struct regcache *regcache, CORE_ADDR pc)
int ptid_get_pid(ptid_t ptid)
static void aarch64_show_debug_reg_state(struct aarch64_debug_reg_state *state, const char *func, CORE_ADDR addr, int len, enum target_hw_bp_type type)
#define PTRACE_GETSIGINFO
static int aarch64_remove_point(enum raw_bkpt_type type, CORE_ADDR addr, int len, struct raw_breakpoint *bp)
unsigned long long dr_changed_t
#define AARCH64_FPSR_REGNO
#define DR_CONTROL_ENABLED(ctrl)
static int aarch64_stopped_by_watchpoint(void)
static const struct regs_info * aarch64_regs_info(void)
#define AARCH64_HWP_MAX_NUM
static void aarch64_store_fpregset(struct regcache *regcache, const void *buf)
static int aarch64_handle_breakpoint(enum target_hw_bp_type type, CORE_ADDR addr, int len, int is_insert)
int(* read_memory)(CORE_ADDR memaddr, unsigned char *myaddr, int len)
#define DR_CONTROL_LENGTH(ctrl)
dr_changed_t dr_changed_wp
#define AARCH64_DEBUG_ARCH(x)
#define Z_PACKET_ACCESS_WP
void perror_with_name(const char *string)
static int aarch64_num_wp_regs
unsigned int dr_ref_count_bp[AARCH64_HBP_MAX_NUM]
unsigned int dr_ctrl_wp[AARCH64_HWP_MAX_NUM]
#define DR_MARK_N_CHANGED(x, n)
long ptid_get_lwp(ptid_t ptid)
static struct usrregs_info aarch64_usrregs_info
static int aarch64_handle_aligned_watchpoint(enum target_hw_bp_type type, CORE_ADDR addr, int len, int is_insert)
static void aarch64_linux_prepare_to_resume(struct lwp_info *lwp)
static void aarch64_init_debug_reg_state(struct aarch64_debug_reg_state *state)
void debug_printf(const char *fmt,...)
static int aarch64_dr_state_insert_one_point(struct aarch64_debug_reg_state *state, enum target_hw_bp_type type, CORE_ADDR addr, int len)
void linux_stop_lwp(struct lwp_info *lwp)
dr_changed_t dr_changed_bp
void supply_register(struct regcache *regcache, int n, const void *buf)
PTR xcalloc(size_t number, size_t size)
static void aarch64_align_watchpoint(CORE_ADDR addr, int len, CORE_ADDR *aligned_addr_p, int *aligned_len_p, CORE_ADDR *next_addr_p, int *next_len_p)
void error(const char *fmt,...)
unsigned int dr_ctrl_bp[AARCH64_HBP_MAX_NUM]
#define AARCH64_V_REGS_NUM
#define Z_PACKET_WRITE_WP
struct inferior_list_entry * find_inferior(struct inferior_list *list, int(*func)(struct inferior_list_entry *, void *), void *arg)
void aarch64_notify_debug_reg_change(const struct aarch64_debug_reg_state *state, int is_watchpoint, unsigned int idx)
static int aarch64_insert_point(enum raw_bkpt_type type, CORE_ADDR addr, int len, struct raw_breakpoint *bp)
CORE_ADDR dr_addr_wp[AARCH64_HWP_MAX_NUM]