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/>. */
27 struct inferior_list_entry entry;
33 struct inferior_list all_threads;
34 struct inferior_list all_dlls;
37 struct thread_info *current_inferior;
39 #define get_thread(inf) ((struct thread_info *)(inf))
40 #define get_dll(inf) ((struct dll_info *)(inf))
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;
50 list->head = new_inferior;
51 list->tail = new_inferior;
55 for_each_inferior (struct inferior_list *list,
56 void (*action) (struct inferior_list_entry *))
58 struct inferior_list_entry *cur = list->head, *next;
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;
83 while (*cur && (*cur)->next != entry)
89 (*cur)->next = entry->next;
91 if (list->tail == entry)
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;
115 thread_id_to_gdb_id (unsigned long thread_id)
117 struct inferior_list_entry *inf = all_threads.head;
121 struct thread_info *thread = get_thread (inf);
122 if (inf->id == thread_id)
123 return thread->gdb_id;
131 thread_to_gdb_id (struct thread_info *thread)
133 return thread->gdb_id;
137 gdb_id_to_thread (unsigned int gdb_id)
139 struct inferior_list_entry *inf = all_threads.head;
143 struct thread_info *thread = get_thread (inf);
144 if (thread->gdb_id == gdb_id)
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;
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));
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;
183 if ((*func) (inf, arg))
191 struct inferior_list_entry *
192 find_inferior_id (struct inferior_list *list, unsigned long id)
194 struct inferior_list_entry *inf = list->head;
207 inferior_target_data (struct thread_info *inferior)
209 return inferior->target_data;
213 set_inferior_target_data (struct thread_info *inferior, void *data)
215 inferior->target_data = data;
219 inferior_regcache_data (struct thread_info *inferior)
221 return inferior->regcache_data;
225 set_inferior_regcache_data (struct thread_info *inferior, void *data)
227 inferior->regcache_data = data;
231 free_one_dll (struct inferior_list_entry *inf)
233 struct dll_info *dll = get_dll (inf);
234 if (dll->name != NULL)
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. */
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)
251 else if (key->name != NULL
252 && iter->name != NULL
253 && strcmp (key->name, iter->name) == 0)
259 /* Record a newly loaded DLL at BASE_ADDR. */
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);
276 /* Record that the DLL with NAME and BASE_ADDR has been unloaded. */
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);
294 #define clear_list(LIST) \
295 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
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
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));
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)
330 remove_inferior (list, new_entry);