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 = ®64; 219 iovec.iov_len = sizeof (reg64); 220 } 221 else 222 { 223 iovec.iov_base = ®32; 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 } 240