GDB (xrefs)
Loading...
Searching...
No Matches
arm-fbsd-tdep.c
Go to the documentation of this file.
1/* Target-dependent code for FreeBSD/arm.
2
3 Copyright (C) 2017-2023 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 "defs.h"
21
22#include "elf/common.h"
23#include "target-descriptions.h"
24#include "aarch32-tdep.h"
25#include "arm-tdep.h"
26#include "arm-fbsd-tdep.h"
27#include "auxv.h"
28#include "fbsd-tdep.h"
29#include "gdbcore.h"
30#include "inferior.h"
31#include "osabi.h"
32#include "solib-svr4.h"
33#include "trad-frame.h"
34#include "tramp-frame.h"
35
36/* Register maps. */
37
38static const struct regcache_map_entry arm_fbsd_gregmap[] =
39 {
40 { 13, ARM_A1_REGNUM, 4 }, /* r0 ... r12 */
41 { 1, ARM_SP_REGNUM, 4 },
42 { 1, ARM_LR_REGNUM, 4 },
43 { 1, ARM_PC_REGNUM, 4 },
44 { 1, ARM_PS_REGNUM, 4 },
45 { 0 }
46 };
47
49 {
50 { 32, ARM_D0_REGNUM, 8 }, /* d0 ... d31 */
51 { 1, ARM_FPSCR_REGNUM, 4 },
52 { 0 }
53 };
54
55/* Register numbers are relative to tdep->tls_regnum. */
56
58 {
59 { 1, 0, 4 }, /* tpidruro */
60 { 0 }
61 };
62
63/* In a signal frame, sp points to a 'struct sigframe' which is
64 defined as:
65
66 struct sigframe {
67 siginfo_t sf_si;
68 ucontext_t sf_uc;
69 mcontext_vfp_t sf_vfp;
70 };
71
72 ucontext_t is defined as:
73
74 struct __ucontext {
75 sigset_t uc_sigmask;
76 mcontext_t uc_mcontext;
77 ...
78 };
79
80 mcontext_t is defined as:
81
82 struct {
83 unsigned int __gregs[17];
84 size_t mc_vfp_size;
85 void *mc_vfp_ptr;
86 ...
87 };
88
89 mcontext_vfp_t is defined as:
90
91 struct {
92 uint64_t mcv_reg[32];
93 uint32_t mcv_fpscr;
94 };
95
96 If the VFP state is valid, then mc_vfp_ptr will point to sf_vfp in
97 the sigframe, otherwise it is NULL. There is no non-VFP floating
98 point register state saved in the signal frame. */
99
100#define ARM_SIGFRAME_UCONTEXT_OFFSET 64
101#define ARM_UCONTEXT_MCONTEXT_OFFSET 16
102#define ARM_MCONTEXT_VFP_PTR_OFFSET 72
103
104/* Implement the "init" method of struct tramp_frame. */
105
106static void
108 frame_info_ptr this_frame,
109 struct trad_frame_cache *this_cache,
110 CORE_ADDR func)
111{
112 struct gdbarch *gdbarch = get_frame_arch (this_frame);
113 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
114 CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
115 CORE_ADDR mcontext_addr = (sp
118 ULONGEST mcontext_vfp_addr;
119
120 trad_frame_set_reg_regmap (this_cache, arm_fbsd_gregmap, mcontext_addr,
122
123 if (safe_read_memory_unsigned_integer (mcontext_addr
125 byte_order,
126 &mcontext_vfp_addr)
127 && mcontext_vfp_addr != 0)
128 trad_frame_set_reg_regmap (this_cache, arm_fbsd_vfpregmap, mcontext_vfp_addr,
130
131 trad_frame_set_id (this_cache, frame_id_build (sp, func));
132}
133
134static const struct tramp_frame arm_fbsd_sigframe =
135{
137 4,
138 {
139 {0xe1a0000d, ULONGEST_MAX}, /* mov r0, sp */
140 {0xe2800040, ULONGEST_MAX}, /* add r0, r0, #SIGF_UC */
141 {0xe59f700c, ULONGEST_MAX}, /* ldr r7, [pc, #12] */
142 {0xef0001a1, ULONGEST_MAX}, /* swi SYS_sigreturn */
143 {TRAMP_SENTINEL_INSN, ULONGEST_MAX}
144 },
146};
147
148/* Register set definitions. */
149
155
161
162static void
164 struct regcache *regcache,
165 int regnum, const void *buf, size_t size)
166{
167 struct gdbarch *gdbarch = regcache->arch ();
168 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
169
171}
172
173static void
175 const struct regcache *regcache,
176 int regnum, void *buf, size_t size)
177{
178 struct gdbarch *gdbarch = regcache->arch ();
179 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
180
182}
183
189
190/* Implement the "iterate_over_regset_sections" gdbarch method. */
191
192static void
195 void *cb_data,
196 const struct regcache *regcache)
197{
198 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
199
201 &arm_fbsd_gregset, NULL, cb_data);
202
203 if (tdep->tls_regnum > 0)
205 &arm_fbsd_tls_regset, NULL, cb_data);
206
207 /* While FreeBSD/arm cores do contain a NT_FPREGSET / ".reg2"
208 register set, it is not populated with register values by the
209 kernel but just contains all zeroes. */
210 if (tdep->vfp_register_count > 0)
212 &arm_fbsd_vfpregset, "VFP floating-point", cb_data);
213}
214
215/* See arm-fbsd-tdep.h. */
216
217const struct target_desc *
218arm_fbsd_read_description_auxv (const gdb::optional<gdb::byte_vector> &auxv,
219 target_ops *target, gdbarch *gdbarch, bool tls)
220{
221 CORE_ADDR arm_hwcap = 0;
222
223 if (!auxv.has_value ()
224 || target_auxv_search (*auxv, target, gdbarch, AT_FREEBSD_HWCAP,
225 &arm_hwcap) != 1)
227
228 if (arm_hwcap & HWCAP_VFP)
229 {
230 if (arm_hwcap & HWCAP_NEON)
231 return aarch32_read_description ();
232 else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32))
235 else
237 }
238
240}
241
242/* See arm-fbsd-tdep.h. */
243
244const struct target_desc *
246{
247 const gdb::optional<gdb::byte_vector> &auxv = target_read_auxv ();
249 current_inferior ()->top_target (),
251 tls);
252}
253
254/* Implement the "core_read_description" gdbarch method. */
255
256static const struct target_desc *
258 struct target_ops *target,
259 bfd *abfd)
260{
261 asection *tls = bfd_get_section_by_name (abfd, ".reg-aarch-tls");
262
263 gdb::optional<gdb::byte_vector> auxv = target_read_auxv_raw (target);
264 return arm_fbsd_read_description_auxv (auxv, target, gdbarch, tls != nullptr);
265}
266
267/* Implement the get_thread_local_address gdbarch method. */
268
269static CORE_ADDR
271 CORE_ADDR lm_addr, CORE_ADDR offset)
272{
273 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
274 struct regcache *regcache;
275
276 regcache = get_thread_arch_regcache (current_inferior ()->process_target (),
277 ptid, gdbarch);
278
280
281 ULONGEST tpidruro;
282 if (regcache->cooked_read (tdep->tls_regnum, &tpidruro) != REG_VALID)
283 error (_("Unable to fetch %%tpidruro"));
284
285 /* %tpidruro points to the TCB whose first member is the dtv
286 pointer. */
287 CORE_ADDR dtv_addr = tpidruro;
288 return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset);
289}
290
291/* Implement the 'init_osabi' method of struct gdb_osabi_handler. */
292
293static void
327
329void
const target_desc * aarch32_read_description()
int regnum
static const struct tramp_frame arm_fbsd_sigframe
#define ARM_UCONTEXT_MCONTEXT_OFFSET
static const struct regcache_map_entry arm_fbsd_gregmap[]
static void arm_fbsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
static void arm_fbsd_sigframe_init(const struct tramp_frame *self, frame_info_ptr this_frame, struct trad_frame_cache *this_cache, CORE_ADDR func)
static void arm_fbsd_collect_tls_regset(const struct regset *regset, const struct regcache *regcache, int regnum, void *buf, size_t size)
#define ARM_SIGFRAME_UCONTEXT_OFFSET
const struct target_desc * arm_fbsd_read_description_auxv(const gdb::optional< gdb::byte_vector > &auxv, target_ops *target, gdbarch *gdbarch, bool tls)
static const struct target_desc * arm_fbsd_core_read_description(struct gdbarch *gdbarch, struct target_ops *target, bfd *abfd)
const struct regset arm_fbsd_vfpregset
static const struct regcache_map_entry arm_fbsd_tls_regmap[]
static const struct regcache_map_entry arm_fbsd_vfpregmap[]
#define ARM_MCONTEXT_VFP_PTR_OFFSET
const struct regset arm_fbsd_gregset
static void arm_fbsd_iterate_over_regset_sections(struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data, const struct regcache *regcache)
void _initialize_arm_fbsd_tdep()
const struct regset arm_fbsd_tls_regset
static void arm_fbsd_supply_tls_regset(const struct regset *regset, struct regcache *regcache, int regnum, const void *buf, size_t size)
static CORE_ADDR arm_fbsd_get_thread_local_address(struct gdbarch *gdbarch, ptid_t ptid, CORE_ADDR lm_addr, CORE_ADDR offset)
#define HWCAP_NEON
#define HWCAP_VFPD32
#define HWCAP_VFP
#define ARM_FBSD_SIZEOF_TLSREGSET
#define HWCAP_VFPv3
#define ARM_FBSD_SIZEOF_VFPREGSET
#define ARM_FBSD_SIZEOF_GREGSET
std::vector< CORE_ADDR > arm_software_single_step(struct regcache *regcache)
Definition arm-tdep.c:7283
const target_desc * arm_read_description(arm_fp_type fp_type, bool tls)
Definition arm-tdep.c:14927
@ ARM_FLOAT_AUTO
Definition arm-tdep.h:64
@ ARM_FLOAT_SOFT_VFP
Definition arm-tdep.h:67
@ ARM_PC_REGNUM
Definition arm.h:46
@ ARM_FPSCR_REGNUM
Definition arm.h:64
@ ARM_LR_REGNUM
Definition arm.h:45
@ ARM_PS_REGNUM
Definition arm.h:52
@ ARM_D0_REGNUM
Definition arm.h:62
@ ARM_A1_REGNUM
Definition arm.h:40
@ ARM_SP_REGNUM
Definition arm.h:44
@ ARM_FP_TYPE_VFPV2
Definition arm.h:96
@ ARM_FP_TYPE_VFPV3
Definition arm.h:97
@ ARM_FP_TYPE_NONE
Definition arm.h:95
int target_auxv_search(const gdb::byte_vector &auxv, target_ops *ops, gdbarch *gdbarch, CORE_ADDR match, CORE_ADDR *valp)
Definition auxv.c:385
const gdb::optional< gdb::byte_vector > & target_read_auxv()
Definition auxv.c:360
gdb::optional< gdb::byte_vector > target_read_auxv_raw(target_ops *ops)
Definition auxv.c:377
enum register_status cooked_read(int regnum, gdb_byte *buf)
Definition regcache.c:698
friend class regcache
Definition regcache.h:269
gdbarch * arch() const
Definition regcache.c:231
void collect_regset(const struct regset *regset, int regbase, int regnum, void *buf, size_t size) const
Definition regcache.c:1283
ptid_t ptid() const
Definition regcache.h:408
void supply_regset(const struct regset *regset, int regbase, int regnum, const void *buf, size_t size)
Definition regcache.c:1261
int safe_read_memory_unsigned_integer(CORE_ADDR memaddr, int len, enum bfd_endian byte_order, ULONGEST *return_value)
Definition corefile.c:282
CORE_ADDR fbsd_get_thread_local_address(struct gdbarch *gdbarch, CORE_ADDR dtv_addr, CORE_ADDR lm_addr, CORE_ADDR offset)
Definition fbsd-tdep.c:2027
void fbsd_init_abi(struct gdbarch_info info, struct gdbarch *gdbarch)
Definition fbsd-tdep.c:2380
ULONGEST get_frame_register_unsigned(frame_info_ptr frame, int regnum)
Definition frame.c:1399
struct frame_id frame_id_build(CORE_ADDR stack_addr, CORE_ADDR code_addr)
Definition frame.c:736
struct gdbarch * get_frame_arch(frame_info_ptr this_frame)
Definition frame.c:3027
@ SIGTRAMP_FRAME
Definition frame.h:198
enum bfd_endian gdbarch_byte_order(struct gdbarch *gdbarch)
Definition gdbarch.c:1396
void set_gdbarch_software_single_step(struct gdbarch *gdbarch, gdbarch_software_single_step_ftype *software_single_step)
void set_gdbarch_get_thread_local_address(struct gdbarch *gdbarch, gdbarch_get_thread_local_address_ftype *get_thread_local_address)
void set_gdbarch_core_read_description(struct gdbarch *gdbarch, gdbarch_core_read_description_ftype *core_read_description)
void set_gdbarch_fetch_tls_load_module_address(struct gdbarch *gdbarch, gdbarch_fetch_tls_load_module_address_ftype *fetch_tls_load_module_address)
void set_gdbarch_iterate_over_regset_sections(struct gdbarch *gdbarch, gdbarch_iterate_over_regset_sections_ftype *iterate_over_regset_sections)
void iterate_over_regset_sections_cb(const char *sect_name, int supply_size, int collect_size, const struct regset *regset, const char *human_name, void *cb_data)
Definition gdbarch.h:104
size_t size
Definition go32-nat.c:239
struct inferior * current_inferior(void)
Definition inferior.c:55
static CORE_ADDR lm_addr(struct so_list *so)
Definition nto-tdep.c:246
void gdbarch_register_osabi(enum bfd_architecture arch, unsigned long machine, enum gdb_osabi osabi, void(*init_osabi)(struct gdbarch_info, struct gdbarch *))
Definition osabi.c:146
@ GDB_OSABI_FREEBSD
Definition osabi.h:33
void regcache_collect_regset(const struct regset *regset, const struct regcache *regcache, int regnum, void *buf, size_t size)
Definition regcache.c:1273
struct regcache * get_thread_arch_regcache(process_stratum_target *target, ptid_t ptid, struct gdbarch *gdbarch)
Definition regcache.c:384
void regcache_supply_regset(const struct regset *regset, struct regcache *regcache, int regnum, const void *buf, size_t size)
Definition regcache.c:1251
static int regcache_map_entry_size(const struct regcache_map_entry *map)
Definition regcache.h:128
void(* func)(remote_target *remote, char *)
void set_solib_svr4_fetch_link_map_offsets(struct gdbarch *gdbarch, struct link_map_offsets *(*flmo)(void))
CORE_ADDR svr4_fetch_objfile_link_map(struct objfile *objfile)
struct link_map_offsets * svr4_ilp32_fetch_link_map_offsets(void)
size_t jb_elt_size
Definition arm-tdep.h:159
Definition regcache.h:111
void target_fetch_registers(struct regcache *regcache, int regno)
Definition target.c:3928
void trad_frame_set_reg_regmap(struct trad_frame_cache *this_trad_cache, const struct regcache_map_entry *regmap, CORE_ADDR addr, size_t size)
Definition trad-frame.c:117
void trad_frame_set_id(struct trad_frame_cache *this_trad_cache, struct frame_id this_id)
Definition trad-frame.c:220
void tramp_frame_prepend_unwinder(struct gdbarch *gdbarch, const struct tramp_frame *tramp_frame)
#define TRAMP_SENTINEL_INSN
Definition tramp-frame.h:44