void sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p) { struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); static CORE_ADDR npc, nnpc; static char npc_save[4], nnpc_save[4]; if (insert_breakpoints_p) { CORE_ADDR pc; pc = sparc_address_from_register (tdep->pc_regnum); npc = sparc_address_from_register (tdep->npc_regnum); /* Analyze the instruction at PC. */ nnpc = sparc_analyze_control_transfer (pc, &npc); if (npc != 0) target_insert_breakpoint (npc, npc_save); if (nnpc != 0) target_insert_breakpoint (nnpc, nnpc_save); /* Assert that we have set at least one breakpoint, and that they're not set at the same spot. */ gdb_assert (npc != 0 || nnpc != 0); gdb_assert (nnpc != npc); } else { if (npc != 0) target_remove_breakpoint (npc, npc_save); if (nnpc != 0) target_remove_breakpoint (nnpc, nnpc_save); } }
void single_step () { branch_type br, isannulled(); CORE_ADDR pc; long pc_instruction; if (!one_stepped) { /* Always set breakpoint for NPC. */ next_pc = read_register (NPC_REGNUM); npc4 = next_pc + 4; /* branch not taken */ target_insert_breakpoint (next_pc, break_mem[0]); /* printf ("set break at %x\n",next_pc); */ pc = read_register (PC_REGNUM); pc_instruction = read_memory_integer (pc, sizeof(pc_instruction)); br = isannulled (pc_instruction, pc, &target); brknpc4 = brktrg = 0; if (br == bicca) { /* Conditional annulled branch will either end up at npc (if taken) or at npc+4 (if not taken). Trap npc+4. */ brknpc4 = 1; target_insert_breakpoint (npc4, break_mem[1]); } else if (br == baa && target != next_pc) { /* Unconditional annulled branch will always end up at the target. */ brktrg = 1; target_insert_breakpoint (target, break_mem[2]); } /* We are ready to let it go */ one_stepped = 1; return; } else { /* Remove breakpoints */ target_remove_breakpoint (next_pc, break_mem[0]); if (brknpc4) target_remove_breakpoint (npc4, break_mem[1]); if (brktrg) target_remove_breakpoint (target, break_mem[2]); one_stepped = 0; } }
static void exec_one_dummy_insn (void) { #define DUMMY_INSN_ADDR (TEXT_SEGMENT_BASE)+0x200 char shadow_contents[BREAKPOINT_MAX]; /* Stash old bkpt addr contents */ int ret, status, pid; CORE_ADDR prev_pc; /* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We assume that this address will never be executed again by the real code. */ target_insert_breakpoint (DUMMY_INSN_ADDR, shadow_contents); /* You might think this could be done with a single ptrace call, and you'd be correct for just about every platform I've ever worked on. However, rs6000-ibm-aix4.1.3 seems to have screwed this up -- the inferior never hits the breakpoint (it's also worth noting powerpc-ibm-aix4.1.3 works correctly). */ prev_pc = read_pc (); write_pc (DUMMY_INSN_ADDR); if (ARCH64 ()) ret = rs6000_ptrace64 (PT_CONTINUE, PIDGET (inferior_ptid), 1, 0, NULL); else ret = rs6000_ptrace32 (PT_CONTINUE, PIDGET (inferior_ptid), (int *)1, 0, NULL); if (ret != 0) perror ("pt_continue"); do { pid = wait (&status); } while (pid != PIDGET (inferior_ptid)); write_pc (prev_pc); target_remove_breakpoint (DUMMY_INSN_ADDR, shadow_contents); }
/* free up a breakpoint */ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint_to_remove) { struct breakpoint *breakpoint = target->breakpoints; struct breakpoint **breakpoint_p = &target->breakpoints; int retval; while (breakpoint) { if (breakpoint == breakpoint_to_remove) break; breakpoint_p = &breakpoint->next; breakpoint = breakpoint->next; } if (breakpoint == NULL) return; retval = target_remove_breakpoint(target, breakpoint); LOG_DEBUG("free BPID: %d --> %d", breakpoint->unique_id, retval); (*breakpoint_p) = breakpoint->next; free(breakpoint->orig_instr); free(breakpoint); }