static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, const td_thrinfo_t *ti_p, int verbose) { td_err_e err; /* Add the thread to GDB's thread list. */ if (!in_thread_list (ptid)) { add_thread (ptid); if (verbose) printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid)); } if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) return; /* A zombie thread -- do not attach. */ if (! IS_THREAD(ptid)) return; if (fbsd_thread_core != 0) return; /* Enable thread event reporting for this thread. */ err = td_thr_event_enable_p (th_p, 1); if (err != TD_OK) error ("Cannot enable thread event reporting for %s: %s", target_pid_to_str (ptid), thread_db_err_str (err)); }
static void inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty) { char *exec_file; pid_t pid; struct inferior *inf; /* Do not change either targets above or the same target if already present. The reason is the target stack is shared across multiple inferiors. */ int ops_already_pushed = target_is_pushed (ops); struct cleanup *back_to = NULL; pid = parse_pid_to_attach (args); if (pid == getpid ()) /* Trying to m********e? */ error (_("I refuse to debug myself!")); if (! ops_already_pushed) { /* target_pid_to_str already uses the target. Also clear possible core file with its process_stratum. */ push_target (ops); back_to = make_cleanup_unpush_target (ops); } if (from_tty) { exec_file = get_exec_file (0); if (exec_file) printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, target_pid_to_str (pid_to_ptid (pid))); else printf_unfiltered (_("Attaching to %s\n"), target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } #ifdef PT_ATTACH errno = 0; ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0); if (errno != 0) perror_with_name (("ptrace")); #else error (_("This system does not support attaching to a process")); #endif inf = current_inferior (); inferior_appeared (inf, pid); inf->attach_flag = 1; inferior_ptid = pid_to_ptid (pid); /* Always add a main thread. If some target extends the ptrace target, it should decorate the ptid later with more info. */ add_thread_silent (inferior_ptid); if (! ops_already_pushed) discard_cleanups (back_to); }
static void child_detach_from_process (int pid, char *args, int from_tty, int after_fork) { #ifdef ATTACH_DETACH { int siggnal = 0; if (from_tty) { char *exec_file = get_exec_file (0); if (exec_file == 0) exec_file = ""; if (after_fork) printf_unfiltered ("Detaching after fork from %s\n", target_pid_to_str (pid_to_ptid (pid))); else printf_unfiltered ("Detaching from program: %s, %s\n", exec_file, target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } if (args) siggnal = atoi (args); if (!after_fork) detach (siggnal); else REQUIRE_DETACH (pid, siggnal); } #else error ("This version of Unix does not support detaching a process."); #endif }
static void inf_ptrace_attach (struct target_ops *ops, char *args, int from_tty) { char *exec_file; pid_t pid; char *dummy; struct inferior *inf; if (!args) error_no_arg (_("process-id to attach")); dummy = args; pid = strtol (args, &dummy, 0); /* Some targets don't set errno on errors, grrr! */ if (pid == 0 && args == dummy) error (_("Illegal process-id: %s."), args); if (pid == getpid ()) /* Trying to m********e? */ error (_("I refuse to debug myself!")); if (from_tty) { exec_file = get_exec_file (0); if (exec_file) printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, target_pid_to_str (pid_to_ptid (pid))); else printf_unfiltered (_("Attaching to %s\n"), target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } #ifdef PT_ATTACH errno = 0; ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0); if (errno != 0) perror_with_name (("ptrace")); #else error (_("This system does not support attaching to a process")); #endif inferior_ptid = pid_to_ptid (pid); inf = add_inferior (pid); inf->attach_flag = 1; /* Always add a main thread. If some target extends the ptrace target, it should decorate the ptid later with more info. */ add_thread_silent (inferior_ptid); push_target(ops); }
static void child_attach_to_process (char *args, int from_tty, int after_fork) { if (!args) error_no_arg ("process-id to attach"); #ifndef ATTACH_DETACH error ("Can't attach to a process on this machine."); #else { char *exec_file; int pid; char *dummy; dummy = args; pid = strtol (args, &dummy, 0); /* Some targets don't set errno on errors, grrr! */ if ((pid == 0) && (args == dummy)) error ("Illegal process-id: %s\n", args); if (pid == getpid ()) /* Trying to m********e? */ error ("I refuse to debug myself!"); if (from_tty) { exec_file = (char *) get_exec_file (0); if (after_fork) printf_unfiltered ("Attaching after fork to %s\n", target_pid_to_str (pid_to_ptid (pid))); else if (exec_file) printf_unfiltered ("Attaching to program: %s, %s\n", exec_file, target_pid_to_str (pid_to_ptid (pid))); else printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } if (!after_fork) attach (pid); else REQUIRE_ATTACH (pid); inferior_ptid = pid_to_ptid (pid); push_target (&child_ops); } #endif /* ATTACH_DETACH */ }
static void inf_ptrace_attach (char *args, int from_tty) { char *exec_file; pid_t pid; char *dummy; if (!args) error_no_arg (_("process-id to attach")); dummy = args; pid = strtol (args, &dummy, 0); /* Some targets don't set errno on errors, grrr! */ if (pid == 0 && args == dummy) error (_("Illegal process-id: %s."), args); if (pid == getpid ()) /* Trying to m********e? */ error (_("I refuse to debug myself!")); if (from_tty) { exec_file = get_exec_file (0); if (exec_file) printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, target_pid_to_str (pid_to_ptid (pid))); else printf_unfiltered (_("Attaching to %s\n"), target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } #ifdef PT_ATTACH errno = 0; ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0); if (errno != 0) perror_with_name (("ptrace")); attach_flag = 1; #else error (_("This system does not support attaching to a process")); #endif inferior_ptid = pid_to_ptid (pid); push_target (ptrace_ops_hack); /* Do this first, before anything has had a chance to query the inferior's symbol table or similar. */ observer_notify_inferior_created (¤t_target, from_tty); }
void btrace_clear (struct thread_info *tp) { struct btrace_thread_info *btinfo; struct btrace_function *it, *trash; DEBUG ("clear thread %d (%s)", tp->num, target_pid_to_str (tp->ptid)); /* Make sure btrace frames that may hold a pointer into the branch trace data are destroyed. */ reinit_frame_cache (); btinfo = &tp->btrace; it = btinfo->begin; while (it != NULL) { trash = it; it = it->flow.next; xfree (trash); } btinfo->begin = NULL; btinfo->end = NULL; btinfo->ngaps = 0; btrace_clear_history (btinfo); }
static void inf_ptrace_detach (char *args, int from_tty) { pid_t pid = ptid_get_pid (inferior_ptid); int sig = 0; if (from_tty) { char *exec_file = get_exec_file (0); if (exec_file == 0) exec_file = ""; printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file, target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } if (args) sig = atoi (args); #ifdef PT_DETACH /* We'd better not have left any breakpoints in the program or it'll die when it hits one. Alsno note that this may only work if we previously attached to the inferior. It *might* work if we started the process ourselves. */ errno = 0; ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, sig); if (errno != 0) perror_with_name (("ptrace")); attach_flag = 0; #else error (_("This system does not support detaching from a process")); #endif inferior_ptid = null_ptid; unpush_target (ptrace_ops_hack); }
static void inf_ptrace_files_info (struct target_ops *ignore) { printf_filtered (_("\tUsing the running image of %s %s.\n"), attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid)); }
void inf_ptrace_target::files_info () { struct inferior *inf = current_inferior (); printf_filtered (_("\tUsing the running image of %s %s.\n"), inf->attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid)); }
/* Fetch register REGNO, or all regs if REGNO is -1. */ static void gnu_fetch_registers (struct target_ops *ops, struct regcache *regcache, int regno) { struct proc *thread; /* Make sure we know about new threads. */ inf_update_procs (gnu_current_inf); thread = inf_tid_to_thread (gnu_current_inf, ptid_get_tid (inferior_ptid)); if (!thread) error (_("Can't fetch registers from thread %s: No such thread"), target_pid_to_str (inferior_ptid)); if (regno < I386_NUM_GREGS || regno == -1) { thread_state_t state; /* This does the dirty work for us. */ state = proc_get_state (thread, 0); if (!state) { warning (_("Couldn't fetch registers from %s"), proc_string (thread)); return; } if (regno == -1) { int i; proc_debug (thread, "fetching all register"); for (i = 0; i < I386_NUM_GREGS; i++) regcache_raw_supply (regcache, i, REG_ADDR (state, i)); thread->fetched_regs = ~0; } else { proc_debug (thread, "fetching register %s", gdbarch_register_name (get_regcache_arch (regcache), regno)); regcache_raw_supply (regcache, regno, REG_ADDR (state, regno)); thread->fetched_regs |= (1 << regno); } } if (regno >= I386_NUM_GREGS || regno == -1) { proc_debug (thread, "fetching floating-point registers"); fetch_fpregs (regcache, thread); } }
static ptid_t record_btrace_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *status, int options) { struct thread_info *tp, *other; DEBUG ("wait %s (0x%x)", target_pid_to_str (ptid), options); /* As long as we're not replaying, just forward the request. */ if (!record_btrace_is_replaying (ops) && execution_direction != EXEC_REVERSE) { for (ops = ops->beneath; ops != NULL; ops = ops->beneath) if (ops->to_wait != NULL) return ops->to_wait (ops, ptid, status, options); error (_("Cannot find target for waiting.")); } /* Let's find a thread to move. */ tp = record_btrace_find_thread_to_move (ptid); if (tp == NULL) { DEBUG ("wait %s: no thread", target_pid_to_str (ptid)); status->kind = TARGET_WAITKIND_IGNORE; return minus_one_ptid; } /* We only move a single thread. We're not able to correlate threads. */ *status = record_btrace_step_thread (tp); /* Stop all other threads. */ if (!non_stop) ALL_THREADS (other) other->btrace.flags &= ~BTHR_MOVE; /* Start record histories anew from the current position. */ record_btrace_clear_histories (&tp->btrace); /* We moved the replay position but did not update registers. */ registers_changed_ptid (tp->ptid); return tp->ptid; }
static void child_attach (char *args, int from_tty) { char *exec_file; int pid; char *dummy; if (!args) error_no_arg (_("process-id to attach")); dummy = args; pid = strtol (args, &dummy, 0); /* Some targets don't set errno on errors, grrr! */ if ((pid == 0) && (args == dummy)) error (_("Illegal process-id: %s."), args); if (pid == getpid ()) /* Trying to m********e? */ error (_("I refuse to debug myself!")); if (from_tty) { exec_file = (char *) get_exec_file (0); if (exec_file) printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, target_pid_to_str (pid_to_ptid (pid))); else printf_unfiltered (_("Attaching to %s\n"), target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } attach (pid); inferior_ptid = pid_to_ptid (pid); push_target (&deprecated_child_ops); /* Do this first, before anything has had a chance to query the inferior's symbol table or similar. */ observer_notify_inferior_created (¤t_target, from_tty); }
static void dcache_info (char *exp, int tty) { splay_tree_node n; int i, refcount; if (exp) { char *linestart; i = strtol (exp, &linestart, 10); if (linestart == exp || i < 0) { printf_filtered (_("Usage: info dcache [linenumber]\n")); return; } dcache_print_line (i); return; } printf_filtered (_("Dcache %u lines of %u bytes each.\n"), dcache_size, last_cache ? (unsigned) last_cache->line_size : dcache_line_size); if (!last_cache || ptid_equal (last_cache->ptid, null_ptid)) { printf_filtered (_("No data cache available.\n")); return; } printf_filtered (_("Contains data for %s\n"), target_pid_to_str (last_cache->ptid)); refcount = 0; n = splay_tree_min (last_cache->tree); i = 0; while (n) { struct dcache_block *db = (struct dcache_block *) n->value; printf_filtered (_("Line %d: address %s [%d hits]\n"), i, paddress (target_gdbarch, db->addr), db->refs); i++; refcount += db->refs; n = splay_tree_successor (last_cache->tree, n->key); } printf_filtered (_("Cache state: %d active lines, %d hits\n"), i, refcount); }
static ptid_t sol_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus) { ptid_t rtnval; ptid_t save_ptid; struct cleanup *old_chain; save_ptid = inferior_ptid; old_chain = save_inferior_ptid (); inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid)); if (PIDGET (inferior_ptid) == -1) inferior_ptid = procfs_first_available (); if (PIDGET (ptid) != -1) { ptid_t save_ptid = ptid; ptid = thread_to_lwp (ptid, -2); if (PIDGET (ptid) == -2) /* Inactive thread */ error ("This version of Solaris can't start inactive threads."); if (info_verbose && PIDGET (ptid) == -1) warning ("Specified thread %ld seems to have terminated", GET_THREAD (save_ptid)); } rtnval = procfs_ops.to_wait (ptid, ourstatus); if (ourstatus->kind != TARGET_WAITKIND_EXITED) { /* Map the LWP of interest back to the appropriate thread ID */ rtnval = lwp_to_thread (rtnval); if (PIDGET (rtnval) == -1) rtnval = save_ptid; /* See if we have a new thread */ if (is_thread (rtnval) && !ptid_equal (rtnval, save_ptid) && !in_thread_list (rtnval)) { printf_filtered ("[New %s]\n", target_pid_to_str (rtnval)); add_thread (rtnval); } } /* During process initialization, we may get here without the thread package being initialized, since that can only happen after we've found the shared libs. */ do_cleanups (old_chain); return rtnval; }
struct address_space * process_stratum_target::thread_address_space (ptid_t ptid) { /* Fall-back to the "main" address space of the inferior. */ inferior *inf = find_inferior_ptid (ptid); if (inf == NULL || inf->aspace == NULL) internal_error (__FILE__, __LINE__, _("Can't determine the current " "address space of thread %s\n"), target_pid_to_str (ptid).c_str ()); return inf->aspace; }
struct btrace_target_info * x86_linux_nat_target::enable_btrace (ptid_t ptid, const struct btrace_config *conf) { struct btrace_target_info *tinfo = nullptr; TRY { tinfo = linux_enable_btrace (ptid, conf); } CATCH (exception, RETURN_MASK_ERROR) { error (_("Could not enable branch tracing for %s: %s"), target_pid_to_str (ptid), exception.message); }
static struct btrace_target_info * x86_linux_enable_btrace (struct target_ops *self, ptid_t ptid, const struct btrace_config *conf) { struct btrace_target_info *tinfo; errno = 0; tinfo = linux_enable_btrace (ptid, conf); if (tinfo == NULL) error (_("Could not enable branch tracing for %s: %s."), target_pid_to_str (ptid), safe_strerror (errno)); return tinfo; }
void btrace_teardown (struct thread_info *tp) { struct btrace_thread_info *btp = &tp->btrace; int errcode = 0; if (btp->target == NULL) return; DEBUG ("teardown thread %d (%s)", tp->num, target_pid_to_str (tp->ptid)); target_teardown_btrace (btp->target); btp->target = NULL; btrace_clear (tp); }
static void record_btrace_resume_thread (struct thread_info *tp, enum btrace_thread_flag flag) { struct btrace_thread_info *btinfo; DEBUG ("resuming %d (%s): %u", tp->num, target_pid_to_str (tp->ptid), flag); btinfo = &tp->btrace; if ((btinfo->flags & BTHR_MOVE) != 0) error (_("Thread already moving.")); /* Fetch the latest branch trace. */ btrace_fetch (tp); btinfo->flags |= flag; }
void btrace_enable (struct thread_info *tp, const struct btrace_config *conf) { if (tp->btrace.target != NULL) return; if (!target_supports_btrace (conf->format)) error (_("Target does not support branch tracing.")); DEBUG ("enable thread %d (%s)", tp->num, target_pid_to_str (tp->ptid)); tp->btrace.target = target_enable_btrace (tp->ptid, conf); /* Add an entry for the current PC so we start tracing from where we enabled it. */ if (tp->btrace.target != NULL) btrace_add_pc (tp); }
static void record_btrace_resume (struct target_ops *ops, ptid_t ptid, int step, enum gdb_signal signal) { struct thread_info *tp, *other; enum btrace_thread_flag flag; DEBUG ("resume %s: %s", target_pid_to_str (ptid), step ? "step" : "cont"); tp = record_btrace_find_resume_thread (ptid); if (tp == NULL) error (_("Cannot find thread to resume.")); /* Stop replaying other threads if the thread to resume is not replaying. */ if (!btrace_is_replaying (tp) && execution_direction != EXEC_REVERSE) ALL_THREADS (other) record_btrace_stop_replaying (other); /* As long as we're not replaying, just forward the request. */ if (!record_btrace_is_replaying (ops) && execution_direction != EXEC_REVERSE) { for (ops = ops->beneath; ops != NULL; ops = ops->beneath) if (ops->to_resume != NULL) return ops->to_resume (ops, ptid, step, signal); error (_("Cannot find target for stepping.")); } /* Compute the btrace thread flag for the requested move. */ if (step == 0) flag = execution_direction == EXEC_REVERSE ? BTHR_RCONT : BTHR_CONT; else flag = execution_direction == EXEC_REVERSE ? BTHR_RSTEP : BTHR_STEP; /* At the moment, we only move a single thread. We could also move all threads in parallel by single-stepping each resumed thread until the first runs into an event. When we do that, we would want to continue all other threads. For now, just resume one thread to not confuse to_wait. */ record_btrace_resume_thread (tp, flag); /* We just indicate the resume intent here. The actual stepping happens in record_btrace_wait below. */ }
static struct btrace_target_info * amd64_linux_enable_btrace (struct target_ops *self, ptid_t ptid) { struct btrace_target_info *tinfo; struct gdbarch *gdbarch; errno = 0; tinfo = linux_enable_btrace (ptid); if (tinfo == NULL) error (_("Could not enable branch tracing for %s: %s."), target_pid_to_str (ptid), safe_strerror (errno)); /* Fill in the size of a pointer in bits. */ gdbarch = target_thread_architecture (ptid); tinfo->ptr_bits = gdbarch_ptr_bit (gdbarch); return tinfo; }
static void record_btrace_info (struct target_ops *self) { struct btrace_thread_info *btinfo; struct thread_info *tp; unsigned int insns, calls; DEBUG ("info"); tp = find_thread_ptid (inferior_ptid); if (tp == NULL) error (_("No thread.")); btrace_fetch (tp); insns = 0; calls = 0; btinfo = &tp->btrace; if (!btrace_is_empty (tp)) { struct btrace_call_iterator call; struct btrace_insn_iterator insn; btrace_call_end (&call, btinfo); btrace_call_prev (&call, 1); calls = btrace_call_number (&call); btrace_insn_end (&insn, btinfo); btrace_insn_prev (&insn, 1); insns = btrace_insn_number (&insn); } printf_unfiltered (_("Recorded %u instructions in %u functions for thread " "%d (%s).\n"), insns, calls, tp->num, target_pid_to_str (tp->ptid)); if (btrace_is_replaying (tp)) printf_unfiltered (_("Replay in progress. At instruction %u.\n"), btrace_insn_number (btinfo->replay)); }
static void child_detach (char *args, int from_tty) { int siggnal = 0; int pid = PIDGET (inferior_ptid); if (from_tty) { char *exec_file = get_exec_file (0); if (exec_file == 0) exec_file = ""; printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file, target_pid_to_str (pid_to_ptid (pid))); gdb_flush (gdb_stdout); } if (args) siggnal = atoi (args); detach (siggnal); inferior_ptid = null_ptid; unpush_target (&deprecated_child_ops); }
static void record_btrace_info (void) { struct btrace_thread_info *btinfo; struct thread_info *tp; unsigned int insts, funcs; DEBUG ("info"); tp = find_thread_ptid (inferior_ptid); if (tp == NULL) error (_("No thread.")); btrace_fetch (tp); btinfo = &tp->btrace; insts = VEC_length (btrace_inst_s, btinfo->itrace); funcs = VEC_length (btrace_func_s, btinfo->ftrace); printf_unfiltered (_("Recorded %u instructions in %u functions for thread " "%d (%s).\n"), insts, funcs, tp->num, target_pid_to_str (tp->ptid)); }
static void detach_thread (ptid_t ptid, int verbose) { if (verbose) printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid)); }
/* Store at least register REGNO, or all regs if REGNO == -1. */ static void gnu_store_registers (struct target_ops *ops, struct regcache *regcache, int regno) { struct proc *thread; struct gdbarch *gdbarch = get_regcache_arch (regcache); /* Make sure we know about new threads. */ inf_update_procs (gnu_current_inf); thread = inf_tid_to_thread (gnu_current_inf, ptid_get_tid (inferior_ptid)); if (!thread) error (_("Couldn't store registers into thread %s: No such thread"), target_pid_to_str (inferior_ptid)); if (regno < I386_NUM_GREGS || regno == -1) { thread_state_t state; thread_state_data_t old_state; int was_aborted = thread->aborted; int was_valid = thread->state_valid; int trace; if (!was_aborted && was_valid) memcpy (&old_state, &thread->state, sizeof (old_state)); state = proc_get_state (thread, 1); if (!state) { warning (_("Couldn't store registers into %s"), proc_string (thread)); return; } /* Save the T bit. We might try to restore the %eflags register below, but changing the T bit would seriously confuse GDB. */ trace = ((struct i386_thread_state *)state)->efl & 0x100; if (!was_aborted && was_valid) /* See which registers have changed after aborting the thread. */ { int check_regno; for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++) if ((thread->fetched_regs & (1 << check_regno)) && memcpy (REG_ADDR (&old_state, check_regno), REG_ADDR (state, check_regno), register_size (gdbarch, check_regno))) /* Register CHECK_REGNO has changed! Ack! */ { warning (_("Register %s changed after the thread was aborted"), gdbarch_register_name (gdbarch, check_regno)); if (regno >= 0 && regno != check_regno) /* Update GDB's copy of the register. */ regcache_raw_supply (regcache, check_regno, REG_ADDR (state, check_regno)); else warning (_("... also writing this register! Suspicious...")); } } if (regno == -1) { int i; proc_debug (thread, "storing all registers"); for (i = 0; i < I386_NUM_GREGS; i++) if (regcache_valid_p (regcache, i)) regcache_raw_collect (regcache, i, REG_ADDR (state, i)); } else { proc_debug (thread, "storing register %s", gdbarch_register_name (gdbarch, regno)); gdb_assert (regcache_valid_p (regcache, regno)); regcache_raw_collect (regcache, regno, REG_ADDR (state, regno)); } /* Restore the T bit. */ ((struct i386_thread_state *)state)->efl &= ~0x100; ((struct i386_thread_state *)state)->efl |= trace; } if (regno >= I386_NUM_GREGS || regno == -1) { proc_debug (thread, "storing floating-point registers"); store_fpregs (regcache, thread, regno); } }
/* Create the status line to display as much information as we can on this single line: target name, process number, current function, current line, current PC, SingleKey mode. */ static char* tui_make_status_line (struct tui_locator_element *loc) { char *string; char line_buf[50], *pname; char *buf; int status_size; int i, proc_width; const char *pid_name; int target_width; int pid_width; int line_width; if (ptid_equal (inferior_ptid, null_ptid)) pid_name = "No process"; else pid_name = target_pid_to_str (inferior_ptid); target_width = strlen (target_shortname); if (target_width > MAX_TARGET_WIDTH) target_width = MAX_TARGET_WIDTH; pid_width = strlen (pid_name); if (pid_width > MAX_PID_WIDTH) pid_width = MAX_PID_WIDTH; status_size = tui_term_width (); string = (char *) xmalloc (status_size + 1); buf = (char*) alloca (status_size + 1); /* Translate line number and obtain its size. */ if (loc->line_no > 0) xsnprintf (line_buf, sizeof (line_buf), "%d", loc->line_no); else strcpy (line_buf, "??"); line_width = strlen (line_buf); if (line_width < MIN_LINE_WIDTH) line_width = MIN_LINE_WIDTH; /* Translate PC address. */ string_file pc_out; fputs_filtered (loc->gdbarch? paddress (loc->gdbarch, loc->addr) : "??", &pc_out); const char *pc_buf = pc_out.c_str (); int pc_width = pc_out.size (); /* First determine the amount of proc name width we have available. The +1 are for a space separator between fields. The -1 are to take into account the \0 counted by sizeof. */ proc_width = (status_size - (target_width + 1) - (pid_width + 1) - (sizeof (PROC_PREFIX) - 1 + 1) - (sizeof (LINE_PREFIX) - 1 + line_width + 1) - (sizeof (PC_PREFIX) - 1 + pc_width + 1) - (tui_current_key_mode == TUI_SINGLE_KEY_MODE ? (sizeof (SINGLE_KEY) - 1 + 1) : 0)); /* If there is no room to print the function name, try by removing some fields. */ if (proc_width < MIN_PROC_WIDTH) { proc_width += target_width + 1; target_width = 0; if (proc_width < MIN_PROC_WIDTH) { proc_width += pid_width + 1; pid_width = 0; if (proc_width <= MIN_PROC_WIDTH) { proc_width += pc_width + sizeof (PC_PREFIX) - 1 + 1; pc_width = 0; if (proc_width < 0) { proc_width += line_width + sizeof (LINE_PREFIX) - 1 + 1; line_width = 0; if (proc_width < 0) proc_width = 0; } } } } /* Now convert elements to string form. */ pname = loc->proc_name; /* Now create the locator line from the string version of the elements. We could use sprintf() here but that wouldn't ensure that we don't overrun the size of the allocated buffer. strcat_to_buf() will. */ *string = (char) 0; if (target_width > 0) { sprintf (buf, "%*.*s ", -target_width, target_width, target_shortname); strcat_to_buf (string, status_size, buf); } if (pid_width > 0) { sprintf (buf, "%*.*s ", -pid_width, pid_width, pid_name); strcat_to_buf (string, status_size, buf); } /* Show whether we are in SingleKey mode. */ if (tui_current_key_mode == TUI_SINGLE_KEY_MODE) { strcat_to_buf (string, status_size, SINGLE_KEY); strcat_to_buf (string, status_size, " "); } /* Procedure/class name. */ if (proc_width > 0) { if (strlen (pname) > proc_width) sprintf (buf, "%s%*.*s* ", PROC_PREFIX, 1 - proc_width, proc_width - 1, pname); else sprintf (buf, "%s%*.*s ", PROC_PREFIX, -proc_width, proc_width, pname); strcat_to_buf (string, status_size, buf); } if (line_width > 0) { sprintf (buf, "%s%*.*s ", LINE_PREFIX, -line_width, line_width, line_buf); strcat_to_buf (string, status_size, buf); } if (pc_width > 0) { strcat_to_buf (string, status_size, PC_PREFIX); strcat_to_buf (string, status_size, pc_buf); } for (i = strlen (string); i < status_size; i++) string[i] = ' '; string[status_size] = (char) 0; return string; }
void inf_ptrace_target::attach (const char *args, int from_tty) { char *exec_file; pid_t pid; struct inferior *inf; /* Do not change either targets above or the same target if already present. The reason is the target stack is shared across multiple inferiors. */ int ops_already_pushed = target_is_pushed (this); pid = parse_pid_to_attach (args); if (pid == getpid ()) /* Trying to m********e? */ error (_("I refuse to debug myself!")); target_unpush_up unpusher; if (! ops_already_pushed) { /* target_pid_to_str already uses the target. Also clear possible core file with its process_stratum. */ push_target (this); unpusher.reset (this); } if (from_tty) { exec_file = get_exec_file (0); if (exec_file) printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file, target_pid_to_str (ptid_t (pid))); else printf_unfiltered (_("Attaching to %s\n"), target_pid_to_str (ptid_t (pid))); gdb_flush (gdb_stdout); } #ifdef PT_ATTACH errno = 0; ptrace (PT_ATTACH, pid, (PTRACE_TYPE_ARG3)0, 0); if (errno != 0) perror_with_name (("ptrace")); #else error (_("This system does not support attaching to a process")); #endif inf = current_inferior (); inferior_appeared (inf, pid); inf->attach_flag = 1; inferior_ptid = ptid_t (pid); /* Always add a main thread. If some target extends the ptrace target, it should decorate the ptid later with more info. */ thread_info *thr = add_thread_silent (inferior_ptid); /* Don't consider the thread stopped until we've processed its initial SIGSTOP stop. */ set_executing (thr->ptid, true); unpusher.release (); }