GDBserver
aarch64-linux.c
Go to the documentation of this file.
1 /* Copyright (C) 2009-2018 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"
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
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
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);
60  }
61 
62  /* Breakpoints. */
63  if (DR_HAS_CHANGED (info->dr_changed_bp))
64  {
65  aarch64_linux_set_debug_regs (state, tid, 0);
67  }
68  }
69 }
70 
71 /* Function to call when a new thread is detected. */
72 
73 void
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). */
83 
84  lwp_set_arch_private_info (lwp, info);
85 }
86 
87 /* See nat/aarch64-linux.h. */
88 
89 void
91 {
92  xfree (arch_lwp);
93 }
94 
95 /* Convert native siginfo FROM to the siginfo in the layout of the
96  inferior's architecture TO. */
97 
98 void
100 {
101  memset (to, 0, sizeof (*to));
102 
103  to->si_signo = from->si_signo;
104  to->si_errno = from->si_errno;
105  to->si_code = from->si_code;
106 
107  if (to->si_code == SI_TIMER)
108  {
109  to->cpt_si_timerid = from->si_timerid;
110  to->cpt_si_overrun = from->si_overrun;
111  to->cpt_si_ptr = (intptr_t) from->si_ptr;
112  }
113  else if (to->si_code == SI_USER)
114  {
115  to->cpt_si_pid = from->si_pid;
116  to->cpt_si_uid = from->si_uid;
117  }
118  else if (to->si_code < 0)
119  {
120  to->cpt_si_pid = from->si_pid;
121  to->cpt_si_uid = from->si_uid;
122  to->cpt_si_ptr = (intptr_t) from->si_ptr;
123  }
124  else
125  {
126  switch (to->si_signo)
127  {
128  case SIGCHLD:
129  to->cpt_si_pid = from->si_pid;
130  to->cpt_si_uid = from->si_uid;
131  to->cpt_si_status = from->si_status;
132  to->cpt_si_utime = from->si_utime;
133  to->cpt_si_stime = from->si_stime;
134  break;
135  case SIGILL:
136  case SIGFPE:
137  case SIGSEGV:
138  case SIGBUS:
139  to->cpt_si_addr = (intptr_t) from->si_addr;
140  break;
141  case SIGPOLL:
142  to->cpt_si_band = from->si_band;
143  to->cpt_si_fd = from->si_fd;
144  break;
145  default:
146  to->cpt_si_pid = from->si_pid;
147  to->cpt_si_uid = from->si_uid;
148  to->cpt_si_ptr = (intptr_t) from->si_ptr;
149  break;
150  }
151  }
152 }
153 
154 /* Convert inferior's architecture siginfo FROM to native siginfo TO. */
155 
156 void
158 {
159  memset (to, 0, sizeof (*to));
160 
161  to->si_signo = from->si_signo;
162  to->si_errno = from->si_errno;
163  to->si_code = from->si_code;
164 
165  if (to->si_code == SI_TIMER)
166  {
167  to->si_timerid = from->cpt_si_timerid;
168  to->si_overrun = from->cpt_si_overrun;
169  to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
170  }
171  else if (to->si_code == SI_USER)
172  {
173  to->si_pid = from->cpt_si_pid;
174  to->si_uid = from->cpt_si_uid;
175  }
176  if (to->si_code < 0)
177  {
178  to->si_pid = from->cpt_si_pid;
179  to->si_uid = from->cpt_si_uid;
180  to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
181  }
182  else
183  {
184  switch (to->si_signo)
185  {
186  case SIGCHLD:
187  to->si_pid = from->cpt_si_pid;
188  to->si_uid = from->cpt_si_uid;
189  to->si_status = from->cpt_si_status;
190  to->si_utime = from->cpt_si_utime;
191  to->si_stime = from->cpt_si_stime;
192  break;
193  case SIGILL:
194  case SIGFPE:
195  case SIGSEGV:
196  case SIGBUS:
197  to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
198  break;
199  case SIGPOLL:
200  to->si_band = from->cpt_si_band;
201  to->si_fd = from->cpt_si_fd;
202  break;
203  default:
204  to->si_pid = from->cpt_si_pid;
205  to->si_uid = from->cpt_si_uid;
206  to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
207  break;
208  }
209  }
210 }
211 
212 /* Called by libthread_db. Returns a pointer to the thread local
213  storage (or its descriptor). */
214 
215 ps_err_e
217  lwpid_t lwpid, int idx, void **base,
218  int is_64bit_p)
219 {
220  struct iovec iovec;
221  uint64_t reg64;
222  uint32_t reg32;
223 
224  if (is_64bit_p)
225  {
226  iovec.iov_base = &reg64;
227  iovec.iov_len = sizeof (reg64);
228  }
229  else
230  {
231  iovec.iov_base = &reg32;
232  iovec.iov_len = sizeof (reg32);
233  }
234 
235  if (ptrace (PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0)
236  return PS_ERR;
237 
238  /* IDX is the bias from the thread pointer to the beginning of the
239  thread descriptor. It has to be subtracted due to implementation
240  quirks in libthread_db. */
241  if (is_64bit_p)
242  *base = (void *) (reg64 - idx);
243  else
244  *base = (void *) (uintptr_t) (reg32 - idx);
245 
246  return PS_OK;
247 }
unsigned int lwpid_t
void aarch64_linux_new_thread(struct lwp_info *lwp)
Definition: aarch64-linux.c:74
ptid_t ptid_of_lwp(struct lwp_info *lwp)
Definition: linux-low.c:144
static void xfree(T *ptr)
Definition: common-utils.h:54
#define DR_CLEAR_CHANGED(x)
int aarch64_num_wp_regs
int ptid_get_pid(const ptid_t &ptid)
Definition: ptid.c:47
int aarch64_num_bp_regs
void aarch64_linux_set_debug_regs(const struct aarch64_debug_reg_state *state, int tid, int watchpoint)
void * memset(T *s, int c, size_t n)=delete
void aarch64_linux_delete_thread(struct arch_lwp_info *arch_lwp)
Definition: aarch64-linux.c:90
ps_err_e
#define DR_MARK_ALL_CHANGED(x, m)
struct aarch64_debug_reg_state * aarch64_get_debug_reg_state(pid_t pid)
PTRACE_TYPE_RET ptrace()
#define DR_HAS_CHANGED(x)
#define XNEW(T)
Definition: poison.h:109
void aarch64_compat_siginfo_from_siginfo(compat_siginfo_t *to, siginfo_t *from)
Definition: aarch64-linux.c:99
Definition: ptid.h:35
int show_debug_regs
Definition: common-debug.c:25
void aarch64_linux_prepare_to_resume(struct lwp_info *lwp)
Definition: aarch64-linux.c:34
long ptid_get_lwp(const ptid_t &ptid)
Definition: ptid.c:55
#define PTRACE_GETREGSET
Definition: linux-ptrace.h:47
ps_err_e aarch64_ps_get_thread_area(struct ps_prochandle *ph, lwpid_t lwpid, int idx, void **base, int is_64bit_p)
dr_changed_t dr_changed_wp
void lwp_set_arch_private_info(struct lwp_info *lwp, struct arch_lwp_info *info)
Definition: linux-low.c:152
void debug_printf(const char *fmt,...)
Definition: common-debug.c:30
dr_changed_t dr_changed_bp
struct arch_lwp_info * lwp_arch_private_info(struct lwp_info *lwp)
Definition: linux-low.c:161
void aarch64_siginfo_from_compat_siginfo(siginfo_t *to, compat_siginfo_t *from)