Update
[gdb.git] / gdb / gdbserver / inferiors.c
blobdaf7aaf0a1fa70ee17b45b71523f6e1222450fa0
1 /* Inferior process information for the remote server for GDB.
2 Copyright (C) 2002, 2005, 2007, 2008 Free Software Foundation, Inc.
4 Contributed by MontaVista Software.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include <stdlib.h>
23 #include "server.h"
25 struct thread_info
27 struct inferior_list_entry entry;
28 void *target_data;
29 void *regcache_data;
30 unsigned int gdb_id;
33 struct inferior_list all_threads;
34 struct inferior_list all_dlls;
35 int dlls_changed;
37 struct thread_info *current_inferior;
39 #define get_thread(inf) ((struct thread_info *)(inf))
40 #define get_dll(inf) ((struct dll_info *)(inf))
42 void
43 add_inferior_to_list (struct inferior_list *list,
44 struct inferior_list_entry *new_inferior)
46 new_inferior->next = NULL;
47 if (list->tail != NULL)
48 list->tail->next = new_inferior;
49 else
50 list->head = new_inferior;
51 list->tail = new_inferior;
54 void
55 for_each_inferior (struct inferior_list *list,
56 void (*action) (struct inferior_list_entry *))
58 struct inferior_list_entry *cur = list->head, *next;
60 while (cur != NULL)
62 next = cur->next;
63 (*action) (cur);
64 cur = next;
68 void
69 remove_inferior (struct inferior_list *list,
70 struct inferior_list_entry *entry)
72 struct inferior_list_entry **cur;
74 if (list->head == entry)
76 list->head = entry->next;
77 if (list->tail == entry)
78 list->tail = list->head;
79 return;
82 cur = &list->head;
83 while (*cur && (*cur)->next != entry)
84 cur = &(*cur)->next;
86 if (*cur == NULL)
87 return;
89 (*cur)->next = entry->next;
91 if (list->tail == entry)
92 list->tail = *cur;
95 void
96 add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
98 struct thread_info *new_thread = malloc (sizeof (*new_thread));
100 memset (new_thread, 0, sizeof (*new_thread));
102 new_thread->entry.id = thread_id;
104 add_inferior_to_list (&all_threads, & new_thread->entry);
106 if (current_inferior == NULL)
107 current_inferior = new_thread;
109 new_thread->target_data = target_data;
110 set_inferior_regcache_data (new_thread, new_register_cache ());
111 new_thread->gdb_id = gdb_id;
114 unsigned int
115 thread_id_to_gdb_id (unsigned long thread_id)
117 struct inferior_list_entry *inf = all_threads.head;
119 while (inf != NULL)
121 struct thread_info *thread = get_thread (inf);
122 if (inf->id == thread_id)
123 return thread->gdb_id;
124 inf = inf->next;
127 return 0;
130 unsigned int
131 thread_to_gdb_id (struct thread_info *thread)
133 return thread->gdb_id;
136 struct thread_info *
137 gdb_id_to_thread (unsigned int gdb_id)
139 struct inferior_list_entry *inf = all_threads.head;
141 while (inf != NULL)
143 struct thread_info *thread = get_thread (inf);
144 if (thread->gdb_id == gdb_id)
145 return thread;
146 inf = inf->next;
149 return NULL;
152 unsigned long
153 gdb_id_to_thread_id (unsigned int gdb_id)
155 struct thread_info *thread = gdb_id_to_thread (gdb_id);
157 return thread ? thread->entry.id : 0;
160 static void
161 free_one_thread (struct inferior_list_entry *inf)
163 struct thread_info *thread = get_thread (inf);
164 free_register_cache (inferior_regcache_data (thread));
165 free (thread);
168 void
169 remove_thread (struct thread_info *thread)
171 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
172 free_one_thread (&thread->entry);
175 struct inferior_list_entry *
176 find_inferior (struct inferior_list *list,
177 int (*func) (struct inferior_list_entry *, void *), void *arg)
179 struct inferior_list_entry *inf = list->head;
181 while (inf != NULL)
183 if ((*func) (inf, arg))
184 return inf;
185 inf = inf->next;
188 return NULL;
191 struct inferior_list_entry *
192 find_inferior_id (struct inferior_list *list, unsigned long id)
194 struct inferior_list_entry *inf = list->head;
196 while (inf != NULL)
198 if (inf->id == id)
199 return inf;
200 inf = inf->next;
203 return NULL;
206 void *
207 inferior_target_data (struct thread_info *inferior)
209 return inferior->target_data;
212 void
213 set_inferior_target_data (struct thread_info *inferior, void *data)
215 inferior->target_data = data;
218 void *
219 inferior_regcache_data (struct thread_info *inferior)
221 return inferior->regcache_data;
224 void
225 set_inferior_regcache_data (struct thread_info *inferior, void *data)
227 inferior->regcache_data = data;
230 static void
231 free_one_dll (struct inferior_list_entry *inf)
233 struct dll_info *dll = get_dll (inf);
234 if (dll->name != NULL)
235 free (dll->name);
236 free (dll);
239 /* Find a DLL with the same name and/or base address. A NULL name in
240 the key is ignored; so is an all-ones base address. */
242 static int
243 match_dll (struct inferior_list_entry *inf, void *arg)
245 struct dll_info *iter = (void *) inf;
246 struct dll_info *key = arg;
248 if (key->base_addr != ~(CORE_ADDR) 0
249 && iter->base_addr == key->base_addr)
250 return 1;
251 else if (key->name != NULL
252 && iter->name != NULL
253 && strcmp (key->name, iter->name) == 0)
254 return 1;
256 return 0;
259 /* Record a newly loaded DLL at BASE_ADDR. */
261 void
262 loaded_dll (const char *name, CORE_ADDR base_addr)
264 struct dll_info *new_dll = malloc (sizeof (*new_dll));
265 memset (new_dll, 0, sizeof (*new_dll));
267 new_dll->entry.id = -1;
269 new_dll->name = strdup (name);
270 new_dll->base_addr = base_addr;
272 add_inferior_to_list (&all_dlls, &new_dll->entry);
273 dlls_changed = 1;
276 /* Record that the DLL with NAME and BASE_ADDR has been unloaded. */
278 void
279 unloaded_dll (const char *name, CORE_ADDR base_addr)
281 struct dll_info *dll;
282 struct dll_info key_dll;
284 /* Be careful not to put the key DLL in any list. */
285 key_dll.name = (char *) name;
286 key_dll.base_addr = base_addr;
288 dll = (void *) find_inferior (&all_dlls, match_dll, &key_dll);
289 remove_inferior (&all_dlls, &dll->entry);
290 free_one_dll (&dll->entry);
291 dlls_changed = 1;
294 #define clear_list(LIST) \
295 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
297 void
298 clear_inferiors (void)
300 for_each_inferior (&all_threads, free_one_thread);
301 for_each_inferior (&all_dlls, free_one_dll);
303 clear_list (&all_threads);
304 clear_list (&all_dlls);
307 /* Two utility functions for a truly degenerate inferior_list: a simple
308 PID listing. */
310 void
311 add_pid_to_list (struct inferior_list *list, unsigned long pid)
313 struct inferior_list_entry *new_entry;
315 new_entry = malloc (sizeof (struct inferior_list_entry));
316 new_entry->id = pid;
317 add_inferior_to_list (list, new_entry);
321 pull_pid_from_list (struct inferior_list *list, unsigned long pid)
323 struct inferior_list_entry *new_entry;
325 new_entry = find_inferior_id (list, pid);
326 if (new_entry == NULL)
327 return 0;
328 else
330 remove_inferior (list, new_entry);
331 free (new_entry);
332 return 1;