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