From fd000fb3dfd9c93e332246bf89b700ab9aac7339 Mon Sep 17 00:00:00 2001 From: Tankut Baris Aktemur Date: Thu, 2 Apr 2020 15:11:28 +0200 Subject: [PATCH] gdbserver/linux-low: turn process/thread addition/deletion ops into methods gdbserver/ChangeLog: 2020-04-02 Tankut Baris Aktemur Turn the 'new_process', 'delete_process', 'new_thread', 'delete_thread', and 'new_fork' linux target ops into methods of linux_process_target. * linux-low.h (struct linux_target_ops): Remove the ops. (class linux_process_target) : Declare. * linux-low.cc (delete_lwp): Turn into... (linux_process_target::delete_lwp): ...this. (linux_process_target::low_delete_thread): Define. (linux_add_process): Turn into... (linux_process_target::add_linux_process): ...this. (linux_process_target::low_new_process): Define. (linux_process_target::low_delete_process): Define. (linux_process_target::low_new_fork): Define. (add_lwp): Turn into... (linux_process_target::add_lwp): ...this. (linux_process_target::low_new_thread): Define. (linux_attach_lwp): Turn into... (linux_process_target::attach_lwp): ...this. (linux_detach_one_lwp): Turn into... (linux_process_target::detach_one_lwp): ...this. (linux_detach_lwp_callback): Remove and inline... (linux_process_target::detach): ...here. (check_zombie_leaders): Turn into... (linux_process_target::check_zombie_leaders): ...this. (filter_exit_event): Turn into... (linux_process_target::filter_exit_event): ...this. Update the callers below. (linux_process_target::handle_extended_wait) (linux_process_target::create_inferior) (attach_proc_task_lwp_callback) (linux_process_target::attach) (linux_process_target::detach) (linux_process_target::mourn) * thread-db.cc (attach_thread) * linux-x86-low.cc (class x86_target) : Declare. (x86_linux_new_process): Turn into... (x86_target::low_new_process): ...this. (x86_linux_delete_process): Turn into... (x86_target::low_delete_process): ...this. (x86_target::low_new_thread): Define. (x86_target::low_delete_thread): Define. (x86_linux_new_fork): Turn into... (x86_target::low_new_fork): ...this. (the_low_target): Remove the op fields. * linux-aarch64-low.cc (class aarch64_target) : Declare. (aarch64_linux_new_process): Turn into... (aarch64_target::low_new_process): ...this. (aarch64_linux_delete_process): Turn into... (aarch64_target::low_delete_process): ...this. (aarch64_target::low_new_thread): Define. (aarch64_target::low_delete_thread): Define. (aarch64_linux_new_fork): Turn into... (aarch64_target::low_new_fork): ...this. (the_low_target): Remove the op fields. * linux-arm-low.cc (class arm_target) : Declare. (arm_new_process): Turn into... (arm_target::low_new_process): ...this. (arm_delete_process): Turn into... (arm_target::low_delete_process): ...this. (arm_new_thread): Turn into... (arm_target::low_new_thread): ...this. (arm_delete_thread): Turn into... (arm_target::low_delete_thread): ...this. (arm_new_fork): Turn into... (arm_target::low_new_fork): ...this. (the_low_target): Remove the op fields. * linux-mips-low.cc (class mips_target) : Declare. (mips_linux_new_process): Turn into... (mips_target::low_new_process): ...this. (mips_linux_delete_process): Turn into... (mips_target::low_delete_process): ...this. (mips_linux_new_thread): Turn into... (mips_target::low_new_thread): ...this. (mips_linux_delete_thread): Turn into... (mips_target::low_delete_thread): ...this. (mips_linux_new_fork): Turn into... (mips_target::low_new_fork): ...this. (the_low_target): Remove the op fields. * linux-bfin-low.cc (the_low_target): Remove the op fields. * linux-crisv32-low.cc (the_low_target): Ditto. * linux-m32r-low.cc (the_low_target): Ditto. * linux-m68k-low.cc (the_low_target): Ditto. * linux-ppc-low.cc (the_low_target): Ditto. * linux-s390-low.cc (the_low_target): Ditto. * linux-sh-low.cc (the_low_target): Ditto. * linux-tic6x-low.cc (the_low_target): Ditto. * linux-tile-low.cc (the_low_target): Ditto. * linux-xtensa-low.cc (the_low_target): Ditto. --- gdbserver/ChangeLog | 122 ++++++++++++++++++++++++++++ gdbserver/linux-aarch64-low.cc | 47 +++++++---- gdbserver/linux-arm-low.cc | 35 ++++---- gdbserver/linux-bfin-low.cc | 5 -- gdbserver/linux-crisv32-low.cc | 5 -- gdbserver/linux-low.cc | 142 +++++++++++++++++---------------- gdbserver/linux-low.h | 73 ++++++++++++----- gdbserver/linux-m32r-low.cc | 5 -- gdbserver/linux-m68k-low.cc | 5 -- gdbserver/linux-mips-low.cc | 47 ++++++----- gdbserver/linux-ppc-low.cc | 5 -- gdbserver/linux-s390-low.cc | 5 -- gdbserver/linux-sh-low.cc | 5 -- gdbserver/linux-tic6x-low.cc | 5 -- gdbserver/linux-tile-low.cc | 5 -- gdbserver/linux-x86-low.cc | 43 +++++++--- gdbserver/linux-xtensa-low.cc | 5 -- gdbserver/thread-db.cc | 2 +- 18 files changed, 356 insertions(+), 205 deletions(-) diff --git a/gdbserver/ChangeLog b/gdbserver/ChangeLog index 6ca38f07e5..bb17a062c7 100644 --- a/gdbserver/ChangeLog +++ b/gdbserver/ChangeLog @@ -1,3 +1,125 @@ +2020-04-02 Tankut Baris Aktemur + + Turn the 'new_process', 'delete_process', 'new_thread', + 'delete_thread', and 'new_fork' linux target ops into methods + of linux_process_target. + + * linux-low.h (struct linux_target_ops): Remove the ops. + (class linux_process_target) + + + + + + + + + + + : Declare. + * linux-low.cc (delete_lwp): Turn into... + (linux_process_target::delete_lwp): ...this. + (linux_process_target::low_delete_thread): Define. + (linux_add_process): Turn into... + (linux_process_target::add_linux_process): ...this. + (linux_process_target::low_new_process): Define. + (linux_process_target::low_delete_process): Define. + (linux_process_target::low_new_fork): Define. + (add_lwp): Turn into... + (linux_process_target::add_lwp): ...this. + (linux_process_target::low_new_thread): Define. + (linux_attach_lwp): Turn into... + (linux_process_target::attach_lwp): ...this. + (linux_detach_one_lwp): Turn into... + (linux_process_target::detach_one_lwp): ...this. + (linux_detach_lwp_callback): Remove and inline... + (linux_process_target::detach): ...here. + (check_zombie_leaders): Turn into... + (linux_process_target::check_zombie_leaders): ...this. + (filter_exit_event): Turn into... + (linux_process_target::filter_exit_event): ...this. + + Update the callers below. + + (linux_process_target::handle_extended_wait) + (linux_process_target::create_inferior) + (attach_proc_task_lwp_callback) + (linux_process_target::attach) + (linux_process_target::detach) + (linux_process_target::mourn) + * thread-db.cc (attach_thread) + + * linux-x86-low.cc (class x86_target) + + + + : Declare. + (x86_linux_new_process): Turn into... + (x86_target::low_new_process): ...this. + (x86_linux_delete_process): Turn into... + (x86_target::low_delete_process): ...this. + (x86_target::low_new_thread): Define. + (x86_target::low_delete_thread): Define. + (x86_linux_new_fork): Turn into... + (x86_target::low_new_fork): ...this. + (the_low_target): Remove the op fields. + * linux-aarch64-low.cc (class aarch64_target) + + + + : Declare. + (aarch64_linux_new_process): Turn into... + (aarch64_target::low_new_process): ...this. + (aarch64_linux_delete_process): Turn into... + (aarch64_target::low_delete_process): ...this. + (aarch64_target::low_new_thread): Define. + (aarch64_target::low_delete_thread): Define. + (aarch64_linux_new_fork): Turn into... + (aarch64_target::low_new_fork): ...this. + (the_low_target): Remove the op fields. + * linux-arm-low.cc (class arm_target) + + + + : Declare. + (arm_new_process): Turn into... + (arm_target::low_new_process): ...this. + (arm_delete_process): Turn into... + (arm_target::low_delete_process): ...this. + (arm_new_thread): Turn into... + (arm_target::low_new_thread): ...this. + (arm_delete_thread): Turn into... + (arm_target::low_delete_thread): ...this. + (arm_new_fork): Turn into... + (arm_target::low_new_fork): ...this. + (the_low_target): Remove the op fields. + * linux-mips-low.cc (class mips_target) + + + + : Declare. + (mips_linux_new_process): Turn into... + (mips_target::low_new_process): ...this. + (mips_linux_delete_process): Turn into... + (mips_target::low_delete_process): ...this. + (mips_linux_new_thread): Turn into... + (mips_target::low_new_thread): ...this. + (mips_linux_delete_thread): Turn into... + (mips_target::low_delete_thread): ...this. + (mips_linux_new_fork): Turn into... + (mips_target::low_new_fork): ...this. + (the_low_target): Remove the op fields. + * linux-bfin-low.cc (the_low_target): Remove the op fields. + * linux-crisv32-low.cc (the_low_target): Ditto. + * linux-m32r-low.cc (the_low_target): Ditto. + * linux-m68k-low.cc (the_low_target): Ditto. + * linux-ppc-low.cc (the_low_target): Ditto. + * linux-s390-low.cc (the_low_target): Ditto. + * linux-sh-low.cc (the_low_target): Ditto. + * linux-tic6x-low.cc (the_low_target): Ditto. + * linux-tile-low.cc (the_low_target): Ditto. + * linux-xtensa-low.cc (the_low_target): Ditto. + 2020-04-02 Tankut Baris Aktemur Turn the 'siginfo_fixup' linux target op into a method of diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 79c7db92e7..3769e81521 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -93,6 +93,16 @@ protected: bool low_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) override; + + arch_process_info *low_new_process () override; + + void low_delete_process (arch_process_info *info) override; + + void low_new_thread (lwp_info *) override; + + void low_delete_thread (arch_lwp_info *) override; + + void low_new_fork (process_info *parent, process_info *child) override; }; /* The singleton target ops object. */ @@ -518,10 +528,10 @@ aarch64_target::low_siginfo_fixup (siginfo_t *native, gdb_byte *inf, return false; } -/* Implementation of linux_target_ops method "new_process". */ +/* Implementation of linux target ops method "low_new_process". */ -static struct arch_process_info * -aarch64_linux_new_process (void) +arch_process_info * +aarch64_target::low_new_process () { struct arch_process_info *info = XCNEW (struct arch_process_info); @@ -530,19 +540,31 @@ aarch64_linux_new_process (void) return info; } -/* Implementation of linux_target_ops method "delete_process". */ +/* Implementation of linux target ops method "low_delete_process". */ -static void -aarch64_linux_delete_process (struct arch_process_info *info) +void +aarch64_target::low_delete_process (arch_process_info *info) { xfree (info); } -/* Implementation of linux_target_ops method "linux_new_fork". */ +void +aarch64_target::low_new_thread (lwp_info *lwp) +{ + aarch64_linux_new_thread (lwp); +} -static void -aarch64_linux_new_fork (struct process_info *parent, - struct process_info *child) +void +aarch64_target::low_delete_thread (arch_lwp_info *arch_lwp) +{ + aarch64_linux_delete_thread (arch_lwp); +} + +/* Implementation of linux target ops method "low_new_fork". */ + +void +aarch64_target::low_new_fork (process_info *parent, + process_info *child) { /* These are allocated by linux_add_process. */ gdb_assert (parent->priv != NULL @@ -3117,11 +3139,6 @@ aarch64_supports_hardware_single_step (void) struct linux_target_ops the_low_target = { - aarch64_linux_new_process, - aarch64_linux_delete_process, - aarch64_linux_new_thread, - aarch64_linux_delete_thread, - aarch64_linux_new_fork, aarch64_linux_prepare_to_resume, NULL, /* process_qsupported */ aarch64_supports_tracepoints, diff --git a/gdbserver/linux-arm-low.cc b/gdbserver/linux-arm-low.cc index 267899f99e..8ec5bc156f 100644 --- a/gdbserver/linux-arm-low.cc +++ b/gdbserver/linux-arm-low.cc @@ -99,6 +99,16 @@ protected: bool low_stopped_by_watchpoint () override; CORE_ADDR low_stopped_data_address () override; + + arch_process_info *low_new_process () override; + + void low_delete_process (arch_process_info *info) override; + + void low_new_thread (lwp_info *) override; + + void low_delete_thread (arch_lwp_info *) override; + + void low_new_fork (process_info *parent, process_info *child) override; }; /* The singleton target ops object. */ @@ -719,8 +729,8 @@ arm_target::low_stopped_data_address () } /* Called when a new process is created. */ -static struct arch_process_info * -arm_new_process (void) +arch_process_info * +arm_target::low_new_process () { struct arch_process_info *info = XCNEW (struct arch_process_info); return info; @@ -728,15 +738,15 @@ arm_new_process (void) /* Called when a process is being deleted. */ -static void -arm_delete_process (struct arch_process_info *info) +void +arm_target::low_delete_process (arch_process_info *info) { xfree (info); } /* Called when a new thread is detected. */ -static void -arm_new_thread (struct lwp_info *lwp) +void +arm_target::low_new_thread (lwp_info *lwp) { struct arch_lwp_info *info = XCNEW (struct arch_lwp_info); int i; @@ -751,14 +761,14 @@ arm_new_thread (struct lwp_info *lwp) /* Function to call when a thread is being deleted. */ -static void -arm_delete_thread (struct arch_lwp_info *arch_lwp) +void +arm_target::low_delete_thread (arch_lwp_info *arch_lwp) { xfree (arch_lwp); } -static void -arm_new_fork (struct process_info *parent, struct process_info *child) +void +arm_target::low_new_fork (process_info *parent, process_info *child) { struct arch_process_info *parent_proc_info; struct arch_process_info *child_proc_info; @@ -1105,11 +1115,6 @@ arm_target::get_regs_info () } struct linux_target_ops the_low_target = { - arm_new_process, - arm_delete_process, - arm_new_thread, - arm_delete_thread, - arm_new_fork, arm_prepare_to_resume, NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/linux-bfin-low.cc b/gdbserver/linux-bfin-low.cc index 6beb61ff3d..c8e9d33f17 100644 --- a/gdbserver/linux-bfin-low.cc +++ b/gdbserver/linux-bfin-low.cc @@ -171,11 +171,6 @@ bfin_target::get_regs_info () } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/linux-crisv32-low.cc b/gdbserver/linux-crisv32-low.cc index a7f8b48079..e87873e8b2 100644 --- a/gdbserver/linux-crisv32-low.cc +++ b/gdbserver/linux-crisv32-low.cc @@ -468,11 +468,6 @@ crisv32_target::get_regs_info () } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/linux-low.cc b/gdbserver/linux-low.cc index 755c3e00a9..019b123103 100644 --- a/gdbserver/linux-low.cc +++ b/gdbserver/linux-low.cc @@ -268,7 +268,6 @@ int using_threads = 1; static int stabilizing_threads; static void unsuspend_all_lwps (struct lwp_info *except); -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 int finish_step_over (struct lwp_info *lwp); @@ -413,8 +412,8 @@ linux_pid_exe_is_elf_64_file (int pid, unsigned int *machine) return elf_64_file_p (file, machine); } -static void -delete_lwp (struct lwp_info *lwp) +void +linux_process_target::delete_lwp (lwp_info *lwp) { struct thread_info *thr = get_lwp_thread (lwp); @@ -423,31 +422,52 @@ delete_lwp (struct lwp_info *lwp) remove_thread (thr); - if (the_low_target.delete_thread != NULL) - the_low_target.delete_thread (lwp->arch_private); - else - gdb_assert (lwp->arch_private == NULL); + low_delete_thread (lwp->arch_private); free (lwp); } -/* Add a process to the common process list, and set its private - data. */ +void +linux_process_target::low_delete_thread (arch_lwp_info *info) +{ + /* Default implementation should be overridden if architecture-specific + info is being used. */ + gdb_assert (info == nullptr); +} -static struct process_info * -linux_add_process (int pid, int attached) +process_info * +linux_process_target::add_linux_process (int pid, int attached) { struct process_info *proc; proc = add_process (pid, attached); proc->priv = XCNEW (struct process_info_private); - if (the_low_target.new_process != NULL) - proc->priv->arch_private = the_low_target.new_process (); + proc->priv->arch_private = low_new_process (); return proc; } +arch_process_info * +linux_process_target::low_new_process () +{ + return nullptr; +} + +void +linux_process_target::low_delete_process (arch_process_info *info) +{ + /* Default implementation must be overridden if architecture-specific + info exists. */ + gdb_assert (info == nullptr); +} + +void +linux_process_target::low_new_fork (process_info *parent, process_info *child) +{ + /* Nop. */ +} + void linux_process_target::arch_setup_thread (thread_info *thread) { @@ -528,7 +548,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, will be detached, since we will need the process object and the breakpoints to remove any breakpoints from memory when we detach, and the client side will access registers. */ - child_proc = linux_add_process (new_pid, 0); + child_proc = add_linux_process (new_pid, 0); gdb_assert (child_proc != NULL); child_lwp = add_lwp (ptid); gdb_assert (child_lwp != NULL); @@ -572,8 +592,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, child_proc->tdesc = tdesc; /* Clone arch-specific process data. */ - if (the_low_target.new_fork != NULL) - the_low_target.new_fork (parent_proc, child_proc); + low_new_fork (parent_proc, child_proc); /* Save fork info in the parent thread. */ if (event == PTRACE_EVENT_FORK) @@ -700,7 +719,7 @@ linux_process_target::handle_extended_wait (lwp_info **orig_event_lwp, current_thread = NULL; /* Create a new process/lwp/thread. */ - proc = linux_add_process (event_pid, 0); + proc = add_linux_process (event_pid, 0); event_lwp = add_lwp (event_ptid); event_thr = get_lwp_thread (event_lwp); gdb_assert (current_thread == event_thr); @@ -921,8 +940,8 @@ linux_process_target::save_stop_reason (lwp_info *lwp) return true; } -static struct lwp_info * -add_lwp (ptid_t ptid) +lwp_info * +linux_process_target::add_lwp (ptid_t ptid) { struct lwp_info *lwp; @@ -932,12 +951,17 @@ add_lwp (ptid_t ptid) lwp->thread = add_thread (ptid, lwp); - if (the_low_target.new_thread != NULL) - the_low_target.new_thread (lwp); + low_new_thread (lwp); return lwp; } +void +linux_process_target::low_new_thread (lwp_info *info) +{ + /* Nop. */ +} + /* Callback to be used when calling fork_inferior, responsible for actually initiating the tracing of the inferior. */ @@ -994,7 +1018,7 @@ linux_process_target::create_inferior (const char *program, NULL, NULL, NULL, NULL); } - linux_add_process (pid, 0); + add_linux_process (pid, 0); ptid = ptid_t (pid, pid, 0); new_lwp = add_lwp (ptid); @@ -1024,11 +1048,8 @@ linux_process_target::post_create_inferior () } } -/* Attach to an inferior process. Returns 0 on success, ERRNO on - error. */ - int -linux_attach_lwp (ptid_t ptid) +linux_process_target::attach_lwp (ptid_t ptid) { struct lwp_info *new_lwp; int lwpid = ptid.lwp (); @@ -1125,7 +1146,7 @@ attach_proc_task_lwp_callback (ptid_t ptid) if (debug_threads) debug_printf ("Found new lwp %d\n", lwpid); - err = linux_attach_lwp (ptid); + err = the_linux_target->attach_lwp (ptid); /* Be quiet if we simply raced with the thread exiting. EPERM is returned if the thread's task still exists, and is marked @@ -1167,11 +1188,11 @@ linux_process_target::attach (unsigned long pid) ptid_t ptid = ptid_t (pid, pid, 0); int err; - proc = linux_add_process (pid, 1); + proc = add_linux_process (pid, 1); /* Attach to PID. We will check for other threads soon. */ - err = linux_attach_lwp (ptid); + err = attach_lwp (ptid); if (err != 0) { remove_process (proc); @@ -1479,10 +1500,8 @@ get_detach_signal (struct thread_info *thread) } } -/* Detach from LWP. */ - -static void -linux_detach_one_lwp (struct lwp_info *lwp) +void +linux_process_target::detach_one_lwp (lwp_info *lwp) { struct thread_info *thread = get_lwp_thread (lwp); int sig; @@ -1564,22 +1583,6 @@ linux_detach_one_lwp (struct lwp_info *lwp) delete_lwp (lwp); } -/* Callback for for_each_thread. Detaches from non-leader threads of a - given process. */ - -static void -linux_detach_lwp_callback (thread_info *thread) -{ - /* We don't actually detach from the thread group leader just yet. - If the thread group exits, we must reap the zombie clone lwps - before we're able to reap the leader. */ - if (thread->id.pid () == thread->id.lwp ()) - return; - - lwp_info *lwp = get_thread_lwp (thread); - linux_detach_one_lwp (lwp); -} - int linux_process_target::detach (process_info *process) { @@ -1606,10 +1609,20 @@ linux_process_target::detach (process_info *process) /* Detach from the clone lwps first. If the thread group exits just while we're detaching, we must reap the clone lwps before we're able to reap the leader. */ - for_each_thread (process->pid, linux_detach_lwp_callback); + for_each_thread (process->pid, [this] (thread_info *thread) + { + /* We don't actually detach from the thread group leader just yet. + If the thread group exits, we must reap the zombie clone lwps + before we're able to reap the leader. */ + if (thread->id.pid () == thread->id.lwp ()) + return; + + lwp_info *lwp = get_thread_lwp (thread); + detach_one_lwp (lwp); + }); main_lwp = find_lwp_pid (ptid_t (process->pid)); - linux_detach_one_lwp (main_lwp); + detach_one_lwp (main_lwp); mourn (process); @@ -1630,17 +1643,14 @@ linux_process_target::mourn (process_info *process) thread_db_mourn (process); #endif - for_each_thread (process->pid, [] (thread_info *thread) + for_each_thread (process->pid, [this] (thread_info *thread) { delete_lwp (get_thread_lwp (thread)); }); /* Freeing all private data. */ priv = process->priv; - if (the_low_target.delete_process != NULL) - the_low_target.delete_process (priv->arch_private); - else - gdb_assert (priv->arch_private == NULL); + low_delete_process (priv->arch_private); free (priv); process->priv = NULL; @@ -1832,13 +1842,10 @@ iterate_over_lwps (ptid_t filter, return get_thread_lwp (thread); } -/* Detect zombie thread group leaders, and "exit" them. We can't reap - their exits until all other threads in the group have exited. */ - -static void -check_zombie_leaders (void) +void +linux_process_target::check_zombie_leaders () { - for_each_process ([] (process_info *proc) { + for_each_process ([this] (process_info *proc) { pid_t leader_pid = pid_of (proc); struct lwp_info *leader_lp; @@ -2943,14 +2950,9 @@ ignore_event (struct target_waitstatus *ourstatus) return null_ptid; } -/* Convenience function that is called when the kernel reports an exit - event. This decides whether to report the event to GDB as a - process exit event, a thread exit event, or to suppress the - event. */ - -static ptid_t -filter_exit_event (struct lwp_info *event_child, - struct target_waitstatus *ourstatus) +ptid_t +linux_process_target::filter_exit_event (lwp_info *event_child, + target_waitstatus *ourstatus) { client_state &cs = get_client_state (); struct thread_info *thread = get_lwp_thread (event_child); diff --git a/gdbserver/linux-low.h b/gdbserver/linux-low.h index 599aead066..f111945cf9 100644 --- a/gdbserver/linux-low.h +++ b/gdbserver/linux-low.h @@ -131,27 +131,6 @@ struct lwp_info; struct linux_target_ops { - /* Hook to call when a new process is created or attached to. - If extra per-process architecture-specific data is needed, - allocate it here. */ - struct arch_process_info * (*new_process) (void); - - /* Hook to call when a process is being deleted. If extra per-process - architecture-specific data is needed, delete it here. */ - void (*delete_process) (struct arch_process_info *info); - - /* Hook to call when a new thread is detected. - If extra per-thread architecture-specific data is needed, - allocate it here. */ - void (*new_thread) (struct lwp_info *); - - /* Hook to call when a thread is being deleted. If extra per-thread - architecture-specific data is needed, delete it here. */ - void (*delete_thread) (struct arch_lwp_info *); - - /* Hook to call, if any, when a new fork is attached. */ - void (*new_fork) (struct process_info *parent, struct process_info *child); - /* Hook to call prior to resuming a thread. */ void (*prepare_to_resume) (struct lwp_info *); @@ -627,6 +606,37 @@ private: void siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction); + /* Add a process to the common process list, and set its private + data. */ + process_info *add_linux_process (int pid, int attached); + + /* Add a new thread. */ + lwp_info *add_lwp (ptid_t ptid); + + /* Delete a thread. */ + void delete_lwp (lwp_info *lwp); + +public: /* Make this public because it's used from outside. */ + /* Attach to an inferior process. Returns 0 on success, ERRNO on + error. */ + int attach_lwp (ptid_t ptid); + +private: /* Back to private. */ + /* Detach from LWP. */ + void detach_one_lwp (lwp_info *lwp); + + /* Detect zombie thread group leaders, and "exit" them. We can't + reap their exits until all other threads in the group have + exited. */ + void check_zombie_leaders (); + + /* Convenience function that is called when the kernel reports an exit + event. This decides whether to report the event to GDB as a + process exit event, a thread exit event, or to suppress the + event. */ + ptid_t filter_exit_event (lwp_info *event_child, + target_waitstatus *ourstatus); + protected: /* The architecture-specific "low" methods are listed below. */ @@ -689,6 +699,27 @@ protected: virtual bool low_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction); + /* Hook to call when a new process is created or attached to. + If extra per-process architecture-specific data is needed, + allocate it here. */ + virtual arch_process_info *low_new_process (); + + /* Hook to call when a process is being deleted. If extra per-process + architecture-specific data is needed, delete it here. */ + virtual void low_delete_process (arch_process_info *info); + + /* Hook to call when a new thread is detected. + If extra per-thread architecture-specific data is needed, + allocate it here. */ + virtual void low_new_thread (lwp_info *); + + /* Hook to call when a thread is being deleted. If extra per-thread + architecture-specific data is needed, delete it here. */ + virtual void low_delete_thread (arch_lwp_info *); + + /* Hook to call, if any, when a new fork is attached. */ + virtual void low_new_fork (process_info *parent, process_info *child); + /* How many bytes the PC should be decremented after a break. */ virtual int low_decr_pc_after_break (); }; diff --git a/gdbserver/linux-m32r-low.cc b/gdbserver/linux-m32r-low.cc index f42cb2792b..4d335c70ed 100644 --- a/gdbserver/linux-m32r-low.cc +++ b/gdbserver/linux-m32r-low.cc @@ -161,11 +161,6 @@ m32r_target::get_regs_info () } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/linux-m68k-low.cc b/gdbserver/linux-m68k-low.cc index bc0f37b52e..2076f0dc8b 100644 --- a/gdbserver/linux-m68k-low.cc +++ b/gdbserver/linux-m68k-low.cc @@ -265,11 +265,6 @@ m68k_supports_hardware_single_step (void) } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/linux-mips-low.cc b/gdbserver/linux-mips-low.cc index b7098a72c6..c77834ebc9 100644 --- a/gdbserver/linux-mips-low.cc +++ b/gdbserver/linux-mips-low.cc @@ -70,6 +70,16 @@ protected: void low_supply_ptrace_register (regcache *regcache, int regno, const char *buf) override; + + arch_process_info *low_new_process () override; + + void low_delete_process (arch_process_info *info) override; + + void low_new_thread (lwp_info *) override; + + void low_delete_thread (arch_lwp_info *) override; + + void low_new_fork (process_info *parent, process_info *child) override; }; /* The singleton target ops object. */ @@ -377,32 +387,32 @@ update_watch_registers_callback (thread_info *thread) linux_stop_lwp (lwp); } -/* This is the implementation of linux_target_ops method - new_process. */ +/* This is the implementation of linux target ops method + low_new_process. */ -static struct arch_process_info * -mips_linux_new_process (void) +arch_process_info * +mips_target::low_new_process () { struct arch_process_info *info = XCNEW (struct arch_process_info); return info; } -/* This is the implementation of linux_target_ops method - delete_process. */ +/* This is the implementation of linux target ops method + low_delete_process. */ -static void -mips_linux_delete_process (struct arch_process_info *info) +void +mips_target::low_delete_process (arch_process_info *info) { xfree (info); } -/* This is the implementation of linux_target_ops method new_thread. +/* This is the implementation of linux target ops method low_new_thread. Mark the watch registers as changed, so the threads' copies will be updated. */ -static void -mips_linux_new_thread (struct lwp_info *lwp) +void +mips_target::low_new_thread (lwp_info *lwp) { struct arch_lwp_info *info = XCNEW (struct arch_lwp_info); @@ -413,8 +423,8 @@ mips_linux_new_thread (struct lwp_info *lwp) /* Function to call when a thread is being deleted. */ -static void -mips_linux_delete_thread (struct arch_lwp_info *arch_lwp) +void +mips_target::low_delete_thread (arch_lwp_info *arch_lwp) { xfree (arch_lwp); } @@ -442,9 +452,9 @@ mips_add_watchpoint (struct arch_process_info *priv, CORE_ADDR addr, int len, /* Hook to call when a new fork is attached. */ -static void -mips_linux_new_fork (struct process_info *parent, - struct process_info *child) +void +mips_target::low_new_fork (process_info *parent, + process_info *child) { struct arch_process_info *parent_private; struct arch_process_info *child_private; @@ -986,11 +996,6 @@ mips_target::get_regs_info () } struct linux_target_ops the_low_target = { - mips_linux_new_process, - mips_linux_delete_process, - mips_linux_new_thread, - mips_linux_delete_thread, - mips_linux_new_fork, mips_linux_prepare_to_resume }; diff --git a/gdbserver/linux-ppc-low.cc b/gdbserver/linux-ppc-low.cc index 573a6d6055..4f3a643f18 100644 --- a/gdbserver/linux-ppc-low.cc +++ b/gdbserver/linux-ppc-low.cc @@ -3428,11 +3428,6 @@ ppc_get_ipa_tdesc_idx (void) } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ ppc_supports_tracepoints, diff --git a/gdbserver/linux-s390-low.cc b/gdbserver/linux-s390-low.cc index cd4dc8ab31..be99c26c58 100644 --- a/gdbserver/linux-s390-low.cc +++ b/gdbserver/linux-s390-low.cc @@ -2845,11 +2845,6 @@ s390_emit_ops (void) } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ s390_supports_tracepoints, diff --git a/gdbserver/linux-sh-low.cc b/gdbserver/linux-sh-low.cc index 070d21fbdd..8b69521f10 100644 --- a/gdbserver/linux-sh-low.cc +++ b/gdbserver/linux-sh-low.cc @@ -192,11 +192,6 @@ sh_target::low_arch_setup () } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/linux-tic6x-low.cc b/gdbserver/linux-tic6x-low.cc index 573b458156..9f62899eaf 100644 --- a/gdbserver/linux-tic6x-low.cc +++ b/gdbserver/linux-tic6x-low.cc @@ -423,11 +423,6 @@ tic6x_target::get_regs_info () } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/linux-tile-low.cc b/gdbserver/linux-tile-low.cc index ce487967aa..21650c846a 100644 --- a/gdbserver/linux-tile-low.cc +++ b/gdbserver/linux-tile-low.cc @@ -224,11 +224,6 @@ tile_supports_hardware_single_step (void) struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc index bf4e6ec2c8..be68e005f0 100644 --- a/gdbserver/linux-x86-low.cc +++ b/gdbserver/linux-x86-low.cc @@ -145,6 +145,16 @@ protected: /* Need to fix up i386 siginfo if host is amd64. */ bool low_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) override; + + arch_process_info *low_new_process () override; + + void low_delete_process (arch_process_info *info) override; + + void low_new_thread (lwp_info *) override; + + void low_delete_thread (arch_lwp_info *) override; + + void low_new_fork (process_info *parent, process_info *child) override; }; /* The singleton target ops object. */ @@ -693,8 +703,8 @@ x86_target::low_stopped_data_address () /* Called when a new process is created. */ -static struct arch_process_info * -x86_linux_new_process (void) +arch_process_info * +x86_target::low_new_process () { struct arch_process_info *info = XCNEW (struct arch_process_info); @@ -705,16 +715,30 @@ x86_linux_new_process (void) /* Called when a process is being deleted. */ -static void -x86_linux_delete_process (struct arch_process_info *info) +void +x86_target::low_delete_process (arch_process_info *info) { xfree (info); } -/* Target routine for linux_new_fork. */ +void +x86_target::low_new_thread (lwp_info *lwp) +{ + /* This comes from nat/. */ + x86_linux_new_thread (lwp); +} -static void -x86_linux_new_fork (struct process_info *parent, struct process_info *child) +void +x86_target::low_delete_thread (arch_lwp_info *alwp) +{ + /* This comes from nat/. */ + x86_linux_delete_thread (alwp); +} + +/* Target routine for new_fork. */ + +void +x86_target::low_new_fork (process_info *parent, process_info *child) { /* These are allocated by linux_add_process. */ gdb_assert (parent->priv != NULL @@ -2930,11 +2954,6 @@ x86_get_ipa_tdesc_idx (void) struct linux_target_ops the_low_target = { - x86_linux_new_process, - x86_linux_delete_process, - x86_linux_new_thread, - x86_linux_delete_thread, - x86_linux_new_fork, x86_linux_prepare_to_resume, x86_linux_process_qsupported, x86_supports_tracepoints, diff --git a/gdbserver/linux-xtensa-low.cc b/gdbserver/linux-xtensa-low.cc index b55a6f6674..dbb87a5997 100644 --- a/gdbserver/linux-xtensa-low.cc +++ b/gdbserver/linux-xtensa-low.cc @@ -329,11 +329,6 @@ xtensa_target::get_regs_info () } struct linux_target_ops the_low_target = { - NULL, /* new_process */ - NULL, /* delete_process */ - NULL, /* new_thread */ - NULL, /* delete_thread */ - NULL, /* new_fork */ NULL, /* prepare_to_resume */ NULL, /* process_qsupported */ NULL, /* supports_tracepoints */ diff --git a/gdbserver/thread-db.cc b/gdbserver/thread-db.cc index 2bb6d28820..89c45cd7b3 100644 --- a/gdbserver/thread-db.cc +++ b/gdbserver/thread-db.cc @@ -221,7 +221,7 @@ attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p) if (debug_threads) debug_printf ("Attaching to thread %ld (LWP %d)\n", (unsigned long) ti_p->ti_tid, ti_p->ti_lid); - err = linux_attach_lwp (ptid); + err = the_linux_target->attach_lwp (ptid); if (err != 0) { std::string reason = linux_ptrace_attach_fail_reason_string (ptid, err);