]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/inf-child.c
gdb, gdbserver: make target_waitstatus safe
[thirdparty/binutils-gdb.git] / gdb / inf-child.c
1 /* Base/prototype target for default child (native) targets.
2
3 Copyright (C) 1988-2021 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 /* This file provides a common base class/target that all native
21 target implementations extend, by calling inf_child_target to get a
22 new prototype target and then overriding target methods as
23 necessary. */
24
25 #include "defs.h"
26 #include "regcache.h"
27 #include "memattr.h"
28 #include "symtab.h"
29 #include "target.h"
30 #include "inferior.h"
31 #include <sys/stat.h>
32 #include "inf-child.h"
33 #include "gdbsupport/fileio.h"
34 #include "gdbsupport/agent.h"
35 #include "gdbsupport/gdb_wait.h"
36 #include "gdbsupport/filestuff.h"
37
38 #include <sys/types.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41
42 static const target_info inf_child_target_info = {
43 "native",
44 N_("Native process"),
45 N_("Native process (started by the \"run\" command).")
46 };
47
48 const target_info &
49 inf_child_target::info () const
50 {
51 return inf_child_target_info;
52 }
53
54 /* Helper function for child_wait and the derivatives of child_wait.
55 HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
56 translation of that in OURSTATUS. */
57 void
58 store_waitstatus (struct target_waitstatus *ourstatus, int hoststatus)
59 {
60 if (WIFEXITED (hoststatus))
61 ourstatus->set_exited (WEXITSTATUS (hoststatus));
62 else if (!WIFSTOPPED (hoststatus))
63 ourstatus->set_signalled (gdb_signal_from_host (WTERMSIG (hoststatus)));
64 else
65 ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (hoststatus)));
66 }
67
68 inf_child_target::~inf_child_target ()
69 {}
70
71 void
72 inf_child_target::post_attach (int pid)
73 {
74 /* This target doesn't require a meaningful "post attach" operation
75 by a debugger. */
76 }
77
78 /* Get ready to modify the registers array. On machines which store
79 individual registers, this doesn't need to do anything. On
80 machines which store all the registers in one fell swoop, this
81 makes sure that registers contains all the registers from the
82 program being debugged. */
83
84 void
85 inf_child_target::prepare_to_store (struct regcache *regcache)
86 {
87 }
88
89 bool
90 inf_child_target::supports_terminal_ours ()
91 {
92 return true;
93 }
94
95 void
96 inf_child_target::terminal_init ()
97 {
98 child_terminal_init (this);
99 }
100
101 void
102 inf_child_target::terminal_inferior ()
103 {
104 child_terminal_inferior (this);
105 }
106
107 void
108 inf_child_target::terminal_save_inferior ()
109 {
110 child_terminal_save_inferior (this);
111 }
112
113 void
114 inf_child_target::terminal_ours_for_output ()
115 {
116 child_terminal_ours_for_output (this);
117 }
118
119 void
120 inf_child_target::terminal_ours ()
121 {
122 child_terminal_ours (this);
123 }
124
125 void
126 inf_child_target::interrupt ()
127 {
128 child_interrupt (this);
129 }
130
131 void
132 inf_child_target::pass_ctrlc ()
133 {
134 child_pass_ctrlc (this);
135 }
136
137 void
138 inf_child_target::terminal_info (const char *args, int from_tty)
139 {
140 child_terminal_info (this, args, from_tty);
141 }
142
143 /* True if the user did "target native". In that case, we won't
144 unpush the child target automatically when the last inferior is
145 gone. */
146 static int inf_child_explicitly_opened;
147
148 /* See inf-child.h. */
149
150 void
151 inf_child_open_target (const char *arg, int from_tty)
152 {
153 target_ops *target = get_native_target ();
154
155 /* There's always only ever one native target, and if we get here,
156 it better be an inf-child target. */
157 gdb_assert (dynamic_cast<inf_child_target *> (target) != NULL);
158
159 target_preopen (from_tty);
160 current_inferior ()->push_target (target);
161 inf_child_explicitly_opened = 1;
162 if (from_tty)
163 printf_filtered ("Done. Use the \"run\" command to start a process.\n");
164 }
165
166 /* Implement the to_disconnect target_ops method. */
167
168 void
169 inf_child_target::disconnect (const char *args, int from_tty)
170 {
171 if (args != NULL)
172 error (_("Argument given to \"disconnect\"."));
173
174 /* This offers to detach/kill current inferiors, and then pops all
175 targets. */
176 target_preopen (from_tty);
177 }
178
179 /* Implement the to_close target_ops method. */
180
181 void
182 inf_child_target::close ()
183 {
184 /* In case we were forcibly closed. */
185 inf_child_explicitly_opened = 0;
186 }
187
188 void
189 inf_child_target::mourn_inferior ()
190 {
191 generic_mourn_inferior ();
192 maybe_unpush_target ();
193 }
194
195 /* See inf-child.h. */
196
197 void
198 inf_child_target::maybe_unpush_target ()
199 {
200 if (!inf_child_explicitly_opened)
201 current_inferior ()->unpush_target (this);
202 }
203
204 void
205 inf_child_target::post_startup_inferior (ptid_t ptid)
206 {
207 /* This target doesn't require a meaningful "post startup inferior"
208 operation by a debugger. */
209 }
210
211 bool
212 inf_child_target::can_run ()
213 {
214 return true;
215 }
216
217 bool
218 inf_child_target::can_create_inferior ()
219 {
220 return true;
221 }
222
223 bool
224 inf_child_target::can_attach ()
225 {
226 return true;
227 }
228
229 char *
230 inf_child_target::pid_to_exec_file (int pid)
231 {
232 /* This target doesn't support translation of a process ID to the
233 filename of the executable file. */
234 return NULL;
235 }
236
237 /* Implementation of to_fileio_open. */
238
239 int
240 inf_child_target::fileio_open (struct inferior *inf, const char *filename,
241 int flags, int mode, int warn_if_slow,
242 int *target_errno)
243 {
244 int nat_flags;
245 mode_t nat_mode;
246 int fd;
247
248 if (fileio_to_host_openflags (flags, &nat_flags) == -1
249 || fileio_to_host_mode (mode, &nat_mode) == -1)
250 {
251 *target_errno = FILEIO_EINVAL;
252 return -1;
253 }
254
255 fd = gdb_open_cloexec (filename, nat_flags, nat_mode).release ();
256 if (fd == -1)
257 *target_errno = host_to_fileio_error (errno);
258
259 return fd;
260 }
261
262 /* Implementation of to_fileio_pwrite. */
263
264 int
265 inf_child_target::fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
266 ULONGEST offset, int *target_errno)
267 {
268 int ret;
269
270 #ifdef HAVE_PWRITE
271 ret = pwrite (fd, write_buf, len, (long) offset);
272 #else
273 ret = -1;
274 #endif
275 /* If we have no pwrite or it failed for this file, use lseek/write. */
276 if (ret == -1)
277 {
278 ret = lseek (fd, (long) offset, SEEK_SET);
279 if (ret != -1)
280 ret = write (fd, write_buf, len);
281 }
282
283 if (ret == -1)
284 *target_errno = host_to_fileio_error (errno);
285
286 return ret;
287 }
288
289 /* Implementation of to_fileio_pread. */
290
291 int
292 inf_child_target::fileio_pread (int fd, gdb_byte *read_buf, int len,
293 ULONGEST offset, int *target_errno)
294 {
295 int ret;
296
297 #ifdef HAVE_PREAD
298 ret = pread (fd, read_buf, len, (long) offset);
299 #else
300 ret = -1;
301 #endif
302 /* If we have no pread or it failed for this file, use lseek/read. */
303 if (ret == -1)
304 {
305 ret = lseek (fd, (long) offset, SEEK_SET);
306 if (ret != -1)
307 ret = read (fd, read_buf, len);
308 }
309
310 if (ret == -1)
311 *target_errno = host_to_fileio_error (errno);
312
313 return ret;
314 }
315
316 /* Implementation of to_fileio_fstat. */
317
318 int
319 inf_child_target::fileio_fstat (int fd, struct stat *sb, int *target_errno)
320 {
321 int ret;
322
323 ret = fstat (fd, sb);
324 if (ret == -1)
325 *target_errno = host_to_fileio_error (errno);
326
327 return ret;
328 }
329
330 /* Implementation of to_fileio_close. */
331
332 int
333 inf_child_target::fileio_close (int fd, int *target_errno)
334 {
335 int ret;
336
337 ret = ::close (fd);
338 if (ret == -1)
339 *target_errno = host_to_fileio_error (errno);
340
341 return ret;
342 }
343
344 /* Implementation of to_fileio_unlink. */
345
346 int
347 inf_child_target::fileio_unlink (struct inferior *inf, const char *filename,
348 int *target_errno)
349 {
350 int ret;
351
352 ret = unlink (filename);
353 if (ret == -1)
354 *target_errno = host_to_fileio_error (errno);
355
356 return ret;
357 }
358
359 /* Implementation of to_fileio_readlink. */
360
361 gdb::optional<std::string>
362 inf_child_target::fileio_readlink (struct inferior *inf, const char *filename,
363 int *target_errno)
364 {
365 /* We support readlink only on systems that also provide a compile-time
366 maximum path length (PATH_MAX), at least for now. */
367 #if defined (PATH_MAX)
368 char buf[PATH_MAX];
369 int len;
370
371 len = readlink (filename, buf, sizeof buf);
372 if (len < 0)
373 {
374 *target_errno = host_to_fileio_error (errno);
375 return {};
376 }
377
378 return std::string (buf, len);
379 #else
380 *target_errno = FILEIO_ENOSYS;
381 return {};
382 #endif
383 }
384
385 bool
386 inf_child_target::use_agent (bool use)
387 {
388 if (agent_loaded_p ())
389 {
390 ::use_agent = use;
391 return true;
392 }
393 else
394 return false;
395 }
396
397 bool
398 inf_child_target::can_use_agent ()
399 {
400 return agent_loaded_p ();
401 }
402
403 void
404 inf_child_target::follow_exec (inferior *follow_inf, ptid_t ptid,
405 const char *execd_pathname)
406 {
407 inferior *orig_inf = current_inferior ();
408
409 process_stratum_target::follow_exec (follow_inf, ptid, execd_pathname);
410
411 if (orig_inf != follow_inf)
412 {
413 /* If the target was implicitly push in the original inferior, unpush
414 it. */
415 scoped_restore_current_thread restore_thread;
416 switch_to_inferior_no_thread (orig_inf);
417 maybe_unpush_target ();
418 }
419 }
420
421 /* See inf-child.h. */
422
423 void
424 add_inf_child_target (inf_child_target *target)
425 {
426 set_native_target (target);
427 add_target (inf_child_target_info, inf_child_open_target);
428 }