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