* inferiors.c (find_inferior): Make it safe for the callback
[deliverable/binutils-gdb.git] / gdb / gdbserver / inferiors.c
1 /* Inferior process information for the remote server for GDB.
2 Copyright (C) 2002, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
3
4 Contributed by MontaVista Software.
5
6 This file is part of GDB.
7
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.
12
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.
17
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/>. */
20
21 #include <stdlib.h>
22
23 #include "server.h"
24
25 struct thread_info
26 {
27 struct inferior_list_entry entry;
28 void *target_data;
29 void *regcache_data;
30 unsigned int gdb_id;
31 };
32
33 struct inferior_list all_threads;
34 struct inferior_list all_dlls;
35 int dlls_changed;
36
37 struct thread_info *current_inferior;
38
39 #define get_thread(inf) ((struct thread_info *)(inf))
40 #define get_dll(inf) ((struct dll_info *)(inf))
41
42 void
43 add_inferior_to_list (struct inferior_list *list,
44 struct inferior_list_entry *new_inferior)
45 {
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;
52 }
53
54 void
55 for_each_inferior (struct inferior_list *list,
56 void (*action) (struct inferior_list_entry *))
57 {
58 struct inferior_list_entry *cur = list->head, *next;
59
60 while (cur != NULL)
61 {
62 next = cur->next;
63 (*action) (cur);
64 cur = next;
65 }
66 }
67
68 void
69 remove_inferior (struct inferior_list *list,
70 struct inferior_list_entry *entry)
71 {
72 struct inferior_list_entry **cur;
73
74 if (list->head == entry)
75 {
76 list->head = entry->next;
77 if (list->tail == entry)
78 list->tail = list->head;
79 return;
80 }
81
82 cur = &list->head;
83 while (*cur && (*cur)->next != entry)
84 cur = &(*cur)->next;
85
86 if (*cur == NULL)
87 return;
88
89 (*cur)->next = entry->next;
90
91 if (list->tail == entry)
92 list->tail = *cur;
93 }
94
95 void
96 add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
97 {
98 struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
99
100 memset (new_thread, 0, sizeof (*new_thread));
101
102 new_thread->entry.id = thread_id;
103
104 add_inferior_to_list (&all_threads, & new_thread->entry);
105
106 if (current_inferior == NULL)
107 current_inferior = new_thread;
108
109 new_thread->target_data = target_data;
110 set_inferior_regcache_data (new_thread, new_register_cache ());
111 new_thread->gdb_id = gdb_id;
112 }
113
114 unsigned int
115 thread_id_to_gdb_id (unsigned long thread_id)
116 {
117 struct inferior_list_entry *inf = all_threads.head;
118
119 while (inf != NULL)
120 {
121 struct thread_info *thread = get_thread (inf);
122 if (inf->id == thread_id)
123 return thread->gdb_id;
124 inf = inf->next;
125 }
126
127 return 0;
128 }
129
130 unsigned int
131 thread_to_gdb_id (struct thread_info *thread)
132 {
133 return thread->gdb_id;
134 }
135
136 struct thread_info *
137 gdb_id_to_thread (unsigned int gdb_id)
138 {
139 struct inferior_list_entry *inf = all_threads.head;
140
141 while (inf != NULL)
142 {
143 struct thread_info *thread = get_thread (inf);
144 if (thread->gdb_id == gdb_id)
145 return thread;
146 inf = inf->next;
147 }
148
149 return NULL;
150 }
151
152 unsigned long
153 gdb_id_to_thread_id (unsigned int gdb_id)
154 {
155 struct thread_info *thread = gdb_id_to_thread (gdb_id);
156
157 return thread ? thread->entry.id : 0;
158 }
159
160 static void
161 free_one_thread (struct inferior_list_entry *inf)
162 {
163 struct thread_info *thread = get_thread (inf);
164 free_register_cache (inferior_regcache_data (thread));
165 free (thread);
166 }
167
168 void
169 remove_thread (struct thread_info *thread)
170 {
171 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
172 free_one_thread (&thread->entry);
173 }
174
175 struct inferior_list_entry *
176 find_inferior (struct inferior_list *list,
177 int (*func) (struct inferior_list_entry *, void *), void *arg)
178 {
179 struct inferior_list_entry *inf = list->head;
180
181 while (inf != NULL)
182 {
183 struct inferior_list_entry *next;
184
185 next = inf->next;
186 if ((*func) (inf, arg))
187 return inf;
188 inf = next;
189 }
190
191 return NULL;
192 }
193
194 struct inferior_list_entry *
195 find_inferior_id (struct inferior_list *list, unsigned long id)
196 {
197 struct inferior_list_entry *inf = list->head;
198
199 while (inf != NULL)
200 {
201 if (inf->id == id)
202 return inf;
203 inf = inf->next;
204 }
205
206 return NULL;
207 }
208
209 void *
210 inferior_target_data (struct thread_info *inferior)
211 {
212 return inferior->target_data;
213 }
214
215 void
216 set_inferior_target_data (struct thread_info *inferior, void *data)
217 {
218 inferior->target_data = data;
219 }
220
221 void *
222 inferior_regcache_data (struct thread_info *inferior)
223 {
224 return inferior->regcache_data;
225 }
226
227 void
228 set_inferior_regcache_data (struct thread_info *inferior, void *data)
229 {
230 inferior->regcache_data = data;
231 }
232
233 static void
234 free_one_dll (struct inferior_list_entry *inf)
235 {
236 struct dll_info *dll = get_dll (inf);
237 if (dll->name != NULL)
238 free (dll->name);
239 free (dll);
240 }
241
242 /* Find a DLL with the same name and/or base address. A NULL name in
243 the key is ignored; so is an all-ones base address. */
244
245 static int
246 match_dll (struct inferior_list_entry *inf, void *arg)
247 {
248 struct dll_info *iter = (void *) inf;
249 struct dll_info *key = arg;
250
251 if (key->base_addr != ~(CORE_ADDR) 0
252 && iter->base_addr == key->base_addr)
253 return 1;
254 else if (key->name != NULL
255 && iter->name != NULL
256 && strcmp (key->name, iter->name) == 0)
257 return 1;
258
259 return 0;
260 }
261
262 /* Record a newly loaded DLL at BASE_ADDR. */
263
264 void
265 loaded_dll (const char *name, CORE_ADDR base_addr)
266 {
267 struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
268 memset (new_dll, 0, sizeof (*new_dll));
269
270 new_dll->entry.id = -1;
271
272 new_dll->name = xstrdup (name);
273 new_dll->base_addr = base_addr;
274
275 add_inferior_to_list (&all_dlls, &new_dll->entry);
276 dlls_changed = 1;
277 }
278
279 /* Record that the DLL with NAME and BASE_ADDR has been unloaded. */
280
281 void
282 unloaded_dll (const char *name, CORE_ADDR base_addr)
283 {
284 struct dll_info *dll;
285 struct dll_info key_dll;
286
287 /* Be careful not to put the key DLL in any list. */
288 key_dll.name = (char *) name;
289 key_dll.base_addr = base_addr;
290
291 dll = (void *) find_inferior (&all_dlls, match_dll, &key_dll);
292 remove_inferior (&all_dlls, &dll->entry);
293 free_one_dll (&dll->entry);
294 dlls_changed = 1;
295 }
296
297 #define clear_list(LIST) \
298 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
299
300 void
301 clear_inferiors (void)
302 {
303 for_each_inferior (&all_threads, free_one_thread);
304 for_each_inferior (&all_dlls, free_one_dll);
305
306 clear_list (&all_threads);
307 clear_list (&all_dlls);
308
309 current_inferior = NULL;
310 }
311
312 /* Two utility functions for a truly degenerate inferior_list: a simple
313 PID listing. */
314
315 void
316 add_pid_to_list (struct inferior_list *list, unsigned long pid)
317 {
318 struct inferior_list_entry *new_entry;
319
320 new_entry = xmalloc (sizeof (struct inferior_list_entry));
321 new_entry->id = pid;
322 add_inferior_to_list (list, new_entry);
323 }
324
325 int
326 pull_pid_from_list (struct inferior_list *list, unsigned long pid)
327 {
328 struct inferior_list_entry *new_entry;
329
330 new_entry = find_inferior_id (list, pid);
331 if (new_entry == NULL)
332 return 0;
333 else
334 {
335 remove_inferior (list, new_entry);
336 free (new_entry);
337 return 1;
338 }
339 }
This page took 0.046027 seconds and 5 git commands to generate.