]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdbserver/linux-aarch32-low.cc
bus error with fuzzed archive element
[thirdparty/binutils-gdb.git] / gdbserver / linux-aarch32-low.cc
CommitLineData
1d506c26 1/* Copyright (C) 1995-2024 Free Software Foundation, Inc.
bd9e6534
YQ
2
3 This file is part of GDB.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
bd9e6534 18#include "arch/arm.h"
6885166d 19#include "arch/arm-linux.h"
bd9e6534
YQ
20#include "linux-low.h"
21#include "linux-aarch32-low.h"
22
23#include <sys/ptrace.h>
24/* Don't include elf.h if linux/elf.h got included by gdb_proc_service.h.
25 On Bionic elf.h and linux/elf.h have conflicting definitions. */
26#ifndef ELFMAG0
27#include <elf.h>
28#endif
29
b2ca446f
YQ
30/* Correct in either endianness. */
31#define arm_abi_breakpoint 0xef9f0001UL
32
33/* For new EABI binaries. We recognize it regardless of which ABI
34 is used for gdbserver, so single threaded debugging should work
35 OK, but for multi-threaded debugging we only insert the current
36 ABI's breakpoint instruction. For now at least. */
37#define arm_eabi_breakpoint 0xe7f001f0UL
38
39#if (defined __ARM_EABI__ || defined __aarch64__)
40static const unsigned long arm_breakpoint = arm_eabi_breakpoint;
41#else
42static const unsigned long arm_breakpoint = arm_abi_breakpoint;
43#endif
44
45#define arm_breakpoint_len 4
46static const unsigned short thumb_breakpoint = 0xde01;
47#define thumb_breakpoint_len 2
1b451dda 48static const unsigned short thumb2_breakpoint[] = { 0xf7f0, 0xa000 };
b2ca446f
YQ
49#define thumb2_breakpoint_len 4
50
16d5f642
JB
51/* Some older versions of GNU/Linux and Android do not define
52 the following macros. */
53#ifndef NT_ARM_VFP
54#define NT_ARM_VFP 0x400
55#endif
56
bd9e6534
YQ
57/* Collect GP registers from REGCACHE to buffer BUF. */
58
59void
60arm_fill_gregset (struct regcache *regcache, void *buf)
61{
62 int i;
04248ead 63 uint32_t *regs = (uint32_t *) buf;
fc6cda2e 64 uint32_t cpsr = regs[ARM_CPSR_GREGNUM];
bd9e6534
YQ
65
66 for (i = ARM_A1_REGNUM; i <= ARM_PC_REGNUM; i++)
67 collect_register (regcache, i, &regs[i]);
68
6885166d 69 collect_register (regcache, ARM_PS_REGNUM, &regs[ARM_CPSR_GREGNUM]);
fc6cda2e
YQ
70 /* Keep reserved bits bit 20 to bit 23. */
71 regs[ARM_CPSR_GREGNUM] = ((regs[ARM_CPSR_GREGNUM] & 0xff0fffff)
72 | (cpsr & 0x00f00000));
bd9e6534
YQ
73}
74
75/* Supply GP registers contents, stored in BUF, to REGCACHE. */
76
77void
78arm_store_gregset (struct regcache *regcache, const void *buf)
79{
80 int i;
81 char zerobuf[8];
04248ead 82 const uint32_t *regs = (const uint32_t *) buf;
3539aa13 83 uint32_t cpsr = regs[ARM_CPSR_GREGNUM];
bd9e6534
YQ
84
85 memset (zerobuf, 0, 8);
86 for (i = ARM_A1_REGNUM; i <= ARM_PC_REGNUM; i++)
87 supply_register (regcache, i, &regs[i]);
88
89 for (; i < ARM_PS_REGNUM; i++)
90 supply_register (regcache, i, zerobuf);
91
3539aa13
YQ
92 /* Clear reserved bits bit 20 to bit 23. */
93 cpsr &= 0xff0fffff;
94 supply_register (regcache, ARM_PS_REGNUM, &cpsr);
bd9e6534
YQ
95}
96
97/* Collect NUM number of VFP registers from REGCACHE to buffer BUF. */
98
99void
100arm_fill_vfpregset_num (struct regcache *regcache, void *buf, int num)
101{
102 int i, base;
103
104 gdb_assert (num == 16 || num == 32);
105
106 base = find_regno (regcache->tdesc, "d0");
107 for (i = 0; i < num; i++)
108 collect_register (regcache, base + i, (char *) buf + i * 8);
109
110 collect_register_by_name (regcache, "fpscr", (char *) buf + 32 * 8);
111}
112
113/* Supply NUM number of VFP registers contents, stored in BUF, to
114 REGCACHE. */
115
116void
117arm_store_vfpregset_num (struct regcache *regcache, const void *buf, int num)
118{
119 int i, base;
120
121 gdb_assert (num == 16 || num == 32);
122
123 base = find_regno (regcache->tdesc, "d0");
124 for (i = 0; i < num; i++)
125 supply_register (regcache, base + i, (char *) buf + i * 8);
126
127 supply_register_by_name (regcache, "fpscr", (char *) buf + 32 * 8);
128}
129
130static void
131arm_fill_vfpregset (struct regcache *regcache, void *buf)
132{
133 arm_fill_vfpregset_num (regcache, buf, 32);
134}
135
136static void
137arm_store_vfpregset (struct regcache *regcache, const void *buf)
138{
139 arm_store_vfpregset_num (regcache, buf, 32);
140}
141
142/* Register sets with using PTRACE_GETREGSET. */
143
144static struct regset_info aarch32_regsets[] = {
350fab54
AH
145 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
146 ARM_CORE_REGS_SIZE + ARM_INT_REGISTER_SIZE, GENERAL_REGS,
bd9e6534 147 arm_fill_gregset, arm_store_gregset },
350fab54 148 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_VFP, ARM_VFP3_REGS_SIZE,
bd9e6534
YQ
149 EXTENDED_REGS,
150 arm_fill_vfpregset, arm_store_vfpregset },
04b3479c 151 NULL_REGSET
bd9e6534
YQ
152};
153
154static struct regsets_info aarch32_regsets_info =
155 {
156 aarch32_regsets, /* regsets */
157 0, /* num_regsets */
158 NULL, /* disabled_regsets */
159 };
160
161struct regs_info regs_info_aarch32 =
162 {
163 NULL, /* regset_bitmap */
164 NULL, /* usrregs */
165 &aarch32_regsets_info
166 };
167
17b1509a
YQ
168/* Returns 1 if the current instruction set is thumb, 0 otherwise. */
169
d9311bfa 170int
17b1509a
YQ
171arm_is_thumb_mode (void)
172{
173 struct regcache *regcache = get_thread_regcache (current_thread, 1);
174 unsigned long cpsr;
175
176 collect_register_by_name (regcache, "cpsr", &cpsr);
177
178 if (cpsr & 0x20)
179 return 1;
180 else
181 return 0;
182}
183
184/* Returns 1 if there is a software breakpoint at location. */
185
186int
187arm_breakpoint_at (CORE_ADDR where)
188{
189 if (arm_is_thumb_mode ())
190 {
191 /* Thumb mode. */
192 unsigned short insn;
193
52405d85 194 the_target->read_memory (where, (unsigned char *) &insn, 2);
17b1509a
YQ
195 if (insn == thumb_breakpoint)
196 return 1;
197
198 if (insn == thumb2_breakpoint[0])
199 {
52405d85 200 the_target->read_memory (where + 2, (unsigned char *) &insn, 2);
17b1509a
YQ
201 if (insn == thumb2_breakpoint[1])
202 return 1;
203 }
204 }
205 else
206 {
207 /* ARM mode. */
208 unsigned long insn;
209
52405d85 210 the_target->read_memory (where, (unsigned char *) &insn, 4);
17b1509a
YQ
211 if (insn == arm_abi_breakpoint)
212 return 1;
213
214 if (insn == arm_eabi_breakpoint)
215 return 1;
216 }
217
218 return 0;
219}
220
17b1509a
YQ
221/* Implementation of linux_target_ops method "breakpoint_kind_from_pc".
222
223 Determine the type and size of breakpoint to insert at PCPTR. Uses the
224 program counter value to determine whether a 16-bit or 32-bit breakpoint
225 should be used. It returns the breakpoint's kind, and adjusts the program
226 counter (if necessary) to point to the actual memory location where the
227 breakpoint should be inserted. */
228
229int
230arm_breakpoint_kind_from_pc (CORE_ADDR *pcptr)
231{
232 if (IS_THUMB_ADDR (*pcptr))
233 {
234 gdb_byte buf[2];
235
236 *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
237
238 /* Check whether we are replacing a thumb2 32-bit instruction. */
694b382c 239 if (target_read_memory (*pcptr, buf, 2) == 0)
17b1509a
YQ
240 {
241 unsigned short inst1 = 0;
242
694b382c 243 target_read_memory (*pcptr, (gdb_byte *) &inst1, 2);
17b1509a
YQ
244 if (thumb_insn_size (inst1) == 4)
245 return ARM_BP_KIND_THUMB2;
246 }
247 return ARM_BP_KIND_THUMB;
248 }
249 else
250 return ARM_BP_KIND_ARM;
251}
252
253/* Implementation of the linux_target_ops method "sw_breakpoint_from_kind". */
254
255const gdb_byte *
256arm_sw_breakpoint_from_kind (int kind , int *size)
257{
258 *size = arm_breakpoint_len;
259 /* Define an ARM-mode breakpoint; we only set breakpoints in the C
260 library, which is most likely to be ARM. If the kernel supports
261 clone events, we will never insert a breakpoint, so even a Thumb
262 C library will work; so will mixing EABI/non-EABI gdbserver and
263 application. */
264 switch (kind)
265 {
266 case ARM_BP_KIND_THUMB:
267 *size = thumb_breakpoint_len;
268 return (gdb_byte *) &thumb_breakpoint;
269 case ARM_BP_KIND_THUMB2:
270 *size = thumb2_breakpoint_len;
271 return (gdb_byte *) &thumb2_breakpoint;
272 case ARM_BP_KIND_ARM:
273 *size = arm_breakpoint_len;
274 return (const gdb_byte *) &arm_breakpoint;
275 default:
276 return NULL;
277 }
278 return NULL;
279}
280
281/* Implementation of the linux_target_ops method
282 "breakpoint_kind_from_current_state". */
283
284int
285arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr)
286{
287 if (arm_is_thumb_mode ())
288 {
289 *pcptr = MAKE_THUMB_ADDR (*pcptr);
290 return arm_breakpoint_kind_from_pc (pcptr);
291 }
292 else
293 {
294 return arm_breakpoint_kind_from_pc (pcptr);
295 }
296}
297
bd9e6534
YQ
298void
299initialize_low_arch_aarch32 (void)
300{
bd9e6534
YQ
301 initialize_regsets_info (&aarch32_regsets_info);
302}