* ppc-linux-nat.c (ppc_linux_target_wordsize): New function.
[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
130void
131for_each_inferior (struct inferior_list *list,
132 void (*action) (struct inferior_list_entry *))
133{
134 struct inferior_list_entry *cur = list->head, *next;
135
136 while (cur != NULL)
137 {
138 next = cur->next;
139 (*action) (cur);
140 cur = next;
141 }
142}
ce3a066d 143
0d62e5e8
DJ
144void
145remove_inferior (struct inferior_list *list,
146 struct inferior_list_entry *entry)
147{
148 struct inferior_list_entry **cur;
ce3a066d 149
0d62e5e8
DJ
150 if (list->head == entry)
151 {
152 list->head = entry->next;
153 if (list->tail == entry)
154 list->tail = list->head;
155 return;
156 }
157
158 cur = &list->head;
159 while (*cur && (*cur)->next != entry)
160 cur = &(*cur)->next;
161
162 if (*cur == NULL)
163 return;
ce3a066d 164
0d62e5e8
DJ
165 (*cur)->next = entry->next;
166
167 if (list->tail == entry)
168 list->tail = *cur;
169}
170
171void
95954743 172add_thread (ptid_t thread_id, void *target_data)
0d62e5e8 173{
bca929d3 174 struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
0d62e5e8
DJ
175
176 memset (new_thread, 0, sizeof (*new_thread));
177
178 new_thread->entry.id = thread_id;
179
180 add_inferior_to_list (&all_threads, & new_thread->entry);
255e7678 181
ce3a066d 182 if (current_inferior == NULL)
0d62e5e8 183 current_inferior = new_thread;
ce3a066d 184
0d62e5e8
DJ
185 new_thread->target_data = target_data;
186 set_inferior_regcache_data (new_thread, new_register_cache ());
a06660f7
DJ
187}
188
95954743
PA
189ptid_t
190thread_id_to_gdb_id (ptid_t thread_id)
a06660f7
DJ
191{
192 struct inferior_list_entry *inf = all_threads.head;
193
194 while (inf != NULL)
195 {
95954743
PA
196 if (ptid_equal (inf->id, thread_id))
197 return thread_id;
a06660f7
DJ
198 inf = inf->next;
199 }
200
95954743 201 return null_ptid;
a06660f7
DJ
202}
203
95954743 204ptid_t
a06660f7
DJ
205thread_to_gdb_id (struct thread_info *thread)
206{
95954743 207 return thread->entry.id;
a06660f7
DJ
208}
209
dae5f5cf 210struct thread_info *
95954743 211find_thread_pid (ptid_t ptid)
a06660f7
DJ
212{
213 struct inferior_list_entry *inf = all_threads.head;
214
215 while (inf != NULL)
216 {
217 struct thread_info *thread = get_thread (inf);
95954743 218 if (ptid_equal (thread->entry.id, ptid))
dae5f5cf 219 return thread;
a06660f7
DJ
220 inf = inf->next;
221 }
222
dae5f5cf
DJ
223 return NULL;
224}
225
95954743
PA
226ptid_t
227gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 228{
95954743 229 struct thread_info *thread = find_thread_pid (gdb_id);
dae5f5cf 230
95954743 231 return thread ? thread->entry.id : null_ptid;
0d62e5e8 232}
c04a1aa8 233
0d62e5e8
DJ
234static void
235free_one_thread (struct inferior_list_entry *inf)
236{
237 struct thread_info *thread = get_thread (inf);
238 free_register_cache (inferior_regcache_data (thread));
239 free (thread);
240}
241
242void
243remove_thread (struct thread_info *thread)
244{
245 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
246 free_one_thread (&thread->entry);
ce3a066d
DJ
247}
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);
366 remove_inferior (&all_dlls, &dll->entry);
367 free_one_dll (&dll->entry);
368 dlls_changed = 1;
369}
370
371#define clear_list(LIST) \
372 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
373
374void
375clear_inferiors (void)
376{
377 for_each_inferior (&all_threads, free_one_thread);
378 for_each_inferior (&all_dlls, free_one_dll);
379
380 clear_list (&all_threads);
381 clear_list (&all_dlls);
7284e1be
UW
382
383 current_inferior = NULL;
255e7678 384}
24a09b5f
DJ
385
386/* Two utility functions for a truly degenerate inferior_list: a simple
387 PID listing. */
388
389void
390add_pid_to_list (struct inferior_list *list, unsigned long pid)
391{
392 struct inferior_list_entry *new_entry;
393
bca929d3 394 new_entry = xmalloc (sizeof (struct inferior_list_entry));
95954743 395 new_entry->id = pid_to_ptid (pid);
24a09b5f
DJ
396 add_inferior_to_list (list, new_entry);
397}
398
399int
400pull_pid_from_list (struct inferior_list *list, unsigned long pid)
401{
402 struct inferior_list_entry *new_entry;
403
95954743 404 new_entry = find_inferior_id (list, pid_to_ptid (pid));
24a09b5f
DJ
405 if (new_entry == NULL)
406 return 0;
407 else
408 {
409 remove_inferior (list, new_entry);
410 free (new_entry);
411 return 1;
412 }
413}
95954743
PA
414
415struct process_info *
416add_process (int pid, int attached)
417{
418 struct process_info *process;
419
420 process = xcalloc (1, sizeof (*process));
421
422 process->head.id = pid_to_ptid (pid);
423 process->attached = attached;
424
425 add_inferior_to_list (&all_processes, &process->head);
426
427 return process;
428}
429
430void
431remove_process (struct process_info *process)
432{
433 clear_symbol_cache (&process->symbol_cache);
434 free_all_breakpoints (process);
435 remove_inferior (&all_processes, &process->head);
436}
437
438struct process_info *
439find_process_pid (int pid)
440{
441 return (struct process_info *)
442 find_inferior_id (&all_processes, pid_to_ptid (pid));
443}
444
445static struct process_info *
446get_thread_process (struct thread_info *thread)
447{
448 int pid = ptid_get_pid (thread->entry.id);
449 return find_process_pid (pid);
450}
451
452struct process_info *
453current_process (void)
454{
455 if (current_inferior == NULL)
456 fatal ("Current inferior requested, but current_inferior is NULL\n");
457
458 return get_thread_process (current_inferior);
459}
460
461void
462initialize_inferiors (void)
463{
464 null_ptid = ptid_build (0, 0, 0);
465 minus_one_ptid = ptid_build (-1, 0, 0);
466}
This page took 0.586836 seconds and 4 git commands to generate.