Replace code accessing list implementation details with API calls.

* dll.c (clear_dlls): Replace accessing list implemention details
	with API function.
	* gdbthread.h (get_first_thread): Declare.
	* inferiors.c (for_each_inferior_with_data): New function.
	(get_first_thread): New function.
	(find_thread_ptid): Simplify.
	(get_first_inferior): New function.
	(clear_list): Delete.
	(one_inferior_p): New function.
	(clear_inferior_list): New function.
	(clear_inferiors): Update.
	* inferiors.h (for_each_inferior_with_data): Declare.
	(clear_inferior_list): Declare.
	(one_inferior_p): Declare.
	(get_first_inferior): Declare.
	* linux-low.c (linux_wait_for_event): Replace accessing list
	implemention details with API function.
	* server.c (target_running): Ditto.
	(accumulate_file_name_length): New function.
	(emit_dll_description): New function.
	(handle_qxfer_libraries): Replace accessing list implemention
	details with API function.
	(handle_qxfer_threads_worker): New function.
	(handle_qxfer_threads_proper): Replace accessing list implemention
	details with API function.
	(handle_query): Ditto.
	(visit_actioned_threads_callback_ftype): New typedef.
	(visit_actioned_threads_data): New struct.
	(visit_actioned_threads): Rewrite to be find_inferior callback.
	(resume): Call find_inferior.
	(handle_status): Replace accessing list implemention
	details with API function.
	(process_serial_event): Replace accessing list implemention details
	with API function.
	* target.c (set_desired_inferior): Replace accessing list implemention
	details with API function.
	* tracepoint.c (same_process_p): New function.
	(gdb_agent_about_to_close): Replace accessing list implemention
	details with API function.
	* win32-low.c (child_delete_thread): Replace accessing list
	implemention details with API function.
	(match_dll_by_basename): New function.
	(dll_is_loaded_by_basename): New function.
	(win32_ensure_ntdll_loaded): Replace accessing list implemention
	details call to dll_is_loaded_by_basename.
This commit is contained in:
Doug Evans 2014-02-19 15:28:50 -08:00
parent b5ad007edc
commit 649ebbcaef
10 changed files with 279 additions and 109 deletions

View File

@ -1,3 +1,51 @@
2014-02-19 Doug Evans <dje@google.com>
* dll.c (clear_dlls): Replace accessing list implemention details
with API function.
* gdbthread.h (get_first_thread): Declare.
* inferiors.c (for_each_inferior_with_data): New function.
(get_first_thread): New function.
(find_thread_ptid): Simplify.
(get_first_inferior): New function.
(clear_list): Delete.
(one_inferior_p): New function.
(clear_inferior_list): New function.
(clear_inferiors): Update.
* inferiors.h (for_each_inferior_with_data): Declare.
(clear_inferior_list): Declare.
(one_inferior_p): Declare.
(get_first_inferior): Declare.
* linux-low.c (linux_wait_for_event): Replace accessing list
implemention details with API function.
* server.c (target_running): Ditto.
(accumulate_file_name_length): New function.
(emit_dll_description): New function.
(handle_qxfer_libraries): Replace accessing list implemention
details with API function.
(handle_qxfer_threads_worker): New function.
(handle_qxfer_threads_proper): Replace accessing list implemention
details with API function.
(handle_query): Ditto.
(visit_actioned_threads_callback_ftype): New typedef.
(visit_actioned_threads_data): New struct.
(visit_actioned_threads): Rewrite to be find_inferior callback.
(resume): Call find_inferior.
(handle_status): Replace accessing list implemention
details with API function.
(process_serial_event): Replace accessing list implemention details
with API function.
* target.c (set_desired_inferior): Replace accessing list implemention
details with API function.
* tracepoint.c (same_process_p): New function.
(gdb_agent_about_to_close): Replace accessing list implemention
details with API function.
* win32-low.c (child_delete_thread): Replace accessing list
implemention details with API function.
(match_dll_by_basename): New function.
(dll_is_loaded_by_basename): New function.
(win32_ensure_ntdll_loaded): Replace accessing list implemention
details call to dll_is_loaded_by_basename.
2014-02-19 Doug Evans <dje@google.com>
* dll.h (struct dll_info): Add comment.

View File

@ -110,5 +110,5 @@ void
clear_dlls (void)
{
for_each_inferior (&all_dlls, free_one_dll);
all_dlls.head = all_dlls.tail = NULL;
clear_inferior_list (&all_dlls);
}

View File

@ -76,6 +76,8 @@ extern struct inferior_list all_threads;
void remove_thread (struct thread_info *thread);
void add_thread (ptid_t ptid, void *target_data);
struct thread_info *get_first_thread (void);
struct thread_info *find_thread_ptid (ptid_t ptid);
/* Get current thread ID (Linux task ID). */

View File

@ -59,6 +59,24 @@ for_each_inferior (struct inferior_list *list,
}
}
/* Invoke ACTION for each inferior in LIST, passing DATA to ACTION. */
void
for_each_inferior_with_data (struct inferior_list *list,
void (*action) (struct inferior_list_entry *,
void *),
void *data)
{
struct inferior_list_entry *cur = list->head, *next;
while (cur != NULL)
{
next = cur->next;
(*action) (cur, data);
cur = next;
}
}
void
remove_inferior (struct inferior_list *list,
struct inferior_list_entry *entry)
@ -111,20 +129,18 @@ thread_to_gdb_id (struct thread_info *thread)
return thread->entry.id;
}
/* Wrapper around get_first_inferior to return a struct thread_info *. */
struct thread_info *
get_first_thread (void)
{
return (struct thread_info *) get_first_inferior (&all_threads);
}
struct thread_info *
find_thread_ptid (ptid_t ptid)
{
struct inferior_list_entry *inf = all_threads.head;
while (inf != NULL)
{
struct thread_info *thread = get_thread (inf);
if (ptid_equal (thread->entry.id, ptid))
return thread;
inf = inf->next;
}
return NULL;
return (struct thread_info *) find_inferior_id (&all_threads, ptid);
}
ptid_t
@ -153,6 +169,18 @@ remove_thread (struct thread_info *thread)
free_one_thread (&thread->entry);
}
/* Return a pointer to the first inferior in LIST, or NULL if there isn't one.
This is for cases where the caller needs a thread, but doesn't care
which one. */
struct inferior_list_entry *
get_first_inferior (struct inferior_list *list)
{
if (all_threads.head != NULL)
return all_threads.head;
return NULL;
}
/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
returns non-zero. If no entry is found then return NULL. */
@ -214,14 +242,28 @@ set_inferior_regcache_data (struct thread_info *inferior, void *data)
inferior->regcache_data = data;
}
#define clear_list(LIST) \
do { (LIST)->head = (LIST)->tail = NULL; } while (0)
/* Return true if LIST has exactly one entry. */
int
one_inferior_p (struct inferior_list *list)
{
return list->head != NULL && list->head == list->tail;
}
/* Reset head,tail of LIST, assuming all entries have already been freed. */
void
clear_inferior_list (struct inferior_list *list)
{
list->head = NULL;
list->tail = NULL;
}
void
clear_inferiors (void)
{
for_each_inferior (&all_threads, free_one_thread);
clear_list (&all_threads);
clear_inferior_list (&all_threads);
clear_dlls ();

View File

@ -86,10 +86,21 @@ void add_inferior_to_list (struct inferior_list *list,
void for_each_inferior (struct inferior_list *list,
void (*action) (struct inferior_list_entry *));
void for_each_inferior_with_data
(struct inferior_list *list,
void (*action) (struct inferior_list_entry *, void *),
void *data);
void clear_inferior_list (struct inferior_list *list);
int one_inferior_p (struct inferior_list *list);
extern struct thread_info *current_inferior;
void remove_inferior (struct inferior_list *list,
struct inferior_list_entry *entry);
struct inferior_list_entry *get_first_inferior (struct inferior_list *list);
struct process_info *add_process (int pid, int attached);
void remove_process (struct process_info *process);
struct process_info *find_process_pid (int pid);

View File

@ -1872,7 +1872,7 @@ linux_wait_for_event (ptid_t ptid, int *wstat, int options)
if (!non_stop)
{
current_inferior = (struct thread_info *) all_threads.head;
current_inferior = get_first_thread ();
if (debug_threads)
debug_printf ("Current inferior is now %ld\n",
lwpid_of (get_thread_lwp (current_inferior)));

View File

@ -192,7 +192,7 @@ struct notif_server notif_stop =
static int
target_running (void)
{
return all_threads.head != NULL;
return get_first_thread () != NULL;
}
static int
@ -1136,6 +1136,48 @@ handle_qxfer_features (const char *annex,
return len;
}
/* Worker routine for handle_qxfer_libraries.
Add to the length pointed to by ARG a conservative estimate of the
length needed to transmit the file name of INF. */
static void
accumulate_file_name_length (struct inferior_list_entry *inf, void *arg)
{
struct dll_info *dll = (struct dll_info *) inf;
unsigned int *total_len = arg;
/* Over-estimate the necessary memory. Assume that every character
in the library name must be escaped. */
*total_len += 128 + 6 * strlen (dll->name);
}
/* Worker routine for handle_qxfer_libraries.
Emit the XML to describe the library in INF. */
static void
emit_dll_description (struct inferior_list_entry *inf, void *arg)
{
struct dll_info *dll = (struct dll_info *) inf;
char **p_ptr = arg;
char *p = *p_ptr;
char *name;
strcpy (p, " <library name=\"");
p = p + strlen (p);
name = xml_escape_text (dll->name);
strcpy (p, name);
free (name);
p = p + strlen (p);
strcpy (p, "\"><segment address=\"");
p = p + strlen (p);
sprintf (p, "0x%lx", (long) dll->base_addr);
p = p + strlen (p);
strcpy (p, "\"/></library>\n");
p = p + strlen (p);
*p_ptr = p;
}
/* Handle qXfer:libraries:read. */
static int
@ -1145,7 +1187,6 @@ handle_qxfer_libraries (const char *annex,
{
unsigned int total_len;
char *document, *p;
struct inferior_list_entry *dll_ptr;
if (writebuf != NULL)
return -2;
@ -1153,11 +1194,9 @@ handle_qxfer_libraries (const char *annex,
if (annex[0] != '\0' || !target_running ())
return -1;
/* Over-estimate the necessary memory. Assume that every character
in the library name must be escaped. */
total_len = 64;
for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next)
total_len += 128 + 6 * strlen (((struct dll_info *) dll_ptr)->name);
for_each_inferior_with_data (&all_dlls, accumulate_file_name_length,
&total_len);
document = malloc (total_len);
if (document == NULL)
@ -1166,24 +1205,7 @@ handle_qxfer_libraries (const char *annex,
strcpy (document, "<library-list>\n");
p = document + strlen (document);
for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next)
{
struct dll_info *dll = (struct dll_info *) dll_ptr;
char *name;
strcpy (p, " <library name=\"");
p = p + strlen (p);
name = xml_escape_text (dll->name);
strcpy (p, name);
free (name);
p = p + strlen (p);
strcpy (p, "\"><segment address=\"");
p = p + strlen (p);
sprintf (p, "0x%lx", (long) dll->base_addr);
p = p + strlen (p);
strcpy (p, "\"/></library>\n");
p = p + strlen (p);
}
for_each_inferior_with_data (&all_dlls, emit_dll_description, &p);
strcpy (p, "</library-list>\n");
@ -1285,36 +1307,43 @@ handle_qxfer_statictrace (const char *annex,
return nbytes;
}
/* Helper for handle_qxfer_threads_proper.
Emit the XML to describe the thread of INF. */
static void
handle_qxfer_threads_worker (struct inferior_list_entry *inf, void *arg)
{
struct thread_info *thread = (struct thread_info *) inf;
struct buffer *buffer = arg;
ptid_t ptid = thread_to_gdb_id (thread);
char ptid_s[100];
int core = target_core_of_thread (ptid);
char core_s[21];
write_ptid (ptid_s, ptid);
if (core != -1)
{
sprintf (core_s, "%d", core);
buffer_xml_printf (buffer, "<thread id=\"%s\" core=\"%s\"/>\n",
ptid_s, core_s);
}
else
{
buffer_xml_printf (buffer, "<thread id=\"%s\"/>\n",
ptid_s);
}
}
/* Helper for handle_qxfer_threads. */
static void
handle_qxfer_threads_proper (struct buffer *buffer)
{
struct inferior_list_entry *thread;
buffer_grow_str (buffer, "<threads>\n");
for (thread = all_threads.head; thread; thread = thread->next)
{
ptid_t ptid = thread_to_gdb_id ((struct thread_info *)thread);
char ptid_s[100];
int core = target_core_of_thread (ptid);
char core_s[21];
write_ptid (ptid_s, ptid);
if (core != -1)
{
sprintf (core_s, "%d", core);
buffer_xml_printf (buffer, "<thread id=\"%s\" core=\"%s\"/>\n",
ptid_s, core_s);
}
else
{
buffer_xml_printf (buffer, "<thread id=\"%s\"/>\n",
ptid_s);
}
}
for_each_inferior_with_data (&all_threads, handle_qxfer_threads_worker,
buffer);
buffer_grow_str0 (buffer, "</threads>\n");
}
@ -1702,7 +1731,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
gdb_id = general_thread;
else
{
thread_ptr = all_threads.head;
thread_ptr = get_first_inferior (&all_threads);
gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
}
@ -1743,7 +1772,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
ptid_t gdb_id;
require_running (own_buf);
thread_ptr = all_threads.head;
thread_ptr = get_first_inferior (&all_threads);
*own_buf++ = 'm';
gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
@ -2121,37 +2150,47 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
static void gdb_wants_all_threads_stopped (void);
static void resume (struct thread_resume *actions, size_t n);
/* The callback that is passed to visit_actioned_threads. */
typedef int (visit_actioned_threads_callback_ftype)
(const struct thread_resume *, struct thread_info *);
/* Struct to pass data to visit_actioned_threads. */
struct visit_actioned_threads_data
{
const struct thread_resume *actions;
size_t num_actions;
visit_actioned_threads_callback_ftype *callback;
};
/* Call CALLBACK for any thread to which ACTIONS applies to. Returns
true if CALLBACK returns true. Returns false if no matching thread
is found or CALLBACK results false. */
is found or CALLBACK results false.
Note: This function is itself a callback for find_inferior. */
static int
visit_actioned_threads (const struct thread_resume *actions,
size_t num_actions,
int (*callback) (const struct thread_resume *,
struct thread_info *))
visit_actioned_threads (struct inferior_list_entry *entry, void *datap)
{
struct inferior_list_entry *entry;
struct visit_actioned_threads_data *data = datap;
const struct thread_resume *actions = data->actions;
size_t num_actions = data->num_actions;
visit_actioned_threads_callback_ftype *callback = data->callback;
size_t i;
for (entry = all_threads.head; entry != NULL; entry = entry->next)
for (i = 0; i < num_actions; i++)
{
size_t i;
const struct thread_resume *action = &actions[i];
for (i = 0; i < num_actions; i++)
if (ptid_equal (action->thread, minus_one_ptid)
|| ptid_equal (action->thread, entry->id)
|| ((ptid_get_pid (action->thread)
== ptid_get_pid (entry->id))
&& ptid_get_lwp (action->thread) == -1))
{
const struct thread_resume *action = &actions[i];
struct thread_info *thread = (struct thread_info *) entry;
if (ptid_equal (action->thread, minus_one_ptid)
|| ptid_equal (action->thread, entry->id)
|| ((ptid_get_pid (action->thread)
== ptid_get_pid (entry->id))
&& ptid_get_lwp (action->thread) == -1))
{
struct thread_info *thread = (struct thread_info *) entry;
if ((*callback) (action, thread))
return 1;
}
if ((*callback) (action, thread))
return 1;
}
}
@ -2309,7 +2348,12 @@ resume (struct thread_resume *actions, size_t num_actions)
one with a pending status to report. If so, skip actually
resuming/stopping and report the pending event
immediately. */
if (visit_actioned_threads (actions, num_actions, handle_pending_status))
struct visit_actioned_threads_data data;
data.actions = actions;
data.num_actions = num_actions;
data.callback = handle_pending_status;
if (find_inferior (&all_threads, visit_actioned_threads, &data) != NULL)
return;
enable_async_io ();
@ -2782,7 +2826,7 @@ handle_status (char *own_buf)
/* If we're still out of luck, simply pick the first thread in
the thread list. */
if (thread == NULL)
thread = all_threads.head;
thread = get_first_inferior (&all_threads);
if (thread != NULL)
{
@ -3541,7 +3585,10 @@ process_serial_event (void)
(struct thread_info *) find_inferior_id (&all_threads,
general_thread);
if (thread == NULL)
thread_id = all_threads.head->id;
{
thread = get_first_thread ();
thread_id = thread->entry.id;
}
}
general_thread = thread_id;

View File

@ -34,7 +34,7 @@ set_desired_inferior (int use_general)
found = find_thread_ptid (cont_thread);
if (found == NULL)
current_inferior = (struct thread_info *) all_threads.head;
current_inferior = get_first_thread ();
else
current_inferior = found;
}

View File

@ -3943,6 +3943,17 @@ cmd_qtstmat (char *packet)
run_inferior_command (packet, strlen (packet) + 1);
}
/* Helper for gdb_agent_about_to_close.
Return non-zero if thread ENTRY is in the same process in DATA. */
static int
same_process_p (struct inferior_list_entry *entry, void *data)
{
int *pid = data;
return ptid_get_pid (entry->id) == *pid;
}
/* Sent the agent a command to close it. */
void
@ -3953,19 +3964,12 @@ gdb_agent_about_to_close (int pid)
if (!maybe_write_ipa_not_loaded (buf))
{
struct thread_info *save_inferior;
struct inferior_list_entry *inf = all_threads.head;
save_inferior = current_inferior;
/* Find a certain thread which belongs to process PID. */
while (inf != NULL)
{
if (ptid_get_pid (inf->id) == pid)
break;
inf = inf->next;
}
current_inferior = (struct thread_info *) inf;
/* Find any thread which belongs to process PID. */
current_inferior = (struct thread_info *)
find_inferior (&all_threads, same_process_p, &pid);
strcpy (buf, "close");

View File

@ -232,7 +232,7 @@ child_delete_thread (DWORD pid, DWORD tid)
ptid_t ptid;
/* If the last thread is exiting, just return. */
if (all_threads.head == all_threads.tail)
if (one_inferior_p (&all_threads))
return;
ptid = ptid_build (pid, tid, 0);
@ -1142,6 +1142,28 @@ failed:
}
#ifndef _WIN32_WCE
/* Helper routine for dll_is_loaded_by_basename.
Return non-zero if the basename in ARG matches the DLL in INF. */
static int
match_dll_by_basename (struct inferior_list_entry *inf, void *arg)
{
struct dll_info *iter = (void *) inf;
const char *basename = arg;
return strcasecmp (lbasename (iter->name), basename) == 0;
}
/* Return non-zero if the DLL specified by BASENAME is loaded. */
static int
dll_is_loaded_by_basename (const char *basename)
{
return find_inferior (&all_dlls, match_dll_by_basename,
(void *) basename) != NULL;
}
/* On certain versions of Windows, the information about ntdll.dll
is not available yet at the time we get the LOAD_DLL_DEBUG_EVENT,
thus preventing us from reporting this DLL as an SO. This has been
@ -1158,20 +1180,14 @@ failed:
static void
win32_ensure_ntdll_loaded (void)
{
struct inferior_list_entry *dll_e;
size_t i;
HMODULE dh_buf[1];
HMODULE *DllHandle = dh_buf;
DWORD cbNeeded;
BOOL ok;
for (dll_e = all_dlls.head; dll_e != NULL; dll_e = dll_e->next)
{
struct dll_info *dll = (struct dll_info *) dll_e;
if (strcasecmp (lbasename (dll->name), "ntdll.dll") == 0)
return;
}
if (dll_is_loaded_by_basename ("ntdll.dll"))
return;
if (!load_psapi ())
return;