1 /* Test case for setting a memory-write unaligned watchpoint on aarch64.
3 This software is provided 'as-is', without any express or implied
4 warranty. In no event will the authors be held liable for any damages
5 arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it
12 #include <sys/ptrace.h>
26 kill (child
, SIGKILL
);
30 /* Macros to extract fields from the hardware debug information word. */
31 #define AARCH64_DEBUG_NUM_SLOTS(x) ((x) & 0xff)
32 #define AARCH64_DEBUG_ARCH(x) (((x) >> 8) & 0xff)
33 /* Macro for the expected version of the ARMv8-A debug architecture. */
34 #define AARCH64_DEBUG_ARCH_V8 0x6
35 #define DR_CONTROL_ENABLED(ctrl) (((ctrl) & 0x1) == 1)
36 #define DR_CONTROL_LENGTH(ctrl) (((ctrl) >> 5) & 0xff)
39 set_watchpoint (pid_t pid
, volatile void *addr
, unsigned len_mask
)
41 struct user_hwdebug_state dreg_state
;
45 assert (len_mask
>= 0x01);
46 assert (len_mask
<= 0xff);
48 iov
.iov_base
= &dreg_state
;
49 iov
.iov_len
= sizeof (dreg_state
);
51 l
= ptrace (PTRACE_GETREGSET
, pid
, NT_ARM_HW_WATCH
, &iov
);
53 assert (AARCH64_DEBUG_ARCH (dreg_state
.dbg_info
) == AARCH64_DEBUG_ARCH_V8
);
54 assert (AARCH64_DEBUG_NUM_SLOTS (dreg_state
.dbg_info
) >= 1);
56 assert (!DR_CONTROL_ENABLED (dreg_state
.dbg_regs
[0].ctrl
));
57 dreg_state
.dbg_regs
[0].ctrl
|= 1;
58 assert ( DR_CONTROL_ENABLED (dreg_state
.dbg_regs
[0].ctrl
));
60 assert (DR_CONTROL_LENGTH (dreg_state
.dbg_regs
[0].ctrl
) == 0);
61 dreg_state
.dbg_regs
[0].ctrl
|= len_mask
<< 5;
62 assert (DR_CONTROL_LENGTH (dreg_state
.dbg_regs
[0].ctrl
) == len_mask
);
64 dreg_state
.dbg_regs
[0].ctrl
|= 2 << 3; // write
65 dreg_state
.dbg_regs
[0].ctrl
|= 2 << 1; // enabled at el0
66 dreg_state
.dbg_regs
[0].addr
= (uintptr_t) addr
;
68 iov
.iov_base
= &dreg_state
;
69 iov
.iov_len
= (offsetof (struct user_hwdebug_state
, dbg_regs
)
70 + sizeof (dreg_state
.dbg_regs
[0]));
72 l
= ptrace (PTRACE_SETREGSET
, pid
, NT_ARM_HW_WATCH
, &iov
);
74 error (1, errno
, "PTRACE_SETREGSET: NT_ARM_HW_WATCH");
78 static volatile long long check
;
93 l
= ptrace (PTRACE_TRACEME
, 0, NULL
, NULL
);
103 got_pid
= waitpid (child
, &status
, 0);
104 assert (got_pid
== child
);
105 assert (WIFSTOPPED (status
));
106 assert (WSTOPSIG (status
) == SIGUSR1
);
108 /* Add a watchpoint to check.
109 Restart the child. It will write to check.
110 Check child has stopped on the watchpoint. */
111 set_watchpoint (child
, &check
, 0x02);
114 l
= ptrace (PTRACE_CONT
, child
, 0l, 0l);
115 assert_perror (errno
);
118 got_pid
= waitpid (child
, &status
, 0);
119 assert (got_pid
== child
);
120 assert (WIFSTOPPED (status
));
121 if (WSTOPSIG (status
) == SIGUSR2
)
123 /* We missed the watchpoint - unsupported by hardware? */
127 assert (WSTOPSIG (status
) == SIGTRAP
);