]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/gdbserver/target.c
gdbserver:prepare_access_memory: pick another thread
[thirdparty/binutils-gdb.git] / gdb / gdbserver / target.c
CommitLineData
ce3a066d 1/* Target operations for the remote server for GDB.
32d0add0 2 Copyright (C) 2002-2015 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 "server.h"
c144c7a0 22#include "tracepoint.h"
ce3a066d
DJ
23
24struct target_ops *the_target;
25
f0db101d 26int
0bfdf32f 27set_desired_thread (int use_general)
0d62e5e8
DJ
28{
29 struct thread_info *found;
30
31 if (use_general == 1)
e09875d4 32 found = find_thread_ptid (general_thread);
0d62e5e8 33 else
943ca1dd 34 found = find_thread_ptid (cont_thread);
0d62e5e8 35
f0db101d
PA
36 current_thread = found;
37 return (current_thread != NULL);
0d62e5e8
DJ
38}
39
a67a9fae
PA
40/* Structure used to look up a thread to use as current when accessing
41 memory. */
42
43struct thread_search
44{
45 /* The PTID of the current general thread. This is an input
46 parameter. */
47 ptid_t current_gen_ptid;
48
49 /* The first thread found. */
50 struct thread_info *first;
51
52 /* The first stopped thread found. */
53 struct thread_info *stopped;
54
55 /* The current general thread, if found. */
56 struct thread_info *current;
57};
58
59/* Callback for find_inferior. Search for a thread to use as current
60 when accessing memory. */
61
62static int
63thread_search_callback (struct inferior_list_entry *entry, void *args)
64{
65 struct thread_info *thread = (struct thread_info *) entry;
66 struct thread_search *s = (struct thread_search *) args;
67
68 if (ptid_get_pid (entry->id) == ptid_get_pid (s->current_gen_ptid)
69 && mythread_alive (ptid_of (thread)))
70 {
71 if (s->stopped == NULL && thread_stopped (thread))
72 s->stopped = thread;
73
74 if (s->first == NULL)
75 s->first = thread;
76
77 if (s->current == NULL && ptid_equal (s->current_gen_ptid, entry->id))
78 s->current = thread;
79 }
80
81 return 0;
82}
83
84/* The thread that was current before prepare_to_access_memory was
85 called. done_accessing_memory uses this to restore the previous
86 selected thread. */
87static ptid_t prev_general_thread;
88
89/* See target.h. */
90
91int
92prepare_to_access_memory (void)
93{
94 struct thread_search search;
95 struct thread_info *thread;
96
97 memset (&search, 0, sizeof (search));
98 search.current_gen_ptid = general_thread;
99 prev_general_thread = general_thread;
100
101 if (the_target->prepare_to_access_memory != NULL)
102 {
103 int res;
104
105 res = the_target->prepare_to_access_memory ();
106 if (res != 0)
107 return res;
108 }
109
110 find_inferior (&all_threads, thread_search_callback, &search);
111
112 /* Prefer a stopped thread. If none is found, try the current
113 thread. Otherwise, take the first thread in the process. If
114 none is found, undo the effects of
115 target->prepare_to_access_memory() and return error. */
116 if (search.stopped != NULL)
117 thread = search.stopped;
118 else if (search.current != NULL)
119 thread = search.current;
120 else if (search.first != NULL)
121 thread = search.first;
122 else
123 {
124 done_accessing_memory ();
125 return 1;
126 }
127
128 current_thread = thread;
129 general_thread = ptid_of (thread);
130
131 return 0;
132}
133
134/* See target.h. */
135
136void
137done_accessing_memory (void)
138{
139 if (the_target->done_accessing_memory != NULL)
140 the_target->done_accessing_memory ();
141
142 /* Restore the previous selected thread. */
143 general_thread = prev_general_thread;
144 current_thread = find_thread_ptid (general_thread);
145}
146
c3e735a6 147int
f450004a 148read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
611cb4a5 149{
c3e735a6
DJ
150 int res;
151 res = (*the_target->read_memory) (memaddr, myaddr, len);
611cb4a5 152 check_mem_read (memaddr, myaddr, len);
c3e735a6 153 return res;
611cb4a5
DJ
154}
155
721ec300
GB
156/* See target/target.h. */
157
158int
159target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
160{
161 return read_inferior_memory (memaddr, myaddr, len);
162}
163
164/* See target/target.h. */
165
166int
167target_read_uint32 (CORE_ADDR memaddr, uint32_t *result)
168{
169 return read_inferior_memory (memaddr, (gdb_byte *) result, sizeof (*result));
170}
171
611cb4a5 172int
f450004a
DJ
173write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
174 int len)
0d62e5e8
DJ
175{
176 /* Lacking cleanups, there is some potential for a memory leak if the
177 write fails and we go through error(). Make sure that no more than
178 one buffer is ever pending by making BUFFER static. */
f450004a 179 static unsigned char *buffer = 0;
0d62e5e8
DJ
180 int res;
181
182 if (buffer != NULL)
183 free (buffer);
184
224c3ddb 185 buffer = (unsigned char *) xmalloc (len);
0d62e5e8 186 memcpy (buffer, myaddr, len);
b9fd1791 187 check_mem_write (memaddr, buffer, myaddr, len);
0d62e5e8
DJ
188 res = (*the_target->write_memory) (memaddr, buffer, len);
189 free (buffer);
190 buffer = NULL;
191
192 return res;
193}
194
721ec300
GB
195/* See target/target.h. */
196
197int
198target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
199{
200 return write_inferior_memory (memaddr, myaddr, len);
201}
202
95954743
PA
203ptid_t
204mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
bd99dc85 205 int connected_wait)
611cb4a5 206{
95954743 207 ptid_t ret;
0d62e5e8
DJ
208
209 if (connected_wait)
210 server_waiting = 1;
211
95954743 212 ret = (*the_target->wait) (ptid, ourstatus, options);
bd99dc85 213
4210d83e
PA
214 /* We don't expose _LOADED events to gdbserver core. See the
215 `dlls_changed' global. */
216 if (ourstatus->kind == TARGET_WAITKIND_LOADED)
217 ourstatus->kind = TARGET_WAITKIND_STOPPED;
218
1a3d890b
PA
219 /* If GDB is connected through TCP/serial, then GDBserver will most
220 probably be running on its own terminal/console, so it's nice to
221 print there why is GDBserver exiting. If however, GDB is
222 connected through stdio, then there's no need to spam the GDB
223 console with this -- the user will already see the exit through
224 regular GDB output, in that same terminal. */
225 if (!remote_connection_is_stdio ())
226 {
227 if (ourstatus->kind == TARGET_WAITKIND_EXITED)
228 fprintf (stderr,
229 "\nChild exited with status %d\n", ourstatus->value.integer);
230 else if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
231 fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
232 gdb_signal_to_host (ourstatus->value.sig),
233 gdb_signal_to_name (ourstatus->value.sig));
234 }
0d62e5e8
DJ
235
236 if (connected_wait)
237 server_waiting = 0;
238
239 return ret;
611cb4a5
DJ
240}
241
f8c1d06b
GB
242/* See target/target.h. */
243
244void
03f4463b 245target_stop_and_wait (ptid_t ptid)
f8c1d06b
GB
246{
247 struct target_waitstatus status;
248 int was_non_stop = non_stop;
249 struct thread_resume resume_info;
250
251 resume_info.thread = ptid;
252 resume_info.kind = resume_stop;
253 resume_info.sig = GDB_SIGNAL_0;
254 (*the_target->resume) (&resume_info, 1);
255
256 non_stop = 1;
257 mywait (ptid, &status, 0, 0);
258 non_stop = was_non_stop;
259}
260
261/* See target/target.h. */
262
263void
03f4463b 264target_continue_no_signal (ptid_t ptid)
f8c1d06b
GB
265{
266 struct thread_resume resume_info;
267
268 resume_info.thread = ptid;
269 resume_info.kind = resume_continue;
270 resume_info.sig = GDB_SIGNAL_0;
271 (*the_target->resume) (&resume_info, 1);
272}
273
bd99dc85
PA
274int
275start_non_stop (int nonstop)
276{
277 if (the_target->start_non_stop == NULL)
278 {
279 if (nonstop)
280 return -1;
281 else
282 return 0;
283 }
284
285 return (*the_target->start_non_stop) (nonstop);
286}
287
ce3a066d
DJ
288void
289set_target_ops (struct target_ops *target)
290{
8d749320 291 the_target = XNEW (struct target_ops);
ce3a066d
DJ
292 memcpy (the_target, target, sizeof (*the_target));
293}
95954743
PA
294
295/* Convert pid to printable format. */
296
297const char *
298target_pid_to_str (ptid_t ptid)
299{
300 static char buf[80];
301
302 if (ptid_equal (ptid, minus_one_ptid))
6cebaf6e 303 xsnprintf (buf, sizeof (buf), "<all threads>");
95954743 304 else if (ptid_equal (ptid, null_ptid))
6cebaf6e 305 xsnprintf (buf, sizeof (buf), "<null thread>");
95954743 306 else if (ptid_get_tid (ptid) != 0)
6cebaf6e 307 xsnprintf (buf, sizeof (buf), "Thread %d.0x%lx",
308 ptid_get_pid (ptid), ptid_get_tid (ptid));
95954743 309 else if (ptid_get_lwp (ptid) != 0)
6cebaf6e 310 xsnprintf (buf, sizeof (buf), "LWP %d.%ld",
311 ptid_get_pid (ptid), ptid_get_lwp (ptid));
95954743 312 else
6cebaf6e 313 xsnprintf (buf, sizeof (buf), "Process %d",
314 ptid_get_pid (ptid));
95954743
PA
315
316 return buf;
317}
8336d594 318
7255706c
YQ
319int
320kill_inferior (int pid)
321{
322 gdb_agent_about_to_close (pid);
323
324 return (*the_target->kill) (pid);
325}
70b90b91
YQ
326
327/* Target can do hardware single step. */
328
329int
330target_can_do_hardware_single_step (void)
331{
332 return 1;
333}
2e6ee069
AT
334
335/* Default implementation for breakpoint_kind_for_pc.
336
337 The default behavior for targets that don't implement breakpoint_kind_for_pc
338 is to use the size of a breakpoint as the kind. */
339
340int
341default_breakpoint_kind_from_pc (CORE_ADDR *pcptr)
342{
343 int size = 0;
344
345 gdb_assert (the_target->sw_breakpoint_from_kind != NULL);
346
347 (*the_target->sw_breakpoint_from_kind) (0, &size);
348 return size;
349}