1 /* Native-dependent code for BSD Unix running on ARM's, for GDB. 2 3 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 1999, 2002, 2004 4 Free Software Foundation, Inc. 5 6 This file is part of GDB. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place - Suite 330, 21 Boston, MA 02111-1307, USA. */ 22 23 #include "defs.h" 24 #include "gdbcore.h" 25 #include "inferior.h" 26 #include "regcache.h" 27 #include "target.h" 28 29 #include "gdb_string.h" 30 #include <sys/types.h> 31 #include <sys/ptrace.h> 32 #include <machine/reg.h> 33 #include <machine/frame.h> 34 35 #include "arm-tdep.h" 36 #include "inf-ptrace.h" 37 38 extern int arm_apcs_32; 39 40 static void 41 supply_gregset (struct reg *gregset) 42 { 43 int regno; 44 CORE_ADDR r_pc; 45 46 /* Integer registers. */ 47 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) 48 regcache_raw_supply (current_regcache, regno, (char *) &gregset->r[regno]); 49 50 regcache_raw_supply (current_regcache, ARM_SP_REGNUM, 51 (char *) &gregset->r_sp); 52 regcache_raw_supply (current_regcache, ARM_LR_REGNUM, 53 (char *) &gregset->r_lr); 54 /* This is ok: we're running native... */ 55 r_pc = ADDR_BITS_REMOVE (gregset->r_pc); 56 regcache_raw_supply (current_regcache, ARM_PC_REGNUM, (char *) &r_pc); 57 58 if (arm_apcs_32) 59 regcache_raw_supply (current_regcache, ARM_PS_REGNUM, 60 (char *) &gregset->r_cpsr); 61 else 62 regcache_raw_supply (current_regcache, ARM_PS_REGNUM, 63 (char *) &gregset->r_pc); 64 } 65 66 static void 67 supply_fparegset (struct fpreg *fparegset) 68 { 69 int regno; 70 71 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) 72 regcache_raw_supply (current_regcache, regno, 73 (char *) &fparegset->fp_reg[regno - ARM_F0_REGNUM]); 74 75 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM, 76 (char *) &fparegset->fp_scr); 77 } 78 79 static void 80 fetch_register (int regno) 81 { 82 struct reg inferior_registers; 83 int ret; 84 85 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 86 (PTRACE_TYPE_ARG3) &inferior_registers, 0); 87 88 if (ret < 0) 89 { 90 warning (_("unable to fetch general register")); 91 return; 92 } 93 94 switch (regno) 95 { 96 case ARM_SP_REGNUM: 97 regcache_raw_supply (current_regcache, ARM_SP_REGNUM, 98 (char *) &inferior_registers.r_sp); 99 break; 100 101 case ARM_LR_REGNUM: 102 regcache_raw_supply (current_regcache, ARM_LR_REGNUM, 103 (char *) &inferior_registers.r_lr); 104 break; 105 106 case ARM_PC_REGNUM: 107 /* This is ok: we're running native... */ 108 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc); 109 regcache_raw_supply (current_regcache, ARM_PC_REGNUM, 110 (char *) &inferior_registers.r_pc); 111 break; 112 113 case ARM_PS_REGNUM: 114 if (arm_apcs_32) 115 regcache_raw_supply (current_regcache, ARM_PS_REGNUM, 116 (char *) &inferior_registers.r_cpsr); 117 else 118 regcache_raw_supply (current_regcache, ARM_PS_REGNUM, 119 (char *) &inferior_registers.r_pc); 120 break; 121 122 default: 123 regcache_raw_supply (current_regcache, regno, 124 (char *) &inferior_registers.r[regno]); 125 break; 126 } 127 } 128 129 static void 130 fetch_regs (void) 131 { 132 struct reg inferior_registers; 133 int ret; 134 int regno; 135 136 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 137 (PTRACE_TYPE_ARG3) &inferior_registers, 0); 138 139 if (ret < 0) 140 { 141 warning (_("unable to fetch general registers")); 142 return; 143 } 144 145 supply_gregset (&inferior_registers); 146 } 147 148 static void 149 fetch_fp_register (int regno) 150 { 151 struct fpreg inferior_fp_registers; 152 int ret; 153 154 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 155 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); 156 157 if (ret < 0) 158 { 159 warning (_("unable to fetch floating-point register")); 160 return; 161 } 162 163 switch (regno) 164 { 165 case ARM_FPS_REGNUM: 166 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM, 167 (char *) &inferior_fp_registers.fp_scr); 168 break; 169 170 default: 171 regcache_raw_supply (current_regcache, regno, 172 (char *) &inferior_fp_registers.fp_reg[regno - ARM_F0_REGNUM]); 173 break; 174 } 175 } 176 177 static void 178 fetch_fp_regs (void) 179 { 180 struct fpreg inferior_fp_registers; 181 int ret; 182 int regno; 183 184 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 185 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); 186 187 if (ret < 0) 188 { 189 warning (_("unable to fetch general registers")); 190 return; 191 } 192 193 supply_fparegset (&inferior_fp_registers); 194 } 195 196 static void 197 armnbsd_fetch_registers (int regno) 198 { 199 if (regno >= 0) 200 { 201 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) 202 fetch_register (regno); 203 else 204 fetch_fp_register (regno); 205 } 206 else 207 { 208 fetch_regs (); 209 fetch_fp_regs (); 210 } 211 } 212 213 214 static void 215 store_register (int regno) 216 { 217 struct reg inferior_registers; 218 int ret; 219 220 ret = ptrace (PT_GETREGS, PIDGET (inferior_ptid), 221 (PTRACE_TYPE_ARG3) &inferior_registers, 0); 222 223 if (ret < 0) 224 { 225 warning (_("unable to fetch general registers")); 226 return; 227 } 228 229 switch (regno) 230 { 231 case ARM_SP_REGNUM: 232 regcache_raw_collect (current_regcache, ARM_SP_REGNUM, 233 (char *) &inferior_registers.r_sp); 234 break; 235 236 case ARM_LR_REGNUM: 237 regcache_raw_collect (current_regcache, ARM_LR_REGNUM, 238 (char *) &inferior_registers.r_lr); 239 break; 240 241 case ARM_PC_REGNUM: 242 if (arm_apcs_32) 243 regcache_raw_collect (current_regcache, ARM_PC_REGNUM, 244 (char *) &inferior_registers.r_pc); 245 else 246 { 247 unsigned pc_val; 248 249 regcache_raw_collect (current_regcache, ARM_PC_REGNUM, 250 (char *) &pc_val); 251 252 pc_val = ADDR_BITS_REMOVE (pc_val); 253 inferior_registers.r_pc 254 ^= ADDR_BITS_REMOVE (inferior_registers.r_pc); 255 inferior_registers.r_pc |= pc_val; 256 } 257 break; 258 259 case ARM_PS_REGNUM: 260 if (arm_apcs_32) 261 regcache_raw_collect (current_regcache, ARM_PS_REGNUM, 262 (char *) &inferior_registers.r_cpsr); 263 else 264 { 265 unsigned psr_val; 266 267 regcache_raw_collect (current_regcache, ARM_PS_REGNUM, 268 (char *) &psr_val); 269 270 psr_val ^= ADDR_BITS_REMOVE (psr_val); 271 inferior_registers.r_pc = ADDR_BITS_REMOVE (inferior_registers.r_pc); 272 inferior_registers.r_pc |= psr_val; 273 } 274 break; 275 276 default: 277 regcache_raw_collect (current_regcache, regno, 278 (char *) &inferior_registers.r[regno]); 279 break; 280 } 281 282 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid), 283 (PTRACE_TYPE_ARG3) &inferior_registers, 0); 284 285 if (ret < 0) 286 warning (_("unable to write register %d to inferior"), regno); 287 } 288 289 static void 290 store_regs (void) 291 { 292 struct reg inferior_registers; 293 int ret; 294 int regno; 295 296 297 for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) 298 regcache_raw_collect (current_regcache, regno, 299 (char *) &inferior_registers.r[regno]); 300 301 regcache_raw_collect (current_regcache, ARM_SP_REGNUM, 302 (char *) &inferior_registers.r_sp); 303 regcache_raw_collect (current_regcache, ARM_LR_REGNUM, 304 (char *) &inferior_registers.r_lr); 305 306 if (arm_apcs_32) 307 { 308 regcache_raw_collect (current_regcache, ARM_PC_REGNUM, 309 (char *) &inferior_registers.r_pc); 310 regcache_raw_collect (current_regcache, ARM_PS_REGNUM, 311 (char *) &inferior_registers.r_cpsr); 312 } 313 else 314 { 315 unsigned pc_val; 316 unsigned psr_val; 317 318 regcache_raw_collect (current_regcache, ARM_PC_REGNUM, 319 (char *) &pc_val); 320 regcache_raw_collect (current_regcache, ARM_PS_REGNUM, 321 (char *) &psr_val); 322 323 pc_val = ADDR_BITS_REMOVE (pc_val); 324 psr_val ^= ADDR_BITS_REMOVE (psr_val); 325 326 inferior_registers.r_pc = pc_val | psr_val; 327 } 328 329 ret = ptrace (PT_SETREGS, PIDGET (inferior_ptid), 330 (PTRACE_TYPE_ARG3) &inferior_registers, 0); 331 332 if (ret < 0) 333 warning (_("unable to store general registers")); 334 } 335 336 static void 337 store_fp_register (int regno) 338 { 339 struct fpreg inferior_fp_registers; 340 int ret; 341 342 ret = ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), 343 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); 344 345 if (ret < 0) 346 { 347 warning (_("unable to fetch floating-point registers")); 348 return; 349 } 350 351 switch (regno) 352 { 353 case ARM_FPS_REGNUM: 354 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM, 355 (char *) &inferior_fp_registers.fp_scr); 356 break; 357 358 default: 359 regcache_raw_collect (current_regcache, regno, 360 (char *) &inferior_fp_registers.fp_reg[regno - ARM_F0_REGNUM]); 361 break; 362 } 363 364 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), 365 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); 366 367 if (ret < 0) 368 warning (_("unable to write register %d to inferior"), regno); 369 } 370 371 static void 372 store_fp_regs (void) 373 { 374 struct fpreg inferior_fp_registers; 375 int ret; 376 int regno; 377 378 379 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) 380 regcache_raw_collect (current_regcache, regno, 381 (char *) &inferior_fp_registers.fp_reg[regno - ARM_F0_REGNUM]); 382 383 regcache_raw_collect (current_regcache, ARM_FPS_REGNUM, 384 (char *) &inferior_fp_registers.fp_scr); 385 386 ret = ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), 387 (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); 388 389 if (ret < 0) 390 warning (_("unable to store floating-point registers")); 391 } 392 393 static void 394 armnbsd_store_registers (int regno) 395 { 396 if (regno >= 0) 397 { 398 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) 399 store_register (regno); 400 else 401 store_fp_register (regno); 402 } 403 else 404 { 405 store_regs (); 406 store_fp_regs (); 407 } 408 } 409 410 struct md_core 411 { 412 struct reg intreg; 413 struct fpreg freg; 414 }; 415 416 static void 417 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, 418 int which, CORE_ADDR ignore) 419 { 420 struct md_core *core_reg = (struct md_core *) core_reg_sect; 421 int regno; 422 CORE_ADDR r_pc; 423 424 supply_gregset (&core_reg->intreg); 425 supply_fparegset (&core_reg->freg); 426 } 427 428 static void 429 fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, 430 int which, CORE_ADDR ignore) 431 { 432 struct reg gregset; 433 struct fpreg fparegset; 434 435 switch (which) 436 { 437 case 0: /* Integer registers. */ 438 if (core_reg_size != sizeof (struct reg)) 439 warning (_("wrong size of register set in core file")); 440 else 441 { 442 /* The memcpy may be unnecessary, but we can't really be sure 443 of the alignment of the data in the core file. */ 444 memcpy (&gregset, core_reg_sect, sizeof (gregset)); 445 supply_gregset (&gregset); 446 } 447 break; 448 449 case 2: 450 if (core_reg_size != sizeof (struct fpreg)) 451 warning (_("wrong size of FPA register set in core file")); 452 else 453 { 454 /* The memcpy may be unnecessary, but we can't really be sure 455 of the alignment of the data in the core file. */ 456 memcpy (&fparegset, core_reg_sect, sizeof (fparegset)); 457 supply_fparegset (&fparegset); 458 } 459 break; 460 461 default: 462 /* Don't know what kind of register request this is; just ignore it. */ 463 break; 464 } 465 } 466 467 static struct core_fns arm_netbsd_core_fns = 468 { 469 bfd_target_unknown_flavour, /* core_flovour. */ 470 default_check_format, /* check_format. */ 471 default_core_sniffer, /* core_sniffer. */ 472 fetch_core_registers, /* core_read_registers. */ 473 NULL 474 }; 475 476 static struct core_fns arm_netbsd_elfcore_fns = 477 { 478 bfd_target_elf_flavour, /* core_flovour. */ 479 default_check_format, /* check_format. */ 480 default_core_sniffer, /* core_sniffer. */ 481 fetch_elfcore_registers, /* core_read_registers. */ 482 NULL 483 }; 484 485 void 486 _initialize_arm_netbsd_nat (void) 487 { 488 struct target_ops *t; 489 490 t = inf_ptrace_target (); 491 t->to_fetch_registers = armnbsd_fetch_registers; 492 t->to_store_registers = armnbsd_store_registers; 493 add_target (t); 494 495 deprecated_add_core_fns (&arm_netbsd_core_fns); 496 deprecated_add_core_fns (&arm_netbsd_elfcore_fns); 497 } 498