]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/inferiors.c
* regcache.c (realloc_register_cache): Invalidate inferior's
[thirdparty/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;
fc7238bb 174 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
0d62e5e8
DJ
175
176 add_inferior_to_list (&all_threads, & new_thread->entry);
255e7678 177
ce3a066d 178 if (current_inferior == NULL)
0d62e5e8 179 current_inferior = new_thread;
ce3a066d 180
0d62e5e8
DJ
181 new_thread->target_data = target_data;
182 set_inferior_regcache_data (new_thread, new_register_cache ());
a06660f7
DJ
183}
184
95954743
PA
185ptid_t
186thread_id_to_gdb_id (ptid_t thread_id)
a06660f7
DJ
187{
188 struct inferior_list_entry *inf = all_threads.head;
189
190 while (inf != NULL)
191 {
95954743
PA
192 if (ptid_equal (inf->id, thread_id))
193 return thread_id;
a06660f7
DJ
194 inf = inf->next;
195 }
196
95954743 197 return null_ptid;
a06660f7
DJ
198}
199
95954743 200ptid_t
a06660f7
DJ
201thread_to_gdb_id (struct thread_info *thread)
202{
95954743 203 return thread->entry.id;
a06660f7
DJ
204}
205
dae5f5cf 206struct thread_info *
e09875d4 207find_thread_ptid (ptid_t ptid)
a06660f7
DJ
208{
209 struct inferior_list_entry *inf = all_threads.head;
210
211 while (inf != NULL)
212 {
213 struct thread_info *thread = get_thread (inf);
95954743 214 if (ptid_equal (thread->entry.id, ptid))
dae5f5cf 215 return thread;
a06660f7
DJ
216 inf = inf->next;
217 }
218
dae5f5cf
DJ
219 return NULL;
220}
221
95954743
PA
222ptid_t
223gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 224{
e09875d4 225 struct thread_info *thread = find_thread_ptid (gdb_id);
dae5f5cf 226
95954743 227 return thread ? thread->entry.id : null_ptid;
0d62e5e8 228}
c04a1aa8 229
0d62e5e8
DJ
230static void
231free_one_thread (struct inferior_list_entry *inf)
232{
233 struct thread_info *thread = get_thread (inf);
234 free_register_cache (inferior_regcache_data (thread));
235 free (thread);
236}
237
238void
239remove_thread (struct thread_info *thread)
240{
241 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
242 free_one_thread (&thread->entry);
ce3a066d
DJ
243}
244
0718675c
JB
245/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
246 returns non-zero. If no entry is found then return NULL. */
247
0d62e5e8
DJ
248struct inferior_list_entry *
249find_inferior (struct inferior_list *list,
250 int (*func) (struct inferior_list_entry *, void *), void *arg)
251{
252 struct inferior_list_entry *inf = list->head;
ce3a066d 253
0d62e5e8 254 while (inf != NULL)
ce3a066d 255 {
a07b2135
PA
256 struct inferior_list_entry *next;
257
258 next = inf->next;
0d62e5e8
DJ
259 if ((*func) (inf, arg))
260 return inf;
a07b2135 261 inf = next;
0d62e5e8 262 }
611cb4a5 263
0d62e5e8
DJ
264 return NULL;
265}
611cb4a5 266
0d62e5e8 267struct inferior_list_entry *
95954743 268find_inferior_id (struct inferior_list *list, ptid_t id)
0d62e5e8
DJ
269{
270 struct inferior_list_entry *inf = list->head;
271
272 while (inf != NULL)
273 {
95954743 274 if (ptid_equal (inf->id, id))
0d62e5e8
DJ
275 return inf;
276 inf = inf->next;
ce3a066d
DJ
277 }
278
0d62e5e8 279 return NULL;
ce3a066d 280}
611cb4a5
DJ
281
282void *
0d62e5e8 283inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
284{
285 return inferior->target_data;
286}
287
288void
0d62e5e8 289set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
290{
291 inferior->target_data = data;
292}
c04a1aa8
DJ
293
294void *
0d62e5e8 295inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
296{
297 return inferior->regcache_data;
298}
299
300void
0d62e5e8 301set_inferior_regcache_data (struct thread_info *inferior, void *data)
c04a1aa8
DJ
302{
303 inferior->regcache_data = data;
304}
255e7678
DJ
305
306static void
307free_one_dll (struct inferior_list_entry *inf)
308{
309 struct dll_info *dll = get_dll (inf);
310 if (dll->name != NULL)
311 free (dll->name);
312 free (dll);
313}
314
315/* Find a DLL with the same name and/or base address. A NULL name in
316 the key is ignored; so is an all-ones base address. */
317
318static int
319match_dll (struct inferior_list_entry *inf, void *arg)
320{
321 struct dll_info *iter = (void *) inf;
322 struct dll_info *key = arg;
323
324 if (key->base_addr != ~(CORE_ADDR) 0
325 && iter->base_addr == key->base_addr)
326 return 1;
327 else if (key->name != NULL
328 && iter->name != NULL
329 && strcmp (key->name, iter->name) == 0)
330 return 1;
331
332 return 0;
333}
334
335/* Record a newly loaded DLL at BASE_ADDR. */
336
337void
338loaded_dll (const char *name, CORE_ADDR base_addr)
339{
bca929d3 340 struct dll_info *new_dll = xmalloc (sizeof (*new_dll));
255e7678
DJ
341 memset (new_dll, 0, sizeof (*new_dll));
342
95954743 343 new_dll->entry.id = minus_one_ptid;
255e7678 344
bca929d3 345 new_dll->name = xstrdup (name);
255e7678
DJ
346 new_dll->base_addr = base_addr;
347
348 add_inferior_to_list (&all_dlls, &new_dll->entry);
349 dlls_changed = 1;
350}
351
352/* Record that the DLL with NAME and BASE_ADDR has been unloaded. */
353
354void
355unloaded_dll (const char *name, CORE_ADDR base_addr)
356{
357 struct dll_info *dll;
358 struct dll_info key_dll;
359
360 /* Be careful not to put the key DLL in any list. */
361 key_dll.name = (char *) name;
362 key_dll.base_addr = base_addr;
363
364 dll = (void *) find_inferior (&all_dlls, match_dll, &key_dll);
0718675c
JB
365
366 if (dll == NULL)
367 /* For some inferiors we might get unloaded_dll events without having
368 a corresponding loaded_dll. In that case, the dll cannot be found
369 in ALL_DLL, and there is nothing further for us to do.
370
371 This has been observed when running 32bit executables on Windows64
372 (i.e. through WOW64, the interface between the 32bits and 64bits
373 worlds). In that case, the inferior always does some strange
374 unloading of unnamed dll. */
375 return;
376 else
377 {
378 /* DLL has been found so remove the entry and free associated
379 resources. */
380 remove_inferior (&all_dlls, &dll->entry);
381 free_one_dll (&dll->entry);
382 dlls_changed = 1;
383 }
255e7678
DJ
384}
385
386#define clear_list(LIST) \
387 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
388
389void
390clear_inferiors (void)
391{
392 for_each_inferior (&all_threads, free_one_thread);
393 for_each_inferior (&all_dlls, free_one_dll);
394
395 clear_list (&all_threads);
396 clear_list (&all_dlls);
7284e1be
UW
397
398 current_inferior = NULL;
255e7678 399}
24a09b5f
DJ
400
401/* Two utility functions for a truly degenerate inferior_list: a simple
402 PID listing. */
403
404void
405add_pid_to_list (struct inferior_list *list, unsigned long pid)
406{
407 struct inferior_list_entry *new_entry;
408
bca929d3 409 new_entry = xmalloc (sizeof (struct inferior_list_entry));
95954743 410 new_entry->id = pid_to_ptid (pid);
24a09b5f
DJ
411 add_inferior_to_list (list, new_entry);
412}
413
414int
415pull_pid_from_list (struct inferior_list *list, unsigned long pid)
416{
417 struct inferior_list_entry *new_entry;
418
95954743 419 new_entry = find_inferior_id (list, pid_to_ptid (pid));
24a09b5f
DJ
420 if (new_entry == NULL)
421 return 0;
422 else
423 {
424 remove_inferior (list, new_entry);
425 free (new_entry);
426 return 1;
427 }
428}
95954743
PA
429
430struct process_info *
431add_process (int pid, int attached)
432{
433 struct process_info *process;
434
435 process = xcalloc (1, sizeof (*process));
436
437 process->head.id = pid_to_ptid (pid);
438 process->attached = attached;
439
440 add_inferior_to_list (&all_processes, &process->head);
441
442 return process;
443}
444
5091eb23
DE
445/* Remove a process from the common process list and free the memory
446 allocated for it.
447 The caller is responsible for freeing private data first. */
448
95954743
PA
449void
450remove_process (struct process_info *process)
451{
452 clear_symbol_cache (&process->symbol_cache);
453 free_all_breakpoints (process);
454 remove_inferior (&all_processes, &process->head);
5091eb23 455 free (process);
95954743
PA
456}
457
458struct process_info *
459find_process_pid (int pid)
460{
461 return (struct process_info *)
462 find_inferior_id (&all_processes, pid_to_ptid (pid));
463}
464
9f767825
DE
465/* Return non-zero if INF, a struct process_info, was started by us,
466 i.e. not attached to. */
467
468static int
469started_inferior_callback (struct inferior_list_entry *entry, void *args)
470{
471 struct process_info *process = (struct process_info *) entry;
472
473 return ! process->attached;
474}
475
476/* Return non-zero if there are any inferiors that we have created
477 (as opposed to attached-to). */
478
479int
480have_started_inferiors_p (void)
481{
482 return (find_inferior (&all_processes, started_inferior_callback, NULL)
483 != NULL);
484}
485
486/* Return non-zero if INF, a struct process_info, was attached to. */
487
488static int
489attached_inferior_callback (struct inferior_list_entry *entry, void *args)
490{
491 struct process_info *process = (struct process_info *) entry;
492
493 return process->attached;
494}
495
496/* Return non-zero if there are any inferiors that we have attached to. */
497
498int
499have_attached_inferiors_p (void)
500{
501 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
502 != NULL);
503}
504
7fe519cb 505struct process_info *
95954743
PA
506get_thread_process (struct thread_info *thread)
507{
508 int pid = ptid_get_pid (thread->entry.id);
509 return find_process_pid (pid);
510}
511
512struct process_info *
513current_process (void)
514{
515 if (current_inferior == NULL)
516 fatal ("Current inferior requested, but current_inferior is NULL\n");
517
518 return get_thread_process (current_inferior);
519}
520
521void
522initialize_inferiors (void)
523{
524 null_ptid = ptid_build (0, 0, 0);
525 minus_one_ptid = ptid_build (-1, 0, 0);
526}