1 /* Target-dependent code for PowerPC systems running FreeBSD.
3 Copyright (C) 2013-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "arch-utils.h"
21 #include "extract-store-integer.h"
24 #include "frame-unwind.h"
31 #include "trad-frame.h"
34 #include "ppc64-tdep.h"
35 #include "ppc-fbsd-tdep.h"
36 #include "fbsd-tdep.h"
37 #include "solib-svr4.h"
41 /* 32-bit regset descriptions. */
43 static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets
=
45 /* General-purpose registers. */
49 /* .pc_offset = */ 144,
50 /* .ps_offset = */ -1,
51 /* .cr_offset = */ 132,
52 /* .lr_offset = */ 128,
53 /* .ctr_offset = */ 140,
54 /* .xer_offset = */ 136,
55 /* .mq_offset = */ -1,
57 /* Floating-point registers. */
59 /* .fpscr_offset = */ 256,
63 /* 64-bit regset descriptions. */
65 static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets
=
67 /* General-purpose registers. */
71 /* .pc_offset = */ 288,
72 /* .ps_offset = */ -1,
73 /* .cr_offset = */ 264,
74 /* .lr_offset = */ 256,
75 /* .ctr_offset = */ 280,
76 /* .xer_offset = */ 272,
77 /* .mq_offset = */ -1,
79 /* Floating-point registers. */
81 /* .fpscr_offset = */ 256,
85 /* 32-bit general-purpose register set. */
87 static const struct regset ppc32_fbsd_gregset
= {
88 &ppc32_fbsd_reg_offsets
,
93 /* 64-bit general-purpose register set. */
95 static const struct regset ppc64_fbsd_gregset
= {
96 &ppc64_fbsd_reg_offsets
,
101 /* 32-/64-bit floating-point register set. */
103 static const struct regset ppc32_fbsd_fpregset
= {
104 &ppc32_fbsd_reg_offsets
,
109 const struct regset
*
110 ppc_fbsd_gregset (int wordsize
)
112 return wordsize
== 8 ? &ppc64_fbsd_gregset
: &ppc32_fbsd_gregset
;
115 const struct regset
*
116 ppc_fbsd_fpregset (void)
118 return &ppc32_fbsd_fpregset
;
121 /* Iterate over core file register note sections. */
124 ppcfbsd_iterate_over_regset_sections (struct gdbarch
*gdbarch
,
125 iterate_over_regset_sections_cb
*cb
,
127 const struct regcache
*regcache
)
129 ppc_gdbarch_tdep
*tdep
= gdbarch_tdep
<ppc_gdbarch_tdep
> (gdbarch
);
131 if (tdep
->wordsize
== 4)
132 cb (".reg", 148, 148, &ppc32_fbsd_gregset
, NULL
, cb_data
);
134 cb (".reg", 296, 296, &ppc64_fbsd_gregset
, NULL
, cb_data
);
135 cb (".reg2", 264, 264, &ppc32_fbsd_fpregset
, NULL
, cb_data
);
138 /* Default page size. */
140 static const int ppcfbsd_page_size
= 4096;
142 /* Offset for sigreturn(2). */
144 static const int ppcfbsd_sigreturn_offset
[] = {
145 0xc, /* FreeBSD 32-bit */
149 /* Signal trampolines. */
152 ppcfbsd_sigtramp_frame_sniffer (const struct frame_unwind
*self
,
153 const frame_info_ptr
&this_frame
,
156 struct gdbarch
*gdbarch
= get_frame_arch (this_frame
);
157 enum bfd_endian byte_order
= gdbarch_byte_order (gdbarch
);
158 CORE_ADDR pc
= get_frame_pc (this_frame
);
159 CORE_ADDR start_pc
= (pc
& ~(ppcfbsd_page_size
- 1));
163 /* A stack trampoline is detected if no name is associated
164 to the current pc and if it points inside a trampoline
167 find_pc_partial_function (pc
, &name
, NULL
, NULL
);
169 /* If we have a name, we have no trampoline, return. */
173 for (offset
= ppcfbsd_sigreturn_offset
; *offset
!= -1; offset
++)
175 gdb_byte buf
[2 * PPC_INSN_SIZE
];
178 if (!safe_frame_unwind_memory (this_frame
, start_pc
+ *offset
,
182 /* Check for "li r0,SYS_sigreturn". */
183 insn
= extract_unsigned_integer (buf
, PPC_INSN_SIZE
, byte_order
);
184 if (insn
!= 0x380001a1)
187 /* Check for "sc". */
188 insn
= extract_unsigned_integer (buf
+ PPC_INSN_SIZE
,
189 PPC_INSN_SIZE
, byte_order
);
190 if (insn
!= 0x44000002)
199 static struct trad_frame_cache
*
200 ppcfbsd_sigtramp_frame_cache (const frame_info_ptr
&this_frame
, void **this_cache
)
202 struct gdbarch
*gdbarch
= get_frame_arch (this_frame
);
203 ppc_gdbarch_tdep
*tdep
= gdbarch_tdep
<ppc_gdbarch_tdep
> (gdbarch
);
204 struct trad_frame_cache
*cache
;
205 CORE_ADDR addr
, base
, func
;
206 gdb_byte buf
[PPC_INSN_SIZE
];
210 return (struct trad_frame_cache
*) *this_cache
;
212 cache
= trad_frame_cache_zalloc (this_frame
);
215 func
= get_frame_pc (this_frame
);
216 func
&= ~(ppcfbsd_page_size
- 1);
217 if (!safe_frame_unwind_memory (this_frame
, func
, {buf
, sizeof buf
}))
220 base
= get_frame_register_unsigned (this_frame
, gdbarch_sp_regnum (gdbarch
));
221 addr
= base
+ 0x10 + 2 * tdep
->wordsize
;
222 for (i
= 0; i
< ppc_num_gprs
; i
++, addr
+= tdep
->wordsize
)
224 int regnum
= i
+ tdep
->ppc_gp0_regnum
;
225 trad_frame_set_reg_addr (cache
, regnum
, addr
);
227 trad_frame_set_reg_addr (cache
, tdep
->ppc_lr_regnum
, addr
);
228 addr
+= tdep
->wordsize
;
229 trad_frame_set_reg_addr (cache
, tdep
->ppc_cr_regnum
, addr
);
230 addr
+= tdep
->wordsize
;
231 trad_frame_set_reg_addr (cache
, tdep
->ppc_xer_regnum
, addr
);
232 addr
+= tdep
->wordsize
;
233 trad_frame_set_reg_addr (cache
, tdep
->ppc_ctr_regnum
, addr
);
234 addr
+= tdep
->wordsize
;
235 trad_frame_set_reg_addr (cache
, gdbarch_pc_regnum (gdbarch
), addr
);
237 addr
+= tdep
->wordsize
;
239 /* Construct the frame ID using the function start. */
240 trad_frame_set_id (cache
, frame_id_build (base
, func
));
246 ppcfbsd_sigtramp_frame_this_id (const frame_info_ptr
&this_frame
,
247 void **this_cache
, struct frame_id
*this_id
)
249 struct trad_frame_cache
*cache
=
250 ppcfbsd_sigtramp_frame_cache (this_frame
, this_cache
);
252 trad_frame_get_id (cache
, this_id
);
255 static struct value
*
256 ppcfbsd_sigtramp_frame_prev_register (const frame_info_ptr
&this_frame
,
257 void **this_cache
, int regnum
)
259 struct trad_frame_cache
*cache
=
260 ppcfbsd_sigtramp_frame_cache (this_frame
, this_cache
);
262 return trad_frame_get_register (cache
, this_frame
, regnum
);
265 static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind
= {
266 "ppc freebsd sigtramp",
268 default_frame_unwind_stop_reason
,
269 ppcfbsd_sigtramp_frame_this_id
,
270 ppcfbsd_sigtramp_frame_prev_register
,
272 ppcfbsd_sigtramp_frame_sniffer
275 static enum return_value_convention
276 ppcfbsd_return_value (struct gdbarch
*gdbarch
, struct value
*function
,
277 struct type
*valtype
, struct regcache
*regcache
,
278 gdb_byte
*readbuf
, const gdb_byte
*writebuf
)
280 return ppc_sysv_abi_broken_return_value (gdbarch
, function
, valtype
,
281 regcache
, readbuf
, writebuf
);
284 /* Implement the "get_thread_local_address" gdbarch method. */
287 ppcfbsd_get_thread_local_address (struct gdbarch
*gdbarch
, ptid_t ptid
,
288 CORE_ADDR lm_addr
, CORE_ADDR offset
)
290 ppc_gdbarch_tdep
*tdep
= gdbarch_tdep
<ppc_gdbarch_tdep
> (gdbarch
);
291 int tp_offset
, tp_regnum
;
293 = get_thread_arch_regcache (current_inferior (), ptid
, gdbarch
);
295 if (tdep
->wordsize
== 4)
298 tp_regnum
= PPC_R0_REGNUM
+ 2;
303 tp_regnum
= PPC_R0_REGNUM
+ 13;
305 target_fetch_registers (regcache
, tp_regnum
);
308 if (regcache
->cooked_read (tp_regnum
, &tp
) != REG_VALID
)
309 error (_("Unable to fetch tcb pointer"));
311 /* tp points to the end of the TCB block. The first member of the
312 TCB is the pointer to the DTV array. */
313 CORE_ADDR dtv_addr
= tp
- tp_offset
;
314 return fbsd_get_thread_local_address (gdbarch
, dtv_addr
, lm_addr
, offset
);
318 ppcfbsd_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
320 ppc_gdbarch_tdep
*tdep
= gdbarch_tdep
<ppc_gdbarch_tdep
> (gdbarch
);
322 /* Generic FreeBSD support. */
323 fbsd_init_abi (info
, gdbarch
);
325 /* FreeBSD doesn't support the 128-bit `long double' from the psABI. */
326 set_gdbarch_long_double_bit (gdbarch
, 64);
327 set_gdbarch_long_double_format (gdbarch
, floatformats_ieee_double
);
329 if (tdep
->wordsize
== 4)
331 set_gdbarch_return_value (gdbarch
, ppcfbsd_return_value
);
333 set_gdbarch_skip_trampoline_code (gdbarch
, find_solib_trampoline_target
);
334 set_solib_svr4_fetch_link_map_offsets (gdbarch
,
335 svr4_ilp32_fetch_link_map_offsets
);
337 frame_unwind_append_unwinder (gdbarch
, &ppcfbsd_sigtramp_frame_unwind
);
338 set_gdbarch_gcore_bfd_target (gdbarch
, "elf32-powerpc");
341 if (tdep
->wordsize
== 8)
343 set_gdbarch_convert_from_func_ptr_addr
344 (gdbarch
, ppc64_convert_from_func_ptr_addr
);
345 set_gdbarch_elf_make_msymbol_special (gdbarch
,
346 ppc64_elf_make_msymbol_special
);
348 set_gdbarch_skip_trampoline_code (gdbarch
, ppc64_skip_trampoline_code
);
349 set_solib_svr4_fetch_link_map_offsets (gdbarch
,
350 svr4_lp64_fetch_link_map_offsets
);
351 set_gdbarch_gcore_bfd_target (gdbarch
, "elf64-powerpc");
354 set_gdbarch_iterate_over_regset_sections
355 (gdbarch
, ppcfbsd_iterate_over_regset_sections
);
357 set_gdbarch_fetch_tls_load_module_address (gdbarch
,
358 svr4_fetch_objfile_link_map
);
359 set_gdbarch_get_thread_local_address (gdbarch
,
360 ppcfbsd_get_thread_local_address
);
363 void _initialize_ppcfbsd_tdep ();
365 _initialize_ppcfbsd_tdep ()
367 gdbarch_register_osabi (bfd_arch_powerpc
, bfd_mach_ppc
, GDB_OSABI_FREEBSD
,
369 gdbarch_register_osabi (bfd_arch_powerpc
, bfd_mach_ppc64
, GDB_OSABI_FREEBSD
,
371 gdbarch_register_osabi (bfd_arch_rs6000
, 0, GDB_OSABI_FREEBSD
,