Home | History | Annotate | Line # | Download | only in gdb
      1      1.1  christos /* Target-dependent code for FreeBSD/arm.
      2      1.1  christos 
      3  1.1.1.4  christos    Copyright (C) 2017-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 
     21      1.1  christos #include "elf/common.h"
     22  1.1.1.2  christos #include "target-descriptions.h"
     23  1.1.1.2  christos #include "aarch32-tdep.h"
     24      1.1  christos #include "arm-tdep.h"
     25      1.1  christos #include "arm-fbsd-tdep.h"
     26      1.1  christos #include "auxv.h"
     27      1.1  christos #include "fbsd-tdep.h"
     28      1.1  christos #include "gdbcore.h"
     29  1.1.1.3  christos #include "inferior.h"
     30      1.1  christos #include "osabi.h"
     31      1.1  christos #include "solib-svr4.h"
     32      1.1  christos #include "trad-frame.h"
     33      1.1  christos #include "tramp-frame.h"
     34      1.1  christos 
     35      1.1  christos /* Register maps.  */
     36      1.1  christos 
     37      1.1  christos static const struct regcache_map_entry arm_fbsd_gregmap[] =
     38      1.1  christos   {
     39      1.1  christos     { 13, ARM_A1_REGNUM, 4 }, /* r0 ... r12 */
     40      1.1  christos     { 1, ARM_SP_REGNUM, 4 },
     41      1.1  christos     { 1, ARM_LR_REGNUM, 4 },
     42      1.1  christos     { 1, ARM_PC_REGNUM, 4 },
     43      1.1  christos     { 1, ARM_PS_REGNUM, 4 },
     44      1.1  christos     { 0 }
     45      1.1  christos   };
     46      1.1  christos 
     47      1.1  christos static const struct regcache_map_entry arm_fbsd_vfpregmap[] =
     48      1.1  christos   {
     49      1.1  christos     { 32, ARM_D0_REGNUM, 8 }, /* d0 ... d31 */
     50      1.1  christos     { 1, ARM_FPSCR_REGNUM, 4 },
     51      1.1  christos     { 0 }
     52      1.1  christos   };
     53      1.1  christos 
     54  1.1.1.3  christos /* Register numbers are relative to tdep->tls_regnum.  */
     55  1.1.1.3  christos 
     56  1.1.1.3  christos static const struct regcache_map_entry arm_fbsd_tls_regmap[] =
     57  1.1.1.3  christos   {
     58  1.1.1.3  christos     { 1, 0, 4 },	/* tpidruro  */
     59  1.1.1.3  christos     { 0 }
     60  1.1.1.3  christos   };
     61  1.1.1.3  christos 
     62      1.1  christos /* In a signal frame, sp points to a 'struct sigframe' which is
     63      1.1  christos    defined as:
     64      1.1  christos 
     65      1.1  christos    struct sigframe {
     66      1.1  christos 	   siginfo_t	sf_si;
     67      1.1  christos 	   ucontext_t	sf_uc;
     68      1.1  christos 	   mcontext_vfp_t sf_vfp;
     69      1.1  christos    };
     70      1.1  christos 
     71      1.1  christos    ucontext_t is defined as:
     72      1.1  christos 
     73      1.1  christos    struct __ucontext {
     74      1.1  christos 	   sigset_t	uc_sigmask;
     75      1.1  christos 	   mcontext_t	uc_mcontext;
     76      1.1  christos 	   ...
     77      1.1  christos    };
     78      1.1  christos 
     79      1.1  christos    mcontext_t is defined as:
     80      1.1  christos 
     81      1.1  christos    struct {
     82      1.1  christos 	   unsigned int __gregs[17];
     83      1.1  christos 	   size_t       mc_vfp_size;
     84      1.1  christos 	   void         *mc_vfp_ptr;
     85      1.1  christos 	   ...
     86      1.1  christos    };
     87      1.1  christos 
     88      1.1  christos    mcontext_vfp_t is defined as:
     89      1.1  christos 
     90      1.1  christos    struct {
     91      1.1  christos 	  uint64_t      mcv_reg[32];
     92      1.1  christos 	  uint32_t      mcv_fpscr;
     93      1.1  christos    };
     94      1.1  christos 
     95      1.1  christos    If the VFP state is valid, then mc_vfp_ptr will point to sf_vfp in
     96      1.1  christos    the sigframe, otherwise it is NULL.  There is no non-VFP floating
     97      1.1  christos    point register state saved in the signal frame.  */
     98      1.1  christos 
     99      1.1  christos #define ARM_SIGFRAME_UCONTEXT_OFFSET	64
    100      1.1  christos #define ARM_UCONTEXT_MCONTEXT_OFFSET	16
    101      1.1  christos #define ARM_MCONTEXT_VFP_PTR_OFFSET	72
    102      1.1  christos 
    103      1.1  christos /* Implement the "init" method of struct tramp_frame.  */
    104      1.1  christos 
    105      1.1  christos static void
    106      1.1  christos arm_fbsd_sigframe_init (const struct tramp_frame *self,
    107  1.1.1.4  christos 			const frame_info_ptr &this_frame,
    108      1.1  christos 			struct trad_frame_cache *this_cache,
    109      1.1  christos 			CORE_ADDR func)
    110      1.1  christos {
    111      1.1  christos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
    112      1.1  christos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    113      1.1  christos   CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
    114      1.1  christos   CORE_ADDR mcontext_addr = (sp
    115      1.1  christos 			     + ARM_SIGFRAME_UCONTEXT_OFFSET
    116      1.1  christos 			     + ARM_UCONTEXT_MCONTEXT_OFFSET);
    117      1.1  christos   ULONGEST mcontext_vfp_addr;
    118      1.1  christos 
    119      1.1  christos   trad_frame_set_reg_regmap (this_cache, arm_fbsd_gregmap, mcontext_addr,
    120      1.1  christos 			     regcache_map_entry_size (arm_fbsd_gregmap));
    121      1.1  christos 
    122      1.1  christos   if (safe_read_memory_unsigned_integer (mcontext_addr
    123      1.1  christos 					 + ARM_MCONTEXT_VFP_PTR_OFFSET, 4,
    124      1.1  christos 					 byte_order,
    125      1.1  christos 					 &mcontext_vfp_addr)
    126      1.1  christos       && mcontext_vfp_addr != 0)
    127      1.1  christos     trad_frame_set_reg_regmap (this_cache, arm_fbsd_vfpregmap, mcontext_vfp_addr,
    128      1.1  christos 			       regcache_map_entry_size (arm_fbsd_vfpregmap));
    129      1.1  christos 
    130      1.1  christos   trad_frame_set_id (this_cache, frame_id_build (sp, func));
    131      1.1  christos }
    132      1.1  christos 
    133      1.1  christos static const struct tramp_frame arm_fbsd_sigframe =
    134      1.1  christos {
    135      1.1  christos   SIGTRAMP_FRAME,
    136      1.1  christos   4,
    137      1.1  christos   {
    138      1.1  christos     {0xe1a0000d, ULONGEST_MAX},		/* mov  r0, sp  */
    139      1.1  christos     {0xe2800040, ULONGEST_MAX},		/* add  r0, r0, #SIGF_UC  */
    140      1.1  christos     {0xe59f700c, ULONGEST_MAX},		/* ldr  r7, [pc, #12]  */
    141      1.1  christos     {0xef0001a1, ULONGEST_MAX},		/* swi  SYS_sigreturn  */
    142      1.1  christos     {TRAMP_SENTINEL_INSN, ULONGEST_MAX}
    143      1.1  christos   },
    144      1.1  christos   arm_fbsd_sigframe_init
    145      1.1  christos };
    146      1.1  christos 
    147      1.1  christos /* Register set definitions.  */
    148      1.1  christos 
    149      1.1  christos const struct regset arm_fbsd_gregset =
    150      1.1  christos   {
    151      1.1  christos     arm_fbsd_gregmap,
    152      1.1  christos     regcache_supply_regset, regcache_collect_regset
    153      1.1  christos   };
    154      1.1  christos 
    155      1.1  christos const struct regset arm_fbsd_vfpregset =
    156      1.1  christos   {
    157      1.1  christos     arm_fbsd_vfpregmap,
    158      1.1  christos     regcache_supply_regset, regcache_collect_regset
    159      1.1  christos   };
    160      1.1  christos 
    161  1.1.1.3  christos static void
    162  1.1.1.3  christos arm_fbsd_supply_tls_regset (const struct regset *regset,
    163  1.1.1.3  christos 			    struct regcache *regcache,
    164  1.1.1.3  christos 			    int regnum, const void *buf, size_t size)
    165  1.1.1.3  christos {
    166  1.1.1.3  christos   struct gdbarch *gdbarch = regcache->arch ();
    167  1.1.1.3  christos   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
    168  1.1.1.3  christos 
    169  1.1.1.3  christos   regcache->supply_regset (regset, tdep->tls_regnum, regnum, buf, size);
    170  1.1.1.3  christos }
    171  1.1.1.3  christos 
    172  1.1.1.3  christos static void
    173  1.1.1.3  christos arm_fbsd_collect_tls_regset (const struct regset *regset,
    174  1.1.1.3  christos 			     const struct regcache *regcache,
    175  1.1.1.3  christos 			     int regnum, void *buf, size_t size)
    176  1.1.1.3  christos {
    177  1.1.1.3  christos   struct gdbarch *gdbarch = regcache->arch ();
    178  1.1.1.3  christos   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
    179  1.1.1.3  christos 
    180  1.1.1.3  christos   regcache->collect_regset (regset, tdep->tls_regnum, regnum, buf, size);
    181  1.1.1.3  christos }
    182  1.1.1.3  christos 
    183  1.1.1.3  christos const struct regset arm_fbsd_tls_regset =
    184  1.1.1.3  christos   {
    185  1.1.1.3  christos     arm_fbsd_tls_regmap,
    186  1.1.1.3  christos     arm_fbsd_supply_tls_regset, arm_fbsd_collect_tls_regset
    187  1.1.1.3  christos   };
    188  1.1.1.3  christos 
    189  1.1.1.2  christos /* Implement the "iterate_over_regset_sections" gdbarch method.  */
    190      1.1  christos 
    191      1.1  christos static void
    192      1.1  christos arm_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
    193      1.1  christos 				       iterate_over_regset_sections_cb *cb,
    194      1.1  christos 				       void *cb_data,
    195      1.1  christos 				       const struct regcache *regcache)
    196      1.1  christos {
    197  1.1.1.3  christos   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
    198      1.1  christos 
    199      1.1  christos   cb (".reg", ARM_FBSD_SIZEOF_GREGSET, ARM_FBSD_SIZEOF_GREGSET,
    200      1.1  christos       &arm_fbsd_gregset, NULL, cb_data);
    201      1.1  christos 
    202  1.1.1.3  christos   if (tdep->tls_regnum > 0)
    203  1.1.1.3  christos     cb (".reg-aarch-tls", ARM_FBSD_SIZEOF_TLSREGSET, ARM_FBSD_SIZEOF_TLSREGSET,
    204  1.1.1.3  christos 	&arm_fbsd_tls_regset, NULL, cb_data);
    205  1.1.1.3  christos 
    206      1.1  christos   /* While FreeBSD/arm cores do contain a NT_FPREGSET / ".reg2"
    207      1.1  christos      register set, it is not populated with register values by the
    208      1.1  christos      kernel but just contains all zeroes.  */
    209      1.1  christos   if (tdep->vfp_register_count > 0)
    210      1.1  christos     cb (".reg-arm-vfp", ARM_FBSD_SIZEOF_VFPREGSET, ARM_FBSD_SIZEOF_VFPREGSET,
    211      1.1  christos 	&arm_fbsd_vfpregset, "VFP floating-point", cb_data);
    212      1.1  christos }
    213      1.1  christos 
    214  1.1.1.3  christos /* See arm-fbsd-tdep.h.  */
    215      1.1  christos 
    216      1.1  christos const struct target_desc *
    217  1.1.1.4  christos arm_fbsd_read_description_auxv (const std::optional<gdb::byte_vector> &auxv,
    218  1.1.1.3  christos 				target_ops *target, gdbarch *gdbarch, bool tls)
    219      1.1  christos {
    220      1.1  christos   CORE_ADDR arm_hwcap = 0;
    221      1.1  christos 
    222  1.1.1.3  christos   if (!auxv.has_value ()
    223  1.1.1.3  christos       || target_auxv_search (*auxv, target, gdbarch, AT_FREEBSD_HWCAP,
    224  1.1.1.3  christos 			     &arm_hwcap) != 1)
    225  1.1.1.3  christos     return arm_read_description (ARM_FP_TYPE_NONE, tls);
    226      1.1  christos 
    227      1.1  christos   if (arm_hwcap & HWCAP_VFP)
    228      1.1  christos     {
    229      1.1  christos       if (arm_hwcap & HWCAP_NEON)
    230  1.1.1.4  christos 	return aarch32_read_description (tls);
    231      1.1  christos       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32))
    232  1.1.1.3  christos 	       == (HWCAP_VFPv3 | HWCAP_VFPD32))
    233  1.1.1.3  christos 	return arm_read_description (ARM_FP_TYPE_VFPV3, tls);
    234      1.1  christos       else
    235  1.1.1.3  christos 	return arm_read_description (ARM_FP_TYPE_VFPV2, tls);
    236      1.1  christos     }
    237      1.1  christos 
    238  1.1.1.3  christos   return arm_read_description (ARM_FP_TYPE_NONE, tls);
    239  1.1.1.3  christos }
    240  1.1.1.3  christos 
    241  1.1.1.3  christos /* See arm-fbsd-tdep.h.  */
    242  1.1.1.3  christos 
    243  1.1.1.3  christos const struct target_desc *
    244  1.1.1.3  christos arm_fbsd_read_description_auxv (bool tls)
    245  1.1.1.3  christos {
    246  1.1.1.4  christos   const std::optional<gdb::byte_vector> &auxv = target_read_auxv ();
    247  1.1.1.3  christos   return arm_fbsd_read_description_auxv (auxv,
    248  1.1.1.3  christos 					 current_inferior ()->top_target (),
    249  1.1.1.4  christos 					 current_inferior ()->arch (),
    250  1.1.1.3  christos 					 tls);
    251      1.1  christos }
    252      1.1  christos 
    253      1.1  christos /* Implement the "core_read_description" gdbarch method.  */
    254      1.1  christos 
    255      1.1  christos static const struct target_desc *
    256      1.1  christos arm_fbsd_core_read_description (struct gdbarch *gdbarch,
    257      1.1  christos 				struct target_ops *target,
    258      1.1  christos 				bfd *abfd)
    259      1.1  christos {
    260  1.1.1.3  christos   asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls");
    261  1.1.1.3  christos 
    262  1.1.1.4  christos   std::optional<gdb::byte_vector> auxv = target_read_auxv_raw (target);
    263  1.1.1.3  christos   return arm_fbsd_read_description_auxv (auxv, target, gdbarch, tls != nullptr);
    264  1.1.1.3  christos }
    265  1.1.1.3  christos 
    266  1.1.1.3  christos /* Implement the get_thread_local_address gdbarch method.  */
    267  1.1.1.3  christos 
    268  1.1.1.3  christos static CORE_ADDR
    269  1.1.1.3  christos arm_fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
    270  1.1.1.3  christos 				   CORE_ADDR lm_addr, CORE_ADDR offset)
    271  1.1.1.3  christos {
    272  1.1.1.3  christos   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
    273  1.1.1.4  christos   regcache *regcache
    274  1.1.1.4  christos     = get_thread_arch_regcache (current_inferior (), ptid, gdbarch);
    275  1.1.1.3  christos 
    276  1.1.1.3  christos   target_fetch_registers (regcache, tdep->tls_regnum);
    277  1.1.1.3  christos 
    278  1.1.1.3  christos   ULONGEST tpidruro;
    279  1.1.1.3  christos   if (regcache->cooked_read (tdep->tls_regnum, &tpidruro) != REG_VALID)
    280  1.1.1.3  christos     error (_("Unable to fetch %%tpidruro"));
    281  1.1.1.3  christos 
    282  1.1.1.3  christos   /* %tpidruro points to the TCB whose first member is the dtv
    283  1.1.1.3  christos       pointer.  */
    284  1.1.1.3  christos   CORE_ADDR dtv_addr = tpidruro;
    285  1.1.1.3  christos   return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset);
    286      1.1  christos }
    287      1.1  christos 
    288      1.1  christos /* Implement the 'init_osabi' method of struct gdb_osabi_handler.  */
    289      1.1  christos 
    290      1.1  christos static void
    291      1.1  christos arm_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
    292      1.1  christos {
    293  1.1.1.3  christos   arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
    294      1.1  christos 
    295      1.1  christos   /* Generic FreeBSD support.  */
    296      1.1  christos   fbsd_init_abi (info, gdbarch);
    297      1.1  christos 
    298      1.1  christos   if (tdep->fp_model == ARM_FLOAT_AUTO)
    299      1.1  christos     tdep->fp_model = ARM_FLOAT_SOFT_VFP;
    300      1.1  christos 
    301      1.1  christos   tramp_frame_prepend_unwinder (gdbarch, &arm_fbsd_sigframe);
    302      1.1  christos 
    303      1.1  christos   set_solib_svr4_fetch_link_map_offsets
    304      1.1  christos     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
    305      1.1  christos 
    306      1.1  christos   tdep->jb_pc = 24;
    307      1.1  christos   tdep->jb_elt_size = 4;
    308      1.1  christos 
    309      1.1  christos   set_gdbarch_iterate_over_regset_sections
    310      1.1  christos     (gdbarch, arm_fbsd_iterate_over_regset_sections);
    311      1.1  christos   set_gdbarch_core_read_description (gdbarch, arm_fbsd_core_read_description);
    312      1.1  christos 
    313  1.1.1.3  christos   if (tdep->tls_regnum > 0)
    314  1.1.1.3  christos     {
    315  1.1.1.3  christos       set_gdbarch_fetch_tls_load_module_address (gdbarch,
    316  1.1.1.3  christos 						 svr4_fetch_objfile_link_map);
    317  1.1.1.3  christos       set_gdbarch_get_thread_local_address (gdbarch,
    318  1.1.1.3  christos 					    arm_fbsd_get_thread_local_address);
    319  1.1.1.3  christos     }
    320  1.1.1.3  christos 
    321      1.1  christos   /* Single stepping.  */
    322      1.1  christos   set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
    323      1.1  christos }
    324      1.1  christos 
    325  1.1.1.2  christos void _initialize_arm_fbsd_tdep ();
    326      1.1  christos void
    327  1.1.1.2  christos _initialize_arm_fbsd_tdep ()
    328      1.1  christos {
    329      1.1  christos   gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_FREEBSD,
    330      1.1  christos 			  arm_fbsd_init_abi);
    331      1.1  christos }
    332