GDBserver
/home/stan/gdb/src/gdb/gdbserver/inferiors.c
Go to the documentation of this file.
00001 /* Inferior process information for the remote server for GDB.
00002    Copyright (C) 2002-2013 Free Software Foundation, Inc.
00003 
00004    Contributed by MontaVista Software.
00005 
00006    This file is part of GDB.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 3 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00020 
00021 #include <stdlib.h>
00022 
00023 #include "server.h"
00024 #include "gdbthread.h"
00025 #include "dll.h"
00026 
00027 struct inferior_list all_processes;
00028 struct inferior_list all_threads;
00029 
00030 struct thread_info *current_inferior;
00031 
00032 #define get_thread(inf) ((struct thread_info *)(inf))
00033 
00034 void
00035 add_inferior_to_list (struct inferior_list *list,
00036                       struct inferior_list_entry *new_inferior)
00037 {
00038   new_inferior->next = NULL;
00039   if (list->tail != NULL)
00040     list->tail->next = new_inferior;
00041   else
00042     list->head = new_inferior;
00043   list->tail = new_inferior;
00044 }
00045 
00046 /* Invoke ACTION for each inferior in LIST.  */
00047 
00048 void
00049 for_each_inferior (struct inferior_list *list,
00050                    void (*action) (struct inferior_list_entry *))
00051 {
00052   struct inferior_list_entry *cur = list->head, *next;
00053 
00054   while (cur != NULL)
00055     {
00056       next = cur->next;
00057       (*action) (cur);
00058       cur = next;
00059     }
00060 }
00061 
00062 void
00063 remove_inferior (struct inferior_list *list,
00064                  struct inferior_list_entry *entry)
00065 {
00066   struct inferior_list_entry **cur;
00067 
00068   if (list->head == entry)
00069     {
00070       list->head = entry->next;
00071       if (list->tail == entry)
00072         list->tail = list->head;
00073       return;
00074     }
00075 
00076   cur = &list->head;
00077   while (*cur && (*cur)->next != entry)
00078     cur = &(*cur)->next;
00079 
00080   if (*cur == NULL)
00081     return;
00082 
00083   (*cur)->next = entry->next;
00084 
00085   if (list->tail == entry)
00086     list->tail = *cur;
00087 }
00088 
00089 void
00090 add_thread (ptid_t thread_id, void *target_data)
00091 {
00092   struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
00093 
00094   memset (new_thread, 0, sizeof (*new_thread));
00095 
00096   new_thread->entry.id = thread_id;
00097   new_thread->last_resume_kind = resume_continue;
00098   new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
00099 
00100   add_inferior_to_list (&all_threads, & new_thread->entry);
00101 
00102   if (current_inferior == NULL)
00103     current_inferior = new_thread;
00104 
00105   new_thread->target_data = target_data;
00106 }
00107 
00108 ptid_t
00109 thread_id_to_gdb_id (ptid_t thread_id)
00110 {
00111   struct inferior_list_entry *inf = all_threads.head;
00112 
00113   while (inf != NULL)
00114     {
00115       if (ptid_equal (inf->id, thread_id))
00116         return thread_id;
00117       inf = inf->next;
00118     }
00119 
00120   return null_ptid;
00121 }
00122 
00123 ptid_t
00124 thread_to_gdb_id (struct thread_info *thread)
00125 {
00126   return thread->entry.id;
00127 }
00128 
00129 struct thread_info *
00130 find_thread_ptid (ptid_t ptid)
00131 {
00132   struct inferior_list_entry *inf = all_threads.head;
00133 
00134   while (inf != NULL)
00135     {
00136       struct thread_info *thread = get_thread (inf);
00137       if (ptid_equal (thread->entry.id, ptid))
00138         return thread;
00139       inf = inf->next;
00140     }
00141 
00142   return NULL;
00143 }
00144 
00145 ptid_t
00146 gdb_id_to_thread_id (ptid_t gdb_id)
00147 {
00148   struct thread_info *thread = find_thread_ptid (gdb_id);
00149 
00150   return thread ? thread->entry.id : null_ptid;
00151 }
00152 
00153 static void
00154 free_one_thread (struct inferior_list_entry *inf)
00155 {
00156   struct thread_info *thread = get_thread (inf);
00157   free_register_cache (inferior_regcache_data (thread));
00158   free (thread);
00159 }
00160 
00161 void
00162 remove_thread (struct thread_info *thread)
00163 {
00164   if (thread->btrace != NULL)
00165     target_disable_btrace (thread->btrace);
00166 
00167   remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
00168   free_one_thread (&thread->entry);
00169 }
00170 
00171 /* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
00172    returns non-zero.  If no entry is found then return NULL.  */
00173 
00174 struct inferior_list_entry *
00175 find_inferior (struct inferior_list *list,
00176                int (*func) (struct inferior_list_entry *, void *), void *arg)
00177 {
00178   struct inferior_list_entry *inf = list->head;
00179 
00180   while (inf != NULL)
00181     {
00182       struct inferior_list_entry *next;
00183 
00184       next = inf->next;
00185       if ((*func) (inf, arg))
00186         return inf;
00187       inf = next;
00188     }
00189 
00190   return NULL;
00191 }
00192 
00193 struct inferior_list_entry *
00194 find_inferior_id (struct inferior_list *list, ptid_t id)
00195 {
00196   struct inferior_list_entry *inf = list->head;
00197 
00198   while (inf != NULL)
00199     {
00200       if (ptid_equal (inf->id, id))
00201         return inf;
00202       inf = inf->next;
00203     }
00204 
00205   return NULL;
00206 }
00207 
00208 void *
00209 inferior_target_data (struct thread_info *inferior)
00210 {
00211   return inferior->target_data;
00212 }
00213 
00214 void
00215 set_inferior_target_data (struct thread_info *inferior, void *data)
00216 {
00217   inferior->target_data = data;
00218 }
00219 
00220 void *
00221 inferior_regcache_data (struct thread_info *inferior)
00222 {
00223   return inferior->regcache_data;
00224 }
00225 
00226 void
00227 set_inferior_regcache_data (struct thread_info *inferior, void *data)
00228 {
00229   inferior->regcache_data = data;
00230 }
00231 
00232 #define clear_list(LIST) \
00233   do { (LIST)->head = (LIST)->tail = NULL; } while (0)
00234 
00235 void
00236 clear_inferiors (void)
00237 {
00238   for_each_inferior (&all_threads, free_one_thread);
00239   clear_list (&all_threads);
00240 
00241   clear_dlls ();
00242 
00243   current_inferior = NULL;
00244 }
00245 
00246 struct process_info *
00247 add_process (int pid, int attached)
00248 {
00249   struct process_info *process;
00250 
00251   process = xcalloc (1, sizeof (*process));
00252 
00253   process->head.id = pid_to_ptid (pid);
00254   process->attached = attached;
00255 
00256   add_inferior_to_list (&all_processes, &process->head);
00257 
00258   return process;
00259 }
00260 
00261 /* Remove a process from the common process list and free the memory
00262    allocated for it.
00263    The caller is responsible for freeing private data first.  */
00264 
00265 void
00266 remove_process (struct process_info *process)
00267 {
00268   clear_symbol_cache (&process->symbol_cache);
00269   free_all_breakpoints (process);
00270   remove_inferior (&all_processes, &process->head);
00271   free (process);
00272 }
00273 
00274 struct process_info *
00275 find_process_pid (int pid)
00276 {
00277   return (struct process_info *)
00278     find_inferior_id (&all_processes, pid_to_ptid (pid));
00279 }
00280 
00281 /* Return non-zero if INF, a struct process_info, was started by us,
00282    i.e. not attached to.  */
00283 
00284 static int
00285 started_inferior_callback (struct inferior_list_entry *entry, void *args)
00286 {
00287   struct process_info *process = (struct process_info *) entry;
00288 
00289   return ! process->attached;
00290 }
00291 
00292 /* Return non-zero if there are any inferiors that we have created
00293    (as opposed to attached-to).  */
00294 
00295 int
00296 have_started_inferiors_p (void)
00297 {
00298   return (find_inferior (&all_processes, started_inferior_callback, NULL)
00299           != NULL);
00300 }
00301 
00302 /* Return non-zero if INF, a struct process_info, was attached to.  */
00303 
00304 static int
00305 attached_inferior_callback (struct inferior_list_entry *entry, void *args)
00306 {
00307   struct process_info *process = (struct process_info *) entry;
00308 
00309   return process->attached;
00310 }
00311 
00312 /* Return non-zero if there are any inferiors that we have attached to.  */
00313 
00314 int
00315 have_attached_inferiors_p (void)
00316 {
00317   return (find_inferior (&all_processes, attached_inferior_callback, NULL)
00318           != NULL);
00319 }
00320 
00321 struct process_info *
00322 get_thread_process (struct thread_info *thread)
00323 {
00324   int pid = ptid_get_pid (thread->entry.id);
00325   return find_process_pid (pid);
00326 }
00327 
00328 struct process_info *
00329 current_process (void)
00330 {
00331   if (current_inferior == NULL)
00332     fatal ("Current inferior requested, but current_inferior is NULL\n");
00333 
00334   return get_thread_process (current_inferior);
00335 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines