Update the copyright header of various files...
[deliverable/binutils-gdb.git] / gdb / gdbserver / inferiors.c
CommitLineData
ce3a066d 1/* Inferior process information for the remote server for GDB.
7b6bb8da 2 Copyright (C) 2002, 2005, 2007, 2008, 2009, 2010, 2011
4c38e0a4 3 Free Software Foundation, Inc.
ce3a066d
DJ
4
5 Contributed by MontaVista Software.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
ce3a066d
DJ
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
ce3a066d
DJ
21
22#include <stdlib.h>
23
24#include "server.h"
25
95954743 26struct inferior_list all_processes;
0d62e5e8 27struct inferior_list all_threads;
255e7678
DJ
28struct inferior_list all_dlls;
29int dlls_changed;
0d62e5e8
DJ
30
31struct thread_info *current_inferior;
32
33#define get_thread(inf) ((struct thread_info *)(inf))
255e7678 34#define get_dll(inf) ((struct dll_info *)(inf))
0d62e5e8
DJ
35
36void
37add_inferior_to_list (struct inferior_list *list,
38 struct inferior_list_entry *new_inferior)
39{
40 new_inferior->next = NULL;
41 if (list->tail != NULL)
42 list->tail->next = new_inferior;
43 else
44 list->head = new_inferior;
45 list->tail = new_inferior;
46}
47
9f767825
DE
48/* Invoke ACTION for each inferior in LIST. */
49
0d62e5e8
DJ
50void
51for_each_inferior (struct inferior_list *list,
52 void (*action) (struct inferior_list_entry *))
53{
54 struct inferior_list_entry *cur = list->head, *next;
55
56 while (cur != NULL)
57 {
58 next = cur->next;
59 (*action) (cur);
60 cur = next;
61 }
62}
ce3a066d 63
0d62e5e8
DJ
64void
65remove_inferior (struct inferior_list *list,
66 struct inferior_list_entry *entry)
67{
68 struct inferior_list_entry **cur;
ce3a066d 69
0d62e5e8
DJ
70 if (list->head == entry)
71 {
72 list->head = entry->next;
73 if (list->tail == entry)
74 list->tail = list->head;
75 return;
76 }
77
78 cur = &list->head;
79 while (*cur && (*cur)->next != entry)
80 cur = &(*cur)->next;
81
82 if (*cur == NULL)
83 return;
ce3a066d 84
0d62e5e8
DJ
85 (*cur)->next = entry->next;
86
87 if (list->tail == entry)
88 list->tail = *cur;
89}
90
91void
95954743 92add_thread (ptid_t thread_id, void *target_data)
0d62e5e8 93{
bca929d3 94 struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
0d62e5e8
DJ
95
96 memset (new_thread, 0, sizeof (*new_thread));
97
98 new_thread->entry.id = thread_id;
8336d594 99 new_thread->last_resume_kind = resume_continue;
fc7238bb 100 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
0d62e5e8
DJ
101
102 add_inferior_to_list (&all_threads, & new_thread->entry);
255e7678 103
ce3a066d 104 if (current_inferior == NULL)
0d62e5e8 105 current_inferior = new_thread;
ce3a066d 106
0d62e5e8
DJ
107 new_thread->target_data = target_data;
108 set_inferior_regcache_data (new_thread, new_register_cache ());
a06660f7
DJ
109}
110
95954743
PA
111ptid_t
112thread_id_to_gdb_id (ptid_t thread_id)
a06660f7
DJ
113{
114 struct inferior_list_entry *inf = all_threads.head;
115
116 while (inf != NULL)
117 {
95954743
PA
118 if (ptid_equal (inf->id, thread_id))
119 return thread_id;
a06660f7
DJ
120 inf = inf->next;
121 }
122
95954743 123 return null_ptid;
a06660f7
DJ
124}
125
95954743 126ptid_t
a06660f7
DJ
127thread_to_gdb_id (struct thread_info *thread)
128{
95954743 129 return thread->entry.id;
a06660f7
DJ
130}
131
dae5f5cf 132struct thread_info *
e09875d4 133find_thread_ptid (ptid_t ptid)
a06660f7
DJ
134{
135 struct inferior_list_entry *inf = all_threads.head;
136
137 while (inf != NULL)
138 {
139 struct thread_info *thread = get_thread (inf);
95954743 140 if (ptid_equal (thread->entry.id, ptid))
dae5f5cf 141 return thread;
a06660f7
DJ
142 inf = inf->next;
143 }
144
dae5f5cf
DJ
145 return NULL;
146}
147
95954743
PA
148ptid_t
149gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 150{
e09875d4 151 struct thread_info *thread = find_thread_ptid (gdb_id);
dae5f5cf 152
95954743 153 return thread ? thread->entry.id : null_ptid;
0d62e5e8 154}
c04a1aa8 155
0d62e5e8
DJ
156static void
157free_one_thread (struct inferior_list_entry *inf)
158{
159 struct thread_info *thread = get_thread (inf);
160 free_register_cache (inferior_regcache_data (thread));
161 free (thread);
162}
163
164void
165remove_thread (struct thread_info *thread)
166{
167 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
168 free_one_thread (&thread->entry);
ce3a066d
DJ
169}
170
0718675c
JB
171/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
172 returns non-zero. If no entry is found then return NULL. */
173
0d62e5e8
DJ
174struct inferior_list_entry *
175find_inferior (struct inferior_list *list,
176 int (*func) (struct inferior_list_entry *, void *), void *arg)
177{
178 struct inferior_list_entry *inf = list->head;
ce3a066d 179
0d62e5e8 180 while (inf != NULL)
ce3a066d 181 {
a07b2135
PA
182 struct inferior_list_entry *next;
183
184 next = inf->next;
0d62e5e8
DJ
185 if ((*func) (inf, arg))
186 return inf;
a07b2135 187 inf = next;
0d62e5e8 188 }
611cb4a5 189
0d62e5e8
DJ
190 return NULL;
191}
611cb4a5 192
0d62e5e8 193struct inferior_list_entry *
95954743 194find_inferior_id (struct inferior_list *list, ptid_t id)
0d62e5e8
DJ
195{
196 struct inferior_list_entry *inf = list->head;
197
198 while (inf != NULL)
199 {
95954743 200 if (ptid_equal (inf->id, id))
0d62e5e8
DJ
201 return inf;
202 inf = inf->next;
ce3a066d
DJ
203 }
204
0d62e5e8 205 return NULL;
ce3a066d 206}
611cb4a5
DJ
207
208void *
0d62e5e8 209inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
210{
211 return inferior->target_data;
212}
213
214void
0d62e5e8 215set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
216{
217 inferior->target_data = data;
218}
c04a1aa8
DJ
219
220void *
0d62e5e8 221inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
222{
223 return inferior->regcache_data;
224}
225
226void
0d62e5e8 227set_inferior_regcache_data (struct thread_info *inferior, void *data)
c04a1aa8
DJ
228{
229 inferior->regcache_data = data;
230}
255e7678
DJ
231
232static void
233free_one_dll (struct inferior_list_entry *inf)
234{
235 struct dll_info *dll = get_dll (inf);
236 if (dll->name != NULL)
237 free (dll->name);
238 free (dll);
239}
240
241/* Find a DLL with the same name and/or base address. A NULL name in
242 the key is ignored; so is an all-ones base address. */
243
244static int
245match_dll (struct inferior_list_entry *inf, void *arg)
246{
247 struct dll_info *iter = (void *) inf;
248 struct dll_info *key = arg;
249
250 if (key->base_addr != ~(CORE_ADDR) 0
251 && iter->base_addr == key->base_addr)
252 return 1;
253 else if (key->name != NULL
254 && iter->name != NULL
255 && strcmp (key->name, iter->name) == 0)
256 return 1;
257
258 return 0;
259}
260
261/* Record a newly loaded DLL at BASE_ADDR. */
262
263void
264loaded_dll (const char *name, CORE_ADDR base_addr)
265{
bca929d3 266 struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
255e7678
DJ
267 memset (new_dll, 0, sizeof (*new_dll));
268
95954743 269 new_dll->entry.id = minus_one_ptid;
255e7678 270
bca929d3 271 new_dll->name = xstrdup (name);
255e7678
DJ
272 new_dll->base_addr = base_addr;
273
274 add_inferior_to_list (&all_dlls, &new_dll->entry);
275 dlls_changed = 1;
276}
277
278/* Record that the DLL with NAME and BASE_ADDR has been unloaded. */
279
280void
281unloaded_dll (const char *name, CORE_ADDR base_addr)
282{
283 struct dll_info *dll;
284 struct dll_info key_dll;
285
286 /* Be careful not to put the key DLL in any list. */
287 key_dll.name = (char *) name;
288 key_dll.base_addr = base_addr;
289
290 dll = (void *) find_inferior (&all_dlls, match_dll, &key_dll);
0718675c
JB
291
292 if (dll == NULL)
293 /* For some inferiors we might get unloaded_dll events without having
294 a corresponding loaded_dll. In that case, the dll cannot be found
295 in ALL_DLL, and there is nothing further for us to do.
296
297 This has been observed when running 32bit executables on Windows64
298 (i.e. through WOW64, the interface between the 32bits and 64bits
299 worlds). In that case, the inferior always does some strange
300 unloading of unnamed dll. */
301 return;
302 else
303 {
304 /* DLL has been found so remove the entry and free associated
305 resources. */
306 remove_inferior (&all_dlls, &dll->entry);
307 free_one_dll (&dll->entry);
308 dlls_changed = 1;
309 }
255e7678
DJ
310}
311
312#define clear_list(LIST) \
313 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
314
315void
316clear_inferiors (void)
317{
318 for_each_inferior (&all_threads, free_one_thread);
319 for_each_inferior (&all_dlls, free_one_dll);
320
321 clear_list (&all_threads);
322 clear_list (&all_dlls);
7284e1be
UW
323
324 current_inferior = NULL;
255e7678 325}
24a09b5f
DJ
326
327/* Two utility functions for a truly degenerate inferior_list: a simple
328 PID listing. */
329
330void
331add_pid_to_list (struct inferior_list *list, unsigned long pid)
332{
333 struct inferior_list_entry *new_entry;
334
bca929d3 335 new_entry = xmalloc (sizeof (struct inferior_list_entry));
95954743 336 new_entry->id = pid_to_ptid (pid);
24a09b5f
DJ
337 add_inferior_to_list (list, new_entry);
338}
339
340int
341pull_pid_from_list (struct inferior_list *list, unsigned long pid)
342{
343 struct inferior_list_entry *new_entry;
344
95954743 345 new_entry = find_inferior_id (list, pid_to_ptid (pid));
24a09b5f
DJ
346 if (new_entry == NULL)
347 return 0;
348 else
349 {
350 remove_inferior (list, new_entry);
351 free (new_entry);
352 return 1;
353 }
354}
95954743
PA
355
356struct process_info *
357add_process (int pid, int attached)
358{
359 struct process_info *process;
360
361 process = xcalloc (1, sizeof (*process));
362
363 process->head.id = pid_to_ptid (pid);
364 process->attached = attached;
365
366 add_inferior_to_list (&all_processes, &process->head);
367
368 return process;
369}
370
5091eb23
DE
371/* Remove a process from the common process list and free the memory
372 allocated for it.
373 The caller is responsible for freeing private data first. */
374
95954743
PA
375void
376remove_process (struct process_info *process)
377{
378 clear_symbol_cache (&process->symbol_cache);
379 free_all_breakpoints (process);
380 remove_inferior (&all_processes, &process->head);
5091eb23 381 free (process);
95954743
PA
382}
383
384struct process_info *
385find_process_pid (int pid)
386{
387 return (struct process_info *)
388 find_inferior_id (&all_processes, pid_to_ptid (pid));
389}
390
9f767825
DE
391/* Return non-zero if INF, a struct process_info, was started by us,
392 i.e. not attached to. */
393
394static int
395started_inferior_callback (struct inferior_list_entry *entry, void *args)
396{
397 struct process_info *process = (struct process_info *) entry;
398
399 return ! process->attached;
400}
401
402/* Return non-zero if there are any inferiors that we have created
403 (as opposed to attached-to). */
404
405int
406have_started_inferiors_p (void)
407{
408 return (find_inferior (&all_processes, started_inferior_callback, NULL)
409 != NULL);
410}
411
412/* Return non-zero if INF, a struct process_info, was attached to. */
413
414static int
415attached_inferior_callback (struct inferior_list_entry *entry, void *args)
416{
417 struct process_info *process = (struct process_info *) entry;
418
419 return process->attached;
420}
421
422/* Return non-zero if there are any inferiors that we have attached to. */
423
424int
425have_attached_inferiors_p (void)
426{
427 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
428 != NULL);
429}
430
7fe519cb 431struct process_info *
95954743
PA
432get_thread_process (struct thread_info *thread)
433{
434 int pid = ptid_get_pid (thread->entry.id);
435 return find_process_pid (pid);
436}
437
438struct process_info *
439current_process (void)
440{
441 if (current_inferior == NULL)
442 fatal ("Current inferior requested, but current_inferior is NULL\n");
443
444 return get_thread_process (current_inferior);
445}
This page took 0.788716 seconds and 4 git commands to generate.