/* GNU/Linux on ARM target support.
- Copyright (C) 1999-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "auxv.h"
#include "xml-syscall.h"
+#include "aarch32-tdep.h"
#include "arch/arm.h"
#include "arch/arm-get-next-pcs.h"
#include "arch/arm-linux.h"
#include "user-regs.h"
#include <ctype.h>
#include "elf/common.h"
-extern int arm_apcs_32;
/* Under ARM GNU/Linux the traditional way of performing a breakpoint
is to execute a particular software interrupt, rather than use a
SoftVFP or VFP (which implies EABI) then the PC is at offset 9 in the
buffer. This is also true for the SoftFPA model. However, for the FPA
model the PC is at offset 21 in the buffer. */
-#define ARM_LINUX_JB_ELEMENT_SIZE INT_REGISTER_SIZE
+#define ARM_LINUX_JB_ELEMENT_SIZE ARM_INT_REGISTER_SIZE
#define ARM_LINUX_JB_PC_FPA 21
#define ARM_LINUX_JB_PC_EABI 9
SIGTRAMP_FRAME,
4,
{
- { ARM_LINUX_SIGRETURN_INSTR, -1 },
+ { ARM_LINUX_SIGRETURN_INSTR, ULONGEST_MAX },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_sigreturn_init
SIGTRAMP_FRAME,
4,
{
- { ARM_LINUX_RT_SIGRETURN_INSTR, -1 },
+ { ARM_LINUX_RT_SIGRETURN_INSTR, ULONGEST_MAX },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_rt_sigreturn_init
SIGTRAMP_FRAME,
4,
{
- { ARM_SET_R7_SIGRETURN, -1 },
- { ARM_EABI_SYSCALL, -1 },
+ { ARM_SET_R7_SIGRETURN, ULONGEST_MAX },
+ { ARM_EABI_SYSCALL, ULONGEST_MAX },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_sigreturn_init
SIGTRAMP_FRAME,
4,
{
- { ARM_SET_R7_RT_SIGRETURN, -1 },
- { ARM_EABI_SYSCALL, -1 },
+ { ARM_SET_R7_RT_SIGRETURN, ULONGEST_MAX },
+ { ARM_EABI_SYSCALL, ULONGEST_MAX },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_rt_sigreturn_init
SIGTRAMP_FRAME,
2,
{
- { THUMB2_SET_R7_SIGRETURN1, -1 },
- { THUMB2_SET_R7_SIGRETURN2, -1 },
- { THUMB2_EABI_SYSCALL, -1 },
+ { THUMB2_SET_R7_SIGRETURN1, ULONGEST_MAX },
+ { THUMB2_SET_R7_SIGRETURN2, ULONGEST_MAX },
+ { THUMB2_EABI_SYSCALL, ULONGEST_MAX },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_sigreturn_init
SIGTRAMP_FRAME,
2,
{
- { THUMB2_SET_R7_RT_SIGRETURN1, -1 },
- { THUMB2_SET_R7_RT_SIGRETURN2, -1 },
- { THUMB2_EABI_SYSCALL, -1 },
+ { THUMB2_SET_R7_RT_SIGRETURN1, ULONGEST_MAX },
+ { THUMB2_SET_R7_RT_SIGRETURN2, ULONGEST_MAX },
+ { THUMB2_EABI_SYSCALL, ULONGEST_MAX },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_rt_sigreturn_init
NORMAL_FRAME,
4,
{
- { ARM_OABI_SYSCALL_RESTART_SYSCALL, -1 },
- { ARM_LDR_PC_SP_12, -1 },
+ { ARM_OABI_SYSCALL_RESTART_SYSCALL, ULONGEST_MAX },
+ { ARM_LDR_PC_SP_12, ULONGEST_MAX },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_restart_syscall_init
NORMAL_FRAME,
4,
{
- { ARM_OABI_SYSCALL_RESTART_SYSCALL, -1 },
- { ARM_LDR_PC_SP_4, -1 },
+ { ARM_OABI_SYSCALL_RESTART_SYSCALL, ULONGEST_MAX },
+ { ARM_LDR_PC_SP_4, ULONGEST_MAX },
{ TRAMP_SENTINEL_INSN }
},
arm_linux_restart_syscall_init
/* Core file and register set support. */
-#define ARM_LINUX_SIZEOF_GREGSET (18 * INT_REGISTER_SIZE)
+#define ARM_LINUX_SIZEOF_GREGSET (18 * ARM_INT_REGISTER_SIZE)
void
arm_linux_supply_gregset (const struct regset *regset,
const gdb_byte *gregs = (const gdb_byte *) gregs_buf;
int regno;
CORE_ADDR reg_pc;
- gdb_byte pc_buf[INT_REGISTER_SIZE];
+ gdb_byte pc_buf[ARM_INT_REGISTER_SIZE];
for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
if (regnum == -1 || regnum == regno)
- regcache_raw_supply (regcache, regno,
- gregs + INT_REGISTER_SIZE * regno);
+ regcache->raw_supply (regno, gregs + ARM_INT_REGISTER_SIZE * regno);
if (regnum == ARM_PS_REGNUM || regnum == -1)
{
if (arm_apcs_32)
- regcache_raw_supply (regcache, ARM_PS_REGNUM,
- gregs + INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
+ regcache->raw_supply (ARM_PS_REGNUM,
+ gregs + ARM_INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
else
- regcache_raw_supply (regcache, ARM_PS_REGNUM,
- gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
+ regcache->raw_supply (ARM_PS_REGNUM,
+ gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
}
if (regnum == ARM_PC_REGNUM || regnum == -1)
{
- reg_pc = extract_unsigned_integer (gregs
- + INT_REGISTER_SIZE * ARM_PC_REGNUM,
- INT_REGISTER_SIZE, byte_order);
+ reg_pc = extract_unsigned_integer (
+ gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM,
+ ARM_INT_REGISTER_SIZE, byte_order);
reg_pc = gdbarch_addr_bits_remove (gdbarch, reg_pc);
- store_unsigned_integer (pc_buf, INT_REGISTER_SIZE, byte_order, reg_pc);
- regcache_raw_supply (regcache, ARM_PC_REGNUM, pc_buf);
+ store_unsigned_integer (pc_buf, ARM_INT_REGISTER_SIZE, byte_order,
+ reg_pc);
+ regcache->raw_supply (ARM_PC_REGNUM, pc_buf);
}
}
for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
if (regnum == -1 || regnum == regno)
- regcache_raw_collect (regcache, regno,
- gregs + INT_REGISTER_SIZE * regno);
+ regcache->raw_collect (regno,
+ gregs + ARM_INT_REGISTER_SIZE * regno);
if (regnum == ARM_PS_REGNUM || regnum == -1)
{
if (arm_apcs_32)
- regcache_raw_collect (regcache, ARM_PS_REGNUM,
- gregs + INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
+ regcache->raw_collect (ARM_PS_REGNUM,
+ gregs + ARM_INT_REGISTER_SIZE * ARM_CPSR_GREGNUM);
else
- regcache_raw_collect (regcache, ARM_PS_REGNUM,
- gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
+ regcache->raw_collect (ARM_PS_REGNUM,
+ gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
}
if (regnum == ARM_PC_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, ARM_PC_REGNUM,
- gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
+ regcache->raw_collect (ARM_PC_REGNUM,
+ gregs + ARM_INT_REGISTER_SIZE * ARM_PC_REGNUM);
}
/* Support for register format used by the NWFPE FPA emulator. */
{
const gdb_byte *reg_data;
gdb_byte reg_tag;
- gdb_byte buf[FP_REGISTER_SIZE];
+ gdb_byte buf[ARM_FP_REGISTER_SIZE];
- reg_data = regs + (regno - ARM_F0_REGNUM) * FP_REGISTER_SIZE;
+ reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
- memset (buf, 0, FP_REGISTER_SIZE);
+ memset (buf, 0, ARM_FP_REGISTER_SIZE);
switch (reg_tag)
{
break;
}
- regcache_raw_supply (regcache, regno, buf);
+ regcache->raw_supply (regno, buf);
}
void
{
gdb_byte *reg_data;
gdb_byte reg_tag;
- gdb_byte buf[FP_REGISTER_SIZE];
+ gdb_byte buf[ARM_FP_REGISTER_SIZE];
- regcache_raw_collect (regcache, regno, buf);
+ regcache->raw_collect (regno, buf);
/* NOTE drow/2006-06-07: This code uses the tag already in the
register buffer. I've preserved that when moving the code
from the native file to the target file. But this doesn't
always make sense. */
- reg_data = regs + (regno - ARM_F0_REGNUM) * FP_REGISTER_SIZE;
+ reg_data = regs + (regno - ARM_F0_REGNUM) * ARM_FP_REGISTER_SIZE;
reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
switch (reg_tag)
int regno;
if (regnum == ARM_FPS_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, ARM_FPS_REGNUM,
+ regcache->raw_supply (ARM_FPS_REGNUM,
regs + NWFPE_FPSR_OFFSET);
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
collect_nwfpe_register (regcache, regno, regs);
if (regnum == ARM_FPS_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, ARM_FPS_REGNUM,
- regs + INT_REGISTER_SIZE * ARM_FPS_REGNUM);
+ regcache->raw_collect (ARM_FPS_REGNUM,
+ regs + ARM_INT_REGISTER_SIZE * ARM_FPS_REGNUM);
}
/* Support VFP register format. */
int regno;
if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, ARM_FPSCR_REGNUM, regs + 32 * 8);
+ regcache->raw_supply (ARM_FPSCR_REGNUM, regs + 32 * 8);
for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
if (regnum == -1 || regnum == regno)
- regcache_raw_supply (regcache, regno,
- regs + (regno - ARM_D0_REGNUM) * 8);
+ regcache->raw_supply (regno, regs + (regno - ARM_D0_REGNUM) * 8);
}
static void
int regno;
if (regnum == ARM_FPSCR_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, ARM_FPSCR_REGNUM, regs + 32 * 8);
+ regcache->raw_collect (ARM_FPSCR_REGNUM, regs + 32 * 8);
for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++)
if (regnum == -1 || regnum == regno)
- regcache_raw_collect (regcache, regno,
- regs + (regno - ARM_D0_REGNUM) * 8);
+ regcache->raw_collect (regno, regs + (regno - ARM_D0_REGNUM) * 8);
}
static const struct regset arm_linux_gregset =
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- cb (".reg", ARM_LINUX_SIZEOF_GREGSET, &arm_linux_gregset, NULL, cb_data);
+ cb (".reg", ARM_LINUX_SIZEOF_GREGSET, ARM_LINUX_SIZEOF_GREGSET,
+ &arm_linux_gregset, NULL, cb_data);
if (tdep->vfp_register_count > 0)
- cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, &arm_linux_vfpregset,
- "VFP floating-point", cb_data);
+ cb (".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, ARM_LINUX_SIZEOF_VFP,
+ &arm_linux_vfpregset, "VFP floating-point", cb_data);
else if (tdep->have_fpa_registers)
- cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, &arm_linux_fpregset,
- "FPA floating-point", cb_data);
+ cb (".reg2", ARM_LINUX_SIZEOF_NWFPE, ARM_LINUX_SIZEOF_NWFPE,
+ &arm_linux_fpregset, "FPA floating-point", cb_data);
}
/* Determine target description from core file. */
struct target_ops *target,
bfd *abfd)
{
- CORE_ADDR arm_hwcap = 0;
-
- if (target_auxv_search (target, AT_HWCAP, &arm_hwcap) != 1)
- return NULL;
+ CORE_ADDR arm_hwcap = linux_get_hwcap (target);
if (arm_hwcap & HWCAP_VFP)
{
/* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support
Neon with VFPv3-D32. */
if (arm_hwcap & HWCAP_NEON)
- return tdesc_arm_with_neon;
+ return aarch32_read_description ();
else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
- return tdesc_arm_with_vfpv3;
- else
- return tdesc_arm_with_vfpv2;
+ return arm_read_description (ARM_FP_TYPE_VFPV3);
+
+ return arm_read_description (ARM_FP_TYPE_VFPV2);
}
- return NULL;
+ return nullptr;
}
static LONGEST
arm_linux_get_syscall_number (struct gdbarch *gdbarch,
- ptid_t ptid)
+ thread_info *thread)
{
- struct regcache *regs = get_thread_regcache (ptid);
+ struct regcache *regs = get_thread_regcache (thread);
ULONGEST pc;
ULONGEST cpsr;
within_scratch = (apparent_pc >= dsc->scratch_base
&& apparent_pc < (dsc->scratch_base
- + DISPLACED_MODIFIED_INSNS * 4 + 4));
+ + ARM_DISPLACED_MODIFIED_INSNS * 4 + 4));
if (debug_displaced)
{
return find_solib_trampoline_target (frame, pc);
}
+/* Implement the gcc_target_options gdbarch method. */
+
+static std::string
+arm_linux_gcc_target_options (struct gdbarch *gdbarch)
+{
+ /* GCC doesn't know "-m32". */
+ return {};
+}
+
static void
arm_linux_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
arm_linux_record_tdep.arg5 = ARM_A1_REGNUM + 4;
arm_linux_record_tdep.arg6 = ARM_A1_REGNUM + 5;
arm_linux_record_tdep.arg7 = ARM_A1_REGNUM + 6;
+
+ set_gdbarch_gcc_target_options (gdbarch, arm_linux_gcc_target_options);
}
void