From 93f9a11fbdb8f09428b17180d51a09a1bda39a52 Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Tue, 8 Nov 2016 14:28:32 +0000 Subject: [PATCH] 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 * 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. --- gdb/ChangeLog | 41 ++++++++++++++++++++++++++++++++++++ gdb/aarch64-tdep.c | 18 ++++++++-------- gdb/alpha-tdep.c | 28 ++++++++++++------------- gdb/alpha-tdep.h | 2 +- gdb/arm-linux-tdep.c | 12 ++++------- gdb/arm-tdep.c | 10 +++------ gdb/arm-tdep.h | 2 +- gdb/breakpoint.c | 27 ++++++++++++++++++++++++ gdb/breakpoint.h | 6 ++++++ gdb/cris-tdep.c | 13 ++++++------ gdb/gdbarch.c | 2 +- gdb/gdbarch.h | 19 +++++++++-------- gdb/gdbarch.sh | 17 ++++++++------- gdb/infrun.c | 8 +++---- gdb/mips-tdep.c | 58 +++++++++++++++++++++++++-------------------------- gdb/mips-tdep.h | 2 +- gdb/moxie-tdep.c | 34 +++++++++++++----------------- gdb/nios2-tdep.c | 8 +++---- gdb/ppc-tdep.h | 2 +- gdb/record-full.c | 18 ++++------------ gdb/rs6000-aix-tdep.c | 12 ++++++----- gdb/rs6000-tdep.c | 12 +++++------ gdb/s390-linux-tdep.c | 16 +++++++------- gdb/sparc-tdep.c | 9 ++++---- gdb/spu-tdep.c | 13 ++++++------ gdb/tic6x-tdep.c | 9 ++++---- 26 files changed, 225 insertions(+), 173 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 3e6bd4c..cc7f9a0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,46 @@ 2016-11-08 Yao Qi + * 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 + * arm-linux-tdep.c (arm_linux_software_single_step): Write adjusted address back to vector. Call insert_single_step_breakpoint in a new loop. diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 1298302..b5a88cc 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -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 diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index 4b5c32d..a0485ef 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -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; } diff --git a/gdb/alpha-tdep.h b/gdb/alpha-tdep.h index abeb326..5b64861 100644 --- a/gdb/alpha-tdep.h +++ b/gdb/alpha-tdep.h @@ -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 *); diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index 4a734b0..c621cd6 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -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); - - do_cleanups (old_chain); + discard_cleanups (old_chain); - return 1; + return next_pcs; } /* Support for displaced stepping of Linux SVC instructions. */ diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 9340b3b..31d33c1 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -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); - - do_cleanups (old_chain); + discard_cleanups (old_chain); - return 1; + return next_pcs; } /* Cleanup/copy SVC (SWI) instructions. These two functions are overridden diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h index 2eecfed..10ab742 100644 --- a/gdb/arm-tdep.h +++ b/gdb/arm-tdep.h @@ -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); diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 9f9cb8a..ff2a53a 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -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 diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 9bdc8ff..e2e15b6 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -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 *); diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c index 1a2641b..460e7eb 100644 --- a/gdb/cris-tdep.c +++ b/gdb/cris-tdep.c @@ -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. */ diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 463f6e0..0c800c5 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -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); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index add7e13..cc95914 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -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 diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index ae7dd97..9b94703 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -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. diff --git a/gdb/infrun.c b/gdb/infrun.c index b10aa03..19e8044 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -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; } diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index da4bef6..c2c88a6 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -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 diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h index 4e547b4..8a870aa 100644 --- a/gdb/mips-tdep.h +++ b/gdb/mips-tdep.h @@ -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); diff --git a/gdb/moxie-tdep.c b/gdb/moxie-tdep.c index aadb270..b341945 100644 --- a/gdb/moxie-tdep.c +++ b/gdb/moxie-tdep.c @@ -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. */ diff --git a/gdb/nios2-tdep.c b/gdb/nios2-tdep.c index 2955a69..67861ca 100644 --- a/gdb/nios2-tdep.c +++ b/gdb/nios2-tdep.c @@ -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. */ diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index 4a1cb0f..0249456 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -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. */ diff --git a/gdb/record-full.c b/gdb/record-full.c index cce9228..803c5d4 100644 --- a/gdb/record-full.c +++ b/gdb/record-full.c @@ -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); } diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c index acd52bb..a7a3937 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -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. */ diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 1588679..5e10893 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -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; } diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c index 57bb992..885aadd 100644 --- a/gdb/s390-linux-tdep.c +++ b/gdb/s390-linux-tdep.c @@ -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 diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index d50d874..ea2435e 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -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 diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c index 308c460..5494a93 100644 --- a/gdb/spu-tdep.c +++ b/gdb/spu-tdep.c @@ -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, ®)) { @@ -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; } diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c index 63be761..399795c 100644 --- a/gdb/tic6x-tdep.c +++ b/gdb/tic6x-tdep.c @@ -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. */ -- 2.7.4