]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/inferiors.c
GDB copyright headers update after running GDB's copyright.py script.
[thirdparty/binutils-gdb.git] / gdb / gdbserver / inferiors.c
CommitLineData
ce3a066d 1/* Inferior process information for the remote server for GDB.
618f726f 2 Copyright (C) 2002-2016 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 20
ce3a066d 21#include "server.h"
623b6bdf 22#include "gdbthread.h"
799cdc37 23#include "dll.h"
ce3a066d 24
95954743 25struct inferior_list all_processes;
0d62e5e8
DJ
26struct inferior_list all_threads;
27
0bfdf32f 28struct thread_info *current_thread;
0d62e5e8
DJ
29
30#define get_thread(inf) ((struct thread_info *)(inf))
31
32void
33add_inferior_to_list (struct inferior_list *list,
34 struct inferior_list_entry *new_inferior)
35{
36 new_inferior->next = NULL;
37 if (list->tail != NULL)
38 list->tail->next = new_inferior;
39 else
40 list->head = new_inferior;
41 list->tail = new_inferior;
42}
43
9f767825
DE
44/* Invoke ACTION for each inferior in LIST. */
45
0d62e5e8
DJ
46void
47for_each_inferior (struct inferior_list *list,
48 void (*action) (struct inferior_list_entry *))
49{
50 struct inferior_list_entry *cur = list->head, *next;
51
52 while (cur != NULL)
53 {
54 next = cur->next;
55 (*action) (cur);
56 cur = next;
57 }
58}
ce3a066d 59
649ebbca
DE
60/* Invoke ACTION for each inferior in LIST, passing DATA to ACTION. */
61
62void
63for_each_inferior_with_data (struct inferior_list *list,
64 void (*action) (struct inferior_list_entry *,
65 void *),
66 void *data)
67{
68 struct inferior_list_entry *cur = list->head, *next;
69
70 while (cur != NULL)
71 {
72 next = cur->next;
73 (*action) (cur, data);
74 cur = next;
75 }
76}
77
0d62e5e8
DJ
78void
79remove_inferior (struct inferior_list *list,
80 struct inferior_list_entry *entry)
81{
82 struct inferior_list_entry **cur;
ce3a066d 83
0d62e5e8
DJ
84 if (list->head == entry)
85 {
86 list->head = entry->next;
87 if (list->tail == entry)
88 list->tail = list->head;
89 return;
90 }
91
92 cur = &list->head;
93 while (*cur && (*cur)->next != entry)
94 cur = &(*cur)->next;
95
96 if (*cur == NULL)
97 return;
ce3a066d 98
0d62e5e8
DJ
99 (*cur)->next = entry->next;
100
101 if (list->tail == entry)
102 list->tail = *cur;
103}
104
f7667f0d 105struct thread_info *
95954743 106add_thread (ptid_t thread_id, void *target_data)
0d62e5e8 107{
8d749320 108 struct thread_info *new_thread = XCNEW (struct thread_info);
0d62e5e8
DJ
109
110 new_thread->entry.id = thread_id;
8336d594 111 new_thread->last_resume_kind = resume_continue;
fc7238bb 112 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
0d62e5e8 113
ecc6f45c 114 add_inferior_to_list (&all_threads, &new_thread->entry);
255e7678 115
0bfdf32f
GB
116 if (current_thread == NULL)
117 current_thread = new_thread;
ce3a066d 118
0d62e5e8 119 new_thread->target_data = target_data;
f7667f0d
DE
120
121 return new_thread;
a06660f7
DJ
122}
123
95954743 124ptid_t
a06660f7
DJ
125thread_to_gdb_id (struct thread_info *thread)
126{
95954743 127 return thread->entry.id;
a06660f7
DJ
128}
129
649ebbca
DE
130/* Wrapper around get_first_inferior to return a struct thread_info *. */
131
dae5f5cf 132struct thread_info *
649ebbca 133get_first_thread (void)
a06660f7 134{
649ebbca
DE
135 return (struct thread_info *) get_first_inferior (&all_threads);
136}
a06660f7 137
649ebbca
DE
138struct thread_info *
139find_thread_ptid (ptid_t ptid)
140{
141 return (struct thread_info *) find_inferior_id (&all_threads, ptid);
dae5f5cf
DJ
142}
143
96e7a1eb
AR
144/* Predicate function for matching thread entry's pid to the given
145 pid value passed by address in ARGS. */
146
147static int
148thread_pid_matches_callback (struct inferior_list_entry *entry, void *args)
149{
150 return (ptid_get_pid (entry->id) == *(pid_t *)args);
151}
152
153/* Find a thread associated with the given PROCESS, or NULL if no
154 such thread exists. */
155
156static struct thread_info *
157find_thread_process (const struct process_info *const process)
158{
159 pid_t pid = ptid_get_pid (ptid_of (process));
160
161 return (struct thread_info *)
162 find_inferior (&all_threads, thread_pid_matches_callback, &pid);
163}
164
34c65914
PA
165/* Helper for find_any_thread_of_pid. Returns true if a thread
166 matches a PID. */
167
168static int
169thread_of_pid (struct inferior_list_entry *entry, void *pid_p)
170{
171 int pid = *(int *) pid_p;
172
173 return (ptid_get_pid (entry->id) == pid);
174}
175
176/* See gdbthread.h. */
177
178struct thread_info *
179find_any_thread_of_pid (int pid)
180{
181 struct inferior_list_entry *entry;
182
183 entry = find_inferior (&all_threads, thread_of_pid, &pid);
184
185 return (struct thread_info *) entry;
186}
187
95954743
PA
188ptid_t
189gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 190{
e09875d4 191 struct thread_info *thread = find_thread_ptid (gdb_id);
dae5f5cf 192
95954743 193 return thread ? thread->entry.id : null_ptid;
0d62e5e8 194}
c04a1aa8 195
0d62e5e8
DJ
196static void
197free_one_thread (struct inferior_list_entry *inf)
198{
199 struct thread_info *thread = get_thread (inf);
200 free_register_cache (inferior_regcache_data (thread));
201 free (thread);
202}
203
204void
205remove_thread (struct thread_info *thread)
206{
9accd112
MM
207 if (thread->btrace != NULL)
208 target_disable_btrace (thread->btrace);
209
465a859e 210 discard_queued_stop_replies (ptid_of (thread));
0d62e5e8
DJ
211 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
212 free_one_thread (&thread->entry);
96e7a1eb
AR
213 if (current_thread == thread)
214 current_thread = NULL;
ce3a066d
DJ
215}
216
649ebbca
DE
217/* Return a pointer to the first inferior in LIST, or NULL if there isn't one.
218 This is for cases where the caller needs a thread, but doesn't care
219 which one. */
220
221struct inferior_list_entry *
222get_first_inferior (struct inferior_list *list)
223{
3b8361aa
DE
224 if (list->head != NULL)
225 return list->head;
649ebbca
DE
226 return NULL;
227}
228
0718675c
JB
229/* Find the first inferior_list_entry E in LIST for which FUNC (E, ARG)
230 returns non-zero. If no entry is found then return NULL. */
231
0d62e5e8
DJ
232struct inferior_list_entry *
233find_inferior (struct inferior_list *list,
234 int (*func) (struct inferior_list_entry *, void *), void *arg)
235{
236 struct inferior_list_entry *inf = list->head;
ce3a066d 237
0d62e5e8 238 while (inf != NULL)
ce3a066d 239 {
a07b2135
PA
240 struct inferior_list_entry *next;
241
242 next = inf->next;
0d62e5e8
DJ
243 if ((*func) (inf, arg))
244 return inf;
a07b2135 245 inf = next;
0d62e5e8 246 }
611cb4a5 247
0d62e5e8
DJ
248 return NULL;
249}
611cb4a5 250
0d62e5e8 251struct inferior_list_entry *
95954743 252find_inferior_id (struct inferior_list *list, ptid_t id)
0d62e5e8
DJ
253{
254 struct inferior_list_entry *inf = list->head;
255
256 while (inf != NULL)
257 {
95954743 258 if (ptid_equal (inf->id, id))
0d62e5e8
DJ
259 return inf;
260 inf = inf->next;
ce3a066d
DJ
261 }
262
0d62e5e8 263 return NULL;
ce3a066d 264}
611cb4a5
DJ
265
266void *
0d62e5e8 267inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
268{
269 return inferior->target_data;
270}
271
272void
0d62e5e8 273set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
274{
275 inferior->target_data = data;
276}
c04a1aa8 277
a44892be 278struct regcache *
0d62e5e8 279inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
280{
281 return inferior->regcache_data;
282}
283
284void
a44892be 285set_inferior_regcache_data (struct thread_info *inferior, struct regcache *data)
c04a1aa8
DJ
286{
287 inferior->regcache_data = data;
288}
255e7678 289
649ebbca
DE
290/* Return true if LIST has exactly one entry. */
291
292int
293one_inferior_p (struct inferior_list *list)
294{
295 return list->head != NULL && list->head == list->tail;
296}
297
298/* Reset head,tail of LIST, assuming all entries have already been freed. */
299
300void
301clear_inferior_list (struct inferior_list *list)
302{
303 list->head = NULL;
304 list->tail = NULL;
305}
255e7678
DJ
306
307void
308clear_inferiors (void)
309{
310 for_each_inferior (&all_threads, free_one_thread);
649ebbca 311 clear_inferior_list (&all_threads);
bf4c19f7
YQ
312
313 clear_dlls ();
7284e1be 314
0bfdf32f 315 current_thread = NULL;
255e7678 316}
24a09b5f 317
95954743
PA
318struct process_info *
319add_process (int pid, int attached)
320{
8d749320 321 struct process_info *process = XCNEW (struct process_info);
95954743 322
80894984 323 process->entry.id = pid_to_ptid (pid);
95954743
PA
324 process->attached = attached;
325
80894984 326 add_inferior_to_list (&all_processes, &process->entry);
95954743
PA
327
328 return process;
329}
330
5091eb23
DE
331/* Remove a process from the common process list and free the memory
332 allocated for it.
333 The caller is responsible for freeing private data first. */
334
95954743
PA
335void
336remove_process (struct process_info *process)
337{
338 clear_symbol_cache (&process->symbol_cache);
339 free_all_breakpoints (process);
96e7a1eb 340 gdb_assert (find_thread_process (process) == NULL);
80894984 341 remove_inferior (&all_processes, &process->entry);
5091eb23 342 free (process);
95954743
PA
343}
344
345struct process_info *
346find_process_pid (int pid)
347{
348 return (struct process_info *)
349 find_inferior_id (&all_processes, pid_to_ptid (pid));
350}
351
3d40fbb5
PA
352/* Wrapper around get_first_inferior to return a struct process_info *. */
353
354struct process_info *
355get_first_process (void)
356{
357 return (struct process_info *) get_first_inferior (&all_processes);
358}
359
9f767825
DE
360/* Return non-zero if INF, a struct process_info, was started by us,
361 i.e. not attached to. */
362
363static int
364started_inferior_callback (struct inferior_list_entry *entry, void *args)
365{
366 struct process_info *process = (struct process_info *) entry;
367
368 return ! process->attached;
369}
370
371/* Return non-zero if there are any inferiors that we have created
372 (as opposed to attached-to). */
373
374int
375have_started_inferiors_p (void)
376{
377 return (find_inferior (&all_processes, started_inferior_callback, NULL)
378 != NULL);
379}
380
381/* Return non-zero if INF, a struct process_info, was attached to. */
382
383static int
384attached_inferior_callback (struct inferior_list_entry *entry, void *args)
385{
386 struct process_info *process = (struct process_info *) entry;
387
388 return process->attached;
389}
390
391/* Return non-zero if there are any inferiors that we have attached to. */
392
393int
394have_attached_inferiors_p (void)
395{
396 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
397 != NULL);
398}
399
7fe519cb 400struct process_info *
95954743
PA
401get_thread_process (struct thread_info *thread)
402{
403 int pid = ptid_get_pid (thread->entry.id);
404 return find_process_pid (pid);
405}
406
407struct process_info *
408current_process (void)
409{
0bfdf32f
GB
410 gdb_assert (current_thread != NULL);
411 return get_thread_process (current_thread);
95954743 412}