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