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