1 /* Copyright (C) 2009-2017 Free Software Foundation, Inc.
2 Contributed by ARM Ltd.
4 This file is part of GDB.
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.
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.
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/>. */
19 #include "common-defs.h"
20 #include "break-common.h"
21 #include "nat/linux-nat.h"
22 #include "nat/aarch64-linux-hw-point.h"
23 #include "nat/aarch64-linux.h"
25 #include "elf/common.h"
26 #include "nat/gdb_ptrace.h"
27 #include <asm/ptrace.h>
30 /* Called when resuming a thread LWP.
31 The hardware debug registers are updated when there is any change. */
34 aarch64_linux_prepare_to_resume (struct lwp_info
*lwp
)
36 struct arch_lwp_info
*info
= lwp_arch_private_info (lwp
);
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
44 if (DR_HAS_CHANGED (info
->dr_changed_bp
)
45 || DR_HAS_CHANGED (info
->dr_changed_wp
))
47 ptid_t ptid
= ptid_of_lwp (lwp
);
48 int tid
= ptid_get_lwp (ptid
);
49 struct aarch64_debug_reg_state
*state
50 = aarch64_get_debug_reg_state (ptid_get_pid (ptid
));
53 debug_printf ("prepare_to_resume thread %d\n", tid
);
56 if (DR_HAS_CHANGED (info
->dr_changed_wp
))
58 aarch64_linux_set_debug_regs (state
, tid
, 1);
59 DR_CLEAR_CHANGED (info
->dr_changed_wp
);
63 if (DR_HAS_CHANGED (info
->dr_changed_bp
))
65 aarch64_linux_set_debug_regs (state
, tid
, 0);
66 DR_CLEAR_CHANGED (info
->dr_changed_bp
);
71 /* Function to call when a new thread is detected. */
74 aarch64_linux_new_thread (struct lwp_info
*lwp
)
76 struct arch_lwp_info
*info
= XNEW (struct arch_lwp_info
);
78 /* Mark that all the hardware breakpoint/watchpoint register pairs
79 for this thread need to be initialized (with data from
80 aarch_process_info.debug_reg_state). */
81 DR_MARK_ALL_CHANGED (info
->dr_changed_bp
, aarch64_num_bp_regs
);
82 DR_MARK_ALL_CHANGED (info
->dr_changed_wp
, aarch64_num_wp_regs
);
84 lwp_set_arch_private_info (lwp
, info
);
87 /* Convert native siginfo FROM to the siginfo in the layout of the
88 inferior's architecture TO. */
91 aarch64_compat_siginfo_from_siginfo (compat_siginfo_t
*to
, siginfo_t
*from
)
93 memset (to
, 0, sizeof (*to
));
95 to
->si_signo
= from
->si_signo
;
96 to
->si_errno
= from
->si_errno
;
97 to
->si_code
= from
->si_code
;
99 if (to
->si_code
== SI_TIMER
)
101 to
->cpt_si_timerid
= from
->si_timerid
;
102 to
->cpt_si_overrun
= from
->si_overrun
;
103 to
->cpt_si_ptr
= (intptr_t) from
->si_ptr
;
105 else if (to
->si_code
== SI_USER
)
107 to
->cpt_si_pid
= from
->si_pid
;
108 to
->cpt_si_uid
= from
->si_uid
;
110 else if (to
->si_code
< 0)
112 to
->cpt_si_pid
= from
->si_pid
;
113 to
->cpt_si_uid
= from
->si_uid
;
114 to
->cpt_si_ptr
= (intptr_t) from
->si_ptr
;
118 switch (to
->si_signo
)
121 to
->cpt_si_pid
= from
->si_pid
;
122 to
->cpt_si_uid
= from
->si_uid
;
123 to
->cpt_si_status
= from
->si_status
;
124 to
->cpt_si_utime
= from
->si_utime
;
125 to
->cpt_si_stime
= from
->si_stime
;
131 to
->cpt_si_addr
= (intptr_t) from
->si_addr
;
134 to
->cpt_si_band
= from
->si_band
;
135 to
->cpt_si_fd
= from
->si_fd
;
138 to
->cpt_si_pid
= from
->si_pid
;
139 to
->cpt_si_uid
= from
->si_uid
;
140 to
->cpt_si_ptr
= (intptr_t) from
->si_ptr
;
146 /* Convert inferior's architecture siginfo FROM to native siginfo TO. */
149 aarch64_siginfo_from_compat_siginfo (siginfo_t
*to
, compat_siginfo_t
*from
)
151 memset (to
, 0, sizeof (*to
));
153 to
->si_signo
= from
->si_signo
;
154 to
->si_errno
= from
->si_errno
;
155 to
->si_code
= from
->si_code
;
157 if (to
->si_code
== SI_TIMER
)
159 to
->si_timerid
= from
->cpt_si_timerid
;
160 to
->si_overrun
= from
->cpt_si_overrun
;
161 to
->si_ptr
= (void *) (intptr_t) from
->cpt_si_ptr
;
163 else if (to
->si_code
== SI_USER
)
165 to
->si_pid
= from
->cpt_si_pid
;
166 to
->si_uid
= from
->cpt_si_uid
;
170 to
->si_pid
= from
->cpt_si_pid
;
171 to
->si_uid
= from
->cpt_si_uid
;
172 to
->si_ptr
= (void *) (intptr_t) from
->cpt_si_ptr
;
176 switch (to
->si_signo
)
179 to
->si_pid
= from
->cpt_si_pid
;
180 to
->si_uid
= from
->cpt_si_uid
;
181 to
->si_status
= from
->cpt_si_status
;
182 to
->si_utime
= from
->cpt_si_utime
;
183 to
->si_stime
= from
->cpt_si_stime
;
189 to
->si_addr
= (void *) (intptr_t) from
->cpt_si_addr
;
192 to
->si_band
= from
->cpt_si_band
;
193 to
->si_fd
= from
->cpt_si_fd
;
196 to
->si_pid
= from
->cpt_si_pid
;
197 to
->si_uid
= from
->cpt_si_uid
;
198 to
->si_ptr
= (void* ) (intptr_t) from
->cpt_si_ptr
;
204 /* Called by libthread_db. Returns a pointer to the thread local
205 storage (or its descriptor). */
208 aarch64_ps_get_thread_area (struct ps_prochandle
*ph
,
209 lwpid_t lwpid
, int idx
, void **base
,
218 iovec
.iov_base
= ®64
;
219 iovec
.iov_len
= sizeof (reg64
);
223 iovec
.iov_base
= ®32
;
224 iovec
.iov_len
= sizeof (reg32
);
227 if (ptrace (PTRACE_GETREGSET
, lwpid
, NT_ARM_TLS
, &iovec
) != 0)
230 /* IDX is the bias from the thread pointer to the beginning of the
231 thread descriptor. It has to be subtracted due to implementation
232 quirks in libthread_db. */
234 *base
= (void *) (reg64
- idx
);
236 *base
= (void *) (uintptr_t) (reg32
- idx
);
This page took 0.050265 seconds and 4 git commands to generate.