static void linux_resume_one_lwp (struct lwp_info *lwp,
int step, int signal, siginfo_t *info);
-static void stop_all_lwps (int suspend, struct lwp_info *except);
-static void unstop_all_lwps (int unsuspend, struct lwp_info *except);
static void unsuspend_all_lwps (struct lwp_info *except);
-static int linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
- int *wstat, int options);
-static int linux_wait_for_event (ptid_t ptid, int *wstat, int options);
static struct lwp_info *add_lwp (ptid_t ptid);
static void mark_lwp_dead (struct lwp_info *lwp, int wstat);
static int lwp_is_marked_dead (struct lwp_info *lwp);
-static void proceed_all_lwps (void);
static int finish_step_over (struct lwp_info *lwp);
static int kill_lwp (unsigned long lwpid, int signo);
static void enqueue_pending_signal (struct lwp_info *lwp, int signal, siginfo_t *info);
-static void complete_ongoing_step_over (void);
static int linux_low_ptrace_options (int attached);
static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp);
static void proceed_one_lwp (thread_info *thread, lwp_info *except);
#define target_is_async_p() (linux_event_pipe[0] != -1)
static void send_sigstop (struct lwp_info *lwp);
-static void wait_for_sigstop (void);
/* Return non-zero if HEADER is a 64-bit ELF file. */
current_thread = saved_thread;
}
-/* Handle a GNU/Linux extended wait response. If we see a clone,
- fork, or vfork event, we need to add the new LWP to our list
- (and return 0 so as not to report the trap to higher layers).
- If we see an exec event, we will modify ORIG_EVENT_LWP to point
- to a new LWP representing the new program. */
-
-static int
-handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
+int
+linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp,
+ int wstat)
{
client_state &cs = get_client_state ();
struct lwp_info *event_lwp = *orig_event_lwp;
syscalls_to_catch = std::move (proc->syscalls_to_catch);
/* Delete the execing process and all its threads. */
- the_target->mourn (proc);
+ mourn (proc);
current_thread = NULL;
/* Create a new process/lwp/thread. */
int wstat, lwpid;
ptid_t pid_ptid = ptid_t (pid);
- lwpid = linux_wait_for_event_filtered (pid_ptid, pid_ptid,
- &wstat, __WALL);
+ lwpid = wait_for_event_filtered (pid_ptid, pid_ptid, &wstat, __WALL);
gdb_assert (lwpid > 0);
lwp = find_lwp_pid (ptid_t (lwpid));
- The loop is most likely unnecessary.
- - We don't use linux_wait_for_event as that could delete lwps
+ - We don't use wait_for_event as that could delete lwps
while we're iterating over them. We're not interested in
any pending status at this point, only in making sure all
wait status on the kernel side are collected until the
return fast_tracepoint_collecting (thread_area, lwp->stop_pc, status);
}
-/* The reason we resume in the caller, is because we want to be able
- to pass lwp->status_pending as WSTAT, and we need to clear
- status_pending_p before resuming, otherwise, linux_resume_one_lwp
- refuses to resume. */
-
-static int
-maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat)
+bool
+linux_process_target::maybe_move_out_of_jump_pad (lwp_info *lwp, int *wstat)
{
struct thread_info *saved_thread;
lwpid_of (current_thread));
current_thread = saved_thread;
- return 1;
+ return true;
}
}
else
lwpid_of (current_thread));
current_thread = saved_thread;
- return 0;
+ return false;
}
/* Enqueue one signal in the "signals to report later when out of the
return options;
}
-/* Do low-level handling of the event, and check if we should go on
- and pass it to caller code. Return the affected lwp if we are, or
- NULL otherwise. */
-
-static struct lwp_info *
-linux_low_filter_event (int lwpid, int wstat)
+lwp_info *
+linux_process_target::filter_event (int lwpid, int wstat)
{
client_state &cs = get_client_state ();
struct lwp_info *child;
}
}
-/* Wait for an event from child(ren) WAIT_PTID, and return any that
- match FILTER_PTID (leaving others pending). The PTIDs can be:
- minus_one_ptid, to specify any child; a pid PTID, specifying all
- lwps of a thread group; or a PTID representing a single lwp. Store
- the stop status through the status pointer WSTAT. OPTIONS is
- passed to the waitpid call. Return 0 if no event was found and
- OPTIONS contains WNOHANG. Return -1 if no unwaited-for children
- was found. Return the PID of the stopped child otherwise. */
-
-static int
-linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
- int *wstatp, int options)
+int
+linux_process_target::wait_for_event_filtered (ptid_t wait_ptid,
+ ptid_t filter_ptid,
+ int *wstatp, int options)
{
struct thread_info *event_thread;
struct lwp_info *event_child, *requested_child;
/* Filter all events. IOW, leave all events pending. We'll
randomly select an event LWP out of all that have events
below. */
- linux_low_filter_event (ret, *wstatp);
+ filter_event (ret, *wstatp);
/* Retry until nothing comes out of waitpid. A single
SIGCHLD can indicate more than one child stopped. */
continue;
return lwpid_of (event_thread);
}
-/* Wait for an event from child(ren) PTID. PTIDs can be:
- minus_one_ptid, to specify any child; a pid PTID, specifying all
- lwps of a thread group; or a PTID representing a single lwp. Store
- the stop status through the status pointer WSTAT. OPTIONS is
- passed to the waitpid call. Return 0 if no event was found and
- OPTIONS contains WNOHANG. Return -1 if no unwaited-for children
- was found. Return the PID of the stopped child otherwise. */
-
-static int
-linux_wait_for_event (ptid_t ptid, int *wstatp, int options)
+int
+linux_process_target::wait_for_event (ptid_t ptid, int *wstatp, int options)
{
- return linux_wait_for_event_filtered (ptid, ptid, wstatp, options);
+ return wait_for_event_filtered (ptid, ptid, wstatp, options);
}
/* Select one LWP out of those that have events pending. */
});
}
-static void move_out_of_jump_pad_callback (thread_info *thread);
static bool stuck_in_jump_pad_callback (thread_info *thread);
static bool lwp_running (thread_info *thread);
-static ptid_t linux_wait_1 (ptid_t ptid,
- struct target_waitstatus *ourstatus,
- int target_options);
/* Stabilize threads (move out of jump pads).
stabilizing_threads = 1;
/* Kick 'em all. */
- for_each_thread (move_out_of_jump_pad_callback);
+ for_each_thread ([this] (thread_info *thread)
+ {
+ move_out_of_jump_pad (thread);
+ });
/* Loop until all are stopped out of the jump pads. */
while (find_thread (lwp_running) != NULL)
/* Note that we go through the full wait even loop. While
moving threads out of jump pad, we need to be able to step
over internal breakpoints and such. */
- linux_wait_1 (minus_one_ptid, &ourstatus, 0);
+ wait_1 (minus_one_ptid, &ourstatus, 0);
if (ourstatus.kind == TARGET_WAITKIND_STOPPED)
{
return 0;
}
-/* Wait for process, returns status. */
-
-static ptid_t
-linux_wait_1 (ptid_t ptid,
- struct target_waitstatus *ourstatus, int target_options)
+ptid_t
+linux_process_target::wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
+ int target_options)
{
client_state &cs = get_client_state ();
int w;
if (debug_threads)
{
debug_enter ();
- debug_printf ("linux_wait_1: [%s]\n", target_pid_to_str (ptid));
+ debug_printf ("wait_1: [%s]\n", target_pid_to_str (ptid));
}
/* Translate generic target options into linux options. */
any_resumed = 0;
if (step_over_bkpt == null_ptid)
- pid = linux_wait_for_event (ptid, &w, options);
+ pid = wait_for_event (ptid, &w, options);
else
{
if (debug_threads)
debug_printf ("step_over_bkpt set [%s], doing a blocking wait\n",
target_pid_to_str (step_over_bkpt));
- pid = linux_wait_for_event (step_over_bkpt, &w, options & ~WNOHANG);
+ pid = wait_for_event (step_over_bkpt, &w, options & ~WNOHANG);
}
if (pid == 0 || (pid == -1 && !any_resumed))
if (debug_threads)
{
- debug_printf ("linux_wait_1 ret = null_ptid, "
+ debug_printf ("wait_1 ret = null_ptid, "
"TARGET_WAITKIND_IGNORE\n");
debug_exit ();
}
{
if (debug_threads)
{
- debug_printf ("linux_wait_1 ret = null_ptid, "
+ debug_printf ("wait_1 ret = null_ptid, "
"TARGET_WAITKIND_NO_RESUMED\n");
debug_exit ();
}
event_child = get_thread_lwp (current_thread);
- /* linux_wait_for_event only returns an exit status for the last
+ /* wait_for_event only returns an exit status for the last
child of a process. Report it. */
if (WIFEXITED (w) || WIFSIGNALED (w))
{
if (debug_threads)
{
- debug_printf ("linux_wait_1 ret = %s, exited with "
+ debug_printf ("wait_1 ret = %s, exited with "
"retcode %d\n",
target_pid_to_str (ptid_of (current_thread)),
WEXITSTATUS (w));
if (debug_threads)
{
- debug_printf ("linux_wait_1 ret = %s, terminated with "
+ debug_printf ("wait_1 ret = %s, terminated with "
"signal %d\n",
target_pid_to_str (ptid_of (current_thread)),
WTERMSIG (w));
int breakpoint_kind = 0;
CORE_ADDR stop_pc = event_child->stop_pc;
- breakpoint_kind =
- the_target->breakpoint_kind_from_current_state (&stop_pc);
- the_target->sw_breakpoint_from_kind (breakpoint_kind, &increment_pc);
+ breakpoint_kind = breakpoint_kind_from_current_state (&stop_pc);
+ sw_breakpoint_from_kind (breakpoint_kind, &increment_pc);
if (debug_threads)
{
if (debug_threads)
{
- debug_printf ("linux_wait_1 ret = %s, stopped "
+ debug_printf ("wait_1 ret = %s, stopped "
"while stabilizing threads\n",
target_pid_to_str (ptid_of (current_thread)));
debug_exit ();
if (debug_threads)
{
- debug_printf ("linux_wait_1 ret = %s, %d, %d\n",
+ debug_printf ("wait_1 ret = %s, %d, %d\n",
target_pid_to_str (ptid_of (current_thread)),
ourstatus->kind, ourstatus->value.sig);
debug_exit ();
do
{
- event_ptid = linux_wait_1 (ptid, ourstatus, target_options);
+ event_ptid = wait_1 (ptid, ourstatus, target_options);
}
while ((target_options & TARGET_WNOHANG) == 0
&& event_ptid == null_ptid
|| WIFSIGNALED (lwp->status_pending)));
}
-/* Wait for all children to stop for the SIGSTOPs we just queued. */
-
-static void
-wait_for_sigstop (void)
+void
+linux_process_target::wait_for_sigstop ()
{
struct thread_info *saved_thread;
ptid_t saved_tid;
/* Passing NULL_PTID as filter indicates we want all events to be
left pending. Eventually this returns when there are no
unwaited-for children left. */
- ret = linux_wait_for_event_filtered (minus_one_ptid, null_ptid,
- &wstat, __WALL);
+ ret = wait_for_event_filtered (minus_one_ptid, null_ptid, &wstat, __WALL);
gdb_assert (ret == -1);
if (saved_thread == NULL || mythread_alive (saved_tid))
!= fast_tpoint_collect_result::not_collecting));
}
-static void
-move_out_of_jump_pad_callback (thread_info *thread)
+void
+linux_process_target::move_out_of_jump_pad (thread_info *thread)
{
struct thread_info *saved_thread;
struct lwp_info *lwp = get_thread_lwp (thread);
return !lwp->stopped;
}
-/* Stop all lwps that aren't stopped yet, except EXCEPT, if not NULL.
- If SUSPEND, then also increase the suspend count of every LWP,
- except EXCEPT. */
-
-static void
-stop_all_lwps (int suspend, struct lwp_info *except)
+void
+linux_process_target::stop_all_lwps (int suspend, lwp_info *except)
{
/* Should not be called recursively. */
gdb_assert (stopping_threads == NOT_STOPPING_THREADS);
return false;
}
-/* Start a step-over operation on LWP. When LWP stopped at a
- breakpoint, to make progress, we need to remove the breakpoint out
- of the way. If we let other threads run while we do that, they may
- pass by the breakpoint location and miss hitting it. To avoid
- that, a step-over momentarily stops all threads while LWP is
- single-stepped by either hardware or software while the breakpoint
- is temporarily uninserted from the inferior. When the single-step
- finishes, we reinsert the breakpoint, and let all threads that are
- supposed to be running, run again. */
-
-static int
-start_step_over (struct lwp_info *lwp)
+void
+linux_process_target::start_step_over (lwp_info *lwp)
{
struct thread_info *thread = get_lwp_thread (lwp);
struct thread_info *saved_thread;
/* Require next event from this LWP. */
step_over_bkpt = thread->id;
- return 1;
}
/* Finish a step-over. Reinsert the breakpoint we had uninserted in
return 0;
}
-/* If there's a step over in progress, wait until all threads stop
- (that is, until the stepping thread finishes its step), and
- unsuspend all lwps. The stepping thread ends with its status
- pending, which is processed later when we get back to processing
- events. */
-
-static void
-complete_ongoing_step_over (void)
+void
+linux_process_target::complete_ongoing_step_over ()
{
if (step_over_bkpt != null_ptid)
{
/* Passing NULL_PTID as filter indicates we want all events to
be left pending. Eventually this returns when there are no
unwaited-for children left. */
- ret = linux_wait_for_event_filtered (minus_one_ptid, null_ptid,
- &wstat, __WALL);
+ ret = wait_for_event_filtered (minus_one_ptid, null_ptid, &wstat,
+ __WALL);
gdb_assert (ret == -1);
lwp = find_lwp_pid (step_over_bkpt);
proceed_one_lwp (thread, except);
}
-/* When we finish a step-over, set threads running again. If there's
- another thread that may need a step-over, now's the time to start
- it. Eventually, we'll move all threads past their breakpoints. */
-
-static void
-proceed_all_lwps (void)
+void
+linux_process_target::proceed_all_lwps ()
{
struct thread_info *need_step_over;
});
}
-/* Stopped LWPs that the client wanted to be running, that don't have
- pending statuses, are set to run again, except for EXCEPT, if not
- NULL. This undoes a stop_all_lwps call. */
-
-static void
-unstop_all_lwps (int unsuspend, struct lwp_info *except)
+void
+linux_process_target::unstop_all_lwps (int unsuspend, lwp_info *except)
{
if (debug_threads)
{
bool supports_catch_syscall () override;
int get_ipa_tdesc_idx () override;
+
+private:
+
+ /* Handle a GNU/Linux extended wait response. If we see a clone,
+ fork, or vfork event, we need to add the new LWP to our list
+ (and return 0 so as not to report the trap to higher layers).
+ If we see an exec event, we will modify ORIG_EVENT_LWP to point
+ to a new LWP representing the new program. */
+ int handle_extended_wait (lwp_info **orig_event_lwp, int wstat);
+
+ /* Do low-level handling of the event, and check if we should go on
+ and pass it to caller code. Return the affected lwp if we are, or
+ NULL otherwise. */
+ lwp_info *filter_event (int lwpid, int wstat);
+
+ /* Wait for an event from child(ren) WAIT_PTID, and return any that
+ match FILTER_PTID (leaving others pending). The PTIDs can be:
+ minus_one_ptid, to specify any child; a pid PTID, specifying all
+ lwps of a thread group; or a PTID representing a single lwp. Store
+ the stop status through the status pointer WSTAT. OPTIONS is
+ passed to the waitpid call. Return 0 if no event was found and
+ OPTIONS contains WNOHANG. Return -1 if no unwaited-for children
+ was found. Return the PID of the stopped child otherwise. */
+ int wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
+ int *wstatp, int options);
+
+ /* Wait for an event from child(ren) PTID. PTIDs can be:
+ minus_one_ptid, to specify any child; a pid PTID, specifying all
+ lwps of a thread group; or a PTID representing a single lwp. Store
+ the stop status through the status pointer WSTAT. OPTIONS is
+ passed to the waitpid call. Return 0 if no event was found and
+ OPTIONS contains WNOHANG. Return -1 if no unwaited-for children
+ was found. Return the PID of the stopped child otherwise. */
+ int wait_for_event (ptid_t ptid, int *wstatp, int options);
+
+ /* Wait for all children to stop for the SIGSTOPs we just queued. */
+ void wait_for_sigstop ();
+
+ /* Wait for process, returns status. */
+ ptid_t wait_1 (ptid_t ptid, target_waitstatus *ourstatus,
+ int target_options);
+
+ /* Stop all lwps that aren't stopped yet, except EXCEPT, if not NULL.
+ If SUSPEND, then also increase the suspend count of every LWP,
+ except EXCEPT. */
+ void stop_all_lwps (int suspend, lwp_info *except);
+
+ /* Stopped LWPs that the client wanted to be running, that don't have
+ pending statuses, are set to run again, except for EXCEPT, if not
+ NULL. This undoes a stop_all_lwps call. */
+ void unstop_all_lwps (int unsuspend, lwp_info *except);
+
+ /* Start a step-over operation on LWP. When LWP stopped at a
+ breakpoint, to make progress, we need to remove the breakpoint out
+ of the way. If we let other threads run while we do that, they may
+ pass by the breakpoint location and miss hitting it. To avoid
+ that, a step-over momentarily stops all threads while LWP is
+ single-stepped by either hardware or software while the breakpoint
+ is temporarily uninserted from the inferior. When the single-step
+ finishes, we reinsert the breakpoint, and let all threads that are
+ supposed to be running, run again. */
+ void start_step_over (lwp_info *lwp);
+
+ /* If there's a step over in progress, wait until all threads stop
+ (that is, until the stepping thread finishes its step), and
+ unsuspend all lwps. The stepping thread ends with its status
+ pending, which is processed later when we get back to processing
+ events. */
+ void complete_ongoing_step_over ();
+
+ /* When we finish a step-over, set threads running again. If there's
+ another thread that may need a step-over, now's the time to start
+ it. Eventually, we'll move all threads past their breakpoints. */
+ void proceed_all_lwps ();
+
+ /* The reason we resume in the caller, is because we want to be able
+ to pass lwp->status_pending as WSTAT, and we need to clear
+ status_pending_p before resuming, otherwise, resume_one_lwp
+ refuses to resume. */
+ bool maybe_move_out_of_jump_pad (lwp_info *lwp, int *wstat);
+
+ /* Move THREAD out of the jump pad. */
+ void move_out_of_jump_pad (thread_info *thread);
};
#define get_thread_lwp(thr) ((struct lwp_info *) (thread_target_data (thr)))