cfba98720f
displaced_step_closure is a type defined in multiple -tdep.c files. Trying to xfree it from the common code (infrun.c) is a problem when we try to poison xfree for non-POD types. Because there can be multiple of these types in the same build, this patch makes a hierarchy of classes with a virtual destructor. When the common code deletes the object through a displaced_step_closure pointer, it will invoke the right destructor. The amd64 used a last-member array with a variable size. That doesn't work with new, so I changed it for an std::vector. Other architectures which used a simple byte buffer as a closure now use a shared buf_displaced_step_closure, a closure type that only contains a gdb::byte_vector. Reg-tested on the buildbot. gdb/ChangeLog: * infrun.h: Include common/byte-vector.h. (struct displaced_step_closure): New struct. (struct buf_displaced_step_closure): New struct. * infrun.c (displaced_step_closure::~displaced_step_closure): Provide default implementation. (displaced_step_clear): Deallocate step closure with delete. * aarch64-tdep.c (displaced_step_closure): Rename to ... (aarch64_displaced_step_closure): ... this, extend displaced_step_closure. (aarch64_displaced_step_data) <dsc>: Change type to aarch64_displaced_step_closure. (aarch64_displaced_step_copy_insn): Adjust to type change, use unique_ptr. (aarch64_displaced_step_fixup): Add cast for displaced step closure. * amd64-tdep.c (displaced_step_closure): Rename to ... (amd64_displaced_step_closure): ... this, extend displaced_step_closure. <insn_buf>: Change type to std::vector<gdb_byte>. <max_len>: Remove. (fixup_riprel): Change type of DSC parameter, adjust to type change of insn_buf. (fixup_displaced_copy): Change type of DSC parameter. (amd64_displaced_step_copy_insn): Instantiate amd64_displaced_step_closure. (amd64_displaced_step_fixup): Add cast for closure type, adjust to type change of insn_buf. * arm-linux-tdep.c (arm_linux_cleanup_svc): Change type of parameter DSC. (arm_linux_copy_svc): Likewise. (cleanup_kernel_helper_return): Likewise. (arm_catch_kernel_helper_return): Likewise. (arm_linux_displaced_step_copy_insn): Instantiate arm_displaced_step_closure. * arm-tdep.c (arm_pc_is_thumb): Add cast for closure. (displaced_read_reg): Change type of parameter DSC. (branch_write_pc): Likewise. (load_write_pc): Likewise. (alu_write_pc): Likewise. (displaced_write_reg): Likewise. (arm_copy_unmodified): Likewise. (thumb_copy_unmodified_32bit): Likewise. (thumb_copy_unmodified_16bit): Likewise. (cleanup_preload): Likewise. (install_preload): Likewise. (arm_copy_preload): Likewise. (thumb2_copy_preload): Likewise. (install_preload_reg): Likewise. (arm_copy_preload_reg): Likewise. (cleanup_copro_load_store): Likewise. (install_copro_load_store): Likewise. (arm_copy_copro_load_store) Likewise. (thumb2_copy_copro_load_store): Likewise. (cleanup_branch): Likewise. (install_b_bl_blx): Likewise. (arm_copy_b_bl_blx): Likewise. (thumb2_copy_b_bl_blx): Likewise. (thumb_copy_b): Likewise. (install_bx_blx_reg): Likewise. (arm_copy_bx_blx_reg): Likewise. (thumb_copy_bx_blx_reg): Likewise. (cleanup_alu_imm): Likewise. (arm_copy_alu_imm): Likewise. (thumb2_copy_alu_imm): Likewise. (cleanup_alu_reg): Likewise. (install_alu_reg): Likewise. (arm_copy_alu_reg): Likewise. (thumb_copy_alu_reg): Likewise. (cleanup_alu_shifted_reg): Likewise. (install_alu_shifted_reg): Likewise. (arm_copy_alu_shifted_reg): Likewise. (cleanup_load): Likewise. (cleanup_store): Likewise. (arm_copy_extra_ld_st): Likewise. (install_load_store): Likewise. (thumb2_copy_load_literal): Likewise. (thumb2_copy_load_reg_imm): Likewise. (arm_copy_ldr_str_ldrb_strb): Likewise. (cleanup_block_load_all): Likewise. (cleanup_block_store_pc): Likewise. (cleanup_block_load_pc): Likewise. (arm_copy_block_xfer): Likewise. (thumb2_copy_block_xfer): Likewise. (cleanup_svc): Likewise. (install_svc): Likewise. (arm_copy_svc): Likewise. (thumb_copy_svc): Likewise. (arm_copy_undef): Likewise. (thumb_32bit_copy_undef): Likewise. (arm_copy_unpred): Likewise. (arm_decode_misc_memhint_neon): Likewise. (arm_decode_unconditional): Likewise. (arm_decode_miscellaneous): Likewise. (arm_decode_dp_misc): Likewise. (arm_decode_ld_st_word_ubyte): Likewise. (arm_decode_media): Likewise. (arm_decode_b_bl_ldmstm): Likewise. (arm_decode_ext_reg_ld_st): Likewise. (thumb2_decode_dp_shift_reg): Likewise. (thumb2_decode_ext_reg_ld_st): Likewise. (arm_decode_svc_copro): Likewise. (thumb2_decode_svc_copro): Likewise. (install_pc_relative): Likewise. (thumb_copy_pc_relative_16bit): Likewise. (thumb_decode_pc_relative_16bit): Likewise. (thumb_copy_pc_relative_32bit): Likewise. (thumb_copy_16bit_ldr_literal): Likewise. (thumb_copy_cbnz_cbz): Likewise. (thumb2_copy_table_branch): Likewise. (cleanup_pop_pc_16bit_all): Likewise. (thumb_copy_pop_pc_16bit): Likewise. (thumb_process_displaced_16bit_insn): Likewise. (decode_thumb_32bit_ld_mem_hints): Likewise. (thumb_process_displaced_32bit_insn): Likewise. (thumb_process_displaced_insn): Likewise. (arm_process_displaced_insn): Likewise. (arm_displaced_init_closure): Likewise. (arm_displaced_step_fixup): Add cast for closure. * arm-tdep.h: Include infrun.h. (displaced_step_closure): Rename to ... (arm_displaced_step_closure): ... this, extend displaced_step_closure. <u::svc::copy_svc_os>: Change type of parameter DSC. <cleanup>: Likewise. (arm_process_displaced_insn): Likewise. (arm_displaced_init_closure): Likewise. (displaced_read_reg): Likewise. (displaced_write_reg): Likewise. * i386-linux-tdep.c (i386_linux_displaced_step_copy_insn): Adjust. * i386-tdep.h: Include infrun.h. (i386_displaced_step_closure): New typedef. * i386-tdep.c (i386_displaced_step_copy_insn): Use i386_displaced_step_closure. (i386_displaced_step_fixup): Adjust. * rs6000-tdep.c (ppc_displaced_step_closure): New typedef. (ppc_displaced_step_copy_insn): Use ppc_displaced_step_closure and unique_ptr. (ppc_displaced_step_fixup): Adjust. * s390-linux-tdep.c (s390_displaced_step_closure): New typedef. (s390_displaced_step_copy_insn): Use s390_displaced_step_closure and unique_ptr. (s390_displaced_step_fixup): Adjust.
301 lines
9.8 KiB
C++
301 lines
9.8 KiB
C++
/* Common target dependent code for GDB on ARM systems.
|
|
Copyright (C) 2002-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/>. */
|
|
|
|
#ifndef ARM_TDEP_H
|
|
#define ARM_TDEP_H
|
|
|
|
/* Forward declarations. */
|
|
struct gdbarch;
|
|
struct regset;
|
|
struct address_space;
|
|
struct get_next_pcs;
|
|
struct arm_get_next_pcs;
|
|
struct gdb_get_next_pcs;
|
|
|
|
#include "arch/arm.h"
|
|
#include "infrun.h"
|
|
|
|
#include <vector>
|
|
|
|
/* Say how long FP registers are. Used for documentation purposes and
|
|
code readability in this header. IEEE extended doubles are 80
|
|
bits. DWORD aligned they use 96 bits. */
|
|
#define FP_REGISTER_SIZE 12
|
|
|
|
/* Say how long VFP double precision registers are. Used for documentation
|
|
purposes and code readability. These are fixed at 64 bits. */
|
|
#define VFP_REGISTER_SIZE 8
|
|
|
|
/* Number of machine registers. The only define actually required
|
|
is gdbarch_num_regs. The other definitions are used for documentation
|
|
purposes and code readability. */
|
|
/* For 26 bit ARM code, a fake copy of the PC is placed in register 25 (PS)
|
|
(and called PS for processor status) so the status bits can be cleared
|
|
from the PC (register 15). For 32 bit ARM code, a copy of CPSR is placed
|
|
in PS. */
|
|
#define NUM_FREGS 8 /* Number of floating point registers. */
|
|
#define NUM_SREGS 2 /* Number of status registers. */
|
|
#define NUM_GREGS 16 /* Number of general purpose registers. */
|
|
|
|
|
|
|
|
/* Type of floating-point code in use by inferior. There are really 3 models
|
|
that are traditionally supported (plus the endianness issue), but gcc can
|
|
only generate 2 of those. The third is APCS_FLOAT, where arguments to
|
|
functions are passed in floating-point registers.
|
|
|
|
In addition to the traditional models, VFP adds two more.
|
|
|
|
If you update this enum, don't forget to update fp_model_strings in
|
|
arm-tdep.c. */
|
|
|
|
enum arm_float_model
|
|
{
|
|
ARM_FLOAT_AUTO, /* Automatic detection. Do not set in tdep. */
|
|
ARM_FLOAT_SOFT_FPA, /* Traditional soft-float (mixed-endian on LE ARM). */
|
|
ARM_FLOAT_FPA, /* FPA co-processor. GCC calling convention. */
|
|
ARM_FLOAT_SOFT_VFP, /* Soft-float with pure-endian doubles. */
|
|
ARM_FLOAT_VFP, /* Full VFP calling convention. */
|
|
ARM_FLOAT_LAST /* Keep at end. */
|
|
};
|
|
|
|
/* ABI used by the inferior. */
|
|
enum arm_abi_kind
|
|
{
|
|
ARM_ABI_AUTO,
|
|
ARM_ABI_APCS,
|
|
ARM_ABI_AAPCS,
|
|
ARM_ABI_LAST
|
|
};
|
|
|
|
/* Convention for returning structures. */
|
|
|
|
enum struct_return
|
|
{
|
|
pcc_struct_return, /* Return "short" structures in memory. */
|
|
reg_struct_return /* Return "short" structures in registers. */
|
|
};
|
|
|
|
/* Target-dependent structure in gdbarch. */
|
|
struct gdbarch_tdep
|
|
{
|
|
/* The ABI for this architecture. It should never be set to
|
|
ARM_ABI_AUTO. */
|
|
enum arm_abi_kind arm_abi;
|
|
|
|
enum arm_float_model fp_model; /* Floating point calling conventions. */
|
|
|
|
int have_fpa_registers; /* Does the target report the FPA registers? */
|
|
int have_wmmx_registers; /* Does the target report the WMMX registers? */
|
|
/* The number of VFP registers reported by the target. It is zero
|
|
if VFP registers are not supported. */
|
|
int vfp_register_count;
|
|
int have_vfp_pseudos; /* Are we synthesizing the single precision
|
|
VFP registers? */
|
|
int have_neon_pseudos; /* Are we synthesizing the quad precision
|
|
NEON registers? Requires
|
|
have_vfp_pseudos. */
|
|
int have_neon; /* Do we have a NEON unit? */
|
|
|
|
int is_m; /* Does the target follow the "M" profile. */
|
|
CORE_ADDR lowest_pc; /* Lowest address at which instructions
|
|
will appear. */
|
|
|
|
const gdb_byte *arm_breakpoint; /* Breakpoint pattern for an ARM insn. */
|
|
int arm_breakpoint_size; /* And its size. */
|
|
const gdb_byte *thumb_breakpoint; /* Breakpoint pattern for a Thumb insn. */
|
|
int thumb_breakpoint_size; /* And its size. */
|
|
|
|
/* If the Thumb breakpoint is an undefined instruction (which is
|
|
affected by IT blocks) rather than a BKPT instruction (which is
|
|
not), then we need a 32-bit Thumb breakpoint to preserve the
|
|
instruction count in IT blocks. */
|
|
const gdb_byte *thumb2_breakpoint;
|
|
int thumb2_breakpoint_size;
|
|
|
|
int jb_pc; /* Offset to PC value in jump buffer.
|
|
If this is negative, longjmp support
|
|
will be disabled. */
|
|
size_t jb_elt_size; /* And the size of each entry in the buf. */
|
|
|
|
/* Convention for returning structures. */
|
|
enum struct_return struct_return;
|
|
|
|
/* ISA-specific data types. */
|
|
struct type *arm_ext_type;
|
|
struct type *neon_double_type;
|
|
struct type *neon_quad_type;
|
|
|
|
/* syscall record. */
|
|
int (*arm_syscall_record) (struct regcache *regcache, unsigned long svc_number);
|
|
};
|
|
|
|
/* Structures used for displaced stepping. */
|
|
|
|
/* The maximum number of temporaries available for displaced instructions. */
|
|
#define DISPLACED_TEMPS 16
|
|
/* The maximum number of modified instructions generated for one single-stepped
|
|
instruction, including the breakpoint (usually at the end of the instruction
|
|
sequence) and any scratch words, etc. */
|
|
#define DISPLACED_MODIFIED_INSNS 8
|
|
|
|
struct arm_displaced_step_closure : public displaced_step_closure
|
|
{
|
|
ULONGEST tmp[DISPLACED_TEMPS];
|
|
int rd;
|
|
int wrote_to_pc;
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
int xfersize;
|
|
int rn; /* Writeback register. */
|
|
unsigned int immed : 1; /* Offset is immediate. */
|
|
unsigned int writeback : 1; /* Perform base-register writeback. */
|
|
unsigned int restore_r4 : 1; /* Used r4 as scratch. */
|
|
} ldst;
|
|
|
|
struct
|
|
{
|
|
unsigned long dest;
|
|
unsigned int link : 1;
|
|
unsigned int exchange : 1;
|
|
unsigned int cond : 4;
|
|
} branch;
|
|
|
|
struct
|
|
{
|
|
unsigned int regmask;
|
|
int rn;
|
|
CORE_ADDR xfer_addr;
|
|
unsigned int load : 1;
|
|
unsigned int user : 1;
|
|
unsigned int increment : 1;
|
|
unsigned int before : 1;
|
|
unsigned int writeback : 1;
|
|
unsigned int cond : 4;
|
|
} block;
|
|
|
|
struct
|
|
{
|
|
unsigned int immed : 1;
|
|
} preload;
|
|
|
|
struct
|
|
{
|
|
/* If non-NULL, override generic SVC handling (e.g. for a particular
|
|
OS). */
|
|
int (*copy_svc_os) (struct gdbarch *gdbarch, struct regcache *regs,
|
|
arm_displaced_step_closure *dsc);
|
|
} svc;
|
|
} u;
|
|
|
|
/* The size of original instruction, 2 or 4. */
|
|
unsigned int insn_size;
|
|
/* True if the original insn (and thus all replacement insns) are Thumb
|
|
instead of ARM. */
|
|
unsigned int is_thumb;
|
|
|
|
/* The slots in the array is used in this way below,
|
|
- ARM instruction occupies one slot,
|
|
- Thumb 16 bit instruction occupies one slot,
|
|
- Thumb 32-bit instruction occupies *two* slots, one part for each. */
|
|
unsigned long modinsn[DISPLACED_MODIFIED_INSNS];
|
|
int numinsns;
|
|
CORE_ADDR insn_addr;
|
|
CORE_ADDR scratch_base;
|
|
void (*cleanup) (struct gdbarch *, struct regcache *,
|
|
arm_displaced_step_closure *);
|
|
};
|
|
|
|
/* Values for the WRITE_PC argument to displaced_write_reg. If the register
|
|
write may write to the PC, specifies the way the CPSR T bit, etc. is
|
|
modified by the instruction. */
|
|
|
|
enum pc_write_style
|
|
{
|
|
BRANCH_WRITE_PC,
|
|
BX_WRITE_PC,
|
|
LOAD_WRITE_PC,
|
|
ALU_WRITE_PC,
|
|
CANNOT_WRITE_PC
|
|
};
|
|
|
|
extern void
|
|
arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
|
|
CORE_ADDR to, struct regcache *regs,
|
|
arm_displaced_step_closure *dsc);
|
|
extern void
|
|
arm_displaced_init_closure (struct gdbarch *gdbarch, CORE_ADDR from,
|
|
CORE_ADDR to, arm_displaced_step_closure *dsc);
|
|
extern ULONGEST
|
|
displaced_read_reg (struct regcache *regs, arm_displaced_step_closure *dsc,
|
|
int regno);
|
|
extern void
|
|
displaced_write_reg (struct regcache *regs,
|
|
arm_displaced_step_closure *dsc, int regno,
|
|
ULONGEST val, enum pc_write_style write_pc);
|
|
|
|
CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
|
|
|
|
ULONGEST arm_get_next_pcs_read_memory_unsigned_integer (CORE_ADDR memaddr,
|
|
int len,
|
|
int byte_order);
|
|
|
|
CORE_ADDR arm_get_next_pcs_addr_bits_remove (struct arm_get_next_pcs *self,
|
|
CORE_ADDR val);
|
|
|
|
int arm_get_next_pcs_is_thumb (struct arm_get_next_pcs *self);
|
|
|
|
std::vector<CORE_ADDR> arm_software_single_step (struct regcache *);
|
|
int arm_is_thumb (struct regcache *regcache);
|
|
int arm_frame_is_thumb (struct frame_info *frame);
|
|
|
|
extern void arm_displaced_step_fixup (struct gdbarch *,
|
|
struct displaced_step_closure *,
|
|
CORE_ADDR, CORE_ADDR, struct regcache *);
|
|
|
|
/* Return the bit mask in ARM_PS_REGNUM that indicates Thumb mode. */
|
|
extern int arm_psr_thumb_bit (struct gdbarch *);
|
|
|
|
/* Is the instruction at the given memory address a Thumb or ARM
|
|
instruction? */
|
|
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
|
|
|
|
extern int arm_process_record (struct gdbarch *gdbarch,
|
|
struct regcache *regcache, CORE_ADDR addr);
|
|
/* Functions exported from arm-bsd-tdep.h. */
|
|
|
|
/* Return the appropriate register set for the core section identified
|
|
by SECT_NAME and SECT_SIZE. */
|
|
|
|
extern void
|
|
armbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
|
|
iterate_over_regset_sections_cb *cb,
|
|
void *cb_data,
|
|
const struct regcache *regcache);
|
|
|
|
/* Target descriptions. */
|
|
extern struct target_desc *tdesc_arm_with_m;
|
|
extern struct target_desc *tdesc_arm_with_iwmmxt;
|
|
extern struct target_desc *tdesc_arm_with_vfpv2;
|
|
extern struct target_desc *tdesc_arm_with_vfpv3;
|
|
extern struct target_desc *tdesc_arm_with_neon;
|
|
|
|
#endif /* arm-tdep.h */
|