static void btrace_add_pc (struct thread_info *tp) { struct btrace_data btrace; struct btrace_block *block; struct regcache *regcache; struct cleanup *cleanup; CORE_ADDR pc; regcache = get_thread_regcache (tp->ptid); pc = regcache_read_pc (regcache); btrace_data_init (&btrace); btrace.format = BTRACE_FORMAT_BTS; btrace.variant.bts.blocks = NULL; cleanup = make_cleanup_btrace_data (&btrace); block = VEC_safe_push (btrace_block_s, btrace.variant.bts.blocks, NULL); block->begin = pc; block->end = pc; btrace_compute_ftrace (tp, &btrace); do_cleanups (cleanup); }
static void darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info) { char *interp_name; CORE_ADDR load_addr = 0; bfd *dyld_bfd = NULL; struct cleanup *cleanup; /* This method doesn't work with an attached process. */ if (current_inferior ()->attach_flag) return; /* Find the program interpreter. */ interp_name = find_program_interpreter (); if (!interp_name) return; cleanup = make_cleanup (null_cleanup, NULL); /* Create a bfd for the interpreter. */ dyld_bfd = gdb_bfd_open (interp_name, gnutarget, -1); if (dyld_bfd) { bfd *sub; make_cleanup_bfd_unref (dyld_bfd); sub = gdb_bfd_mach_o_fat_extract (dyld_bfd, bfd_object, gdbarch_bfd_arch_info (target_gdbarch ())); if (sub) { dyld_bfd = sub; make_cleanup_bfd_unref (sub); } else dyld_bfd = NULL; } if (!dyld_bfd) { do_cleanups (cleanup); return; } /* We find the dynamic linker's base address by examining the current pc (which should point at the entry point for the dynamic linker) and subtracting the offset of the entry point. */ load_addr = (regcache_read_pc (get_current_regcache ()) - bfd_get_start_address (dyld_bfd)); /* Now try to set a breakpoint in the dynamic linker. */ info->all_image_addr = lookup_symbol_from_bfd (dyld_bfd, "_dyld_all_image_infos"); do_cleanups (cleanup); if (info->all_image_addr == 0) return; info->all_image_addr += load_addr; }
void default_skip_permanent_breakpoint (struct regcache *regcache) { struct gdbarch *gdbarch = get_regcache_arch (regcache); CORE_ADDR current_pc = regcache_read_pc (regcache); int bp_len; gdbarch_breakpoint_from_pc (gdbarch, ¤t_pc, &bp_len); current_pc += bp_len; regcache_write_pc (regcache, current_pc); }
static void check_event (ptid_t ptid) { struct regcache *regcache = get_thread_regcache (ptid); struct gdbarch *gdbarch = get_regcache_arch (regcache); td_event_msg_t msg; td_thrinfo_t ti; td_err_e err; CORE_ADDR stop_pc; int loop = 0; /* Bail out early if we're not at a thread event breakpoint. */ stop_pc = regcache_read_pc (regcache) - gdbarch_decr_pc_after_break (gdbarch); if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr) return; loop = 1; do { err = td_ta_event_getmsg_p (thread_agent, &msg); if (err != TD_OK) { if (err == TD_NOMSG) return; error ("Cannot get thread event message: %s", thread_db_err_str (err)); } err = td_thr_get_info_p ((void *)(uintptr_t)msg.th_p, &ti); if (err != TD_OK) error ("Cannot get thread info: %s", thread_db_err_str (err)); ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid)); switch (msg.event) { case TD_CREATE: /* We may already know about this thread, for instance when the user has issued the `info threads' command before the SIGTRAP for hitting the thread creation breakpoint was reported. */ attach_thread (ptid, (void *)(uintptr_t)msg.th_p, &ti, 1); break; case TD_DEATH: if (!in_thread_list (ptid)) error ("Spurious thread death event."); detach_thread (ptid, 1); break; default: error ("Spurious thread event."); } } while (loop); }
/* When PC is at a syscall instruction, return the PC of the next instruction to be executed. */ static CORE_ADDR get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self) { CORE_ADDR next_pc = 0; CORE_ADDR pc = regcache_read_pc (self->regcache); int is_thumb = arm_is_thumb_mode (); ULONGEST svc_number = 0; struct regcache *regcache = self->regcache; if (is_thumb) { collect_register (regcache, 7, &svc_number); next_pc = pc + 2; } else { unsigned long this_instr; unsigned long svc_operand; target_read_memory (pc, (unsigned char *) &this_instr, 4); svc_operand = (0x00ffffff & this_instr); if (svc_operand) /* OABI. */ { svc_number = svc_operand - 0x900000; } else /* EABI. */ { collect_register (regcache, 7, &svc_number); } next_pc = pc + 4; } /* This is a sigreturn or sigreturn_rt syscall. */ if (svc_number == __NR_sigreturn || svc_number == __NR_rt_sigreturn) { /* SIGRETURN or RT_SIGRETURN may affect the arm thumb mode, so update IS_THUMB. */ next_pc = arm_sigreturn_next_pc (regcache, svc_number, &is_thumb); } /* Addresses for calling Thumb functions have the bit 0 set. */ if (is_thumb) next_pc = MAKE_THUMB_ADDR (next_pc); return next_pc; }
static void exec_one_dummy_insn (struct regcache *regcache) { #define DUMMY_INSN_ADDR AIX_TEXT_SEGMENT_BASE+0x200 struct gdbarch *gdbarch = get_regcache_arch (regcache); int ret, status, pid; CORE_ADDR prev_pc; void *bp; /* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We assume that this address will never be executed again by the real code. */ bp = deprecated_insert_raw_breakpoint (gdbarch, NULL, DUMMY_INSN_ADDR); /* 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 = regcache_read_pc (regcache); regcache_write_pc (regcache, DUMMY_INSN_ADDR); if (ARCH64 ()) ret = rs6000_ptrace64 (PT_CONTINUE, ptid_get_pid (inferior_ptid), 1, 0, NULL); else ret = rs6000_ptrace32 (PT_CONTINUE, ptid_get_pid (inferior_ptid), (int *) 1, 0, NULL); if (ret != 0) perror (_("pt_continue")); do { pid = waitpid (ptid_get_pid (inferior_ptid), &status, 0); } while (pid != ptid_get_pid (inferior_ptid)); regcache_write_pc (regcache, prev_pc); deprecated_remove_raw_breakpoint (gdbarch, bp); }
static void save_bookmark_command (char *args, int from_tty) { /* Get target's idea of a bookmark. */ gdb_byte *bookmark_id = target_get_bookmark (args, from_tty); struct bookmark *b, *b1; struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ()); /* CR should not cause another identical bookmark. */ dont_repeat (); if (bookmark_id == NULL) error (_("target_get_bookmark failed.")); /* Set up a bookmark struct. */ b = xcalloc (1, sizeof (struct bookmark)); b->number = ++bookmark_count; init_sal (&b->sal); b->pc = regcache_read_pc (get_current_regcache ()); b->sal = find_pc_line (b->pc, 0); b->sal.pspace = get_frame_program_space (get_current_frame ()); b->opaque_data = bookmark_id; b->next = NULL; /* Add this bookmark to the end of the chain, so that a list of bookmarks will come out in order of increasing numbers. */ b1 = bookmark_chain; if (b1 == 0) bookmark_chain = b; else { while (b1->next) b1 = b1->next; b1->next = b; } printf_filtered (_("Saved bookmark %d at %s\n"), b->number, paddress (gdbarch, b->sal.pc)); }
/* If the PPU thread is currently stopped on a spu_run system call, return to FD and ADDR the file handle and NPC parameter address used with the system call. Return non-zero if successful. */ static int parse_spufs_run (ptid_t ptid, int *fd, CORE_ADDR *addr) { enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); struct gdbarch_tdep *tdep; struct regcache *regcache; gdb_byte buf[4]; #ifdef ALLOW_UNUSED_VARIABLES CORE_ADDR pc; #endif /* ALLOW_UNUSED_VARIABLES */ ULONGEST regval; /* If we're not on PPU, there's nothing to detect. */ if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_powerpc) return 0; /* Get PPU-side registers. */ regcache = get_thread_arch_regcache (ptid, target_gdbarch); tdep = new_gdbarch_tdep(target_gdbarch); /* Fetch instruction preceding current NIP. */ if (target_read_memory (regcache_read_pc (regcache) - 4, buf, 4) != 0) return 0; /* It should be a "sc" instruction. */ if (extract_unsigned_integer_with_byte_order(buf, 4, byte_order) != INSTR_SC) return 0; /* System call number should be NR_spu_run. */ regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum, ®val); if (regval != NR_spu_run) return 0; /* Register 3 contains fd, register 4 the NPC param pointer. */ regcache_cooked_read_unsigned (regcache, PPC_ORIG_R3_REGNUM, ®val); *fd = (int) regval; regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 4, ®val); *addr = (CORE_ADDR) regval; return 1; }
CORE_ADDR arm_linux_get_next_pcs_fixup (struct arm_get_next_pcs *self, CORE_ADDR nextpc) { /* The Linux kernel offers some user-mode helpers in a high page. We can not read this page (as of 2.6.23), and even if we could then we couldn't set breakpoints in it, and even if we could then the atomic operations would fail when interrupted. They are all (tail) called as functions and return to the address in LR. However, when GDB single step this instruction, this instruction isn't executed yet, and LR may not be updated yet. In other words, GDB can get the target address from LR if this instruction isn't BL or BLX. */ if (nextpc > 0xffff0000) { int bl_blx_p = 0; CORE_ADDR pc = regcache_read_pc (self->regcache); int pc_incr = 0; if (self->ops->is_thumb (self)) { unsigned short inst1 = self->ops->read_mem_uint (pc, 2, self->byte_order_for_code); if (bits (inst1, 8, 15) == 0x47 && bit (inst1, 7)) { /* BLX Rm */ bl_blx_p = 1; pc_incr = 2; } else if (thumb_insn_size (inst1) == 4) { unsigned short inst2; inst2 = self->ops->read_mem_uint (pc + 2, 2, self->byte_order_for_code); if ((inst1 & 0xf800) == 0xf000 && bits (inst2, 14, 15) == 0x3) { /* BL <label> and BLX <label> */ bl_blx_p = 1; pc_incr = 4; } } pc_incr = MAKE_THUMB_ADDR (pc_incr); } else { unsigned int insn = self->ops->read_mem_uint (pc, 4, self->byte_order_for_code); if (bits (insn, 28, 31) == INST_NV) { if (bits (insn, 25, 27) == 0x5) /* BLX <label> */ bl_blx_p = 1; } else { if (bits (insn, 24, 27) == 0xb /* BL <label> */ || bits (insn, 4, 27) == 0x12fff3 /* BLX Rm */) bl_blx_p = 1; } pc_incr = 4; } /* If the instruction BL or BLX, the target address is the following instruction of BL or BLX, otherwise, the target address is in LR already. */ if (bl_blx_p) nextpc = pc + pc_incr; else nextpc = regcache_raw_get_unsigned (self->regcache, ARM_LR_REGNUM); } return nextpc; }