1/* Target-dependent code for NetBSD/arm. 2 3 Copyright (C) 2002-2020 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "osabi.h" 22#include "gdbcore.h" 23#include "regset.h" 24 25#include "arch/arm.h" 26#include "arm-nbsd-tdep.h" 27#include "nbsd-tdep.h" 28#include "arm-tdep.h" 29#include "regset.h" 30#include "solib-svr4.h" 31 32/* Description of the longjmp buffer. */ 33#define ARM_NBSD_JB_PC 24 34#define ARM_NBSD_JB_ELEMENT_SIZE ARM_INT_REGISTER_SIZE 35 36/* For compatibility with previous implementations of GDB on arm/NetBSD, 37 override the default little-endian breakpoint. */ 38static const gdb_byte arm_nbsd_arm_le_breakpoint[] = {0x11, 0x00, 0x00, 0xe6}; 39static const gdb_byte arm_nbsd_arm_be_breakpoint[] = {0xe6, 0x00, 0x00, 0x11}; 40static const gdb_byte arm_nbsd_thumb_le_breakpoint[] = {0xfe, 0xde}; 41static const gdb_byte arm_nbsd_thumb_be_breakpoint[] = {0xde, 0xfe}; 42 43/* This matches struct reg from NetBSD's sys/arch/arm/include/reg.h: 44 https://github.com/NetBSD/src/blob/7c13e6e6773bb171f4ed3ed53013e9d24b3c1eac/sys/arch/arm/include/reg.h#L39 45 */ 46struct arm_nbsd_reg 47{ 48 uint32_t reg[13]; 49 uint32_t sp; 50 uint32_t lr; 51 uint32_t pc; 52 uint32_t cpsr; 53}; 54 55void 56arm_nbsd_supply_gregset (const struct regset *regset, struct regcache *regcache, 57 int regnum, const void *gregs, size_t len) 58{ 59 const arm_nbsd_reg *gregset = static_cast<const arm_nbsd_reg *>(gregs); 60 gdb_assert (len >= sizeof (arm_nbsd_reg)); 61 62 /* Integer registers. */ 63 for (int i = ARM_A1_REGNUM; i < ARM_SP_REGNUM; i++) 64 if (regnum == -1 || regnum == i) 65 regcache->raw_supply (i, (char *) &gregset->reg[i]); 66 67 if (regnum == -1 || regnum == ARM_SP_REGNUM) 68 regcache->raw_supply (ARM_SP_REGNUM, (char *) &gregset->sp); 69 70 if (regnum == -1 || regnum == ARM_LR_REGNUM) 71 regcache->raw_supply (ARM_LR_REGNUM, (char *) &gregset->lr); 72 73 if (regnum == -1 || regnum == ARM_PC_REGNUM) 74 { 75 uint32_t r_pc = gdbarch_addr_bits_remove (regcache->arch (), gregset->pc); 76 regcache->raw_supply (ARM_PC_REGNUM, (char *) &r_pc); 77 } 78 79 if (regnum == -1 || regnum == ARM_PS_REGNUM) 80 { 81 if (arm_apcs_32) 82 regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->cpsr); 83 else 84 regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->pc); 85 } 86} 87 88static const struct regset arm_nbsd_regset = { 89 nullptr, 90 arm_nbsd_supply_gregset, 91 /* We don't need a collect function because we only use this reading registers 92 (via iterate_over_regset_sections and fetch_regs/fetch_register). */ 93 nullptr, 94 0 95}; 96 97static void 98arm_nbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, 99 iterate_over_regset_sections_cb *cb, 100 void *cb_data, 101 const struct regcache *regcache) 102{ 103 cb (".reg", sizeof (arm_nbsd_reg), sizeof (arm_nbsd_reg), &arm_nbsd_regset, 104 NULL, cb_data); 105 /* cbiesinger/2020-02-12 -- as far as I can tell, ARM/NetBSD does 106 not write any floating point registers into the core file (tested 107 with NetBSD 9.1_RC1). When it does, this function will need to read them, 108 and the arm-netbsd gdbarch will need a core_read_description function 109 to return the right description for them. */ 110} 111 112static void 113arm_netbsd_init_abi_common (struct gdbarch_info info, 114 struct gdbarch *gdbarch) 115{ 116 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 117 118 tdep->lowest_pc = 0x8000; 119 switch (info.byte_order_for_code) 120 { 121 case BFD_ENDIAN_LITTLE: 122 tdep->arm_breakpoint = arm_nbsd_arm_le_breakpoint; 123 tdep->thumb_breakpoint = arm_nbsd_thumb_le_breakpoint; 124 tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_le_breakpoint); 125 tdep->thumb_breakpoint_size = sizeof (arm_nbsd_thumb_le_breakpoint); 126 break; 127 128 case BFD_ENDIAN_BIG: 129 tdep->arm_breakpoint = arm_nbsd_arm_be_breakpoint; 130 tdep->thumb_breakpoint = arm_nbsd_thumb_be_breakpoint; 131 tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_be_breakpoint); 132 tdep->thumb_breakpoint_size = sizeof (arm_nbsd_thumb_be_breakpoint); 133 break; 134 135 default: 136 internal_error (__FILE__, __LINE__, 137 _("arm_gdbarch_init: bad byte order for float format")); 138 } 139 140 tdep->jb_pc = ARM_NBSD_JB_PC; 141 tdep->jb_elt_size = ARM_NBSD_JB_ELEMENT_SIZE; 142 143 set_gdbarch_iterate_over_regset_sections 144 (gdbarch, arm_nbsd_iterate_over_regset_sections); 145 /* Single stepping. */ 146 set_gdbarch_software_single_step (gdbarch, arm_software_single_step); 147 /* Core support */ 148 set_gdbarch_iterate_over_regset_sections 149 (gdbarch, arm_nbsd_iterate_over_regset_sections); 150 151} 152 153static void 154arm_netbsd_elf_init_abi (struct gdbarch_info info, 155 struct gdbarch *gdbarch) 156{ 157 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 158 159 arm_netbsd_init_abi_common (info, gdbarch); 160 161 nbsd_init_abi (info, gdbarch); 162 163 if (tdep->fp_model == ARM_FLOAT_AUTO) 164 tdep->fp_model = ARM_FLOAT_SOFT_VFP; 165 166 /* NetBSD ELF uses SVR4-style shared libraries. */ 167 set_solib_svr4_fetch_link_map_offsets 168 (gdbarch, svr4_ilp32_fetch_link_map_offsets); 169} 170 171void _initialize_arm_netbsd_tdep (); 172void 173_initialize_arm_netbsd_tdep () 174{ 175 gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD, 176 arm_netbsd_elf_init_abi); 177} 178