Home | History | Annotate | Line # | Download | only in aarch64
      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