OSDN Git Service

Updated copyright notices for most files.
[pf3gnuchains/pf3gnuchains3x.git] / gdb / gdbserver / inferiors.c
1 /* Inferior process information for the remote server for GDB.
2    Copyright (C) 2002, 2005, 2007, 2008 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 = malloc (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       if ((*func) (inf, arg))
184         return inf;
185       inf = inf->next;
186     }
187
188   return NULL;
189 }
190
191 struct inferior_list_entry *
192 find_inferior_id (struct inferior_list *list, unsigned long id)
193 {
194   struct inferior_list_entry *inf = list->head;
195
196   while (inf != NULL)
197     {
198       if (inf->id == id)
199         return inf;
200       inf = inf->next;
201     }
202
203   return NULL;
204 }
205
206 void *
207 inferior_target_data (struct thread_info *inferior)
208 {
209   return inferior->target_data;
210 }
211
212 void
213 set_inferior_target_data (struct thread_info *inferior, void *data)
214 {
215   inferior->target_data = data;
216 }
217
218 void *
219 inferior_regcache_data (struct thread_info *inferior)
220 {
221   return inferior->regcache_data;
222 }
223
224 void
225 set_inferior_regcache_data (struct thread_info *inferior, void *data)
226 {
227   inferior->regcache_data = data;
228 }
229
230 static void
231 free_one_dll (struct inferior_list_entry *inf)
232 {
233   struct dll_info *dll = get_dll (inf);
234   if (dll->name != NULL)
235     free (dll->name);
236   free (dll);
237 }
238
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.  */
241
242 static int
243 match_dll (struct inferior_list_entry *inf, void *arg)
244 {
245   struct dll_info *iter = (void *) inf;
246   struct dll_info *key = arg;
247
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;
255
256   return 0;
257 }
258
259 /* Record a newly loaded DLL at BASE_ADDR.  */
260
261 void
262 loaded_dll (const char *name, CORE_ADDR base_addr)
263 {
264   struct dll_info *new_dll = malloc (sizeof (*new_dll));
265   memset (new_dll, 0, sizeof (*new_dll));
266
267   new_dll->entry.id = -1;
268
269   new_dll->name = strdup (name);
270   new_dll->base_addr = base_addr;
271
272   add_inferior_to_list (&all_dlls, &new_dll->entry);
273   dlls_changed = 1;
274 }
275
276 /* Record that the DLL with NAME and BASE_ADDR has been unloaded.  */
277
278 void
279 unloaded_dll (const char *name, CORE_ADDR base_addr)
280 {
281   struct dll_info *dll;
282   struct dll_info key_dll;
283
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;
287
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;
292 }
293
294 #define clear_list(LIST) \
295   do { (LIST)->head = (LIST)->tail = NULL; } while (0)
296
297 void
298 clear_inferiors (void)
299 {
300   for_each_inferior (&all_threads, free_one_thread);
301   for_each_inferior (&all_dlls, free_one_dll);
302
303   clear_list (&all_threads);
304   clear_list (&all_dlls);
305 }
306
307 /* Two utility functions for a truly degenerate inferior_list: a simple
308    PID listing.  */
309
310 void
311 add_pid_to_list (struct inferior_list *list, unsigned long pid)
312 {
313   struct inferior_list_entry *new_entry;
314
315   new_entry = malloc (sizeof (struct inferior_list_entry));
316   new_entry->id = pid;
317   add_inferior_to_list (list, new_entry);
318 }
319
320 int
321 pull_pid_from_list (struct inferior_list *list, unsigned long pid)
322 {
323   struct inferior_list_entry *new_entry;
324
325   new_entry = find_inferior_id (list, pid);
326   if (new_entry == NULL)
327     return 0;
328   else
329     {
330       remove_inferior (list, new_entry);
331       free (new_entry);
332       return 1;
333     }
334 }