xref: /netbsd-src/external/gpl3/gdb/dist/sim/aarch64/interp.c (revision 4d1eaf9104083d3c1d72a17f5c414777b18c6935)
1 /* interp.c -- AArch64 sim interface to GDB.
2 
3    Copyright (C) 2015-2024 Free Software Foundation, Inc.
4 
5    Contributed by Red Hat.
6 
7    This file is part of GDB.
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21 
22 /* This must come before any other includes.  */
23 #include "defs.h"
24 
25 #include <stdio.h>
26 #include <assert.h>
27 #include <signal.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31 
32 #include "ansidecl.h"
33 #include "bfd.h"
34 #include "sim/callback.h"
35 #include "sim/sim.h"
36 #include "gdb/signals.h"
37 #include "sim/sim-aarch64.h"
38 
39 #include "sim-main.h"
40 #include "sim-options.h"
41 #include "memory.h"
42 #include "simulator.h"
43 #include "sim-assert.h"
44 
45 #include "aarch64-sim.h"
46 
47 /* Filter out (in place) symbols that are useless for disassembly.
48    COUNT is the number of elements in SYMBOLS.
49    Return the number of useful symbols. */
50 
51 static long
52 remove_useless_symbols (asymbol **symbols, long count)
53 {
54   asymbol **in_ptr  = symbols;
55   asymbol **out_ptr = symbols;
56 
57   while (count-- > 0)
58     {
59       asymbol *sym = *in_ptr++;
60 
61       if (strstr (sym->name, "gcc2_compiled"))
62 	continue;
63       if (sym->name == NULL || sym->name[0] == '\0')
64 	continue;
65       if (sym->flags & (BSF_DEBUGGING))
66 	continue;
67       if (   bfd_is_und_section (sym->section)
68 	  || bfd_is_com_section (sym->section))
69 	continue;
70       if (sym->name[0] == '$')
71 	continue;
72 
73       *out_ptr++ = sym;
74     }
75   return out_ptr - symbols;
76 }
77 
78 static signed int
79 compare_symbols (const void *ap, const void *bp)
80 {
81   const asymbol *a = * (const asymbol **) ap;
82   const asymbol *b = * (const asymbol **) bp;
83 
84   if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
85     return 1;
86   if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
87     return -1;
88   return 0;
89 }
90 
91 /* Find the name of the function at ADDR.  */
92 const char *
93 aarch64_get_func (SIM_DESC sd, uint64_t addr)
94 {
95   long symcount = STATE_PROG_SYMS_COUNT (sd);
96   asymbol **symtab = STATE_PROG_SYMS (sd);
97   int  min, max;
98 
99   min = -1;
100   max = symcount;
101   while (min < max - 1)
102     {
103       int sym;
104       bfd_vma sa;
105 
106       sym = (min + max) / 2;
107       sa = bfd_asymbol_value (symtab[sym]);
108 
109       if (sa > addr)
110 	max = sym;
111       else if (sa < addr)
112 	min = sym;
113       else
114 	{
115 	  min = sym;
116 	  break;
117 	}
118     }
119 
120   if (min != -1)
121     return bfd_asymbol_name (symtab [min]);
122 
123   return "";
124 }
125 
126 SIM_RC
127 sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
128 		     char * const *argv, char * const *env)
129 {
130   sim_cpu *cpu = STATE_CPU (sd, 0);
131   host_callback *cb = STATE_CALLBACK (sd);
132   bfd_vma addr = 0;
133 
134   if (abfd != NULL)
135     addr = bfd_get_start_address (abfd);
136 
137   aarch64_set_next_PC (cpu, addr);
138   aarch64_update_PC (cpu);
139 
140   /* Standalone mode (i.e. `run`) will take care of the argv for us in
141      sim_open() -> sim_parse_args().  But in debug mode (i.e. 'target sim'
142      with `gdb`), we need to handle it because the user can change the
143      argv on the fly via gdb's 'run'.  */
144   if (STATE_PROG_ARGV (sd) != argv)
145     {
146       freeargv (STATE_PROG_ARGV (sd));
147       STATE_PROG_ARGV (sd) = dupargv (argv);
148     }
149 
150   if (STATE_PROG_ENVP (sd) != env)
151     {
152       freeargv (STATE_PROG_ENVP (sd));
153       STATE_PROG_ENVP (sd) = dupargv (env);
154     }
155 
156   cb->argv = STATE_PROG_ARGV (sd);
157   cb->envp = STATE_PROG_ENVP (sd);
158 
159   if (trace_load_symbols (sd))
160     {
161       STATE_PROG_SYMS_COUNT (sd) =
162 	remove_useless_symbols (STATE_PROG_SYMS (sd),
163 				STATE_PROG_SYMS_COUNT (sd));
164       qsort (STATE_PROG_SYMS (sd), STATE_PROG_SYMS_COUNT (sd),
165 	     sizeof (asymbol *), compare_symbols);
166     }
167 
168   aarch64_init (cpu, addr);
169 
170   return SIM_RC_OK;
171 }
172 
173 /* Read the LENGTH bytes at BUF as a little-endian value.  */
174 
175 static bfd_vma
176 get_le (const unsigned char *buf, unsigned int length)
177 {
178   bfd_vma acc = 0;
179 
180   while (length -- > 0)
181     acc = (acc << 8) + buf[length];
182 
183   return acc;
184 }
185 
186 /* Store VAL as a little-endian value in the LENGTH bytes at BUF.  */
187 
188 static void
189 put_le (unsigned char *buf, unsigned int length, bfd_vma val)
190 {
191   int i;
192 
193   for (i = 0; i < length; i++)
194     {
195       buf[i] = val & 0xff;
196       val >>= 8;
197     }
198 }
199 
200 static int
201 check_regno (int regno)
202 {
203   return 0 <= regno && regno < AARCH64_MAX_REGNO;
204 }
205 
206 static size_t
207 reg_size (int regno)
208 {
209   if (regno == AARCH64_CPSR_REGNO || regno == AARCH64_FPSR_REGNO)
210     return 32;
211   return 64;
212 }
213 
214 static int
215 aarch64_reg_get (SIM_CPU *cpu, int regno, void *buf, int length)
216 {
217   size_t size;
218   bfd_vma val;
219 
220   if (!check_regno (regno))
221     return 0;
222 
223   size = reg_size (regno);
224 
225   if (length != size)
226     return 0;
227 
228   switch (regno)
229     {
230     case AARCH64_MIN_GR ... AARCH64_MAX_GR:
231       val = aarch64_get_reg_u64 (cpu, regno, 0);
232       break;
233 
234     case AARCH64_MIN_FR ... AARCH64_MAX_FR:
235       val = aarch64_get_FP_double (cpu, regno - 32);
236       break;
237 
238     case AARCH64_PC_REGNO:
239       val = aarch64_get_PC (cpu);
240       break;
241 
242     case AARCH64_CPSR_REGNO:
243       val = aarch64_get_CPSR (cpu);
244       break;
245 
246     case AARCH64_FPSR_REGNO:
247       val = aarch64_get_FPSR (cpu);
248       break;
249 
250     default:
251       sim_io_eprintf (CPU_STATE (cpu),
252 		      "sim: unrecognized register number: %d\n", regno);
253       return -1;
254     }
255 
256   put_le (buf, length, val);
257 
258   return size;
259 }
260 
261 static int
262 aarch64_reg_set (SIM_CPU *cpu, int regno, const void *buf, int length)
263 {
264   size_t size;
265   bfd_vma val;
266 
267   if (!check_regno (regno))
268     return -1;
269 
270   size = reg_size (regno);
271 
272   if (length != size)
273     return -1;
274 
275   val = get_le (buf, length);
276 
277   switch (regno)
278     {
279     case AARCH64_MIN_GR ... AARCH64_MAX_GR:
280       aarch64_set_reg_u64 (cpu, regno, 1, val);
281       break;
282 
283     case AARCH64_MIN_FR ... AARCH64_MAX_FR:
284       aarch64_set_FP_double (cpu, regno - 32, (double) val);
285       break;
286 
287     case AARCH64_PC_REGNO:
288       aarch64_set_next_PC (cpu, val);
289       aarch64_update_PC (cpu);
290       break;
291 
292     case AARCH64_CPSR_REGNO:
293       aarch64_set_CPSR (cpu, val);
294       break;
295 
296     case AARCH64_FPSR_REGNO:
297       aarch64_set_FPSR (cpu, val);
298       break;
299 
300     default:
301       sim_io_eprintf (CPU_STATE (cpu),
302 		      "sim: unrecognized register number: %d\n", regno);
303       return 0;
304     }
305 
306   return size;
307 }
308 
309 static sim_cia
310 aarch64_pc_get (sim_cpu *cpu)
311 {
312   return aarch64_get_PC (cpu);
313 }
314 
315 static void
316 aarch64_pc_set (sim_cpu *cpu, sim_cia pc)
317 {
318   aarch64_set_next_PC (cpu, pc);
319   aarch64_update_PC (cpu);
320 }
321 
322 static void
323 free_state (SIM_DESC sd)
324 {
325   if (STATE_MODULES (sd) != NULL)
326     sim_module_uninstall (sd);
327   sim_cpu_free_all (sd);
328   sim_state_free (sd);
329 }
330 
331 SIM_DESC
332 sim_open (SIM_OPEN_KIND                  kind,
333 	  struct host_callback_struct *  callback,
334 	  struct bfd *                   abfd,
335 	  char * const *                 argv)
336 {
337   sim_cpu *cpu;
338   SIM_DESC sd = sim_state_alloc (kind, callback);
339 
340   if (sd == NULL)
341     return sd;
342 
343   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
344 
345   /* We use NONSTRICT_ALIGNMENT as the default because AArch64 only enforces
346      4-byte alignment, even for 8-byte reads/writes.  The common core does not
347      support this, so we opt for non-strict alignment instead.  */
348   current_alignment = NONSTRICT_ALIGNMENT;
349 
350   /* Perform the initialization steps one by one.  */
351   if (sim_cpu_alloc_all_extra (sd, 0, sizeof (struct aarch64_sim_cpu))
352       != SIM_RC_OK
353       || sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK
354       || sim_parse_args (sd, argv) != SIM_RC_OK
355       || sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK
356       || sim_config (sd) != SIM_RC_OK
357       || sim_post_argv_init (sd) != SIM_RC_OK)
358     {
359       free_state (sd);
360       return NULL;
361     }
362 
363   aarch64_init_LIT_table ();
364 
365   assert (MAX_NR_PROCESSORS == 1);
366   cpu = STATE_CPU (sd, 0);
367   CPU_PC_FETCH (cpu) = aarch64_pc_get;
368   CPU_PC_STORE (cpu) = aarch64_pc_set;
369   CPU_REG_FETCH (cpu) = aarch64_reg_get;
370   CPU_REG_STORE (cpu) = aarch64_reg_set;
371 
372   /* Set SP, FP and PC to 0 and set LR to -1
373      so we can detect a top-level return.  */
374   aarch64_set_reg_u64 (cpu, SP, 1, 0);
375   aarch64_set_reg_u64 (cpu, FP, 1, 0);
376   aarch64_set_reg_u64 (cpu, LR, 1, TOP_LEVEL_RETURN_PC);
377   aarch64_set_next_PC (cpu, 0);
378   aarch64_update_PC (cpu);
379 
380   /* Default to a 128 Mbyte (== 2^27) memory space.  */
381   sim_do_commandf (sd, "memory-size 0x8000000");
382 
383   return sd;
384 }
385 
386 void
387 sim_engine_run (SIM_DESC sd,
388 		int next_cpu_nr ATTRIBUTE_UNUSED,
389 		int nr_cpus ATTRIBUTE_UNUSED,
390 		int siggnal ATTRIBUTE_UNUSED)
391 {
392   aarch64_run (sd);
393 }
394