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