1 /* Inferior process information for the remote server for GDB.
2 Copyright (C) 2002, 2005, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
5 Contributed by MontaVista Software.
7 This file is part of GDB.
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.
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.
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/>. */
26 struct inferior_list all_processes
;
27 struct inferior_list all_threads
;
28 struct inferior_list all_dlls
;
31 struct thread_info
*current_inferior
;
33 #define get_thread(inf) ((struct thread_info *)(inf))
34 #define get_dll(inf) ((struct dll_info *)(inf))
37 add_inferior_to_list (struct inferior_list
*list
,
38 struct inferior_list_entry
*new_inferior
)
40 new_inferior
->next
= NULL
;
41 if (list
->tail
!= NULL
)
42 list
->tail
->next
= new_inferior
;
44 list
->head
= new_inferior
;
45 list
->tail
= new_inferior
;
48 /* Invoke ACTION for each inferior in LIST. */
51 for_each_inferior (struct inferior_list
*list
,
52 void (*action
) (struct inferior_list_entry
*))
54 struct inferior_list_entry
*cur
= list
->head
, *next
;
65 remove_inferior (struct inferior_list
*list
,
66 struct inferior_list_entry
*entry
)
68 struct inferior_list_entry
**cur
;
70 if (list
->head
== entry
)
72 list
->head
= entry
->next
;
73 if (list
->tail
== entry
)
74 list
->tail
= list
->head
;
79 while (*cur
&& (*cur
)->next
!= entry
)
85 (*cur
)->next
= entry
->next
;
87 if (list
->tail
== entry
)
92 add_thread (ptid_t thread_id
, void *target_data
)
94 struct thread_info
*new_thread
= xmalloc (sizeof (*new_thread
));
96 memset (new_thread
, 0, sizeof (*new_thread
));
98 new_thread
->entry
.id
= thread_id
;
99 new_thread
->last_resume_kind
= resume_continue
;
100 new_thread
->last_status
.kind
= TARGET_WAITKIND_IGNORE
;
102 add_inferior_to_list (&all_threads
, & new_thread
->entry
);
104 if (current_inferior
== NULL
)
105 current_inferior
= new_thread
;
107 new_thread
->target_data
= target_data
;
108 set_inferior_regcache_data (new_thread
, new_register_cache ());
112 thread_id_to_gdb_id (ptid_t thread_id
)
114 struct inferior_list_entry
*inf
= all_threads
.head
;
118 if (ptid_equal (inf
->id
, thread_id
))
127 thread_to_gdb_id (struct thread_info
*thread
)
129 return thread
->entry
.id
;
133 find_thread_ptid (ptid_t ptid
)
135 struct inferior_list_entry
*inf
= all_threads
.head
;
139 struct thread_info
*thread
= get_thread (inf
);
140 if (ptid_equal (thread
->entry
.id
, ptid
))
149 gdb_id_to_thread_id (ptid_t gdb_id
)
151 struct thread_info
*thread
= find_thread_ptid (gdb_id
);
153 return thread
? thread
->entry
.id
: null_ptid
;
157 free_one_thread (struct inferior_list_entry
*inf
)
159 struct thread_info
*thread
= get_thread (inf
);
160 free_register_cache (inferior_regcache_data (thread
));
165 remove_thread (struct thread_info
*thread
)
167 remove_inferior (&all_threads
, (struct inferior_list_entry
*) thread
);
168 free_one_thread (&thread
->entry
);
171 /* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
172 returns non-zero. If no entry is found then return NULL. */
174 struct inferior_list_entry
*
175 find_inferior (struct inferior_list
*list
,
176 int (*func
) (struct inferior_list_entry
*, void *), void *arg
)
178 struct inferior_list_entry
*inf
= list
->head
;
182 struct inferior_list_entry
*next
;
185 if ((*func
) (inf
, arg
))
193 struct inferior_list_entry
*
194 find_inferior_id (struct inferior_list
*list
, ptid_t id
)
196 struct inferior_list_entry
*inf
= list
->head
;
200 if (ptid_equal (inf
->id
, id
))
209 inferior_target_data (struct thread_info
*inferior
)
211 return inferior
->target_data
;
215 set_inferior_target_data (struct thread_info
*inferior
, void *data
)
217 inferior
->target_data
= data
;
221 inferior_regcache_data (struct thread_info
*inferior
)
223 return inferior
->regcache_data
;
227 set_inferior_regcache_data (struct thread_info
*inferior
, void *data
)
229 inferior
->regcache_data
= data
;
233 free_one_dll (struct inferior_list_entry
*inf
)
235 struct dll_info
*dll
= get_dll (inf
);
236 if (dll
->name
!= NULL
)
241 /* Find a DLL with the same name and/or base address. A NULL name in
242 the key is ignored; so is an all-ones base address. */
245 match_dll (struct inferior_list_entry
*inf
, void *arg
)
247 struct dll_info
*iter
= (void *) inf
;
248 struct dll_info
*key
= arg
;
250 if (key
->base_addr
!= ~(CORE_ADDR
) 0
251 && iter
->base_addr
== key
->base_addr
)
253 else if (key
->name
!= NULL
254 && iter
->name
!= NULL
255 && strcmp (key
->name
, iter
->name
) == 0)
261 /* Record a newly loaded DLL at BASE_ADDR. */
264 loaded_dll (const char *name
, CORE_ADDR base_addr
)
266 struct dll_info
*new_dll
= xmalloc (sizeof (*new_dll
));
267 memset (new_dll
, 0, sizeof (*new_dll
));
269 new_dll
->entry
.id
= minus_one_ptid
;
271 new_dll
->name
= xstrdup (name
);
272 new_dll
->base_addr
= base_addr
;
274 add_inferior_to_list (&all_dlls
, &new_dll
->entry
);
278 /* Record that the DLL with NAME and BASE_ADDR has been unloaded. */
281 unloaded_dll (const char *name
, CORE_ADDR base_addr
)
283 struct dll_info
*dll
;
284 struct dll_info key_dll
;
286 /* Be careful not to put the key DLL in any list. */
287 key_dll
.name
= (char *) name
;
288 key_dll
.base_addr
= base_addr
;
290 dll
= (void *) find_inferior (&all_dlls
, match_dll
, &key_dll
);
293 /* For some inferiors we might get unloaded_dll events without having
294 a corresponding loaded_dll. In that case, the dll cannot be found
295 in ALL_DLL, and there is nothing further for us to do.
297 This has been observed when running 32bit executables on Windows64
298 (i.e. through WOW64, the interface between the 32bits and 64bits
299 worlds). In that case, the inferior always does some strange
300 unloading of unnamed dll. */
304 /* DLL has been found so remove the entry and free associated
306 remove_inferior (&all_dlls
, &dll
->entry
);
307 free_one_dll (&dll
->entry
);
312 #define clear_list(LIST) \
313 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
316 clear_inferiors (void)
318 for_each_inferior (&all_threads
, free_one_thread
);
319 for_each_inferior (&all_dlls
, free_one_dll
);
321 clear_list (&all_threads
);
322 clear_list (&all_dlls
);
324 current_inferior
= NULL
;
327 /* Two utility functions for a truly degenerate inferior_list: a simple
331 add_pid_to_list (struct inferior_list
*list
, unsigned long pid
)
333 struct inferior_list_entry
*new_entry
;
335 new_entry
= xmalloc (sizeof (struct inferior_list_entry
));
336 new_entry
->id
= pid_to_ptid (pid
);
337 add_inferior_to_list (list
, new_entry
);
341 pull_pid_from_list (struct inferior_list
*list
, unsigned long pid
)
343 struct inferior_list_entry
*new_entry
;
345 new_entry
= find_inferior_id (list
, pid_to_ptid (pid
));
346 if (new_entry
== NULL
)
350 remove_inferior (list
, new_entry
);
356 struct process_info
*
357 add_process (int pid
, int attached
)
359 struct process_info
*process
;
361 process
= xcalloc (1, sizeof (*process
));
363 process
->head
.id
= pid_to_ptid (pid
);
364 process
->attached
= attached
;
366 add_inferior_to_list (&all_processes
, &process
->head
);
371 /* Remove a process from the common process list and free the memory
373 The caller is responsible for freeing private data first. */
376 remove_process (struct process_info
*process
)
378 clear_symbol_cache (&process
->symbol_cache
);
379 free_all_breakpoints (process
);
380 remove_inferior (&all_processes
, &process
->head
);
384 struct process_info
*
385 find_process_pid (int pid
)
387 return (struct process_info
*)
388 find_inferior_id (&all_processes
, pid_to_ptid (pid
));
391 /* Return non-zero if INF, a struct process_info, was started by us,
392 i.e. not attached to. */
395 started_inferior_callback (struct inferior_list_entry
*entry
, void *args
)
397 struct process_info
*process
= (struct process_info
*) entry
;
399 return ! process
->attached
;
402 /* Return non-zero if there are any inferiors that we have created
403 (as opposed to attached-to). */
406 have_started_inferiors_p (void)
408 return (find_inferior (&all_processes
, started_inferior_callback
, NULL
)
412 /* Return non-zero if INF, a struct process_info, was attached to. */
415 attached_inferior_callback (struct inferior_list_entry
*entry
, void *args
)
417 struct process_info
*process
= (struct process_info
*) entry
;
419 return process
->attached
;
422 /* Return non-zero if there are any inferiors that we have attached to. */
425 have_attached_inferiors_p (void)
427 return (find_inferior (&all_processes
, attached_inferior_callback
, NULL
)
431 struct process_info
*
432 get_thread_process (struct thread_info
*thread
)
434 int pid
= ptid_get_pid (thread
->entry
.id
);
435 return find_process_pid (pid
);
438 struct process_info
*
439 current_process (void)
441 if (current_inferior
== NULL
)
442 fatal ("Current inferior requested, but current_inferior is NULL\n");
444 return get_thread_process (current_inferior
);