GDBserver
|
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 }