Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / nat / aarch64-linux.c
CommitLineData
88b9d363 1/* Copyright (C) 2009-2022 Free Software Foundation, Inc.
db3cb7cb
YQ
2 Contributed by ARM Ltd.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
268a13a5
TT
19#include "gdbsupport/common-defs.h"
20#include "gdbsupport/break-common.h"
db3cb7cb
YQ
21#include "nat/linux-nat.h"
22#include "nat/aarch64-linux-hw-point.h"
23#include "nat/aarch64-linux.h"
24
a0cc84cd
YQ
25#include "elf/common.h"
26#include "nat/gdb_ptrace.h"
27#include <asm/ptrace.h>
28#include <sys/uio.h>
29
db3cb7cb
YQ
30/* Called when resuming a thread LWP.
31 The hardware debug registers are updated when there is any change. */
32
33void
34aarch64_linux_prepare_to_resume (struct lwp_info *lwp)
35{
36 struct arch_lwp_info *info = lwp_arch_private_info (lwp);
37
38 /* NULL means this is the main thread still going through the shell,
39 or, no watchpoint has been set yet. In that case, there's
40 nothing to do. */
41 if (info == NULL)
42 return;
43
44 if (DR_HAS_CHANGED (info->dr_changed_bp)
45 || DR_HAS_CHANGED (info->dr_changed_wp))
46 {
47 ptid_t ptid = ptid_of_lwp (lwp);
e38504b3 48 int tid = ptid.lwp ();
db3cb7cb 49 struct aarch64_debug_reg_state *state
e99b03dc 50 = aarch64_get_debug_reg_state (ptid.pid ());
db3cb7cb
YQ
51
52 if (show_debug_regs)
53 debug_printf ("prepare_to_resume thread %d\n", tid);
54
55 /* Watchpoints. */
56 if (DR_HAS_CHANGED (info->dr_changed_wp))
57 {
58 aarch64_linux_set_debug_regs (state, tid, 1);
59 DR_CLEAR_CHANGED (info->dr_changed_wp);
60 }
61
62 /* Breakpoints. */
63 if (DR_HAS_CHANGED (info->dr_changed_bp))
64 {
65 aarch64_linux_set_debug_regs (state, tid, 0);
66 DR_CLEAR_CHANGED (info->dr_changed_bp);
67 }
68 }
69}
ed8b7b42
YQ
70
71/* Function to call when a new thread is detected. */
72
73void
74aarch64_linux_new_thread (struct lwp_info *lwp)
75{
754e3168
AH
76 ptid_t ptid = ptid_of_lwp (lwp);
77 struct aarch64_debug_reg_state *state
78 = aarch64_get_debug_reg_state (ptid.pid ());
6594e122 79 struct arch_lwp_info *info = XCNEW (struct arch_lwp_info);
ed8b7b42 80
754e3168
AH
81 /* If there are hardware breakpoints/watchpoints in the process then mark that
82 all the hardware breakpoint/watchpoint register pairs for this thread need
83 to be initialized (with data from aarch_process_info.debug_reg_state). */
84 if (aarch64_linux_any_set_debug_regs_state (state, false))
85 DR_MARK_ALL_CHANGED (info->dr_changed_bp, aarch64_num_bp_regs);
86 if (aarch64_linux_any_set_debug_regs_state (state, true))
87 DR_MARK_ALL_CHANGED (info->dr_changed_wp, aarch64_num_wp_regs);
ed8b7b42
YQ
88
89 lwp_set_arch_private_info (lwp, info);
90}
ade90bde 91
466eecee
SM
92/* See nat/aarch64-linux.h. */
93
94void
95aarch64_linux_delete_thread (struct arch_lwp_info *arch_lwp)
96{
97 xfree (arch_lwp);
98}
99
ade90bde
YQ
100/* Convert native siginfo FROM to the siginfo in the layout of the
101 inferior's architecture TO. */
102
103void
104aarch64_compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
105{
106 memset (to, 0, sizeof (*to));
107
108 to->si_signo = from->si_signo;
109 to->si_errno = from->si_errno;
110 to->si_code = from->si_code;
111
112 if (to->si_code == SI_TIMER)
113 {
114 to->cpt_si_timerid = from->si_timerid;
115 to->cpt_si_overrun = from->si_overrun;
116 to->cpt_si_ptr = (intptr_t) from->si_ptr;
117 }
118 else if (to->si_code == SI_USER)
119 {
120 to->cpt_si_pid = from->si_pid;
121 to->cpt_si_uid = from->si_uid;
122 }
123 else if (to->si_code < 0)
124 {
125 to->cpt_si_pid = from->si_pid;
126 to->cpt_si_uid = from->si_uid;
127 to->cpt_si_ptr = (intptr_t) from->si_ptr;
128 }
129 else
130 {
131 switch (to->si_signo)
132 {
133 case SIGCHLD:
134 to->cpt_si_pid = from->si_pid;
135 to->cpt_si_uid = from->si_uid;
136 to->cpt_si_status = from->si_status;
137 to->cpt_si_utime = from->si_utime;
138 to->cpt_si_stime = from->si_stime;
139 break;
140 case SIGILL:
141 case SIGFPE:
142 case SIGSEGV:
143 case SIGBUS:
144 to->cpt_si_addr = (intptr_t) from->si_addr;
145 break;
146 case SIGPOLL:
147 to->cpt_si_band = from->si_band;
148 to->cpt_si_fd = from->si_fd;
149 break;
150 default:
151 to->cpt_si_pid = from->si_pid;
152 to->cpt_si_uid = from->si_uid;
153 to->cpt_si_ptr = (intptr_t) from->si_ptr;
154 break;
155 }
156 }
157}
158
159/* Convert inferior's architecture siginfo FROM to native siginfo TO. */
160
161void
162aarch64_siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
163{
164 memset (to, 0, sizeof (*to));
165
166 to->si_signo = from->si_signo;
167 to->si_errno = from->si_errno;
168 to->si_code = from->si_code;
169
170 if (to->si_code == SI_TIMER)
171 {
172 to->si_timerid = from->cpt_si_timerid;
173 to->si_overrun = from->cpt_si_overrun;
174 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
175 }
176 else if (to->si_code == SI_USER)
177 {
178 to->si_pid = from->cpt_si_pid;
179 to->si_uid = from->cpt_si_uid;
180 }
181 if (to->si_code < 0)
182 {
183 to->si_pid = from->cpt_si_pid;
184 to->si_uid = from->cpt_si_uid;
185 to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
186 }
187 else
188 {
189 switch (to->si_signo)
190 {
191 case SIGCHLD:
192 to->si_pid = from->cpt_si_pid;
193 to->si_uid = from->cpt_si_uid;
194 to->si_status = from->cpt_si_status;
195 to->si_utime = from->cpt_si_utime;
196 to->si_stime = from->cpt_si_stime;
197 break;
198 case SIGILL:
199 case SIGFPE:
200 case SIGSEGV:
201 case SIGBUS:
202 to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
203 break;
204 case SIGPOLL:
205 to->si_band = from->cpt_si_band;
206 to->si_fd = from->cpt_si_fd;
207 break;
208 default:
209 to->si_pid = from->cpt_si_pid;
210 to->si_uid = from->cpt_si_uid;
211 to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
212 break;
213 }
214 }
215}
a0cc84cd
YQ
216
217/* Called by libthread_db. Returns a pointer to the thread local
218 storage (or its descriptor). */
219
220ps_err_e
754653a7 221aarch64_ps_get_thread_area (struct ps_prochandle *ph,
a0cc84cd
YQ
222 lwpid_t lwpid, int idx, void **base,
223 int is_64bit_p)
224{
225 struct iovec iovec;
226 uint64_t reg64;
227 uint32_t reg32;
228
229 if (is_64bit_p)
230 {
231 iovec.iov_base = &reg64;
232 iovec.iov_len = sizeof (reg64);
233 }
234 else
235 {
236 iovec.iov_base = &reg32;
237 iovec.iov_len = sizeof (reg32);
238 }
239
240 if (ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0)
241 return PS_ERR;
242
243 /* IDX is the bias from the thread pointer to the beginning of the
244 thread descriptor. It has to be subtracted due to implementation
245 quirks in libthread_db. */
246 if (is_64bit_p)
247 *base = (void *) (reg64 - idx);
248 else
249 *base = (void *) (uintptr_t) (reg32 - idx);
250
251 return PS_OK;
252}
This page took 0.589287 seconds and 4 git commands to generate.