Home | History | Annotate | Line # | Download | only in gdb
      1 /* none on ARM target support.
      2 
      3    Copyright (C) 2020-2024 Free Software Foundation, Inc.
      4 
      5    This file is part of GDB.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19 
     20 #include "arm-tdep.h"
     21 #include "arch-utils.h"
     22 #include "extract-store-integer.h"
     23 #include "regcache.h"
     24 #include "elf-bfd.h"
     25 #include "regset.h"
     26 #include "user-regs.h"
     27 
     28 #ifdef HAVE_ELF
     29 #include "elf-none-tdep.h"
     30 #endif
     31 
     32 /* Core file and register set support.  */
     33 #define ARM_NONE_SIZEOF_GREGSET (18 * ARM_INT_REGISTER_SIZE)
     34 
     35 /* Support VFP register format.  */
     36 #define ARM_NONE_SIZEOF_VFP (32 * 8 + 4)
     37 
     38 /* The index to access CPSR in user_regs as defined in GLIBC.  */
     39 #define ARM_NONE_CPSR_GREGNUM 16
     40 
     41 /* Supply register REGNUM from buffer GREGS_BUF (length LEN bytes) into
     42    REGCACHE.  If REGNUM is -1 then supply all registers.  The set of
     43    registers that this function will supply is limited to the general
     44    purpose registers.
     45 
     46    The layout of the registers here is based on the ARM GNU/Linux
     47    layout.  */
     48 
     49 static void
     50 arm_none_supply_gregset (const struct regset *regset,
     51 			 struct regcache *regcache,
     52 			 int regnum, const void *gregs_buf, size_t len)
     53 {
     54   struct gdbarch *gdbarch = regcache->arch ();
     55   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
     56   const gdb_byte *gregs = (const gdb_byte *) gregs_buf;
     57 
     58   for (int regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
     59     if (regnum == -1 || regnum == regno)
     60       regcache->raw_supply (regno, gregs + ARM_INT_REGISTER_SIZE * regno);
     61 
     62   if (regnum == ARM_PS_REGNUM || regnum == -1)
     63     {
     64       if (arm_apcs_32)
     65 	regcache->raw_supply (ARM_PS_REGNUM,
     66 			      gregs + ARM_INT_REGISTER_SIZE
     67 			      * ARM_NONE_CPSR_GREGNUM);
     68       else
     69 	regcache->raw_supply (ARM_PS_REGNUM,
     70 			     gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
     71     }
     72 
     73   if (regnum == ARM_PC_REGNUM || regnum == -1)
     74     {
     75       gdb_byte pc_buf[ARM_INT_REGISTER_SIZE];
     76 
     77       CORE_ADDR reg_pc
     78 	= extract_unsigned_integer (gregs + ARM_INT_REGISTER_SIZE
     79 				    * ARM_PC_REGNUM,
     80 				    ARM_INT_REGISTER_SIZE, byte_order);
     81       reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc);
     82       store_unsigned_integer (pc_buf, ARM_INT_REGISTER_SIZE, byte_order,
     83 			      reg_pc);
     84       regcache->raw_supply (ARM_PC_REGNUM, pc_buf);
     85     }
     86 }
     87 
     88 /* Collect register REGNUM from REGCACHE and place it into buffer GREGS_BUF
     89    (length LEN bytes).  If REGNUM is -1 then collect all registers.  The
     90    set of registers that this function will collect is limited to the
     91    general purpose registers.
     92 
     93    The layout of the registers here is based on the ARM GNU/Linux
     94    layout.  */
     95 
     96 static void
     97 arm_none_collect_gregset (const struct regset *regset,
     98 			  const struct regcache *regcache,
     99 			  int regnum, void *gregs_buf, size_t len)
    100 {
    101   gdb_byte *gregs = (gdb_byte *) gregs_buf;
    102 
    103   for (int regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
    104     if (regnum == -1 || regnum == regno)
    105       regcache->raw_collect (regno,
    106 			     gregs + ARM_INT_REGISTER_SIZE * regno);
    107 
    108   if (regnum == ARM_PS_REGNUM || regnum == -1)
    109     {
    110       if (arm_apcs_32)
    111 	regcache->raw_collect (ARM_PS_REGNUM,
    112 			       gregs + ARM_INT_REGISTER_SIZE
    113 			       * ARM_NONE_CPSR_GREGNUM);
    114       else
    115 	regcache->raw_collect (ARM_PS_REGNUM,
    116 			       gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
    117     }
    118 
    119   if (regnum == ARM_PC_REGNUM || regnum == -1)
    120     regcache->raw_collect (ARM_PC_REGNUM,
    121 			   gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
    122 }
    123 
    124 /* Supply VFP registers from REGS_BUF into REGCACHE.  */
    125 
    126 static void
    127 arm_none_supply_vfp (const struct regset *regset,
    128 		     struct regcache *regcache,
    129 		     int regnum, const void *regs_buf, size_t len)
    130 {
    131   const gdb_byte *regs = (const gdb_byte *) regs_buf;
    132 
    133   if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
    134     regcache->raw_supply (ARM_FPSCR_REGNUM, regs + 32 * 8);
    135 
    136   for (int regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
    137     if (regnum == -1 || regnum == regno)
    138       regcache->raw_supply (regno, regs + (regno - ARM_D0_REGNUM) * 8);
    139 }
    140 
    141 /* Collect VFP registers from REGCACHE into REGS_BUF.  */
    142 
    143 static void
    144 arm_none_collect_vfp (const struct regset *regset,
    145 		      const struct regcache *regcache,
    146 		      int regnum, void *regs_buf, size_t len)
    147 {
    148   gdb_byte *regs = (gdb_byte *) regs_buf;
    149 
    150   if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
    151     regcache->raw_collect (ARM_FPSCR_REGNUM, regs + 32 * 8);
    152 
    153   for (int regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
    154     if (regnum == -1 || regnum == regno)
    155       regcache->raw_collect (regno, regs + (regno - ARM_D0_REGNUM) * 8);
    156 }
    157 
    158 /* The general purpose register set.  */
    159 
    160 static const struct regset arm_none_gregset =
    161   {
    162     nullptr, arm_none_supply_gregset, arm_none_collect_gregset
    163   };
    164 
    165 /* The VFP register set.  */
    166 
    167 static const struct regset arm_none_vfpregset =
    168   {
    169     nullptr, arm_none_supply_vfp, arm_none_collect_vfp
    170   };
    171 
    172 /* Iterate over core file register note sections.  */
    173 
    174 static void
    175 arm_none_iterate_over_regset_sections (struct gdbarch *gdbarch,
    176 				       iterate_over_regset_sections_cb *cb,
    177 				       void *cb_data,
    178 				       const struct regcache *regcache)
    179 {
    180   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
    181 
    182   cb (".reg", ARM_NONE_SIZEOF_GREGSET, ARM_NONE_SIZEOF_GREGSET,
    183       &arm_none_gregset, nullptr, cb_data);
    184 
    185   if (tdep->vfp_register_count > 0)
    186     cb (".reg-arm-vfp", ARM_NONE_SIZEOF_VFP, ARM_NONE_SIZEOF_VFP,
    187 	&arm_none_vfpregset, "VFP floating-point", cb_data);
    188 }
    189 
    190 /* Initialize ARM bare-metal ABI info.  */
    191 
    192 static void
    193 arm_none_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    194 {
    195 #ifdef HAVE_ELF
    196   elf_none_init_abi (gdbarch);
    197 #endif
    198 
    199   /* Iterate over registers for reading and writing bare metal ARM core
    200      files.  */
    201   set_gdbarch_iterate_over_regset_sections
    202     (gdbarch, arm_none_iterate_over_regset_sections);
    203 }
    204 
    205 /* Initialize ARM bare-metal target support.  */
    206 
    207 void _initialize_arm_none_tdep ();
    208 void
    209 _initialize_arm_none_tdep ()
    210 {
    211   gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NONE,
    212 			  arm_none_init_abi);
    213 }
    214