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