1 /* Copyright (C) 2009-2020 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 "gdbsupport/common-defs.h" 20 #include "gdbsupport/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.lwp (); 49 struct aarch64_debug_reg_state *state 50 = aarch64_get_debug_reg_state (ptid.pid ()); 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 ptid_t ptid = ptid_of_lwp (lwp); 77 struct aarch64_debug_reg_state *state 78 = aarch64_get_debug_reg_state (ptid.pid ()); 79 struct arch_lwp_info *info = XCNEW (struct arch_lwp_info); 80 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); 88 89 lwp_set_arch_private_info (lwp, info); 90 } 91 92 /* See nat/aarch64-linux.h. */ 93 94 void 95 aarch64_linux_delete_thread (struct arch_lwp_info *arch_lwp) 96 { 97 xfree (arch_lwp); 98 } 99 100 /* Convert native siginfo FROM to the siginfo in the layout of the 101 inferior's architecture TO. */ 102 103 void 104 aarch64_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 161 void 162 aarch64_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 } 216 217 /* Called by libthread_db. Returns a pointer to the thread local 218 storage (or its descriptor). */ 219 220 ps_err_e 221 aarch64_ps_get_thread_area (struct ps_prochandle *ph, 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 = ®64; 232 iovec.iov_len = sizeof (reg64); 233 } 234 else 235 { 236 iovec.iov_base = ®32; 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 } 253