1 /* S390 native-dependent code for GDB, the GNU debugger. 2 Copyright 2001, 2003 Free Software Foundation, Inc 3 4 Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 5 for IBM Deutschland Entwicklung GmbH, IBM Corporation. 6 7 This file is part of GDB. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 22 02111-1307, USA. */ 23 24 #include "defs.h" 25 #include "tm.h" 26 #include "regcache.h" 27 #include "inferior.h" 28 29 #include "s390-tdep.h" 30 31 #include <asm/ptrace.h> 32 #include <sys/ptrace.h> 33 #include <asm/types.h> 34 #include <sys/procfs.h> 35 #include <sys/user.h> 36 #include <sys/ucontext.h> 37 38 39 /* Map registers to gregset/ptrace offsets. 40 These arrays are defined in s390-tdep.c. */ 41 42 #ifdef __s390x__ 43 #define regmap_gregset s390x_regmap_gregset 44 #else 45 #define regmap_gregset s390_regmap_gregset 46 #endif 47 48 #define regmap_fpregset s390_regmap_fpregset 49 50 /* When debugging a 32-bit executable running under a 64-bit kernel, 51 we have to fix up the 64-bit registers we get from the kernel 52 to make them look like 32-bit registers. */ 53 #ifdef __s390x__ 54 #define SUBOFF(i) \ 55 ((TARGET_PTR_BIT == 32 \ 56 && ((i) == S390_PSWA_REGNUM \ 57 || ((i) >= S390_R0_REGNUM && (i) <= S390_R15_REGNUM)))? 4 : 0) 58 #else 59 #define SUBOFF(i) 0 60 #endif 61 62 63 /* Fill GDB's register array with the general-purpose register values 64 in *REGP. */ 65 void 66 supply_gregset (gregset_t *regp) 67 { 68 int i; 69 for (i = 0; i < S390_NUM_REGS; i++) 70 if (regmap_gregset[i] != -1) 71 regcache_raw_supply (current_regcache, i, 72 (char *)regp + regmap_gregset[i] + SUBOFF (i)); 73 } 74 75 /* Fill register REGNO (if it is a general-purpose register) in 76 *REGP with the value in GDB's register array. If REGNO is -1, 77 do this for all registers. */ 78 void 79 fill_gregset (gregset_t *regp, int regno) 80 { 81 int i; 82 for (i = 0; i < S390_NUM_REGS; i++) 83 if (regmap_gregset[i] != -1) 84 if (regno == -1 || regno == i) 85 regcache_raw_collect (current_regcache, i, 86 (char *)regp + regmap_gregset[i] + SUBOFF (i)); 87 } 88 89 /* Fill GDB's register array with the floating-point register values 90 in *REGP. */ 91 void 92 supply_fpregset (fpregset_t *regp) 93 { 94 int i; 95 for (i = 0; i < S390_NUM_REGS; i++) 96 if (regmap_fpregset[i] != -1) 97 regcache_raw_supply (current_regcache, i, 98 ((char *)regp) + regmap_fpregset[i]); 99 } 100 101 /* Fill register REGNO (if it is a general-purpose register) in 102 *REGP with the value in GDB's register array. If REGNO is -1, 103 do this for all registers. */ 104 void 105 fill_fpregset (fpregset_t *regp, int regno) 106 { 107 int i; 108 for (i = 0; i < S390_NUM_REGS; i++) 109 if (regmap_fpregset[i] != -1) 110 if (regno == -1 || regno == i) 111 regcache_raw_collect (current_regcache, i, 112 ((char *)regp) + regmap_fpregset[i]); 113 } 114 115 /* Find the TID for the current inferior thread to use with ptrace. */ 116 static int 117 s390_inferior_tid (void) 118 { 119 /* GNU/Linux LWP ID's are process ID's. */ 120 int tid = TIDGET (inferior_ptid); 121 if (tid == 0) 122 tid = PIDGET (inferior_ptid); /* Not a threaded program. */ 123 124 return tid; 125 } 126 127 /* Fetch all general-purpose registers from process/thread TID and 128 store their values in GDB's register cache. */ 129 static void 130 fetch_regs (int tid) 131 { 132 gregset_t regs; 133 ptrace_area parea; 134 135 parea.len = sizeof (regs); 136 parea.process_addr = (addr_t) ®s; 137 parea.kernel_addr = offsetof (struct user_regs_struct, psw); 138 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0) 139 perror_with_name ("Couldn't get registers"); 140 141 supply_gregset (®s); 142 } 143 144 /* Store all valid general-purpose registers in GDB's register cache 145 into the process/thread specified by TID. */ 146 static void 147 store_regs (int tid, int regnum) 148 { 149 gregset_t regs; 150 ptrace_area parea; 151 152 parea.len = sizeof (regs); 153 parea.process_addr = (addr_t) ®s; 154 parea.kernel_addr = offsetof (struct user_regs_struct, psw); 155 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0) 156 perror_with_name ("Couldn't get registers"); 157 158 fill_gregset (®s, regnum); 159 160 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0) 161 perror_with_name ("Couldn't write registers"); 162 } 163 164 /* Fetch all floating-point registers from process/thread TID and store 165 their values in GDB's register cache. */ 166 static void 167 fetch_fpregs (int tid) 168 { 169 fpregset_t fpregs; 170 ptrace_area parea; 171 172 parea.len = sizeof (fpregs); 173 parea.process_addr = (addr_t) &fpregs; 174 parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs); 175 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0) 176 perror_with_name ("Couldn't get floating point status"); 177 178 supply_fpregset (&fpregs); 179 } 180 181 /* Store all valid floating-point registers in GDB's register cache 182 into the process/thread specified by TID. */ 183 static void 184 store_fpregs (int tid, int regnum) 185 { 186 fpregset_t fpregs; 187 ptrace_area parea; 188 189 parea.len = sizeof (fpregs); 190 parea.process_addr = (addr_t) &fpregs; 191 parea.kernel_addr = offsetof (struct user_regs_struct, fp_regs); 192 if (ptrace (PTRACE_PEEKUSR_AREA, tid, (long) &parea) < 0) 193 perror_with_name ("Couldn't get floating point status"); 194 195 fill_fpregset (&fpregs, regnum); 196 197 if (ptrace (PTRACE_POKEUSR_AREA, tid, (long) &parea) < 0) 198 perror_with_name ("Couldn't write floating point status"); 199 } 200 201 /* Fetch register REGNUM from the child process. If REGNUM is -1, do 202 this for all registers. */ 203 void 204 fetch_inferior_registers (int regnum) 205 { 206 int tid = s390_inferior_tid (); 207 208 if (regnum == -1 209 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1)) 210 fetch_regs (tid); 211 212 if (regnum == -1 213 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1)) 214 fetch_fpregs (tid); 215 } 216 217 /* Store register REGNUM back into the child process. If REGNUM is 218 -1, do this for all registers. */ 219 void 220 store_inferior_registers (int regnum) 221 { 222 int tid = s390_inferior_tid (); 223 224 if (regnum == -1 225 || (regnum < S390_NUM_REGS && regmap_gregset[regnum] != -1)) 226 store_regs (tid, regnum); 227 228 if (regnum == -1 229 || (regnum < S390_NUM_REGS && regmap_fpregset[regnum] != -1)) 230 store_fpregs (tid, regnum); 231 } 232 233 234 /* Hardware-assisted watchpoint handling. */ 235 236 /* We maintain a list of all currently active watchpoints in order 237 to properly handle watchpoint removal. 238 239 The only thing we actually need is the total address space area 240 spanned by the watchpoints. */ 241 242 struct watch_area 243 { 244 struct watch_area *next; 245 CORE_ADDR lo_addr; 246 CORE_ADDR hi_addr; 247 }; 248 249 static struct watch_area *watch_base = NULL; 250 251 int 252 s390_stopped_by_watchpoint (void) 253 { 254 per_lowcore_bits per_lowcore; 255 ptrace_area parea; 256 257 /* Speed up common case. */ 258 if (!watch_base) 259 return 0; 260 261 parea.len = sizeof (per_lowcore); 262 parea.process_addr = (addr_t) & per_lowcore; 263 parea.kernel_addr = offsetof (struct user_regs_struct, per_info.lowcore); 264 if (ptrace (PTRACE_PEEKUSR_AREA, s390_inferior_tid (), &parea) < 0) 265 perror_with_name ("Couldn't retrieve watchpoint status"); 266 267 return per_lowcore.perc_storage_alteration == 1 268 && per_lowcore.perc_store_real_address == 0; 269 } 270 271 static void 272 s390_fix_watch_points (void) 273 { 274 int tid = s390_inferior_tid (); 275 276 per_struct per_info; 277 ptrace_area parea; 278 279 CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0; 280 struct watch_area *area; 281 282 for (area = watch_base; area; area = area->next) 283 { 284 watch_lo_addr = min (watch_lo_addr, area->lo_addr); 285 watch_hi_addr = max (watch_hi_addr, area->hi_addr); 286 } 287 288 parea.len = sizeof (per_info); 289 parea.process_addr = (addr_t) & per_info; 290 parea.kernel_addr = offsetof (struct user_regs_struct, per_info); 291 if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0) 292 perror_with_name ("Couldn't retrieve watchpoint status"); 293 294 if (watch_base) 295 { 296 per_info.control_regs.bits.em_storage_alteration = 1; 297 per_info.control_regs.bits.storage_alt_space_ctl = 1; 298 } 299 else 300 { 301 per_info.control_regs.bits.em_storage_alteration = 0; 302 per_info.control_regs.bits.storage_alt_space_ctl = 0; 303 } 304 per_info.starting_addr = watch_lo_addr; 305 per_info.ending_addr = watch_hi_addr; 306 307 if (ptrace (PTRACE_POKEUSR_AREA, tid, &parea) < 0) 308 perror_with_name ("Couldn't modify watchpoint status"); 309 } 310 311 int 312 s390_insert_watchpoint (CORE_ADDR addr, int len) 313 { 314 struct watch_area *area = xmalloc (sizeof (struct watch_area)); 315 if (!area) 316 return -1; 317 318 area->lo_addr = addr; 319 area->hi_addr = addr + len - 1; 320 321 area->next = watch_base; 322 watch_base = area; 323 324 s390_fix_watch_points (); 325 return 0; 326 } 327 328 int 329 s390_remove_watchpoint (CORE_ADDR addr, int len) 330 { 331 struct watch_area *area, **parea; 332 333 for (parea = &watch_base; *parea; parea = &(*parea)->next) 334 if ((*parea)->lo_addr == addr 335 && (*parea)->hi_addr == addr + len - 1) 336 break; 337 338 if (!*parea) 339 { 340 fprintf_unfiltered (gdb_stderr, 341 "Attempt to remove nonexistent watchpoint.\n"); 342 return -1; 343 } 344 345 area = *parea; 346 *parea = area->next; 347 xfree (area); 348 349 s390_fix_watch_points (); 350 return 0; 351 } 352 353 354 int 355 kernel_u_size (void) 356 { 357 return sizeof (struct user); 358 } 359 360