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