GDBserver disconnected tracing support.
[deliverable/binutils-gdb.git] / gdb / gdbserver / inferiors.c
1 /* Inferior process information for the remote server for GDB.
2 Copyright (C) 2002, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
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
11 the Free Software Foundation; either version 3 of the License, or
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
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include <stdlib.h>
23
24 #include "server.h"
25
26 struct inferior_list all_processes;
27 struct inferior_list all_threads;
28 struct inferior_list all_dlls;
29 int dlls_changed;
30
31 struct thread_info *current_inferior;
32
33
34 /* Oft used ptids */
35 ptid_t null_ptid;
36 ptid_t minus_one_ptid;
37
38 /* Create a ptid given the necessary PID, LWP, and TID components. */
39
40 ptid_t
41 ptid_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
53 ptid_t
54 pid_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
61 int
62 ptid_get_pid (ptid_t ptid)
63 {
64 return ptid.pid;
65 }
66
67 /* Fetch the lwp (lightweight process) component from a ptid. */
68
69 long
70 ptid_get_lwp (ptid_t ptid)
71 {
72 return ptid.lwp;
73 }
74
75 /* Fetch the tid (thread id) component from a ptid. */
76
77 long
78 ptid_get_tid (ptid_t ptid)
79 {
80 return ptid.tid;
81 }
82
83 /* ptid_equal() is used to test equality of two ptids. */
84
85 int
86 ptid_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
95 int
96 ptid_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
108 #define get_thread(inf) ((struct thread_info *)(inf))
109 #define get_dll(inf) ((struct dll_info *)(inf))
110
111 void
112 add_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
123 /* Invoke ACTION for each inferior in LIST. */
124
125 void
126 for_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 }
138
139 void
140 remove_inferior (struct inferior_list *list,
141 struct inferior_list_entry *entry)
142 {
143 struct inferior_list_entry **cur;
144
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;
159
160 (*cur)->next = entry->next;
161
162 if (list->tail == entry)
163 list->tail = *cur;
164 }
165
166 void
167 add_thread (ptid_t thread_id, void *target_data)
168 {
169 struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
170
171 memset (new_thread, 0, sizeof (*new_thread));
172
173 new_thread->entry.id = thread_id;
174 new_thread->last_resume_kind = resume_continue;
175 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
176
177 add_inferior_to_list (&all_threads, & new_thread->entry);
178
179 if (current_inferior == NULL)
180 current_inferior = new_thread;
181
182 new_thread->target_data = target_data;
183 set_inferior_regcache_data (new_thread, new_register_cache ());
184 }
185
186 ptid_t
187 thread_id_to_gdb_id (ptid_t thread_id)
188 {
189 struct inferior_list_entry *inf = all_threads.head;
190
191 while (inf != NULL)
192 {
193 if (ptid_equal (inf->id, thread_id))
194 return thread_id;
195 inf = inf->next;
196 }
197
198 return null_ptid;
199 }
200
201 ptid_t
202 thread_to_gdb_id (struct thread_info *thread)
203 {
204 return thread->entry.id;
205 }
206
207 struct thread_info *
208 find_thread_ptid (ptid_t ptid)
209 {
210 struct inferior_list_entry *inf = all_threads.head;
211
212 while (inf != NULL)
213 {
214 struct thread_info *thread = get_thread (inf);
215 if (ptid_equal (thread->entry.id, ptid))
216 return thread;
217 inf = inf->next;
218 }
219
220 return NULL;
221 }
222
223 ptid_t
224 gdb_id_to_thread_id (ptid_t gdb_id)
225 {
226 struct thread_info *thread = find_thread_ptid (gdb_id);
227
228 return thread ? thread->entry.id : null_ptid;
229 }
230
231 static void
232 free_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
239 void
240 remove_thread (struct thread_info *thread)
241 {
242 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
243 free_one_thread (&thread->entry);
244 }
245
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
249 struct inferior_list_entry *
250 find_inferior (struct inferior_list *list,
251 int (*func) (struct inferior_list_entry *, void *), void *arg)
252 {
253 struct inferior_list_entry *inf = list->head;
254
255 while (inf != NULL)
256 {
257 struct inferior_list_entry *next;
258
259 next = inf->next;
260 if ((*func) (inf, arg))
261 return inf;
262 inf = next;
263 }
264
265 return NULL;
266 }
267
268 struct inferior_list_entry *
269 find_inferior_id (struct inferior_list *list, ptid_t id)
270 {
271 struct inferior_list_entry *inf = list->head;
272
273 while (inf != NULL)
274 {
275 if (ptid_equal (inf->id, id))
276 return inf;
277 inf = inf->next;
278 }
279
280 return NULL;
281 }
282
283 void *
284 inferior_target_data (struct thread_info *inferior)
285 {
286 return inferior->target_data;
287 }
288
289 void
290 set_inferior_target_data (struct thread_info *inferior, void *data)
291 {
292 inferior->target_data = data;
293 }
294
295 void *
296 inferior_regcache_data (struct thread_info *inferior)
297 {
298 return inferior->regcache_data;
299 }
300
301 void
302 set_inferior_regcache_data (struct thread_info *inferior, void *data)
303 {
304 inferior->regcache_data = data;
305 }
306
307 static void
308 free_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
319 static int
320 match_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
338 void
339 loaded_dll (const char *name, CORE_ADDR base_addr)
340 {
341 struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
342 memset (new_dll, 0, sizeof (*new_dll));
343
344 new_dll->entry.id = minus_one_ptid;
345
346 new_dll->name = xstrdup (name);
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
355 void
356 unloaded_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);
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 }
385 }
386
387 #define clear_list(LIST) \
388 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
389
390 void
391 clear_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);
398
399 current_inferior = NULL;
400 }
401
402 /* Two utility functions for a truly degenerate inferior_list: a simple
403 PID listing. */
404
405 void
406 add_pid_to_list (struct inferior_list *list, unsigned long pid)
407 {
408 struct inferior_list_entry *new_entry;
409
410 new_entry = xmalloc (sizeof (struct inferior_list_entry));
411 new_entry->id = pid_to_ptid (pid);
412 add_inferior_to_list (list, new_entry);
413 }
414
415 int
416 pull_pid_from_list (struct inferior_list *list, unsigned long pid)
417 {
418 struct inferior_list_entry *new_entry;
419
420 new_entry = find_inferior_id (list, pid_to_ptid (pid));
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 }
430
431 struct process_info *
432 add_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
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
450 void
451 remove_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);
456 free (process);
457 }
458
459 struct process_info *
460 find_process_pid (int pid)
461 {
462 return (struct process_info *)
463 find_inferior_id (&all_processes, pid_to_ptid (pid));
464 }
465
466 /* Return non-zero if INF, a struct process_info, was started by us,
467 i.e. not attached to. */
468
469 static int
470 started_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
480 int
481 have_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
489 static int
490 attached_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
499 int
500 have_attached_inferiors_p (void)
501 {
502 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
503 != NULL);
504 }
505
506 struct process_info *
507 get_thread_process (struct thread_info *thread)
508 {
509 int pid = ptid_get_pid (thread->entry.id);
510 return find_process_pid (pid);
511 }
512
513 struct process_info *
514 current_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
522 void
523 initialize_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.048177 seconds and 5 git commands to generate.