From patchwork Fri Mar 6 21:31:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tankut Baris Aktemur X-Patchwork-Id: 38512 Received: (qmail 55800 invoked by alias); 6 Mar 2020 21:33:05 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 53712 invoked by uid 89); 6 Mar 2020 21:32:49 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=detached X-HELO: mga07.intel.com Received: from mga07.intel.com (HELO mga07.intel.com) (134.134.136.100) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 06 Mar 2020 21:32:31 +0000 Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 06 Mar 2020 13:32:21 -0800 Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga006.jf.intel.com with ESMTP; 06 Mar 2020 13:32:20 -0800 Received: from ulvlx001.iul.intel.com (ulvlx001.iul.intel.com [172.28.207.17]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id 026LWJpI022485; Fri, 6 Mar 2020 21:32:19 GMT Received: from ulvlx001.iul.intel.com (localhost [127.0.0.1]) by ulvlx001.iul.intel.com with ESMTP id 026LWJWJ020481; Fri, 6 Mar 2020 22:32:19 +0100 Received: (from taktemur@localhost) by ulvlx001.iul.intel.com with LOCAL id 026LWJ4j020477; Fri, 6 Mar 2020 22:32:19 +0100 From: Tankut Baris Aktemur To: gdb-patches@sourceware.org Subject: [PATCH 20/31] gdbserver/linux-low: turn process/thread addition/deletion ops into methods Date: Fri, 6 Mar 2020 22:31:28 +0100 Message-Id: <26d0ac036ac31925ab8d9d635b10141f3341ba09.1583529167.git.tankut.baris.aktemur@intel.com> In-Reply-To: References: In-Reply-To: References: X-IsSubscribed: yes gdbserver/ChangeLog: 2020-03-06 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/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 +- 17 files changed, 234 insertions(+), 205 deletions(-) diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 458c5a77209..1b5efd56168 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -94,6 +94,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. */ @@ -519,10 +529,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); @@ -531,19 +541,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 @@ -3118,11 +3140,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 55859780ae7..cc2f3919e27 100644 --- a/gdbserver/linux-arm-low.cc +++ b/gdbserver/linux-arm-low.cc @@ -101,6 +101,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. */ @@ -721,8 +731,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; @@ -730,15 +740,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; @@ -753,14 +763,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; @@ -1107,11 +1117,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 5843ac29f36..21facb24cd0 100644 --- a/gdbserver/linux-bfin-low.cc +++ b/gdbserver/linux-bfin-low.cc @@ -165,11 +165,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 0e228a859e2..1397603ee36 100644 --- a/gdbserver/linux-crisv32-low.cc +++ b/gdbserver/linux-crisv32-low.cc @@ -470,11 +470,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 47a36ee3052..50addb9d68e 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 ced71f34cf0..16d9b389275 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 *); @@ -629,6 +608,37 @@ class linux_process_target : public process_stratum_target 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. */ @@ -691,6 +701,27 @@ class linux_process_target : public process_stratum_target 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. */ int m_decr_pc_after_break; }; diff --git a/gdbserver/linux-m32r-low.cc b/gdbserver/linux-m32r-low.cc index e664c6d2a82..bb1a2a0cd17 100644 --- a/gdbserver/linux-m32r-low.cc +++ b/gdbserver/linux-m32r-low.cc @@ -163,11 +163,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 39e45171428..bfc682bacbe 100644 --- a/gdbserver/linux-m68k-low.cc +++ b/gdbserver/linux-m68k-low.cc @@ -259,11 +259,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 52be7f0f748..3ec56d404e5 100644 --- a/gdbserver/linux-mips-low.cc +++ b/gdbserver/linux-mips-low.cc @@ -72,6 +72,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. */ @@ -379,32 +389,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); @@ -415,8 +425,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); } @@ -444,9 +454,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; @@ -988,11 +998,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 625bc012623..9035b82be9d 100644 --- a/gdbserver/linux-ppc-low.cc +++ b/gdbserver/linux-ppc-low.cc @@ -3430,11 +3430,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 937628fe25f..27bd292b20a 100644 --- a/gdbserver/linux-s390-low.cc +++ b/gdbserver/linux-s390-low.cc @@ -2839,11 +2839,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 1bbfb472409..3a111658b81 100644 --- a/gdbserver/linux-sh-low.cc +++ b/gdbserver/linux-sh-low.cc @@ -194,11 +194,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 77ffc28f186..00821e0d85f 100644 --- a/gdbserver/linux-tic6x-low.cc +++ b/gdbserver/linux-tic6x-low.cc @@ -425,11 +425,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 66302ef6fe5..0b2aafcf5c4 100644 --- a/gdbserver/linux-tile-low.cc +++ b/gdbserver/linux-tile-low.cc @@ -226,11 +226,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 5d16e89aca4..b55fb44fb10 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. */ @@ -686,8 +696,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); @@ -698,16 +708,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 @@ -2923,11 +2947,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 957858980d6..c17c53c9bf9 100644 --- a/gdbserver/linux-xtensa-low.cc +++ b/gdbserver/linux-xtensa-low.cc @@ -331,11 +331,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 2bb6d28820e..89c45cd7b38 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);