gdbarch software_single_step returns VEC (CORE_ADDR) *

This patch changes gdbarch method software_single_step to return a
vector of addresses on which GDB should insert breakpoints, and don't
insert breakpoints.  Instead, the caller of
gdbarch_software_single_step inserts breakpoints if the returned
vector is not NULL.

gdb:

2016-11-08  Yao Qi  <yao.qi@linaro.org>

	* aarch64-tdep.c (aarch64_software_single_step): Return
	VEC (CORE_ADDR) *.  Return NULL instead of 0.  Don't call
	insert_single_step_breakpoint.
	* alpha-tdep.c (alpha_deal_with_atomic_sequence): Likewise.
	(alpha_software_single_step): Likewise.
	* alpha-tdep.h (alpha_software_single_step): Update declaration.
	* arm-linux-tdep.c (arm_linux_software_single_step): Return
	VEC (CORE_ADDR) *.  Return NULL instead of 0.
	* arm-tdep.c (arm_software_single_step): Return NULL instead of	0.
	* arm-tdep.h (arm_software_single_step): Update declaration.
	* breakpoint.c (insert_single_step_breakpoints): New function.
	* breakpoint.h (insert_single_step_breakpoints): Declare.
	* cris-tdep.c (cris_software_single_step): Return
	VEC (CORE_ADDR) *.  Don't call insert_single_step_breakpoint.
	* gdbarch.sh (software_single_step): Change it to return
	VEC (CORE_ADDR) *.
	* gdbarch.c, gdbarch.h: Regenerated.
	* infrun.c (maybe_software_singlestep): Adjust.
	* mips-tdep.c (mips_deal_with_atomic_sequence): Return
	VEC (CORE_ADDR) *.  Don't call insert_single_step_breakpoint.
	(micromips_deal_with_atomic_sequence): Likewise.
	(deal_with_atomic_sequence): Likewise.
	(mips_software_single_step): Likewise.
	* mips-tdep.h (mips_software_single_step): Update declaration.
	* moxie-tdep.c (moxie_software_single_step): Likewise.
	* nios2-tdep.c (nios2_software_single_step): Likewise.
	* ppc-tdep.h (ppc_deal_with_atomic_sequence): Update
	declaration.
	* record-full.c (record_full_resume): Adjust.
	(record_full_wait_1): Likewise.
	* rs6000-aix-tdep.c (rs6000_software_single_step): Return
	VEC (CORE_ADDR) *.  Don't call insert_single_step_breakpoint.
	* rs6000-tdep.c	(ppc_deal_with_atomic_sequence): Return
	VEC (CORE_ADDR) *.  Don't call insert_single_step_breakpoint.
	* s390-linux-tdep.c (s390_software_single_step): Likewise.
	* sparc-tdep.c (sparc_software_single_step): Likewise.
	* spu-tdep.c (spu_software_single_step): Likewise.
	* tic6x-tdep.c (tic6x_software_single_step): Likewise.
This commit is contained in:
Yao Qi 2016-11-08 14:28:32 +00:00
parent 0bc5d801ec
commit 93f9a11fbd
26 changed files with 225 additions and 173 deletions

View File

@ -1,3 +1,44 @@
2016-11-08 Yao Qi <yao.qi@linaro.org>
* aarch64-tdep.c (aarch64_software_single_step): Return
VEC (CORE_ADDR) *. Return NULL instead of 0. Don't call
insert_single_step_breakpoint.
* alpha-tdep.c (alpha_deal_with_atomic_sequence): Likewise.
(alpha_software_single_step): Likewise.
* alpha-tdep.h (alpha_software_single_step): Update declaration.
* arm-linux-tdep.c (arm_linux_software_single_step): Return
VEC (CORE_ADDR) *. Return NULL instead of 0.
* arm-tdep.c (arm_software_single_step): Return NULL instead of 0.
* arm-tdep.h (arm_software_single_step): Update declaration.
* breakpoint.c (insert_single_step_breakpoints): New function.
* breakpoint.h (insert_single_step_breakpoints): Declare.
* cris-tdep.c (cris_software_single_step): Return
VEC (CORE_ADDR) *. Don't call insert_single_step_breakpoint.
* gdbarch.sh (software_single_step): Change it to return
VEC (CORE_ADDR) *.
* gdbarch.c, gdbarch.h: Regenerated.
* infrun.c (maybe_software_singlestep): Adjust.
* mips-tdep.c (mips_deal_with_atomic_sequence): Return
VEC (CORE_ADDR) *. Don't call insert_single_step_breakpoint.
(micromips_deal_with_atomic_sequence): Likewise.
(deal_with_atomic_sequence): Likewise.
(mips_software_single_step): Likewise.
* mips-tdep.h (mips_software_single_step): Update declaration.
* moxie-tdep.c (moxie_software_single_step): Likewise.
* nios2-tdep.c (nios2_software_single_step): Likewise.
* ppc-tdep.h (ppc_deal_with_atomic_sequence): Update
declaration.
* record-full.c (record_full_resume): Adjust.
(record_full_wait_1): Likewise.
* rs6000-aix-tdep.c (rs6000_software_single_step): Return
VEC (CORE_ADDR) *. Don't call insert_single_step_breakpoint.
* rs6000-tdep.c (ppc_deal_with_atomic_sequence): Return
VEC (CORE_ADDR) *. Don't call insert_single_step_breakpoint.
* s390-linux-tdep.c (s390_software_single_step): Likewise.
* sparc-tdep.c (sparc_software_single_step): Likewise.
* spu-tdep.c (spu_software_single_step): Likewise.
* tic6x-tdep.c (tic6x_software_single_step): Likewise.
2016-11-08 Yao Qi <yao.qi@linaro.org>
* arm-linux-tdep.c (arm_linux_software_single_step): Write

View File

@ -2224,11 +2224,10 @@ value_of_aarch64_user_reg (struct frame_info *frame, const void *baton)
/* Implement the "software_single_step" gdbarch method, needed to
single step through atomic sequences on AArch64. */
static int
static VEC (CORE_ADDR) *
aarch64_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
const int insn_size = 4;
const int atomic_sequence_length = 16; /* Instruction sequence length. */
@ -2243,13 +2242,14 @@ aarch64_software_single_step (struct frame_info *frame)
int bc_insn_count = 0; /* Conditional branch instruction count. */
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
aarch64_inst inst;
VEC (CORE_ADDR) *next_pcs = NULL;
if (aarch64_decode_insn (insn, &inst, 1) != 0)
return 0;
return NULL;
/* Look for a Load Exclusive instruction which begins the sequence. */
if (inst.opcode->iclass != ldstexcl || bit (insn, 22) == 0)
return 0;
return NULL;
for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
{
@ -2258,14 +2258,14 @@ aarch64_software_single_step (struct frame_info *frame)
byte_order_for_code);
if (aarch64_decode_insn (insn, &inst, 1) != 0)
return 0;
return NULL;
/* Check if the instruction is a conditional branch. */
if (inst.opcode->iclass == condbranch)
{
gdb_assert (inst.operands[0].type == AARCH64_OPND_ADDR_PCREL19);
if (bc_insn_count >= 1)
return 0;
return NULL;
/* It is, so we'll try to set a breakpoint at the destination. */
breaks[1] = loc + inst.operands[0].imm.value;
@ -2284,7 +2284,7 @@ aarch64_software_single_step (struct frame_info *frame)
/* We didn't find a closing Store Exclusive instruction, fall back. */
if (!closing_insn)
return 0;
return NULL;
/* Insert breakpoint after the end of the atomic sequence. */
breaks[0] = loc + insn_size;
@ -2299,9 +2299,9 @@ aarch64_software_single_step (struct frame_info *frame)
/* Insert the breakpoint at the end of the sequence, and one at the
destination of the conditional branch, if it exists. */
for (index = 0; index <= last_breakpoint; index++)
insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
VEC_safe_push (CORE_ADDR, next_pcs, breaks[index]);
return 1;
return next_pcs;
}
struct displaced_step_closure

View File

@ -765,11 +765,10 @@ static const int stq_c_opcode = 0x2f;
is found, attempt to step through it. A breakpoint is placed at the end of
the sequence. */
static int
static VEC (CORE_ADDR) *
alpha_deal_with_atomic_sequence (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR pc = get_frame_pc (frame);
CORE_ADDR breaks[2] = {-1, -1};
CORE_ADDR loc = pc;
@ -780,11 +779,12 @@ alpha_deal_with_atomic_sequence (struct frame_info *frame)
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
const int atomic_sequence_length = 16; /* Instruction sequence length. */
int bc_insn_count = 0; /* Conditional branch instruction count. */
VEC (CORE_ADDR) *next_pcs = NULL;
/* Assume all atomic sequences start with a LDL_L/LDQ_L instruction. */
if (INSN_OPCODE (insn) != ldl_l_opcode
&& INSN_OPCODE (insn) != ldq_l_opcode)
return 0;
return NULL;
/* Assume that no atomic sequence is longer than "atomic_sequence_length"
instructions. */
@ -803,8 +803,8 @@ alpha_deal_with_atomic_sequence (struct frame_info *frame)
immediate = (immediate ^ 0x400000) - 0x400000;
if (bc_insn_count >= 1)
return 0; /* More than one branch found, fallback
to the standard single-step code. */
return NULL; /* More than one branch found, fallback
to the standard single-step code. */
breaks[1] = loc + ALPHA_INSN_SIZE + immediate;
@ -820,7 +820,7 @@ alpha_deal_with_atomic_sequence (struct frame_info *frame)
/* Assume that the atomic sequence ends with a STL_C/STQ_C instruction. */
if (INSN_OPCODE (insn) != stl_c_opcode
&& INSN_OPCODE (insn) != stq_c_opcode)
return 0;
return NULL;
closing_insn = loc;
loc += ALPHA_INSN_SIZE;
@ -835,11 +835,10 @@ alpha_deal_with_atomic_sequence (struct frame_info *frame)
|| (breaks[1] >= pc && breaks[1] <= closing_insn)))
last_breakpoint = 0;
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
VEC_safe_push (CORE_ADDR, next_pcs, breaks[index]);
return 1;
return next_pcs;
}
@ -1718,18 +1717,17 @@ alpha_next_pc (struct frame_info *frame, CORE_ADDR pc)
return (pc + ALPHA_INSN_SIZE);
}
int
VEC (CORE_ADDR) *
alpha_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR pc, next_pc;
CORE_ADDR pc;
VEC (CORE_ADDR) *next_pcs = NULL;
pc = get_frame_pc (frame);
next_pc = alpha_next_pc (frame, pc);
insert_single_step_breakpoint (gdbarch, aspace, next_pc);
return 1;
VEC_safe_push (CORE_ADDR, next_pcs, alpha_next_pc (frame, pc));
return next_pcs;
}

View File

@ -103,7 +103,7 @@ struct gdbarch_tdep
};
extern unsigned int alpha_read_insn (struct gdbarch *gdbarch, CORE_ADDR pc);
extern int alpha_software_single_step (struct frame_info *frame);
extern VEC (CORE_ADDR) *alpha_software_single_step (struct frame_info *frame);
extern CORE_ADDR alpha_after_prologue (CORE_ADDR pc);
extern void alpha_mdebug_init_abi (struct gdbarch_info, struct gdbarch *);

View File

@ -921,12 +921,11 @@ arm_linux_get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self)
/* Insert a single step breakpoint at the next executed instruction. */
static int
static VEC (CORE_ADDR) *
arm_linux_software_single_step (struct frame_info *frame)
{
struct regcache *regcache = get_current_regcache ();
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct address_space *aspace = get_regcache_aspace (regcache);
struct arm_get_next_pcs next_pcs_ctx;
CORE_ADDR pc;
int i;
@ -936,7 +935,7 @@ arm_linux_software_single_step (struct frame_info *frame)
/* If the target does have hardware single step, GDB doesn't have
to bother software single step. */
if (target_can_do_single_step () == 1)
return 0;
return NULL;
old_chain = make_cleanup (VEC_cleanup (CORE_ADDR), &next_pcs);
@ -955,12 +954,9 @@ arm_linux_software_single_step (struct frame_info *frame)
VEC_replace (CORE_ADDR, next_pcs, i, pc);
}
for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
insert_single_step_breakpoint (gdbarch, aspace, pc);
discard_cleanups (old_chain);
do_cleanups (old_chain);
return 1;
return next_pcs;
}
/* Support for displaced stepping of Linux SVC instructions. */

View File

@ -6286,12 +6286,11 @@ arm_get_next_pcs_is_thumb (struct arm_get_next_pcs *self)
single-step support. We find the target of the coming instructions
and breakpoint them. */
int
VEC (CORE_ADDR) *
arm_software_single_step (struct frame_info *frame)
{
struct regcache *regcache = get_current_regcache ();
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct address_space *aspace = get_regcache_aspace (regcache);
struct arm_get_next_pcs next_pcs_ctx;
CORE_ADDR pc;
int i;
@ -6313,12 +6312,9 @@ arm_software_single_step (struct frame_info *frame)
VEC_replace (CORE_ADDR, next_pcs, i, pc);
}
for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
insert_single_step_breakpoint (gdbarch, aspace, pc);
discard_cleanups (old_chain);
do_cleanups (old_chain);
return 1;
return next_pcs;
}
/* Cleanup/copy SVC (SWI) instructions. These two functions are overridden

View File

@ -259,7 +259,7 @@ CORE_ADDR arm_get_next_pcs_addr_bits_remove (struct arm_get_next_pcs *self,
int arm_get_next_pcs_is_thumb (struct arm_get_next_pcs *self);
int arm_software_single_step (struct frame_info *);
VEC (CORE_ADDR) *arm_software_single_step (struct frame_info *);
int arm_is_thumb (struct regcache *regcache);
int arm_frame_is_thumb (struct frame_info *frame);

View File

@ -15232,6 +15232,33 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch,
update_global_location_list (UGLL_INSERT);
}
/* Insert single step breakpoints according to the current state. */
int
insert_single_step_breakpoints (struct gdbarch *gdbarch)
{
struct frame_info *frame = get_current_frame ();
VEC (CORE_ADDR) * next_pcs;
next_pcs = gdbarch_software_single_step (gdbarch, frame);
if (next_pcs != NULL)
{
int i;
CORE_ADDR pc;
struct address_space *aspace = get_frame_address_space (frame);
for (i = 0; VEC_iterate (CORE_ADDR, next_pcs, i, pc); i++)
insert_single_step_breakpoint (gdbarch, aspace, pc);
VEC_free (CORE_ADDR, next_pcs);
return 1;
}
else
return 0;
}
/* See breakpoint.h. */
int

View File

@ -1530,6 +1530,12 @@ extern void delete_command (char *arg, int from_tty);
extern void insert_single_step_breakpoint (struct gdbarch *,
struct address_space *,
CORE_ADDR);
/* Insert all software single step breakpoints for the current frame.
Return true if any software single step breakpoints are inserted,
otherwise, return false. */
extern int insert_single_step_breakpoints (struct gdbarch *);
/* Check if any hardware watchpoints have triggered, according to the
target. */
int watchpoints_triggered (struct target_waitstatus *);

View File

@ -2060,12 +2060,12 @@ find_step_target (struct frame_info *frame, inst_env_type *inst_env)
digs through the opcodes in order to find all possible targets.
Either one ordinary target or two targets for branches may be found. */
static int
static VEC (CORE_ADDR) *
cris_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
inst_env_type inst_env;
VEC (CORE_ADDR) *next_pcs = NULL;
/* Analyse the present instruction environment and insert
breakpoints. */
@ -2082,18 +2082,19 @@ cris_software_single_step (struct frame_info *frame)
and possibly another one for a branch, jump, etc. */
CORE_ADDR next_pc
= (CORE_ADDR) inst_env.reg[gdbarch_pc_regnum (gdbarch)];
insert_single_step_breakpoint (gdbarch, aspace, next_pc);
VEC_safe_push (CORE_ADDR, next_pcs, next_pc);
if (inst_env.branch_found
&& (CORE_ADDR) inst_env.branch_break_address != next_pc)
{
CORE_ADDR branch_target_address
= (CORE_ADDR) inst_env.branch_break_address;
insert_single_step_breakpoint (gdbarch,
aspace, branch_target_address);
VEC_safe_push (CORE_ADDR, next_pcs, branch_target_address);
}
}
return 1;
return next_pcs;
}
/* Calculates the prefix value for quick offset addressing mode. */

View File

@ -3165,7 +3165,7 @@ gdbarch_software_single_step_p (struct gdbarch *gdbarch)
return gdbarch->software_single_step != NULL;
}
int
VEC (CORE_ADDR) *
gdbarch_software_single_step (struct gdbarch *gdbarch, struct frame_info *frame)
{
gdb_assert (gdbarch != NULL);

View File

@ -677,18 +677,19 @@ extern void set_gdbarch_addr_bits_remove (struct gdbarch *gdbarch, gdbarch_addr_
FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the
target can single step. If not, then implement single step using breakpoints.
A return value of 1 means that the software_single_step breakpoints
were inserted; 0 means they were not. Multiple breakpoints may be
inserted for some instructions such as conditional branch. However,
each implementation must always evaluate the condition and only put
the breakpoint at the branch destination if the condition is true, so
that we ensure forward progress when stepping past a conditional
branch to self. */
Return a vector of addresses on which the software single step
breakpoints should be inserted. NULL means software single step is
not used.
Multiple breakpoints may be inserted for some instructions such as
conditional branch. However, each implementation must always evaluate
the condition and only put the breakpoint at the branch destination if
the condition is true, so that we ensure forward progress when stepping
past a conditional branch to self. */
extern int gdbarch_software_single_step_p (struct gdbarch *gdbarch);
typedef int (gdbarch_software_single_step_ftype) (struct frame_info *frame);
extern int gdbarch_software_single_step (struct gdbarch *gdbarch, struct frame_info *frame);
typedef VEC (CORE_ADDR) * (gdbarch_software_single_step_ftype) (struct frame_info *frame);
extern VEC (CORE_ADDR) * gdbarch_software_single_step (struct gdbarch *gdbarch, struct frame_info *frame);
extern void set_gdbarch_software_single_step (struct gdbarch *gdbarch, gdbarch_software_single_step_ftype *software_single_step);
/* Return non-zero if the processor is executing a delay slot and a

View File

@ -626,14 +626,15 @@ m:CORE_ADDR:addr_bits_remove:CORE_ADDR addr:addr::core_addr_identity::0
# FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the
# target can single step. If not, then implement single step using breakpoints.
#
# A return value of 1 means that the software_single_step breakpoints
# were inserted; 0 means they were not. Multiple breakpoints may be
# inserted for some instructions such as conditional branch. However,
# each implementation must always evaluate the condition and only put
# the breakpoint at the branch destination if the condition is true, so
# that we ensure forward progress when stepping past a conditional
# branch to self.
F:int:software_single_step:struct frame_info *frame:frame
# Return a vector of addresses on which the software single step
# breakpoints should be inserted. NULL means software single step is
# not used.
# Multiple breakpoints may be inserted for some instructions such as
# conditional branch. However, each implementation must always evaluate
# the condition and only put the breakpoint at the branch destination if
# the condition is true, so that we ensure forward progress when stepping
# past a conditional branch to self.
F:VEC (CORE_ADDR) *:software_single_step:struct frame_info *frame:frame
# Return non-zero if the processor is executing a delay slot and a
# further single-step is needed before the instruction finishes.

View File

@ -2254,11 +2254,9 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc)
int hw_step = 1;
if (execution_direction == EXEC_FORWARD
&& gdbarch_software_single_step_p (gdbarch)
&& gdbarch_software_single_step (gdbarch, get_current_frame ()))
{
hw_step = 0;
}
&& gdbarch_software_single_step_p (gdbarch))
hw_step = !insert_single_step_breakpoints (gdbarch);
return hw_step;
}

View File

@ -3877,9 +3877,8 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
#define SC_OPCODE 0x38
#define SCD_OPCODE 0x3c
static int
mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
struct address_space *aspace, CORE_ADDR pc)
static VEC (CORE_ADDR) *
mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
{
CORE_ADDR breaks[2] = {-1, -1};
CORE_ADDR loc = pc;
@ -3889,11 +3888,12 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
int index;
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
const int atomic_sequence_length = 16; /* Instruction sequence length. */
VEC (CORE_ADDR) *next_pcs = NULL;
insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL);
/* Assume all atomic sequences start with a ll/lld instruction. */
if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
return 0;
return NULL;
/* Assume that no atomic sequence is longer than "atomic_sequence_length"
instructions. */
@ -3957,7 +3957,7 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
/* Assume that the atomic sequence ends with a sc/scd instruction. */
if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE)
return 0;
return NULL;
loc += MIPS_INSN32_SIZE;
@ -3971,14 +3971,13 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
VEC_safe_push (CORE_ADDR, next_pcs, breaks[index]);
return 1;
return next_pcs;
}
static int
static VEC (CORE_ADDR) *
micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
struct address_space *aspace,
CORE_ADDR pc)
{
const int atomic_sequence_length = 16; /* Instruction sequence length. */
@ -3991,16 +3990,17 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
ULONGEST insn;
int insn_count;
int index;
VEC (CORE_ADDR) *next_pcs = NULL;
/* Assume all atomic sequences start with a ll/lld instruction. */
insn = mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL);
if (micromips_op (insn) != 0x18) /* POOL32C: bits 011000 */
return 0;
return NULL;
loc += MIPS_INSN16_SIZE;
insn <<= 16;
insn |= mips_fetch_instruction (gdbarch, ISA_MICROMIPS, loc, NULL);
if ((b12s4_op (insn) & 0xb) != 0x3) /* LL, LLD: bits 011000 0x11 */
return 0;
return NULL;
loc += MIPS_INSN16_SIZE;
/* Assume all atomic sequences end with an sc/scd instruction. Assume
@ -4097,24 +4097,24 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
&& b5s5_op (insn) != 0x18)
/* JRADDIUSP: bits 010001 11000 */
break;
return 0; /* Fall back to the standard single-step code. */
return NULL; /* Fall back to the standard single-step code. */
case 0x33: /* B16: bits 110011 */
return 0; /* Fall back to the standard single-step code. */
return NULL; /* Fall back to the standard single-step code. */
}
break;
}
if (is_branch)
{
if (last_breakpoint >= 1)
return 0; /* More than one branch found, fallback to the
return NULL; /* More than one branch found, fallback to the
standard single-step code. */
breaks[1] = branch_bp;
last_breakpoint++;
}
}
if (!sc_found)
return 0;
return NULL;
/* Insert a breakpoint right after the end of the atomic sequence. */
breaks[0] = loc;
@ -4126,21 +4126,20 @@ micromips_deal_with_atomic_sequence (struct gdbarch *gdbarch,
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
VEC_safe_push (CORE_ADDR, next_pcs, breaks[index]);
return 1;
return next_pcs;
}
static int
deal_with_atomic_sequence (struct gdbarch *gdbarch,
struct address_space *aspace, CORE_ADDR pc)
static VEC (CORE_ADDR) *
deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
{
if (mips_pc_is_mips (pc))
return mips_deal_with_atomic_sequence (gdbarch, aspace, pc);
return mips_deal_with_atomic_sequence (gdbarch, pc);
else if (mips_pc_is_micromips (gdbarch, pc))
return micromips_deal_with_atomic_sequence (gdbarch, aspace, pc);
return micromips_deal_with_atomic_sequence (gdbarch, pc);
else
return 0;
return NULL;
}
/* mips_software_single_step() is called just before we want to resume
@ -4148,21 +4147,22 @@ deal_with_atomic_sequence (struct gdbarch *gdbarch,
or kernel single-step support (MIPS on GNU/Linux for example). We find
the target of the coming instruction and breakpoint it. */
int
VEC (CORE_ADDR) *
mips_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR pc, next_pc;
VEC (CORE_ADDR) *next_pcs;
pc = get_frame_pc (frame);
if (deal_with_atomic_sequence (gdbarch, aspace, pc))
return 1;
next_pcs = deal_with_atomic_sequence (gdbarch, pc);
if (next_pcs != NULL)
return next_pcs;
next_pc = mips_next_pc (frame, pc);
insert_single_step_breakpoint (gdbarch, aspace, next_pc);
return 1;
VEC_safe_push (CORE_ADDR, next_pcs, next_pc);
return next_pcs;
}
/* Test whether the PC points to the return instruction at the

View File

@ -154,7 +154,7 @@ enum
};
/* Single step based on where the current instruction will take us. */
extern int mips_software_single_step (struct frame_info *frame);
extern VEC (CORE_ADDR) *mips_software_single_step (struct frame_info *frame);
/* Strip the ISA (compression) bit off from ADDR. */
extern CORE_ADDR mips_unmake_compact_addr (CORE_ADDR addr);

View File

@ -299,11 +299,10 @@ moxie_process_readu (CORE_ADDR addr, gdb_byte *buf,
/* Insert a single step breakpoint. */
static int
static VEC (CORE_ADDR) *
moxie_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR addr;
gdb_byte buf[4];
uint16_t inst;
@ -311,6 +310,7 @@ moxie_software_single_step (struct frame_info *frame)
ULONGEST fp;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct regcache *regcache = get_current_regcache ();
VEC (CORE_ADDR) *next_pcs = NULL;
addr = get_frame_pc (frame);
@ -338,8 +338,9 @@ moxie_software_single_step (struct frame_info *frame)
case 0x09: /* bleu */
/* Insert breaks on both branches, because we can't currently tell
which way things will go. */
insert_single_step_breakpoint (gdbarch, aspace, addr + 2);
insert_single_step_breakpoint (gdbarch, aspace, addr + 2 + INST2OFFSET(inst));
VEC_safe_push (CORE_ADDR, next_pcs, addr + 2);
VEC_safe_push (CORE_ADDR, next_pcs,
addr + 2 + INST2OFFSET(inst));
break;
default:
{
@ -351,7 +352,7 @@ moxie_software_single_step (struct frame_info *frame)
else
{
/* This is a Form 2 instruction. They are all 16 bits. */
insert_single_step_breakpoint (gdbarch, aspace, addr + 2);
VEC_safe_push (CORE_ADDR, next_pcs, addr + 2);
}
}
else
@ -398,7 +399,7 @@ moxie_software_single_step (struct frame_info *frame)
case 0x32: /* udiv.l */
case 0x33: /* mod.l */
case 0x34: /* umod.l */
insert_single_step_breakpoint (gdbarch, aspace, addr + 2);
VEC_safe_push (CORE_ADDR, next_pcs, addr + 2);
break;
/* 32-bit instructions. */
@ -408,7 +409,7 @@ moxie_software_single_step (struct frame_info *frame)
case 0x37: /* sto.b */
case 0x38: /* ldo.s */
case 0x39: /* sto.s */
insert_single_step_breakpoint (gdbarch, aspace, addr + 4);
VEC_safe_push (CORE_ADDR, next_pcs, addr + 4);
break;
/* 48-bit instructions. */
@ -421,32 +422,27 @@ moxie_software_single_step (struct frame_info *frame)
case 0x20: /* ldi.s (immediate) */
case 0x22: /* lda.s */
case 0x24: /* sta.s */
insert_single_step_breakpoint (gdbarch, aspace, addr + 6);
VEC_safe_push (CORE_ADDR, next_pcs, addr + 6);
break;
/* Control flow instructions. */
case 0x03: /* jsra */
case 0x1a: /* jmpa */
insert_single_step_breakpoint (gdbarch, aspace,
moxie_process_readu (addr + 2,
buf, 4,
byte_order));
VEC_safe_push (CORE_ADDR, next_pcs,
moxie_process_readu (addr + 2, buf, 4, byte_order));
break;
case 0x04: /* ret */
regcache_cooked_read_unsigned (regcache, MOXIE_FP_REGNUM, &fp);
insert_single_step_breakpoint (gdbarch, aspace,
moxie_process_readu (fp + 4,
buf, 4,
byte_order));
VEC_safe_push (CORE_ADDR, next_pcs,
moxie_process_readu (fp + 4, buf, 4, byte_order));
break;
case 0x19: /* jsr */
case 0x25: /* jmp */
regcache_raw_read (regcache,
(inst >> 4) & 0xf, (gdb_byte *) & tmpu32);
insert_single_step_breakpoint (gdbarch, aspace,
tmpu32);
VEC_safe_push (CORE_ADDR, next_pcs, tmpu32);
break;
case 0x30: /* swi */
@ -456,7 +452,7 @@ moxie_software_single_step (struct frame_info *frame)
}
}
return 1;
return next_pcs;
}
/* Implement the "read_pc" gdbarch method. */

View File

@ -2219,16 +2219,16 @@ nios2_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
/* Implement the software_single_step gdbarch method. */
static int
static VEC (CORE_ADDR) *
nios2_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR next_pc = nios2_get_next_pc (frame, get_frame_pc (frame));
VEC (CORE_ADDR) *next_pcs = NULL;
insert_single_step_breakpoint (gdbarch, aspace, next_pc);
VEC_safe_push (CORE_ADDR, next_pcs, next_pc);
return 1;
return next_pcs;
}
/* Implement the get_longjump_target gdbarch method. */

View File

@ -76,7 +76,7 @@ int ppc_altivec_support_p (struct gdbarch *gdbarch);
/* Return non-zero if the architecture described by GDBARCH has
VSX registers (vsr0 --- vsr63). */
int vsx_support_p (struct gdbarch *gdbarch);
int ppc_deal_with_atomic_sequence (struct frame_info *frame);
VEC (CORE_ADDR) *ppc_deal_with_atomic_sequence (struct frame_info *frame);
/* Register set description. */

View File

@ -976,17 +976,7 @@ record_full_resume (struct target_ops *ops, ptid_t ptid, int step,
record_full_resume_step = 1;
}
else
{
/* This is a continue.
Try to insert a soft single step breakpoint. */
if (!gdbarch_software_single_step (gdbarch,
get_current_frame ()))
{
/* This system don't want use soft single step.
Use hard sigle step. */
step = 1;
}
}
step = !insert_single_step_breakpoints (gdbarch);
}
}
@ -1168,9 +1158,9 @@ record_full_wait_1 (struct target_ops *ops,
If insert success, set step to 0. */
set_executing (inferior_ptid, 0);
reinit_frame_cache ();
if (gdbarch_software_single_step (gdbarch,
get_current_frame ()))
step = 0;
step = !insert_single_step_breakpoints (gdbarch);
set_executing (inferior_ptid, 1);
}

View File

@ -669,7 +669,7 @@ branch_dest (struct frame_info *frame, int opcode, int instr,
/* AIX does not support PT_STEP. Simulate it. */
static int
static VEC (CORE_ADDR) *
rs6000_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
@ -679,13 +679,15 @@ rs6000_software_single_step (struct frame_info *frame)
CORE_ADDR loc;
CORE_ADDR breaks[2];
int opcode;
VEC (CORE_ADDR) *next_pcs;
loc = get_frame_pc (frame);
insn = read_memory_integer (loc, 4, byte_order);
if (ppc_deal_with_atomic_sequence (frame))
return 1;
next_pcs = ppc_deal_with_atomic_sequence (frame);
if (next_pcs != NULL)
return next_pcs;
breaks[0] = loc + PPC_INSN_SIZE;
opcode = insn >> 26;
@ -700,12 +702,12 @@ rs6000_software_single_step (struct frame_info *frame)
/* ignore invalid breakpoint. */
if (breaks[ii] == -1)
continue;
insert_single_step_breakpoint (gdbarch, aspace, breaks[ii]);
VEC_safe_push (CORE_ADDR, next_pcs, breaks[ii]);
}
errno = 0; /* FIXME, don't ignore errors! */
/* What errors? {read,write}_memory call error(). */
return 1;
return next_pcs;
}
/* Implement the "auto_wide_charset" gdbarch method for this platform. */

View File

@ -1143,7 +1143,7 @@ ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
is found, attempt to step through it. A breakpoint is placed at the end of
the sequence. */
int
VEC (CORE_ADDR) *
ppc_deal_with_atomic_sequence (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
@ -1159,11 +1159,12 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */
const int atomic_sequence_length = 16; /* Instruction sequence length. */
int bc_insn_count = 0; /* Conditional branch instruction count. */
VEC (CORE_ADDR) *next_pcs = NULL;
/* Assume all atomic sequences start with a lwarx/ldarx instruction. */
if ((insn & LWARX_MASK) != LWARX_INSTRUCTION
&& (insn & LWARX_MASK) != LDARX_INSTRUCTION)
return 0;
return NULL;
/* Assume that no atomic sequence is longer than "atomic_sequence_length"
instructions. */
@ -1201,7 +1202,7 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
/* Assume that the atomic sequence ends with a stwcx/stdcx instruction. */
if ((insn & STWCX_MASK) != STWCX_INSTRUCTION
&& (insn & STWCX_MASK) != STDCX_INSTRUCTION)
return 0;
return NULL;
closing_insn = loc;
loc += PPC_INSN_SIZE;
@ -1217,11 +1218,10 @@ ppc_deal_with_atomic_sequence (struct frame_info *frame)
|| (breaks[1] >= pc && breaks[1] <= closing_insn)))
last_breakpoint = 0;
/* Effectively inserts the breakpoints. */
for (index = 0; index <= last_breakpoint; index++)
insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
VEC_safe_push (CORE_ADDR, next_pcs, breaks[index]);
return 1;
return next_pcs;
}

View File

@ -722,7 +722,7 @@ s390_is_partial_instruction (struct gdbarch *gdbarch, CORE_ADDR loc, int *len)
process about 4kiB of it each time, leading to O(n**2) memory and time
complexity. */
static int
static VEC (CORE_ADDR) *
s390_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
@ -731,33 +731,33 @@ s390_software_single_step (struct frame_info *frame)
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int len;
uint16_t insn;
VEC (CORE_ADDR) *next_pcs = NULL;
/* Special handling only if recording. */
if (!record_full_is_used ())
return 0;
return NULL;
/* First, match a partial instruction. */
if (!s390_is_partial_instruction (gdbarch, loc, &len))
return 0;
return NULL;
loc += len;
/* Second, look for a branch back to it. */
insn = read_memory_integer (loc, 2, byte_order);
if (insn != 0xa714) /* BRC with mask 1 */
return 0;
return NULL;
insn = read_memory_integer (loc + 2, 2, byte_order);
if (insn != (uint16_t) -(len / 2))
return 0;
return NULL;
loc += 4;
/* Found it, step past the whole thing. */
VEC_safe_push (CORE_ADDR, next_pcs, loc);
insert_single_step_breakpoint (gdbarch, aspace, loc);
return 1;
return next_pcs;
}
static int

View File

@ -1599,7 +1599,7 @@ sparc_step_trap (struct frame_info *frame, unsigned long insn)
return 0;
}
static int
static VEC (CORE_ADDR) *
sparc_software_single_step (struct frame_info *frame)
{
struct gdbarch *arch = get_frame_arch (frame);
@ -1608,6 +1608,7 @@ sparc_software_single_step (struct frame_info *frame)
CORE_ADDR npc, nnpc;
CORE_ADDR pc, orig_npc;
VEC (CORE_ADDR) *next_pcs = NULL;
pc = get_frame_register_unsigned (frame, tdep->pc_regnum);
orig_npc = npc = get_frame_register_unsigned (frame, tdep->npc_regnum);
@ -1615,10 +1616,10 @@ sparc_software_single_step (struct frame_info *frame)
/* Analyze the instruction at PC. */
nnpc = sparc_analyze_control_transfer (frame, pc, &npc);
if (npc != 0)
insert_single_step_breakpoint (arch, aspace, npc);
VEC_safe_push (CORE_ADDR, next_pcs, npc);
if (nnpc != 0)
insert_single_step_breakpoint (arch, aspace, nnpc);
VEC_safe_push (CORE_ADDR, next_pcs, nnpc);
/* Assert that we have set at least one breakpoint, and that
they're not set at the same spot - unless we're going
@ -1626,7 +1627,7 @@ sparc_software_single_step (struct frame_info *frame)
gdb_assert (npc != 0 || nnpc != 0 || orig_npc == 0);
gdb_assert (nnpc != npc || orig_npc == 0);
return 1;
return next_pcs;
}
static void

View File

@ -1610,17 +1610,17 @@ spu_memory_remove_breakpoint (struct gdbarch *gdbarch,
/* Software single-stepping support. */
static int
static VEC (CORE_ADDR) *
spu_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR pc, next_pc;
unsigned int insn;
int offset, reg;
gdb_byte buf[4];
ULONGEST lslr;
VEC (CORE_ADDR) *next_pcs = NULL;
pc = get_frame_pc (frame);
@ -1643,8 +1643,7 @@ spu_software_single_step (struct frame_info *frame)
else
next_pc = (SPUADDR_ADDR (pc) + 4) & lslr;
insert_single_step_breakpoint (gdbarch,
aspace, SPUADDR (SPUADDR_SPU (pc), next_pc));
VEC_safe_push (CORE_ADDR, next_pcs, SPUADDR (SPUADDR_SPU (pc), next_pc));
if (is_branch (insn, &offset, &reg))
{
@ -1674,11 +1673,11 @@ spu_software_single_step (struct frame_info *frame)
target = target & lslr;
if (target != next_pc)
insert_single_step_breakpoint (gdbarch, aspace,
SPUADDR (SPUADDR_SPU (pc), target));
VEC_safe_push (CORE_ADDR, next_pcs, SPUADDR (SPUADDR_SPU (pc),
target));
}
return 1;
return next_pcs;
}

View File

@ -699,16 +699,15 @@ tic6x_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
/* This is the implementation of gdbarch method software_single_step. */
static int
static VEC (CORE_ADDR) *
tic6x_software_single_step (struct frame_info *frame)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
struct address_space *aspace = get_frame_address_space (frame);
CORE_ADDR next_pc = tic6x_get_next_pc (frame, get_frame_pc (frame));
VEC (CORE_ADDR) *next_pcs = NULL;
insert_single_step_breakpoint (gdbarch, aspace, next_pc);
VEC_safe_push (CORE_ADDR, next_pcs, next_pc);
return 1;
return next_pcs;
}
/* This is the implementation of gdbarch method frame_align. */