Add new target_read_raw_memory function, and consolidate comments.
[deliverable/binutils-gdb.git] / gdb / gdbserver / inferiors.c
CommitLineData
ce3a066d 1/* Inferior process information for the remote server for GDB.
28e7fd62 2 Copyright (C) 2002-2013 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"
623b6bdf 24#include "gdbthread.h"
799cdc37 25#include "dll.h"
ce3a066d 26
95954743 27struct inferior_list all_processes;
0d62e5e8
DJ
28struct inferior_list all_threads;
29
30struct thread_info *current_inferior;
31
32#define get_thread(inf) ((struct thread_info *)(inf))
33
34void
35add_inferior_to_list (struct inferior_list *list,
36 struct inferior_list_entry *new_inferior)
37{
38 new_inferior->next = NULL;
39 if (list->tail != NULL)
40 list->tail->next = new_inferior;
41 else
42 list->head = new_inferior;
43 list->tail = new_inferior;
44}
45
9f767825
DE
46/* Invoke ACTION for each inferior in LIST. */
47
0d62e5e8
DJ
48void
49for_each_inferior (struct inferior_list *list,
50 void (*action) (struct inferior_list_entry *))
51{
52 struct inferior_list_entry *cur = list->head, *next;
53
54 while (cur != NULL)
55 {
56 next = cur->next;
57 (*action) (cur);
58 cur = next;
59 }
60}
ce3a066d 61
0d62e5e8
DJ
62void
63remove_inferior (struct inferior_list *list,
64 struct inferior_list_entry *entry)
65{
66 struct inferior_list_entry **cur;
ce3a066d 67
0d62e5e8
DJ
68 if (list->head == entry)
69 {
70 list->head = entry->next;
71 if (list->tail == entry)
72 list->tail = list->head;
73 return;
74 }
75
76 cur = &list->head;
77 while (*cur && (*cur)->next != entry)
78 cur = &(*cur)->next;
79
80 if (*cur == NULL)
81 return;
ce3a066d 82
0d62e5e8
DJ
83 (*cur)->next = entry->next;
84
85 if (list->tail == entry)
86 list->tail = *cur;
87}
88
89void
95954743 90add_thread (ptid_t thread_id, void *target_data)
0d62e5e8 91{
bca929d3 92 struct thread_info *new_thread = xmalloc (sizeof (*new_thread));
0d62e5e8
DJ
93
94 memset (new_thread, 0, sizeof (*new_thread));
95
96 new_thread->entry.id = thread_id;
8336d594 97 new_thread->last_resume_kind = resume_continue;
fc7238bb 98 new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
0d62e5e8
DJ
99
100 add_inferior_to_list (&all_threads, & new_thread->entry);
255e7678 101
ce3a066d 102 if (current_inferior == NULL)
0d62e5e8 103 current_inferior = new_thread;
ce3a066d 104
0d62e5e8 105 new_thread->target_data = target_data;
a06660f7
DJ
106}
107
95954743
PA
108ptid_t
109thread_id_to_gdb_id (ptid_t thread_id)
a06660f7
DJ
110{
111 struct inferior_list_entry *inf = all_threads.head;
112
113 while (inf != NULL)
114 {
95954743
PA
115 if (ptid_equal (inf->id, thread_id))
116 return thread_id;
a06660f7
DJ
117 inf = inf->next;
118 }
119
95954743 120 return null_ptid;
a06660f7
DJ
121}
122
95954743 123ptid_t
a06660f7
DJ
124thread_to_gdb_id (struct thread_info *thread)
125{
95954743 126 return thread->entry.id;
a06660f7
DJ
127}
128
dae5f5cf 129struct thread_info *
e09875d4 130find_thread_ptid (ptid_t ptid)
a06660f7
DJ
131{
132 struct inferior_list_entry *inf = all_threads.head;
133
134 while (inf != NULL)
135 {
136 struct thread_info *thread = get_thread (inf);
95954743 137 if (ptid_equal (thread->entry.id, ptid))
dae5f5cf 138 return thread;
a06660f7
DJ
139 inf = inf->next;
140 }
141
dae5f5cf
DJ
142 return NULL;
143}
144
95954743
PA
145ptid_t
146gdb_id_to_thread_id (ptid_t gdb_id)
dae5f5cf 147{
e09875d4 148 struct thread_info *thread = find_thread_ptid (gdb_id);
dae5f5cf 149
95954743 150 return thread ? thread->entry.id : null_ptid;
0d62e5e8 151}
c04a1aa8 152
0d62e5e8
DJ
153static void
154free_one_thread (struct inferior_list_entry *inf)
155{
156 struct thread_info *thread = get_thread (inf);
157 free_register_cache (inferior_regcache_data (thread));
158 free (thread);
159}
160
161void
162remove_thread (struct thread_info *thread)
163{
9accd112
MM
164 if (thread->btrace != NULL)
165 target_disable_btrace (thread->btrace);
166
0d62e5e8
DJ
167 remove_inferior (&all_threads, (struct inferior_list_entry *) thread);
168 free_one_thread (&thread->entry);
ce3a066d
DJ
169}
170
0718675c
JB
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. */
173
0d62e5e8
DJ
174struct inferior_list_entry *
175find_inferior (struct inferior_list *list,
176 int (*func) (struct inferior_list_entry *, void *), void *arg)
177{
178 struct inferior_list_entry *inf = list->head;
ce3a066d 179
0d62e5e8 180 while (inf != NULL)
ce3a066d 181 {
a07b2135
PA
182 struct inferior_list_entry *next;
183
184 next = inf->next;
0d62e5e8
DJ
185 if ((*func) (inf, arg))
186 return inf;
a07b2135 187 inf = next;
0d62e5e8 188 }
611cb4a5 189
0d62e5e8
DJ
190 return NULL;
191}
611cb4a5 192
0d62e5e8 193struct inferior_list_entry *
95954743 194find_inferior_id (struct inferior_list *list, ptid_t id)
0d62e5e8
DJ
195{
196 struct inferior_list_entry *inf = list->head;
197
198 while (inf != NULL)
199 {
95954743 200 if (ptid_equal (inf->id, id))
0d62e5e8
DJ
201 return inf;
202 inf = inf->next;
ce3a066d
DJ
203 }
204
0d62e5e8 205 return NULL;
ce3a066d 206}
611cb4a5
DJ
207
208void *
0d62e5e8 209inferior_target_data (struct thread_info *inferior)
611cb4a5
DJ
210{
211 return inferior->target_data;
212}
213
214void
0d62e5e8 215set_inferior_target_data (struct thread_info *inferior, void *data)
611cb4a5
DJ
216{
217 inferior->target_data = data;
218}
c04a1aa8
DJ
219
220void *
0d62e5e8 221inferior_regcache_data (struct thread_info *inferior)
c04a1aa8
DJ
222{
223 return inferior->regcache_data;
224}
225
226void
0d62e5e8 227set_inferior_regcache_data (struct thread_info *inferior, void *data)
c04a1aa8
DJ
228{
229 inferior->regcache_data = data;
230}
255e7678 231
255e7678
DJ
232#define clear_list(LIST) \
233 do { (LIST)->head = (LIST)->tail = NULL; } while (0)
234
235void
236clear_inferiors (void)
237{
238 for_each_inferior (&all_threads, free_one_thread);
255e7678 239 clear_list (&all_threads);
bf4c19f7
YQ
240
241 clear_dlls ();
7284e1be
UW
242
243 current_inferior = NULL;
255e7678 244}
24a09b5f 245
95954743
PA
246struct process_info *
247add_process (int pid, int attached)
248{
249 struct process_info *process;
250
251 process = xcalloc (1, sizeof (*process));
252
253 process->head.id = pid_to_ptid (pid);
254 process->attached = attached;
255
256 add_inferior_to_list (&all_processes, &process->head);
257
258 return process;
259}
260
5091eb23
DE
261/* Remove a process from the common process list and free the memory
262 allocated for it.
263 The caller is responsible for freeing private data first. */
264
95954743
PA
265void
266remove_process (struct process_info *process)
267{
268 clear_symbol_cache (&process->symbol_cache);
269 free_all_breakpoints (process);
270 remove_inferior (&all_processes, &process->head);
5091eb23 271 free (process);
95954743
PA
272}
273
274struct process_info *
275find_process_pid (int pid)
276{
277 return (struct process_info *)
278 find_inferior_id (&all_processes, pid_to_ptid (pid));
279}
280
9f767825
DE
281/* Return non-zero if INF, a struct process_info, was started by us,
282 i.e. not attached to. */
283
284static int
285started_inferior_callback (struct inferior_list_entry *entry, void *args)
286{
287 struct process_info *process = (struct process_info *) entry;
288
289 return ! process->attached;
290}
291
292/* Return non-zero if there are any inferiors that we have created
293 (as opposed to attached-to). */
294
295int
296have_started_inferiors_p (void)
297{
298 return (find_inferior (&all_processes, started_inferior_callback, NULL)
299 != NULL);
300}
301
302/* Return non-zero if INF, a struct process_info, was attached to. */
303
304static int
305attached_inferior_callback (struct inferior_list_entry *entry, void *args)
306{
307 struct process_info *process = (struct process_info *) entry;
308
309 return process->attached;
310}
311
312/* Return non-zero if there are any inferiors that we have attached to. */
313
314int
315have_attached_inferiors_p (void)
316{
317 return (find_inferior (&all_processes, attached_inferior_callback, NULL)
318 != NULL);
319}
320
7fe519cb 321struct process_info *
95954743
PA
322get_thread_process (struct thread_info *thread)
323{
324 int pid = ptid_get_pid (thread->entry.id);
325 return find_process_pid (pid);
326}
327
328struct process_info *
329current_process (void)
330{
331 if (current_inferior == NULL)
332 fatal ("Current inferior requested, but current_inferior is NULL\n");
333
334 return get_thread_process (current_inferior);
335}
This page took 0.965823 seconds and 4 git commands to generate.