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