mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-28 20:43:45 +08:00
9c80ecd646
Remove the usage of inferior_list for the all_threads list in gdbserver. The entry field in thread_info is removed, and replaced by a simple ptid field. I added some functions to iterate (for_each_thread) and find threads (find_thread). However, changing all the users of find_inferior & co to use these new functions would have made the patch way too big. So I opted instead to make find_inferior & co some shims, so that the existing code only needs to be updated minimally. We can then update the existing code to use the new functions incrementally (I've started to do the work, but I'll post it afterwards, see [1] if you want a peek). This patch has been built-tested on all relevant platforms, except lynx. I also regtested using the native-gdbserver and native-extended-gdbserver boards on x86. [1] https://github.com/simark/binutils-gdb/commits/kill-inferior-list-entry gdb/gdbserver/ChangeLog: * inferiors.h: (struct inferior_list): Remove. (struct inferior_list_entry); Remove. (add_inferior_to_list, clear_inferior_list, one_inferior_p, A_I_NEXT, ALL_INFERIORS_TYPE, ALL_INFERIORS, remove_inferior, get_first_inferior): Remove. (for_each_inferior, for_each_inferior_with_data, find_inferior, find_inferior_id, find_inferior_in_random): Change signature. * inferiors.c (all_threads): Change type to std::list<thread_info *>. (get_thread): Remove macro. (find_inferior, find_inferior_id): Change signature, implement using find_thread. (find_inferior_in_random): Change signature, implement using find_thread_in_random. (for_each_inferior, for_each_inferior_with_data): Change signature, implement using for_each_thread. (add_inferior_to_list, remove_inferior): Remove. (add_thread, get_first_thread, thread_of_pid, find_any_thread_of_pid, free_one_thread, remove_thread): Update. (get_first_inferior, one_inferior_p, clear_inferior_list): Remove. (clear_inferiors, get_thread_process): Update. * gdbthread.h: Include <list>. (struct thread_info) <entry>: Remove field. <id>: New field. (all_threads): Change type to std::list<thread_info *>. (get_first_inferior): Add doc. (find_thread, for_each_thread, find_thread_in_random): New functions. (current_ptid, pid_of, ptid_of, lwpid_of): Update. * linux-arm-low.c (update_registers_callback): Update. * linux-low.c (second_thread_of_pid_p): Update. (kill_one_lwp_callback, linux_detach_lwp_callback, delete_lwp_callback, status_pending_p_callback, same_lwp, find_lwp_pid, num_lwps, iterate_over_lwps_filter, iterate_over_lwps, not_stopped_callback, resume_stopped_resumed_lwps, count_events_callback, select_singlestep_lwp_callback, select_event_lwp_callback, unsuspend_one_lwp, linux_wait_1, send_sigstop_callback, suspend_and_send_sigstop_callback, wait_for_sigstop, stuck_in_jump_pad_callback, move_out_of_jump_pad_callback, lwp_running, linux_set_resume_request, resume_status_pending_p, need_step_over_p, start_step_over, linux_resume_one_thread, proceed_one_lwp, unsuspend_and_proceed_one_lwp, reset_lwp_ptrace_options_callback): Update. * linux-mips-low.c (update_watch_registers_callback): Update. * regcache.c (regcache_invalidate_one, regcache_invalidate): Update. (free_register_cache_thread_one): Remove. (regcache_release): Update. * server.c (handle_btrace_enable_bts, handle_btrace_enable_pt, handle_qxfer_threads_worker): Update. (handle_query): Update, use list iterator. (visit_actioned_threads, handle_pending_status, queue_stop_reply_callback, gdb_wants_all_threads_stopped, clear_pending_status_callback, set_pending_status_callback, find_status_pending_thread_callback, handle_status, process_serial_event): Update. * target.c (thread_search_callback): Update. * thread-db.c (thread_db_get_tls_address): Update. * tracepoint.c (tracepoint_finished_step, tracepoint_was_hit): Update. * win32-i386-low.c (update_debug_registers_callback): Update. * win32-low.c (delete_thread_info, child_delete_thread, continue_one_thread, suspend_one_thread, get_child_debug_event): Adjust.
324 lines
7.0 KiB
C
324 lines
7.0 KiB
C
/* Inferior process information for the remote server for GDB.
|
|
Copyright (C) 2002-2017 Free Software Foundation, Inc.
|
|
|
|
Contributed by MontaVista Software.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "server.h"
|
|
#include "gdbthread.h"
|
|
#include "dll.h"
|
|
|
|
std::list<process_info *> all_processes;
|
|
std::list<thread_info *> all_threads;
|
|
|
|
struct thread_info *current_thread;
|
|
|
|
/* The current working directory used to start the inferior. */
|
|
static const char *current_inferior_cwd = NULL;
|
|
|
|
thread_info *
|
|
find_inferior (std::list<thread_info *> *thread_list,
|
|
int (*func) (thread_info *, void *),
|
|
void *arg)
|
|
{
|
|
gdb_assert (thread_list == &all_threads);
|
|
|
|
return find_thread ([&] (thread_info *thread) {
|
|
return func (thread, arg);
|
|
});
|
|
}
|
|
|
|
thread_info *
|
|
find_inferior_id (std::list<thread_info *> *thread_list, ptid_t id)
|
|
{
|
|
gdb_assert (thread_list == &all_threads);
|
|
|
|
return find_thread ([&] (thread_info *thread) {
|
|
return thread->id == id;
|
|
});
|
|
}
|
|
|
|
thread_info *
|
|
find_inferior_in_random (std::list<thread_info *> *thread_list,
|
|
int (*func) (thread_info *, void *),
|
|
void *arg)
|
|
{
|
|
gdb_assert (thread_list == &all_threads);
|
|
|
|
return find_thread_in_random ([&] (thread_info *thread) {
|
|
return func (thread, arg);
|
|
});
|
|
}
|
|
|
|
void
|
|
for_each_inferior (std::list<thread_info *> *thread_list,
|
|
void (*action) (thread_info *))
|
|
{
|
|
gdb_assert (thread_list == &all_threads);
|
|
|
|
for_each_thread ([&] (thread_info *thread) {
|
|
action (thread);
|
|
});
|
|
}
|
|
|
|
void
|
|
for_each_inferior_with_data (std::list<thread_info *> *thread_list,
|
|
void (*action) (thread_info *, void *),
|
|
void *data)
|
|
{
|
|
gdb_assert (thread_list == &all_threads);
|
|
|
|
for_each_thread ([&] (thread_info *thread) {
|
|
action (thread, data);
|
|
});
|
|
}
|
|
|
|
struct thread_info *
|
|
add_thread (ptid_t thread_id, void *target_data)
|
|
{
|
|
struct thread_info *new_thread = XCNEW (struct thread_info);
|
|
|
|
new_thread->id = thread_id;
|
|
new_thread->last_resume_kind = resume_continue;
|
|
new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
|
|
|
|
all_threads.push_back (new_thread);
|
|
|
|
if (current_thread == NULL)
|
|
current_thread = new_thread;
|
|
|
|
new_thread->target_data = target_data;
|
|
|
|
return new_thread;
|
|
}
|
|
|
|
/* See gdbthread.h. */
|
|
|
|
struct thread_info *
|
|
get_first_thread (void)
|
|
{
|
|
if (!all_threads.empty ())
|
|
return all_threads.front ();
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
struct thread_info *
|
|
find_thread_ptid (ptid_t ptid)
|
|
{
|
|
return (struct thread_info *) find_inferior_id (&all_threads, ptid);
|
|
}
|
|
|
|
/* Find a thread associated with the given PROCESS, or NULL if no
|
|
such thread exists. */
|
|
|
|
static struct thread_info *
|
|
find_thread_process (const struct process_info *const process)
|
|
{
|
|
return find_any_thread_of_pid (process->pid);
|
|
}
|
|
|
|
/* Helper for find_any_thread_of_pid. Returns true if a thread
|
|
matches a PID. */
|
|
|
|
static int
|
|
thread_of_pid (thread_info *entry, void *pid_p)
|
|
{
|
|
int pid = *(int *) pid_p;
|
|
|
|
return (ptid_get_pid (entry->id) == pid);
|
|
}
|
|
|
|
/* See gdbthread.h. */
|
|
|
|
struct thread_info *
|
|
find_any_thread_of_pid (int pid)
|
|
{
|
|
return find_inferior (&all_threads, thread_of_pid, &pid);
|
|
}
|
|
|
|
static void
|
|
free_one_thread (thread_info *thread)
|
|
{
|
|
free_register_cache (thread_regcache_data (thread));
|
|
free (thread);
|
|
}
|
|
|
|
void
|
|
remove_thread (struct thread_info *thread)
|
|
{
|
|
if (thread->btrace != NULL)
|
|
target_disable_btrace (thread->btrace);
|
|
|
|
discard_queued_stop_replies (ptid_of (thread));
|
|
all_threads.remove (thread);
|
|
free_one_thread (thread);
|
|
if (current_thread == thread)
|
|
current_thread = NULL;
|
|
}
|
|
|
|
void *
|
|
thread_target_data (struct thread_info *thread)
|
|
{
|
|
return thread->target_data;
|
|
}
|
|
|
|
struct regcache *
|
|
thread_regcache_data (struct thread_info *thread)
|
|
{
|
|
return thread->regcache_data;
|
|
}
|
|
|
|
void
|
|
set_thread_regcache_data (struct thread_info *thread, struct regcache *data)
|
|
{
|
|
thread->regcache_data = data;
|
|
}
|
|
|
|
void
|
|
clear_inferiors (void)
|
|
{
|
|
for_each_inferior (&all_threads, free_one_thread);
|
|
all_threads.clear ();
|
|
|
|
clear_dlls ();
|
|
|
|
current_thread = NULL;
|
|
}
|
|
|
|
struct process_info *
|
|
add_process (int pid, int attached)
|
|
{
|
|
struct process_info *process = XCNEW (struct process_info);
|
|
|
|
process->pid = pid;
|
|
process->attached = attached;
|
|
|
|
all_processes.push_back (process);
|
|
|
|
return process;
|
|
}
|
|
|
|
/* Remove a process from the common process list and free the memory
|
|
allocated for it.
|
|
The caller is responsible for freeing private data first. */
|
|
|
|
void
|
|
remove_process (struct process_info *process)
|
|
{
|
|
clear_symbol_cache (&process->symbol_cache);
|
|
free_all_breakpoints (process);
|
|
gdb_assert (find_thread_process (process) == NULL);
|
|
all_processes.remove (process);
|
|
VEC_free (int, process->syscalls_to_catch);
|
|
free (process);
|
|
}
|
|
|
|
process_info *
|
|
find_process_pid (int pid)
|
|
{
|
|
return find_process ([&] (process_info *process) {
|
|
return process->pid == pid;
|
|
});
|
|
}
|
|
|
|
/* Get the first process in the process list, or NULL if the list is empty. */
|
|
|
|
process_info *
|
|
get_first_process (void)
|
|
{
|
|
if (!all_processes.empty ())
|
|
return all_processes.front ();
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/* Return non-zero if there are any inferiors that we have created
|
|
(as opposed to attached-to). */
|
|
|
|
int
|
|
have_started_inferiors_p (void)
|
|
{
|
|
return find_process ([] (process_info *process) {
|
|
return !process->attached;
|
|
}) != NULL;
|
|
}
|
|
|
|
/* Return non-zero if there are any inferiors that we have attached to. */
|
|
|
|
int
|
|
have_attached_inferiors_p (void)
|
|
{
|
|
return find_process ([] (process_info *process) {
|
|
return process->attached;
|
|
}) != NULL;
|
|
}
|
|
|
|
struct process_info *
|
|
get_thread_process (const struct thread_info *thread)
|
|
{
|
|
return find_process_pid (thread->id.pid ());
|
|
}
|
|
|
|
struct process_info *
|
|
current_process (void)
|
|
{
|
|
gdb_assert (current_thread != NULL);
|
|
return get_thread_process (current_thread);
|
|
}
|
|
|
|
static void
|
|
do_restore_current_thread_cleanup (void *arg)
|
|
{
|
|
current_thread = (struct thread_info *) arg;
|
|
}
|
|
|
|
struct cleanup *
|
|
make_cleanup_restore_current_thread (void)
|
|
{
|
|
return make_cleanup (do_restore_current_thread_cleanup, current_thread);
|
|
}
|
|
|
|
/* See common/common-gdbthread.h. */
|
|
|
|
void
|
|
switch_to_thread (ptid_t ptid)
|
|
{
|
|
gdb_assert (ptid != minus_one_ptid);
|
|
current_thread = find_thread_ptid (ptid);
|
|
}
|
|
|
|
/* See common/common-inferior.h. */
|
|
|
|
const char *
|
|
get_inferior_cwd ()
|
|
{
|
|
return current_inferior_cwd;
|
|
}
|
|
|
|
/* See common/common-inferior.h. */
|
|
|
|
void
|
|
set_inferior_cwd (const char *cwd)
|
|
{
|
|
xfree ((void *) current_inferior_cwd);
|
|
if (cwd != NULL)
|
|
current_inferior_cwd = xstrdup (cwd);
|
|
else
|
|
current_inferior_cwd = NULL;
|
|
}
|