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