Sync proc_service definition with GLIBC
[deliverable/binutils-gdb.git] / gdb / nat / aarch64-linux.c
1 /* Copyright (C) 2009-2016 Free Software Foundation, Inc.
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
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"
24
25 #include "elf/common.h"
26 #include "nat/gdb_ptrace.h"
27 #include <asm/ptrace.h>
28 #include <sys/uio.h>
29
30 /* Called when resuming a thread LWP.
31 The hardware debug registers are updated when there is any change. */
32
33 void
34 aarch64_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);
48 int tid = ptid_get_lwp (ptid);
49 struct aarch64_debug_reg_state *state
50 = aarch64_get_debug_reg_state (ptid_get_pid (ptid));
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 }
70
71 /* Function to call when a new thread is detected. */
72
73 void
74 aarch64_linux_new_thread (struct lwp_info *lwp)
75 {
76 struct arch_lwp_info *info = XNEW (struct arch_lwp_info);
77
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);
83
84 lwp_set_arch_private_info (lwp, info);
85 }
86
87 /* Convert native siginfo FROM to the siginfo in the layout of the
88 inferior's architecture TO. */
89
90 void
91 aarch64_compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
92 {
93 memset (to, 0, sizeof (*to));
94
95 to->si_signo = from->si_signo;
96 to->si_errno = from->si_errno;
97 to->si_code = from->si_code;
98
99 if (to->si_code == SI_TIMER)
100 {
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;
104 }
105 else if (to->si_code == SI_USER)
106 {
107 to->cpt_si_pid = from->si_pid;
108 to->cpt_si_uid = from->si_uid;
109 }
110 else if (to->si_code < 0)
111 {
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;
115 }
116 else
117 {
118 switch (to->si_signo)
119 {
120 case SIGCHLD:
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;
126 break;
127 case SIGILL:
128 case SIGFPE:
129 case SIGSEGV:
130 case SIGBUS:
131 to->cpt_si_addr = (intptr_t) from->si_addr;
132 break;
133 case SIGPOLL:
134 to->cpt_si_band = from->si_band;
135 to->cpt_si_fd = from->si_fd;
136 break;
137 default:
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;
141 break;
142 }
143 }
144 }
145
146 /* Convert inferior's architecture siginfo FROM to native siginfo TO. */
147
148 void
149 aarch64_siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
150 {
151 memset (to, 0, sizeof (*to));
152
153 to->si_signo = from->si_signo;
154 to->si_errno = from->si_errno;
155 to->si_code = from->si_code;
156
157 if (to->si_code == SI_TIMER)
158 {
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;
162 }
163 else if (to->si_code == SI_USER)
164 {
165 to->si_pid = from->cpt_si_pid;
166 to->si_uid = from->cpt_si_uid;
167 }
168 if (to->si_code < 0)
169 {
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;
173 }
174 else
175 {
176 switch (to->si_signo)
177 {
178 case SIGCHLD:
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;
184 break;
185 case SIGILL:
186 case SIGFPE:
187 case SIGSEGV:
188 case SIGBUS:
189 to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
190 break;
191 case SIGPOLL:
192 to->si_band = from->cpt_si_band;
193 to->si_fd = from->cpt_si_fd;
194 break;
195 default:
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;
199 break;
200 }
201 }
202 }
203
204 /* Called by libthread_db. Returns a pointer to the thread local
205 storage (or its descriptor). */
206
207 ps_err_e
208 aarch64_ps_get_thread_area (struct ps_prochandle *ph,
209 lwpid_t lwpid, int idx, void **base,
210 int is_64bit_p)
211 {
212 struct iovec iovec;
213 uint64_t reg64;
214 uint32_t reg32;
215
216 if (is_64bit_p)
217 {
218 iovec.iov_base = &reg64;
219 iovec.iov_len = sizeof (reg64);
220 }
221 else
222 {
223 iovec.iov_base = &reg32;
224 iovec.iov_len = sizeof (reg32);
225 }
226
227 if (ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0)
228 return PS_ERR;
229
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. */
233 if (is_64bit_p)
234 *base = (void *) (reg64 - idx);
235 else
236 *base = (void *) (uintptr_t) (reg32 - idx);
237
238 return PS_OK;
239 }
This page took 0.044627 seconds and 4 git commands to generate.