]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/inferiors.c
Non-stop mode support.
[thirdparty/binutils-gdb.git] / gdb / gdbserver / inferiors.c
CommitLineData
ce3a066d 1/* Inferior process information for the remote server for GDB.
0fb0cc75 2 Copyright (C) 2002, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
ce3a066d
DJ
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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
ce3a066d
DJ
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
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
ce3a066d
DJ
20
21#include <stdlib.h>
22
23#include "server.h"
24
0d62e5e8 25struct thread_info
ce3a066d 26{
0d62e5e8 27 struct inferior_list_entry entry;
611cb4a5 28 void *target_data;
c04a1aa8 29 void *regcache_data;
a06660f7 30 unsigned int gdb_id;
ce3a066d
DJ
31};
32
0d62e5e8 33struct inferior_list all_threads;
255e7678
DJ
34struct inferior_list all_dlls;
35int dlls_changed;
0d62e5e8
DJ
36
37struct thread_info *current_inferior;
38
39#define get_thread(inf) ((struct thread_info *)(inf))
255e7678 40#define get_dll(inf) ((struct dll_info *)(inf))
0d62e5e8
DJ
41
42void
43add_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
54void
55for_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}
ce3a066d 67
0d62e5e8
DJ
68void
69remove_inferior (struct inferior_list *list,
70 struct inferior_list_entry *entry)
71{
72 struct inferior_list_entry **cur;
ce3a066d 73
0d62e5e8
DJ
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;
ce3a066d 88
0d62e5e8
DJ
89 (*cur)->next = entry->next;
90
91 if (list->tail == entry)
92 list->tail = *cur;
93}
94
95void
a06660f7 96add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
0d62e5e8 97{
bca929d3 98 struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
0d62e5e8
DJ
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);
255e7678 105
ce3a066d 106 if (current_inferior == NULL)
0d62e5e8 107 current_inferior = new_thread;
ce3a066d 108
0d62e5e8
DJ
109 new_thread->target_data = target_data;
110 set_inferior_regcache_data (new_thread, new_register_cache ());
a06660f7
DJ
111 new_thread->gdb_id = gdb_id;
112}
113
114unsigned int
115thread_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
130unsigned int
131thread_to_gdb_id (struct thread_info *thread)
132{
133 return thread->gdb_id;
134}
135
dae5f5cf
DJ
136struct thread_info *
137gdb_id_to_thread (unsigned int gdb_id)
a06660f7
DJ
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)
dae5f5cf 145 return thread;
a06660f7
DJ
146 inf = inf->next;
147 }
148
dae5f5cf
DJ
149 return NULL;
150}
151
152unsigned long
153gdb_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;
0d62e5e8 158}
c04a1aa8 159
0d62e5e8
DJ
160static void
161free_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
168void
169remove_thread (struct thread_info *thread)
170{
171 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
172 free_one_thread (&thread->entry);
ce3a066d
DJ
173}
174
0d62e5e8
DJ
175struct inferior_list_entry *
176find_inferior (struct inferior_list *list,
177 int (*func) (struct inferior_list_entry *, void *), void *arg)
178{
179 struct inferior_list_entry *inf = list->head;
ce3a066d 180
0d62e5e8 181 while (inf != NULL)
ce3a066d 182 {
a07b2135
PA
183 struct inferior_list_entry *next;
184
185 next = inf->next;
0d62e5e8
DJ
186 if ((*func) (inf, arg))
187 return inf;
a07b2135 188 inf = next;
0d62e5e8 189 }
611cb4a5 190
0d62e5e8
DJ
191 return NULL;
192}
611cb4a5 193
0d62e5e8 194struct inferior_list_entry *
a1928bad 195find_inferior_id (struct inferior_list *list, unsigned long id)
0d62e5e8
DJ
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;
ce3a066d
DJ
204 }
205
0d62e5e8 206 return NULL;
ce3a066d 207}
611cb4a5
DJ
208
209void *
0d62e5e8 210inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
211{
212 return inferior->target_data;
213}
214
215void
0d62e5e8 216set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
217{
218 inferior->target_data = data;
219}
c04a1aa8
DJ
220
221void *
0d62e5e8 222inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
223{
224 return inferior->regcache_data;
225}
226
227void
0d62e5e8 228set_inferior_regcache_data (struct thread_info *inferior, void *data)
c04a1aa8
DJ
229{
230 inferior->regcache_data = data;
231}
255e7678
DJ
232
233static void
234free_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
245static int
246match_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
264void
265loaded_dll (const char *name, CORE_ADDR base_addr)
266{
bca929d3 267 struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
255e7678
DJ
268 memset (new_dll, 0, sizeof (*new_dll));
269
270 new_dll->entry.id = -1;
271
bca929d3 272 new_dll->name = xstrdup (name);
255e7678
DJ
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
281void
282unloaded_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
300void
301clear_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);
7284e1be
UW
308
309 current_inferior = NULL;
255e7678 310}
24a09b5f
DJ
311
312/* Two utility functions for a truly degenerate inferior_list: a simple
313 PID listing. */
314
315void
316add_pid_to_list (struct inferior_list *list, unsigned long pid)
317{
318 struct inferior_list_entry *new_entry;
319
bca929d3 320 new_entry = xmalloc (sizeof (struct inferior_list_entry));
24a09b5f
DJ
321 new_entry->id = pid;
322 add_inferior_to_list (list, new_entry);
323}
324
325int
326pull_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}