arm-netbsd-tdep.c revision 1.1.1.2 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