Home | History | Annotate | Line # | Download | only in gdb
      1      1.1  christos /* Target-dependent code for NetBSD/arm.
      2      1.1  christos 
      3  1.1.1.2  christos    Copyright (C) 2002-2024 Free Software Foundation, Inc.
      4      1.1  christos 
      5      1.1  christos    This file is part of GDB.
      6      1.1  christos 
      7      1.1  christos    This program is free software; you can redistribute it and/or modify
      8      1.1  christos    it under the terms of the GNU General Public License as published by
      9      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10      1.1  christos    (at your option) any later version.
     11      1.1  christos 
     12      1.1  christos    This program is distributed in the hope that it will be useful,
     13      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  christos    GNU General Public License for more details.
     16      1.1  christos 
     17      1.1  christos    You should have received a copy of the GNU General Public License
     18      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19      1.1  christos 
     20      1.1  christos #include "osabi.h"
     21      1.1  christos 
     22      1.1  christos #include "arch/arm.h"
     23      1.1  christos #include "arm-netbsd-tdep.h"
     24      1.1  christos #include "netbsd-tdep.h"
     25      1.1  christos #include "arm-tdep.h"
     26      1.1  christos #include "regset.h"
     27      1.1  christos #include "solib-svr4.h"
     28      1.1  christos 
     29      1.1  christos /* Description of the longjmp buffer.  */
     30      1.1  christos #define ARM_NBSD_JB_PC 24
     31      1.1  christos #define ARM_NBSD_JB_ELEMENT_SIZE ARM_INT_REGISTER_SIZE
     32      1.1  christos 
     33      1.1  christos /* For compatibility with previous implementations of GDB on arm/NetBSD,
     34      1.1  christos    override the default little-endian breakpoint.  */
     35      1.1  christos static const gdb_byte arm_nbsd_arm_le_breakpoint[] = {0x11, 0x00, 0x00, 0xe6};
     36      1.1  christos static const gdb_byte arm_nbsd_arm_be_breakpoint[] = {0xe6, 0x00, 0x00, 0x11};
     37      1.1  christos static const gdb_byte arm_nbsd_thumb_le_breakpoint[] = {0xfe, 0xde};
     38      1.1  christos static const gdb_byte arm_nbsd_thumb_be_breakpoint[] = {0xde, 0xfe};
     39      1.1  christos 
     40      1.1  christos /* This matches struct reg from NetBSD's sys/arch/arm/include/reg.h:
     41      1.1  christos    https://github.com/NetBSD/src/blob/7c13e6e6773bb171f4ed3ed53013e9d24b3c1eac/sys/arch/arm/include/reg.h#L39
     42      1.1  christos  */
     43      1.1  christos struct arm_nbsd_reg
     44      1.1  christos {
     45      1.1  christos   uint32_t reg[13];
     46      1.1  christos   uint32_t sp;
     47      1.1  christos   uint32_t lr;
     48      1.1  christos   uint32_t pc;
     49      1.1  christos   uint32_t cpsr;
     50      1.1  christos };
     51      1.1  christos 
     52      1.1  christos void
     53      1.1  christos arm_nbsd_supply_gregset (const struct regset *regset, struct regcache *regcache,
     54      1.1  christos 			 int regnum, const void *gregs, size_t len)
     55      1.1  christos {
     56      1.1  christos   const arm_nbsd_reg *gregset = static_cast<const arm_nbsd_reg *>(gregs);
     57      1.1  christos   gdb_assert (len >= sizeof (arm_nbsd_reg));
     58      1.1  christos 
     59      1.1  christos   /* Integer registers.  */
     60      1.1  christos   for (int i = ARM_A1_REGNUM; i < ARM_SP_REGNUM; i++)
     61      1.1  christos     if (regnum == -1 || regnum == i)
     62      1.1  christos       regcache->raw_supply (i, (char *) &gregset->reg[i]);
     63      1.1  christos 
     64      1.1  christos   if (regnum == -1 || regnum == ARM_SP_REGNUM)
     65      1.1  christos     regcache->raw_supply (ARM_SP_REGNUM, (char *) &gregset->sp);
     66      1.1  christos 
     67      1.1  christos   if (regnum == -1 || regnum == ARM_LR_REGNUM)
     68      1.1  christos     regcache->raw_supply (ARM_LR_REGNUM, (char *) &gregset->lr);
     69      1.1  christos 
     70      1.1  christos   if (regnum == -1 || regnum == ARM_PC_REGNUM)
     71      1.1  christos     {
     72      1.1  christos       /* XXX Use uint32_t instead of CORE_ADDR (aka uint64_t; see
     73      1.1  christos 	 gdbsupport/common-types.h).  Otherwise, zero-filled word
     74      1.1  christos 	 will be stored for big-endian targets.  */
     75      1.1  christos       uint32_t r_pc = gdbarch_addr_bits_remove (regcache->arch (), gregset->pc);
     76      1.1  christos       regcache->raw_supply (ARM_PC_REGNUM, (char *) &r_pc);
     77      1.1  christos     }
     78      1.1  christos 
     79      1.1  christos   if (regnum == -1 || regnum == ARM_PS_REGNUM)
     80      1.1  christos     {
     81      1.1  christos       if (arm_apcs_32)
     82      1.1  christos 	regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->cpsr);
     83      1.1  christos       else
     84      1.1  christos 	regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->pc);
     85      1.1  christos     }
     86      1.1  christos }
     87      1.1  christos 
     88      1.1  christos static const struct regset arm_nbsd_regset = {
     89      1.1  christos   nullptr,
     90      1.1  christos   arm_nbsd_supply_gregset,
     91      1.1  christos   /* We don't need a collect function because we only use this reading registers
     92      1.1  christos      (via iterate_over_regset_sections and fetch_regs/fetch_register).  */
     93      1.1  christos   nullptr,
     94      1.1  christos   0
     95      1.1  christos };
     96      1.1  christos 
     97      1.1  christos static void
     98      1.1  christos arm_nbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
     99      1.1  christos 				       iterate_over_regset_sections_cb *cb,
    100      1.1  christos 				       void *cb_data,
    101      1.1  christos 				       const struct regcache *regcache)
    102      1.1  christos {
    103      1.1  christos   cb (".reg", sizeof (arm_nbsd_reg), sizeof (arm_nbsd_reg), &arm_nbsd_regset,
    104      1.1  christos       NULL, cb_data);
    105      1.1  christos   /* cbiesinger/2020-02-12 -- as far as I can tell, ARM/NetBSD does
    106      1.1  christos      not write any floating point registers into the core file (tested
    107      1.1  christos      with NetBSD 9.1_RC1).  When it does, this function will need to read them,
    108      1.1  christos      and the arm-netbsd gdbarch will need a core_read_description function
    109      1.1  christos      to return the right description for them.  */
    110      1.1  christos }
    111      1.1  christos 
    112      1.1  christos static void
    113      1.1  christos arm_netbsd_init_abi_common (struct gdbarch_info info,
    114      1.1  christos 			    struct gdbarch *gdbarch)
    115      1.1  christos {
    116      1.1  christos   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
    117      1.1  christos 
    118      1.1  christos   tdep->lowest_pc = 0x8000;
    119      1.1  christos   /* For armv[67]eb (BE8), insns are encoded in little-endian.
    120      1.1  christos      Therefore, we cannot use info.byte_order here.  */
    121      1.1  christos   switch (info.byte_order_for_code)
    122      1.1  christos     {
    123      1.1  christos     case BFD_ENDIAN_LITTLE:
    124      1.1  christos       tdep->arm_breakpoint = arm_nbsd_arm_le_breakpoint;
    125      1.1  christos       tdep->thumb_breakpoint = arm_nbsd_thumb_le_breakpoint;
    126      1.1  christos       tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_le_breakpoint);
    127      1.1  christos       tdep->thumb_breakpoint_size = sizeof (arm_nbsd_thumb_le_breakpoint);
    128      1.1  christos       break;
    129      1.1  christos 
    130      1.1  christos     case BFD_ENDIAN_BIG:
    131      1.1  christos       tdep->arm_breakpoint = arm_nbsd_arm_be_breakpoint;
    132      1.1  christos       tdep->thumb_breakpoint = arm_nbsd_thumb_be_breakpoint;
    133      1.1  christos       tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_be_breakpoint);
    134      1.1  christos       tdep->thumb_breakpoint_size = sizeof (arm_nbsd_thumb_be_breakpoint);
    135      1.1  christos       break;
    136      1.1  christos 
    137      1.1  christos     default:
    138      1.1  christos       internal_error (_("arm_gdbarch_init: bad byte order for float format"));
    139      1.1  christos     }
    140      1.1  christos 
    141      1.1  christos   tdep->jb_pc = ARM_NBSD_JB_PC;
    142      1.1  christos   tdep->jb_elt_size = ARM_NBSD_JB_ELEMENT_SIZE;
    143      1.1  christos 
    144      1.1  christos   set_gdbarch_iterate_over_regset_sections
    145      1.1  christos     (gdbarch, arm_nbsd_iterate_over_regset_sections);
    146      1.1  christos   /* Single stepping.  */
    147      1.1  christos   set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
    148      1.1  christos }
    149      1.1  christos 
    150      1.1  christos static void
    151      1.1  christos arm_netbsd_elf_init_abi (struct gdbarch_info info,
    152      1.1  christos 			 struct gdbarch *gdbarch)
    153      1.1  christos {
    154      1.1  christos   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
    155      1.1  christos 
    156      1.1  christos   arm_netbsd_init_abi_common (info, gdbarch);
    157      1.1  christos 
    158      1.1  christos   nbsd_init_abi (info, gdbarch);
    159      1.1  christos 
    160      1.1  christos   if (tdep->fp_model == ARM_FLOAT_AUTO)
    161      1.1  christos     tdep->fp_model = ARM_FLOAT_SOFT_VFP;
    162      1.1  christos 
    163      1.1  christos   /* NetBSD ELF uses SVR4-style shared libraries.  */
    164      1.1  christos   set_solib_svr4_fetch_link_map_offsets
    165      1.1  christos     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
    166      1.1  christos }
    167      1.1  christos 
    168      1.1  christos void _initialize_arm_netbsd_tdep ();
    169      1.1  christos void
    170      1.1  christos _initialize_arm_netbsd_tdep ()
    171      1.1  christos {
    172      1.1  christos   gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD,
    173      1.1  christos 			  arm_netbsd_elf_init_abi);
    174      1.1  christos }
    175