]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/aarch64/interp.c
sim: create header namespace
[thirdparty/binutils-gdb.git] / sim / aarch64 / interp.c
CommitLineData
2e8cf49e
NC
1/* interp.c -- AArch64 sim interface to GDB.
2
3666a048 3 Copyright (C) 2015-2021 Free Software Foundation, Inc.
2e8cf49e
NC
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#include "config.h"
23#include <stdio.h>
24#include <assert.h>
25#include <signal.h>
26#include <string.h>
27#include <ctype.h>
28#include <stdlib.h>
29
30#include "ansidecl.h"
5357150c 31#include "bfd.h"
df68e12b
MF
32#include "sim/callback.h"
33#include "sim/sim.h"
2e8cf49e
NC
34#include "gdb/signals.h"
35#include "gdb/sim-aarch64.h"
36
37#include "sim-main.h"
38#include "sim-options.h"
39#include "memory.h"
40#include "simulator.h"
cd5b6074 41#include "sim-assert.h"
2e8cf49e 42
2e8cf49e
NC
43/* Filter out (in place) symbols that are useless for disassembly.
44 COUNT is the number of elements in SYMBOLS.
45 Return the number of useful symbols. */
46
5357150c
MF
47static long
48remove_useless_symbols (asymbol **symbols, long count)
2e8cf49e
NC
49{
50 asymbol **in_ptr = symbols;
51 asymbol **out_ptr = symbols;
52
53 while (count-- > 0)
54 {
55 asymbol *sym = *in_ptr++;
56
57 if (strstr (sym->name, "gcc2_compiled"))
58 continue;
59 if (sym->name == NULL || sym->name[0] == '\0')
60 continue;
61 if (sym->flags & (BSF_DEBUGGING))
62 continue;
63 if ( bfd_is_und_section (sym->section)
64 || bfd_is_com_section (sym->section))
65 continue;
66 if (sym->name[0] == '$')
67 continue;
68
69 *out_ptr++ = sym;
70 }
71 return out_ptr - symbols;
72}
73
74static signed int
75compare_symbols (const void *ap, const void *bp)
76{
77 const asymbol *a = * (const asymbol **) ap;
78 const asymbol *b = * (const asymbol **) bp;
79
80 if (bfd_asymbol_value (a) > bfd_asymbol_value (b))
81 return 1;
82 if (bfd_asymbol_value (a) < bfd_asymbol_value (b))
83 return -1;
84 return 0;
85}
86
87/* Find the name of the function at ADDR. */
88const char *
5357150c 89aarch64_get_func (SIM_DESC sd, uint64_t addr)
2e8cf49e 90{
5357150c
MF
91 long symcount = STATE_PROG_SYMS_COUNT (sd);
92 asymbol **symtab = STATE_PROG_SYMS (sd);
2e8cf49e
NC
93 int min, max;
94
95 min = -1;
96 max = symcount;
97 while (min < max - 1)
98 {
99 int sym;
100 bfd_vma sa;
101
102 sym = (min + max) / 2;
103 sa = bfd_asymbol_value (symtab[sym]);
104
105 if (sa > addr)
106 max = sym;
107 else if (sa < addr)
108 min = sym;
109 else
110 {
111 min = sym;
112 break;
113 }
114 }
115
116 if (min != -1)
117 return bfd_asymbol_name (symtab [min]);
118
119 return "";
120}
121
2e8cf49e 122SIM_RC
2e3d4f4d
MF
123sim_create_inferior (SIM_DESC sd, struct bfd *abfd,
124 char * const *argv, char * const *env)
2e8cf49e
NC
125{
126 sim_cpu *cpu = STATE_CPU (sd, 0);
2e8cf49e
NC
127 bfd_vma addr = 0;
128
129 if (abfd != NULL)
130 addr = bfd_get_start_address (abfd);
131
132 aarch64_set_next_PC (cpu, addr);
133 aarch64_update_PC (cpu);
134
0e967299
MF
135 /* Standalone mode (i.e. `run`) will take care of the argv for us in
136 sim_open() -> sim_parse_args(). But in debug mode (i.e. 'target sim'
137 with `gdb`), we need to handle it because the user can change the
138 argv on the fly via gdb's 'run'. */
139 if (STATE_PROG_ARGV (sd) != argv)
2e8cf49e
NC
140 {
141 freeargv (STATE_PROG_ARGV (sd));
142 STATE_PROG_ARGV (sd) = dupargv (argv);
143 }
144
5357150c 145 if (trace_load_symbols (sd))
2e8cf49e 146 {
5357150c
MF
147 STATE_PROG_SYMS_COUNT (sd) =
148 remove_useless_symbols (STATE_PROG_SYMS (sd),
149 STATE_PROG_SYMS_COUNT (sd));
150 qsort (STATE_PROG_SYMS (sd), STATE_PROG_SYMS_COUNT (sd),
151 sizeof (asymbol *), compare_symbols);
2e8cf49e
NC
152 }
153
6a277579 154 aarch64_init (cpu, addr);
2e8cf49e
NC
155
156 return SIM_RC_OK;
157}
158
159/* Read the LENGTH bytes at BUF as a little-endian value. */
160
161static bfd_vma
162get_le (unsigned char *buf, unsigned int length)
163{
164 bfd_vma acc = 0;
165
166 while (length -- > 0)
167 acc = (acc << 8) + buf[length];
168
169 return acc;
170}
171
172/* Store VAL as a little-endian value in the LENGTH bytes at BUF. */
173
174static void
175put_le (unsigned char *buf, unsigned int length, bfd_vma val)
176{
177 int i;
178
179 for (i = 0; i < length; i++)
180 {
181 buf[i] = val & 0xff;
182 val >>= 8;
183 }
184}
185
186static int
187check_regno (int regno)
188{
189 return 0 <= regno && regno < AARCH64_MAX_REGNO;
190}
191
192static size_t
193reg_size (int regno)
194{
195 if (regno == AARCH64_CPSR_REGNO || regno == AARCH64_FPSR_REGNO)
196 return 32;
197 return 64;
198}
199
200static int
201aarch64_reg_get (SIM_CPU *cpu, int regno, unsigned char *buf, int length)
202{
203 size_t size;
204 bfd_vma val;
205
206 if (!check_regno (regno))
207 return 0;
208
209 size = reg_size (regno);
210
211 if (length != size)
212 return 0;
213
214 switch (regno)
215 {
216 case AARCH64_MIN_GR ... AARCH64_MAX_GR:
217 val = aarch64_get_reg_u64 (cpu, regno, 0);
218 break;
219
220 case AARCH64_MIN_FR ... AARCH64_MAX_FR:
221 val = aarch64_get_FP_double (cpu, regno - 32);
222 break;
223
224 case AARCH64_PC_REGNO:
225 val = aarch64_get_PC (cpu);
226 break;
227
228 case AARCH64_CPSR_REGNO:
229 val = aarch64_get_CPSR (cpu);
230 break;
231
232 case AARCH64_FPSR_REGNO:
233 val = aarch64_get_FPSR (cpu);
234 break;
235
236 default:
237 sim_io_eprintf (CPU_STATE (cpu),
238 "sim: unrecognized register number: %d\n", regno);
239 return -1;
240 }
241
242 put_le (buf, length, val);
243
244 return size;
245}
246
247static int
248aarch64_reg_set (SIM_CPU *cpu, int regno, unsigned char *buf, int length)
249{
250 size_t size;
251 bfd_vma val;
252
253 if (!check_regno (regno))
254 return -1;
255
256 size = reg_size (regno);
257
258 if (length != size)
259 return -1;
260
261 val = get_le (buf, length);
262
263 switch (regno)
264 {
265 case AARCH64_MIN_GR ... AARCH64_MAX_GR:
266 aarch64_set_reg_u64 (cpu, regno, 1, val);
267 break;
268
269 case AARCH64_MIN_FR ... AARCH64_MAX_FR:
270 aarch64_set_FP_double (cpu, regno - 32, (double) val);
271 break;
272
273 case AARCH64_PC_REGNO:
274 aarch64_set_next_PC (cpu, val);
275 aarch64_update_PC (cpu);
276 break;
277
278 case AARCH64_CPSR_REGNO:
279 aarch64_set_CPSR (cpu, val);
280 break;
281
282 case AARCH64_FPSR_REGNO:
283 aarch64_set_FPSR (cpu, val);
284 break;
285
286 default:
287 sim_io_eprintf (CPU_STATE (cpu),
288 "sim: unrecognized register number: %d\n", regno);
289 return 0;
290 }
291
292 return size;
293}
294
295static sim_cia
296aarch64_pc_get (sim_cpu *cpu)
297{
298 return aarch64_get_PC (cpu);
299}
300
301static void
302aarch64_pc_set (sim_cpu *cpu, sim_cia pc)
303{
304 aarch64_set_next_PC (cpu, pc);
305 aarch64_update_PC (cpu);
306}
307
308static void
309free_state (SIM_DESC sd)
310{
311 if (STATE_MODULES (sd) != NULL)
312 sim_module_uninstall (sd);
313 sim_cpu_free_all (sd);
314 sim_state_free (sd);
315}
316
2e8cf49e
NC
317SIM_DESC
318sim_open (SIM_OPEN_KIND kind,
319 struct host_callback_struct * callback,
320 struct bfd * abfd,
2e3d4f4d 321 char * const * argv)
2e8cf49e 322{
2e8cf49e
NC
323 sim_cpu *cpu;
324 SIM_DESC sd = sim_state_alloc (kind, callback);
325
326 if (sd == NULL)
327 return sd;
328
329 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
330
2e8cf49e 331 /* Perform the initialization steps one by one. */
d5a71b11 332 if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK
2e8cf49e
NC
333 || sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK
334 || sim_parse_args (sd, argv) != SIM_RC_OK
335 || sim_analyze_program (sd,
336 (STATE_PROG_ARGV (sd) != NULL
337 ? *STATE_PROG_ARGV (sd)
338 : NULL), abfd) != SIM_RC_OK
339 || sim_config (sd) != SIM_RC_OK
340 || sim_post_argv_init (sd) != SIM_RC_OK)
341 {
342 free_state (sd);
343 return NULL;
344 }
345
346 aarch64_init_LIT_table ();
347
348 assert (MAX_NR_PROCESSORS == 1);
349 cpu = STATE_CPU (sd, 0);
350 CPU_PC_FETCH (cpu) = aarch64_pc_get;
351 CPU_PC_STORE (cpu) = aarch64_pc_set;
352 CPU_REG_FETCH (cpu) = aarch64_reg_get;
353 CPU_REG_STORE (cpu) = aarch64_reg_set;
354
355 /* Set SP, FP and PC to 0 and set LR to -1
356 so we can detect a top-level return. */
357 aarch64_set_reg_u64 (cpu, SP, 1, 0);
358 aarch64_set_reg_u64 (cpu, FP, 1, 0);
359 aarch64_set_reg_u64 (cpu, LR, 1, TOP_LEVEL_RETURN_PC);
360 aarch64_set_next_PC (cpu, 0);
361 aarch64_update_PC (cpu);
362
363 /* Default to a 128 Mbyte (== 2^27) memory space. */
364 sim_do_commandf (sd, "memory-size 0x8000000");
365
366 return sd;
367}
368
369void
370sim_engine_run (SIM_DESC sd,
371 int next_cpu_nr ATTRIBUTE_UNUSED,
372 int nr_cpus ATTRIBUTE_UNUSED,
373 int siggnal ATTRIBUTE_UNUSED)
374{
375 aarch64_run (sd);
376}