gdb: move displaced stepping logic to gdbarch, allow starting concurrent displaced...
[deliverable/binutils-gdb.git] / gdb / testsuite / gdb.arch / aarch64-dbreg-contents.c
1 /* Test case for setting a memory-write unaligned watchpoint on aarch64.
2
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.
6
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it
9 freely. */
10
11 #define _GNU_SOURCE 1
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <sys/ptrace.h>
15 #include <asm/ptrace.h>
16 #include <assert.h>
17 #include <sys/wait.h>
18 #include <stddef.h>
19 #include <errno.h>
20 #include <sys/uio.h>
21 #include <elf.h>
22 #include <error.h>
23
24 static pid_t child;
25
26 static void
27 cleanup (void)
28 {
29 if (child > 0)
30 kill (child, SIGKILL);
31 child = 0;
32 }
33
34 /* Macros to extract fields from the hardware debug information word. */
35 #define AARCH64_DEBUG_NUM_SLOTS(x) ((x) & 0xff)
36 #define AARCH64_DEBUG_ARCH(x) (((x) >> 8) & 0xff)
37 /* Macro for the expected version of the ARMv8-A debug architecture. */
38 #define AARCH64_DEBUG_ARCH_V8 0x6
39 #define DR_CONTROL_ENABLED(ctrl) (((ctrl) & 0x1) == 1)
40 #define DR_CONTROL_LENGTH(ctrl) (((ctrl) >> 5) & 0xff)
41
42 static void
43 set_watchpoint (pid_t pid, volatile void *addr, unsigned len_mask)
44 {
45 struct user_hwdebug_state dreg_state;
46 struct iovec iov;
47 long l;
48
49 assert (len_mask >= 0x01);
50 assert (len_mask <= 0xff);
51
52 iov.iov_base = &dreg_state;
53 iov.iov_len = sizeof (dreg_state);
54 errno = 0;
55 l = ptrace (PTRACE_GETREGSET, pid, NT_ARM_HW_WATCH, &iov);
56 assert (l == 0);
57 assert (AARCH64_DEBUG_ARCH (dreg_state.dbg_info) == AARCH64_DEBUG_ARCH_V8);
58 assert (AARCH64_DEBUG_NUM_SLOTS (dreg_state.dbg_info) >= 1);
59
60 assert (!DR_CONTROL_ENABLED (dreg_state.dbg_regs[0].ctrl));
61 dreg_state.dbg_regs[0].ctrl |= 1;
62 assert ( DR_CONTROL_ENABLED (dreg_state.dbg_regs[0].ctrl));
63
64 assert (DR_CONTROL_LENGTH (dreg_state.dbg_regs[0].ctrl) == 0);
65 dreg_state.dbg_regs[0].ctrl |= len_mask << 5;
66 assert (DR_CONTROL_LENGTH (dreg_state.dbg_regs[0].ctrl) == len_mask);
67
68 dreg_state.dbg_regs[0].ctrl |= 2 << 3; // write
69 dreg_state.dbg_regs[0].ctrl |= 2 << 1; // enabled at el0
70 dreg_state.dbg_regs[0].addr = (uintptr_t) addr;
71
72 iov.iov_base = &dreg_state;
73 iov.iov_len = (offsetof (struct user_hwdebug_state, dbg_regs)
74 + sizeof (dreg_state.dbg_regs[0]));
75 errno = 0;
76 l = ptrace (PTRACE_SETREGSET, pid, NT_ARM_HW_WATCH, &iov);
77 if (errno != 0)
78 error (1, errno, "PTRACE_SETREGSET: NT_ARM_HW_WATCH");
79 assert (l == 0);
80 }
81
82 static volatile long long check;
83
84 int
85 main (void)
86 {
87 pid_t got_pid;
88 int i, status;
89 long l;
90
91 atexit (cleanup);
92
93 child = fork ();
94 assert (child >= 0);
95 if (child == 0)
96 {
97 l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
98 assert (l == 0);
99 i = raise (SIGUSR1);
100 assert (i == 0);
101 check = -1;
102 i = raise (SIGUSR2);
103 /* NOTREACHED */
104 assert (0);
105 }
106
107 got_pid = waitpid (child, &status, 0);
108 assert (got_pid == child);
109 assert (WIFSTOPPED (status));
110 assert (WSTOPSIG (status) == SIGUSR1);
111
112 /* Add a watchpoint to check.
113 Restart the child. It will write to check.
114 Check child has stopped on the watchpoint. */
115 set_watchpoint (child, &check, 0x02);
116
117 errno = 0;
118 l = ptrace (PTRACE_CONT, child, 0l, 0l);
119 assert_perror (errno);
120 assert (l == 0);
121
122 got_pid = waitpid (child, &status, 0);
123 assert (got_pid == child);
124 assert (WIFSTOPPED (status));
125 if (WSTOPSIG (status) == SIGUSR2)
126 {
127 /* We missed the watchpoint - unsupported by hardware? */
128 cleanup ();
129 return 2;
130 }
131 assert (WSTOPSIG (status) == SIGTRAP);
132
133 return 0;
134 }
This page took 0.038437 seconds and 4 git commands to generate.