* rs6000-tdep.c (BL_MASK, BL_INSTRUCTION, BL_DISPLACEMENT_MASK):
[deliverable/binutils-gdb.git] / gdb / gdbserver / inferiors.c
CommitLineData
ce3a066d 1/* Inferior process information for the remote server for GDB.
9b254dd1 2 Copyright (C) 2002, 2005, 2007, 2008 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{
255e7678 98 struct thread_info *new_thread = malloc (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 {
0d62e5e8
DJ
183 if ((*func) (inf, arg))
184 return inf;
185 inf = inf->next;
186 }
611cb4a5 187
0d62e5e8
DJ
188 return NULL;
189}
611cb4a5 190
0d62e5e8 191struct inferior_list_entry *
a1928bad 192find_inferior_id (struct inferior_list *list, unsigned long id)
0d62e5e8
DJ
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;
ce3a066d
DJ
201 }
202
0d62e5e8 203 return NULL;
ce3a066d 204}
611cb4a5
DJ
205
206void *
0d62e5e8 207inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
208{
209 return inferior->target_data;
210}
211
212void
0d62e5e8 213set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
214{
215 inferior->target_data = data;
216}
c04a1aa8
DJ
217
218void *
0d62e5e8 219inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
220{
221 return inferior->regcache_data;
222}
223
224void
0d62e5e8 225set_inferior_regcache_data (struct thread_info *inferior, void *data)
c04a1aa8
DJ
226{
227 inferior->regcache_data = data;
228}
255e7678
DJ
229
230static void
231free_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
242static int
243match_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
261void
262loaded_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
278void
279unloaded_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
297void
298clear_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);
7284e1be
UW
305
306 current_inferior = NULL;
255e7678 307}
24a09b5f
DJ
308
309/* Two utility functions for a truly degenerate inferior_list: a simple
310 PID listing. */
311
312void
313add_pid_to_list (struct inferior_list *list, unsigned long pid)
314{
315 struct inferior_list_entry *new_entry;
316
317 new_entry = malloc (sizeof (struct inferior_list_entry));
318 new_entry->id = pid;
319 add_inferior_to_list (list, new_entry);
320}
321
322int
323pull_pid_from_list (struct inferior_list *list, unsigned long pid)
324{
325 struct inferior_list_entry *new_entry;
326
327 new_entry = find_inferior_id (list, pid);
328 if (new_entry == NULL)
329 return 0;
330 else
331 {
332 remove_inferior (list, new_entry);
333 free (new_entry);
334 return 1;
335 }
336}
This page took 0.447971 seconds and 4 git commands to generate.