mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
Add FreeBSD/arm architecture.
Support for collecting and supplying general purpose and floating point registers is provided along with signal frame unwinding. While FreeBSD/arm kernels do populate NT_FPREGSET notes, they are always zero-filled, so this implementation ignores them. Recent FreeBSD/arm kernels generate NT_ARM_VFP notes which are used to supply floating-point registers. As with Linux, the AT_HWCAP feature flags are used to determine the correct target description. gdb/ChangeLog: * Makefile.in (ALL_TARGET_OBS): Add arm-fbsd-tdep.o. (ALLDEPFILES): Add arm-fbsd-tdep.c. * NEWS: Mention new FreeBSD/arm target. * configure.tgt: Add arm*-*-freebsd*. * arm-fbsd-tdep.c: New file. * arm-fbsd-tdep.h: New file.
This commit is contained in:
parent
39865a7f42
commit
7176dfd28d
@ -1,3 +1,12 @@
|
||||
2017-10-11 John Baldwin <jhb@FreeBSD.org>
|
||||
|
||||
* Makefile.in (ALL_TARGET_OBS): Add arm-fbsd-tdep.o.
|
||||
(ALLDEPFILES): Add arm-fbsd-tdep.c.
|
||||
* NEWS: Mention new FreeBSD/arm target.
|
||||
* configure.tgt: Add arm*-*-freebsd*.
|
||||
* arm-fbsd-tdep.c: New file.
|
||||
* arm-fbsd-tdep.h: New file.
|
||||
|
||||
2017-10-11 Maciej W. Rozycki <macro@imgtec.com>
|
||||
|
||||
* linux-tdep.c (linux_make_corefile_notes): Remove call to
|
||||
|
@ -798,6 +798,7 @@ ALL_TARGET_OBS = \
|
||||
arch/arm-linux.o \
|
||||
arch/i386.o \
|
||||
arm-bsd-tdep.o \
|
||||
arm-fbsd-tdep.o \
|
||||
arm-linux-tdep.o \
|
||||
arm-nbsd-tdep.o \
|
||||
arm-obsd-tdep.o \
|
||||
@ -2541,6 +2542,7 @@ ALLDEPFILES = \
|
||||
arc-tdep.c \
|
||||
arm.c \
|
||||
arm-bsd-tdep.c \
|
||||
arm-fbsd-tdep.c \
|
||||
arm-get-next-pcs.c \
|
||||
arm-linux.c \
|
||||
arm-linux-nat.c \
|
||||
|
1
gdb/NEWS
1
gdb/NEWS
@ -130,6 +130,7 @@ FreeBSD/aarch64 aarch64*-*-freebsd*
|
||||
* New targets
|
||||
|
||||
FreeBSD/aarch64 aarch64*-*-freebsd*
|
||||
FreeBSD/arm arm*-*-freebsd*
|
||||
|
||||
* Removed targets and native configurations
|
||||
|
||||
|
257
gdb/arm-fbsd-tdep.c
Normal file
257
gdb/arm-fbsd-tdep.c
Normal file
@ -0,0 +1,257 @@
|
||||
/* Target-dependent code for FreeBSD/arm.
|
||||
|
||||
Copyright (C) 2017 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
#include "elf/common.h"
|
||||
#include "arm-tdep.h"
|
||||
#include "arm-fbsd-tdep.h"
|
||||
#include "auxv.h"
|
||||
#include "fbsd-tdep.h"
|
||||
#include "gdbcore.h"
|
||||
#include "osabi.h"
|
||||
#include "solib-svr4.h"
|
||||
#include "trad-frame.h"
|
||||
#include "tramp-frame.h"
|
||||
|
||||
/* In a signal frame, sp points to a 'struct sigframe' which is
|
||||
defined as:
|
||||
|
||||
struct sigframe {
|
||||
siginfo_t sf_si;
|
||||
ucontext_t sf_uc;
|
||||
mcontext_vfp_t sf_vfp;
|
||||
};
|
||||
|
||||
ucontext_t is defined as:
|
||||
|
||||
struct __ucontext {
|
||||
sigset_t uc_sigmask;
|
||||
mcontext_t uc_mcontext;
|
||||
...
|
||||
};
|
||||
|
||||
mcontext_t is defined as:
|
||||
|
||||
struct {
|
||||
unsigned int __gregs[17];
|
||||
size_t mc_vfp_size;
|
||||
void *mc_vfp_ptr;
|
||||
...
|
||||
};
|
||||
|
||||
mcontext_vfp_t is defined as:
|
||||
|
||||
struct {
|
||||
uint64_t mcv_reg[32];
|
||||
uint32_t mcv_fpscr;
|
||||
};
|
||||
|
||||
If the VFP state is valid, then mc_vfp_ptr will point to sf_vfp in
|
||||
the sigframe, otherwise it is NULL. There is no non-VFP floating
|
||||
point register state saved in the signal frame. */
|
||||
|
||||
#define ARM_MCONTEXT_REG_SIZE 4
|
||||
#define ARM_MCONTEXT_VFP_REG_SIZE 8
|
||||
#define ARM_SIGFRAME_UCONTEXT_OFFSET 64
|
||||
#define ARM_UCONTEXT_MCONTEXT_OFFSET 16
|
||||
#define ARM_MCONTEXT_VFP_PTR_OFFSET 72
|
||||
|
||||
/* Implement the "init" method of struct tramp_frame. */
|
||||
|
||||
static void
|
||||
arm_fbsd_sigframe_init (const struct tramp_frame *self,
|
||||
struct frame_info *this_frame,
|
||||
struct trad_frame_cache *this_cache,
|
||||
CORE_ADDR func)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
|
||||
CORE_ADDR mcontext_addr = (sp
|
||||
+ ARM_SIGFRAME_UCONTEXT_OFFSET
|
||||
+ ARM_UCONTEXT_MCONTEXT_OFFSET);
|
||||
ULONGEST mcontext_vfp_addr;
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
trad_frame_set_reg_addr (this_cache,
|
||||
ARM_A1_REGNUM + i,
|
||||
mcontext_addr + i * ARM_MCONTEXT_REG_SIZE);
|
||||
}
|
||||
trad_frame_set_reg_addr (this_cache, ARM_PS_REGNUM,
|
||||
mcontext_addr + 16 * ARM_MCONTEXT_REG_SIZE);
|
||||
|
||||
if (safe_read_memory_unsigned_integer (mcontext_addr
|
||||
+ ARM_MCONTEXT_VFP_PTR_OFFSET, 4,
|
||||
byte_order,
|
||||
&mcontext_vfp_addr)
|
||||
&& mcontext_vfp_addr != 0)
|
||||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
trad_frame_set_reg_addr (this_cache, ARM_D0_REGNUM + i,
|
||||
mcontext_vfp_addr
|
||||
+ i * ARM_MCONTEXT_VFP_REG_SIZE);
|
||||
}
|
||||
trad_frame_set_reg_addr (this_cache, ARM_FPSCR_REGNUM,
|
||||
mcontext_vfp_addr
|
||||
+ 32 * ARM_MCONTEXT_VFP_REG_SIZE);
|
||||
}
|
||||
|
||||
trad_frame_set_id (this_cache, frame_id_build (sp, func));
|
||||
}
|
||||
|
||||
static const struct tramp_frame arm_fbsd_sigframe =
|
||||
{
|
||||
SIGTRAMP_FRAME,
|
||||
4,
|
||||
{
|
||||
{0xe1a0000d, -1}, /* mov r0, sp */
|
||||
{0xe2800040, -1}, /* add r0, r0, #SIGF_UC */
|
||||
{0xe59f700c, -1}, /* ldr r7, [pc, #12] */
|
||||
{0xef0001a1, -1}, /* swi SYS_sigreturn */
|
||||
{TRAMP_SENTINEL_INSN, -1}
|
||||
},
|
||||
arm_fbsd_sigframe_init
|
||||
};
|
||||
|
||||
/* Register maps. */
|
||||
|
||||
static const struct regcache_map_entry arm_fbsd_gregmap[] =
|
||||
{
|
||||
{ 13, ARM_A1_REGNUM, 4 }, /* r0 ... r12 */
|
||||
{ 1, ARM_SP_REGNUM, 4 },
|
||||
{ 1, ARM_LR_REGNUM, 4 },
|
||||
{ 1, ARM_PC_REGNUM, 4 },
|
||||
{ 1, ARM_PS_REGNUM, 4 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct regcache_map_entry arm_fbsd_vfpregmap[] =
|
||||
{
|
||||
{ 32, ARM_D0_REGNUM, 8 }, /* d0 ... d31 */
|
||||
{ 1, ARM_FPSCR_REGNUM, 4 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Register set definitions. */
|
||||
|
||||
const struct regset arm_fbsd_gregset =
|
||||
{
|
||||
arm_fbsd_gregmap,
|
||||
regcache_supply_regset, regcache_collect_regset
|
||||
};
|
||||
|
||||
const struct regset arm_fbsd_vfpregset =
|
||||
{
|
||||
arm_fbsd_vfpregmap,
|
||||
regcache_supply_regset, regcache_collect_regset
|
||||
};
|
||||
|
||||
/* Implement the "regset_from_core_section" gdbarch method. */
|
||||
|
||||
static void
|
||||
arm_fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
|
||||
iterate_over_regset_sections_cb *cb,
|
||||
void *cb_data,
|
||||
const struct regcache *regcache)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
cb (".reg", ARM_FBSD_SIZEOF_GREGSET, &arm_fbsd_gregset, NULL, cb_data);
|
||||
|
||||
/* While FreeBSD/arm cores do contain a NT_FPREGSET / ".reg2"
|
||||
register set, it is not populated with register values by the
|
||||
kernel but just contains all zeroes. */
|
||||
if (tdep->vfp_register_count > 0)
|
||||
cb (".reg-arm-vfp", ARM_FBSD_SIZEOF_VFPREGSET, &arm_fbsd_vfpregset,
|
||||
"VFP floating-point", cb_data);
|
||||
}
|
||||
|
||||
/* Lookup a target description from a target's AT_HWCAP auxiliary
|
||||
vector. */
|
||||
|
||||
const struct target_desc *
|
||||
arm_fbsd_read_description_auxv (struct target_ops *target)
|
||||
{
|
||||
CORE_ADDR arm_hwcap = 0;
|
||||
|
||||
if (target_auxv_search (target, AT_FREEBSD_HWCAP, &arm_hwcap) != 1)
|
||||
return NULL;
|
||||
|
||||
if (arm_hwcap & HWCAP_VFP)
|
||||
{
|
||||
if (arm_hwcap & HWCAP_NEON)
|
||||
return tdesc_arm_with_neon;
|
||||
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPD32))
|
||||
== (HWCAP_VFPv3 | HWCAP_VFPD32))
|
||||
return tdesc_arm_with_vfpv3;
|
||||
else
|
||||
return tdesc_arm_with_vfpv2;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Implement the "core_read_description" gdbarch method. */
|
||||
|
||||
static const struct target_desc *
|
||||
arm_fbsd_core_read_description (struct gdbarch *gdbarch,
|
||||
struct target_ops *target,
|
||||
bfd *abfd)
|
||||
{
|
||||
return arm_fbsd_read_description_auxv (target);
|
||||
}
|
||||
|
||||
/* Implement the 'init_osabi' method of struct gdb_osabi_handler. */
|
||||
|
||||
static void
|
||||
arm_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* Generic FreeBSD support. */
|
||||
fbsd_init_abi (info, gdbarch);
|
||||
|
||||
if (tdep->fp_model == ARM_FLOAT_AUTO)
|
||||
tdep->fp_model = ARM_FLOAT_SOFT_VFP;
|
||||
|
||||
tramp_frame_prepend_unwinder (gdbarch, &arm_fbsd_sigframe);
|
||||
|
||||
set_solib_svr4_fetch_link_map_offsets
|
||||
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
|
||||
|
||||
tdep->jb_pc = 24;
|
||||
tdep->jb_elt_size = 4;
|
||||
|
||||
set_gdbarch_iterate_over_regset_sections
|
||||
(gdbarch, arm_fbsd_iterate_over_regset_sections);
|
||||
set_gdbarch_core_read_description (gdbarch, arm_fbsd_core_read_description);
|
||||
|
||||
/* Single stepping. */
|
||||
set_gdbarch_software_single_step (gdbarch, arm_software_single_step);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_arm_fbsd_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_FREEBSD,
|
||||
arm_fbsd_init_abi);
|
||||
}
|
40
gdb/arm-fbsd-tdep.h
Normal file
40
gdb/arm-fbsd-tdep.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* FreeBSD/arm target support, prototypes.
|
||||
|
||||
Copyright (C) 2017 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "regset.h"
|
||||
|
||||
/* The general-purpose regset consists of 13 R registers, plus SP, LR,
|
||||
PC, and CPSR registers. */
|
||||
#define ARM_FBSD_SIZEOF_GREGSET (17 * 4)
|
||||
|
||||
/* The VFP regset consists of 32 D registers plus FPSCR, and the whole
|
||||
structure is padded to 64-bit alignment. */
|
||||
#define ARM_FBSD_SIZEOF_VFPREGSET (33 * 8)
|
||||
|
||||
extern const struct regset arm_fbsd_gregset;
|
||||
extern const struct regset arm_fbsd_vfpregset;
|
||||
|
||||
/* Flags passed in AT_HWCAP. */
|
||||
#define HWCAP_VFP 0x00000040
|
||||
#define HWCAP_NEON 0x00001000
|
||||
#define HWCAP_VFPv3 0x00002000
|
||||
#define HWCAP_VFPD32 0x00080000
|
||||
|
||||
extern const struct target_desc *
|
||||
arm_fbsd_read_description_auxv (struct target_ops *target);
|
@ -160,6 +160,10 @@ arm*-*-linux*)
|
||||
solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o"
|
||||
build_gdbserver=yes
|
||||
;;
|
||||
arm*-*-freebsd*)
|
||||
# Target: FreeBSD/arm
|
||||
gdb_target_obs="arm-fbsd-tdep.o"
|
||||
;;
|
||||
arm*-*-netbsd* | arm*-*-knetbsd*-gnu)
|
||||
# Target: NetBSD/arm
|
||||
gdb_target_obs="arm-nbsd-tdep.o"
|
||||
|
Loading…
Reference in New Issue
Block a user