xref: /netbsd-src/external/gpl3/gdb/dist/gdbserver/linux-aarch32-low.cc (revision f1c2b495c8d0ed769f039187bdd4f963026e012b)
1 /* Copyright (C) 1995-2024 Free Software Foundation, Inc.
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 
18 #include "arch/arm.h"
19 #include "arch/arm-linux.h"
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 
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__)
40 static const unsigned long arm_breakpoint = arm_eabi_breakpoint;
41 #else
42 static const unsigned long arm_breakpoint = arm_abi_breakpoint;
43 #endif
44 
45 #define arm_breakpoint_len 4
46 static const unsigned short thumb_breakpoint = 0xde01;
47 #define thumb_breakpoint_len 2
48 static const unsigned short thumb2_breakpoint[] = { 0xf7f0, 0xa000 };
49 #define thumb2_breakpoint_len 4
50 
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 
57 /* Collect GP registers from REGCACHE to buffer BUF.  */
58 
59 void
60 arm_fill_gregset (struct regcache *regcache, void *buf)
61 {
62   int i;
63   uint32_t *regs = (uint32_t *) buf;
64   uint32_t cpsr = regs[ARM_CPSR_GREGNUM];
65 
66   for (i = ARM_A1_REGNUM; i <= ARM_PC_REGNUM; i++)
67     collect_register (regcache, i, &regs[i]);
68 
69   collect_register (regcache, ARM_PS_REGNUM, &regs[ARM_CPSR_GREGNUM]);
70   /* Keep reserved bits bit 20 to bit 23.  */
71   regs[ARM_CPSR_GREGNUM] = ((regs[ARM_CPSR_GREGNUM] & 0xff0fffff)
72 			    | (cpsr & 0x00f00000));
73 }
74 
75 /* Supply GP registers contents, stored in BUF, to REGCACHE.  */
76 
77 void
78 arm_store_gregset (struct regcache *regcache, const void *buf)
79 {
80   int i;
81   char zerobuf[8];
82   const uint32_t *regs = (const uint32_t *) buf;
83   uint32_t cpsr = regs[ARM_CPSR_GREGNUM];
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 
92   /* Clear reserved bits bit 20 to bit 23.  */
93   cpsr &= 0xff0fffff;
94   supply_register (regcache, ARM_PS_REGNUM, &cpsr);
95 }
96 
97 /* Collect NUM number of VFP registers from REGCACHE to buffer BUF.  */
98 
99 void
100 arm_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 
116 void
117 arm_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 
130 static void
131 arm_fill_vfpregset (struct regcache *regcache, void *buf)
132 {
133   arm_fill_vfpregset_num (regcache, buf, 32);
134 }
135 
136 static void
137 arm_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 
144 static struct regset_info aarch32_regsets[] = {
145   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
146     ARM_CORE_REGS_SIZE + ARM_INT_REGISTER_SIZE, GENERAL_REGS,
147     arm_fill_gregset, arm_store_gregset },
148   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_VFP, ARM_VFP3_REGS_SIZE,
149     EXTENDED_REGS,
150     arm_fill_vfpregset, arm_store_vfpregset },
151   NULL_REGSET
152 };
153 
154 static struct regsets_info aarch32_regsets_info =
155   {
156     aarch32_regsets, /* regsets */
157     0, /* num_regsets */
158     NULL, /* disabled_regsets */
159   };
160 
161 struct regs_info regs_info_aarch32 =
162   {
163     NULL, /* regset_bitmap */
164     NULL, /* usrregs */
165     &aarch32_regsets_info
166   };
167 
168 /* Returns 1 if the current instruction set is thumb, 0 otherwise.  */
169 
170 int
171 arm_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 
186 int
187 arm_breakpoint_at (CORE_ADDR where)
188 {
189   if (arm_is_thumb_mode ())
190     {
191       /* Thumb mode.  */
192       unsigned short insn;
193 
194       the_target->read_memory (where, (unsigned char *) &insn, 2);
195       if (insn == thumb_breakpoint)
196 	return 1;
197 
198       if (insn == thumb2_breakpoint[0])
199 	{
200 	  the_target->read_memory (where + 2, (unsigned char *) &insn, 2);
201 	  if (insn == thumb2_breakpoint[1])
202 	    return 1;
203 	}
204     }
205   else
206     {
207       /* ARM mode.  */
208       unsigned long insn;
209 
210       the_target->read_memory (where, (unsigned char *) &insn, 4);
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 
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 
229 int
230 arm_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.  */
239       if (target_read_memory (*pcptr, buf, 2) == 0)
240 	{
241 	  unsigned short inst1 = 0;
242 
243 	  target_read_memory (*pcptr, (gdb_byte *) &inst1, 2);
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 
255 const gdb_byte *
256 arm_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 
284 int
285 arm_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 
298 void
299 initialize_low_arch_aarch32 (void)
300 {
301   initialize_regsets_info (&aarch32_regsets_info);
302 }
303