Commit | Line | Data |
---|---|---|
3aa6856a | 1 | /* Target-vector operations for controlling Unix child processes, for GDB. |
310cc570 | 2 | Copyright 1990, 1991, 1992 Free Software Foundation, Inc. |
bd5635a1 RP |
3 | Contributed by Cygnus Support. |
4 | ||
5 | This file is part of GDB. | |
6 | ||
dcc8abce | 7 | This program is free software; you can redistribute it and/or modify |
bd5635a1 | 8 | it under the terms of the GNU General Public License as published by |
dcc8abce JG |
9 | the Free Software Foundation; either version 2 of the License, or |
10 | (at your option) any later version. | |
bd5635a1 | 11 | |
dcc8abce | 12 | This program is distributed in the hope that it will be useful, |
bd5635a1 RP |
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 | |
dcc8abce JG |
18 | along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
bd5635a1 | 20 | |
bd5635a1 | 21 | #include "defs.h" |
bd5635a1 RP |
22 | #include "frame.h" /* required by inferior.h */ |
23 | #include "inferior.h" | |
24 | #include "target.h" | |
25 | #include "wait.h" | |
26 | #include "gdbcore.h" | |
100f92e2 | 27 | #include "command.h" |
310cc570 RP |
28 | #include <signal.h> |
29 | ||
dcc8abce JG |
30 | static void |
31 | child_prepare_to_store PARAMS ((void)); | |
32 | ||
de43d7d0 | 33 | #ifndef CHILD_WAIT |
dcc8abce | 34 | static int |
67ac9759 | 35 | child_wait PARAMS ((int, struct target_waitstatus *)); |
de43d7d0 | 36 | #endif /* CHILD_WAIT */ |
dcc8abce JG |
37 | |
38 | static void | |
39 | child_open PARAMS ((char *, int)); | |
40 | ||
41 | static void | |
42 | child_files_info PARAMS ((struct target_ops *)); | |
43 | ||
44 | static void | |
45 | child_detach PARAMS ((char *, int)); | |
bd5635a1 | 46 | |
310cc570 RP |
47 | static void |
48 | child_attach PARAMS ((char *, int)); | |
49 | ||
de43d7d0 SG |
50 | static void |
51 | ptrace_me PARAMS ((void)); | |
52 | ||
53 | static void | |
54 | ptrace_him PARAMS ((int)); | |
55 | ||
310cc570 RP |
56 | static void |
57 | child_create_inferior PARAMS ((char *, char *, char **)); | |
58 | ||
59 | static void | |
60 | child_mourn_inferior PARAMS ((void)); | |
61 | ||
3aa6856a JG |
62 | static int |
63 | child_can_run PARAMS ((void)); | |
64 | ||
310cc570 RP |
65 | extern char **environ; |
66 | ||
bd5635a1 RP |
67 | /* Forward declaration */ |
68 | extern struct target_ops child_ops; | |
69 | ||
67ac9759 JK |
70 | /* Convert host signal to our signals. */ |
71 | enum target_signal | |
72 | target_signal_from_host (hostsig) | |
73 | int hostsig; | |
74 | { | |
75 | /* A switch statement would make sense but would require special kludges | |
76 | to deal with the cases where more than one signal has the same number. */ | |
77 | ||
78 | if (hostsig == 0) return TARGET_SIGNAL_0; | |
79 | ||
80 | #if defined (SIGHUP) | |
81 | if (hostsig == SIGHUP) return TARGET_SIGNAL_HUP; | |
82 | #endif | |
83 | #if defined (SIGINT) | |
84 | if (hostsig == SIGINT) return TARGET_SIGNAL_INT; | |
85 | #endif | |
86 | #if defined (SIGQUIT) | |
87 | if (hostsig == SIGQUIT) return TARGET_SIGNAL_QUIT; | |
88 | #endif | |
89 | #if defined (SIGILL) | |
90 | if (hostsig == SIGILL) return TARGET_SIGNAL_ILL; | |
91 | #endif | |
92 | #if defined (SIGTRAP) | |
93 | if (hostsig == SIGTRAP) return TARGET_SIGNAL_TRAP; | |
94 | #endif | |
95 | #if defined (SIGABRT) | |
96 | if (hostsig == SIGABRT) return TARGET_SIGNAL_ABRT; | |
97 | #endif | |
98 | #if defined (SIGEMT) | |
99 | if (hostsig == SIGEMT) return TARGET_SIGNAL_EMT; | |
100 | #endif | |
101 | #if defined (SIGFPE) | |
102 | if (hostsig == SIGFPE) return TARGET_SIGNAL_FPE; | |
103 | #endif | |
104 | #if defined (SIGKILL) | |
105 | if (hostsig == SIGKILL) return TARGET_SIGNAL_KILL; | |
106 | #endif | |
107 | #if defined (SIGBUS) | |
108 | if (hostsig == SIGBUS) return TARGET_SIGNAL_BUS; | |
109 | #endif | |
110 | #if defined (SIGSEGV) | |
111 | if (hostsig == SIGSEGV) return TARGET_SIGNAL_SEGV; | |
112 | #endif | |
113 | #if defined (SIGSYS) | |
114 | if (hostsig == SIGSYS) return TARGET_SIGNAL_SYS; | |
115 | #endif | |
116 | #if defined (SIGPIPE) | |
117 | if (hostsig == SIGPIPE) return TARGET_SIGNAL_PIPE; | |
118 | #endif | |
119 | #if defined (SIGALRM) | |
120 | if (hostsig == SIGALRM) return TARGET_SIGNAL_ALRM; | |
121 | #endif | |
122 | #if defined (SIGTERM) | |
123 | if (hostsig == SIGTERM) return TARGET_SIGNAL_TERM; | |
124 | #endif | |
125 | #if defined (SIGUSR1) | |
126 | if (hostsig == SIGUSR1) return TARGET_SIGNAL_USR1; | |
127 | #endif | |
128 | #if defined (SIGUSR2) | |
129 | if (hostsig == SIGUSR2) return TARGET_SIGNAL_USR2; | |
130 | #endif | |
131 | #if defined (SIGCLD) | |
132 | if (hostsig == SIGCLD) return TARGET_SIGNAL_CHLD; | |
133 | #endif | |
134 | #if defined (SIGCHLD) | |
135 | if (hostsig == SIGCHLD) return TARGET_SIGNAL_CHLD; | |
136 | #endif | |
137 | #if defined (SIGPWR) | |
138 | if (hostsig == SIGPWR) return TARGET_SIGNAL_PWR; | |
139 | #endif | |
140 | #if defined (SIGWINCH) | |
141 | if (hostsig == SIGWINCH) return TARGET_SIGNAL_WINCH; | |
142 | #endif | |
143 | #if defined (SIGURG) | |
144 | if (hostsig == SIGURG) return TARGET_SIGNAL_URG; | |
145 | #endif | |
146 | #if defined (SIGIO) | |
147 | if (hostsig == SIGIO) return TARGET_SIGNAL_IO; | |
148 | #endif | |
149 | #if defined (SIGPOLL) | |
150 | if (hostsig == SIGPOLL) return TARGET_SIGNAL_POLL; | |
151 | #endif | |
152 | #if defined (SIGSTOP) | |
153 | if (hostsig == SIGSTOP) return TARGET_SIGNAL_STOP; | |
154 | #endif | |
155 | #if defined (SIGTSTP) | |
156 | if (hostsig == SIGTSTP) return TARGET_SIGNAL_TSTP; | |
157 | #endif | |
158 | #if defined (SIGCONT) | |
159 | if (hostsig == SIGCONT) return TARGET_SIGNAL_CONT; | |
160 | #endif | |
161 | #if defined (SIGTTIN) | |
162 | if (hostsig == SIGTTIN) return TARGET_SIGNAL_TTIN; | |
163 | #endif | |
164 | #if defined (SIGTTOU) | |
165 | if (hostsig == SIGTTOU) return TARGET_SIGNAL_TTOU; | |
166 | #endif | |
167 | #if defined (SIGVTALRM) | |
168 | if (hostsig == SIGVTALRM) return TARGET_SIGNAL_VTALRM; | |
169 | #endif | |
170 | #if defined (SIGPROF) | |
171 | if (hostsig == SIGPROF) return TARGET_SIGNAL_PROF; | |
172 | #endif | |
173 | #if defined (SIGXCPU) | |
174 | if (hostsig == SIGXCPU) return TARGET_SIGNAL_XCPU; | |
175 | #endif | |
176 | #if defined (SIGXFSZ) | |
177 | if (hostsig == SIGXFSZ) return TARGET_SIGNAL_XFSZ; | |
178 | #endif | |
179 | #if defined (SIGWIND) | |
180 | if (hostsig == SIGWIND) return TARGET_SIGNAL_WIND; | |
181 | #endif | |
182 | #if defined (SIGPHONE) | |
183 | if (hostsig == SIGPHONE) return TARGET_SIGNAL_PHONE; | |
184 | #endif | |
185 | #if defined (SIGLOST) | |
186 | if (hostsig == SIGLOST) return TARGET_SIGNAL_LOST; | |
187 | #endif | |
188 | #if defined (SIGWAITING) | |
189 | if (hostsig == SIGWAITING) return TARGET_SIGNAL_WAITING; | |
190 | #endif | |
191 | #if defined (SIGLWP) | |
192 | if (hostsig == SIGLWP) return TARGET_SIGNAL_LWP; | |
193 | #endif | |
194 | #if defined (SIGDANGER) | |
195 | if (hostsig == SIGDANGER) return TARGET_SIGNAL_DANGER; | |
196 | #endif | |
197 | #if defined (SIGGRANT) | |
198 | if (hostsig == SIGGRANT) return TARGET_SIGNAL_GRANT; | |
199 | #endif | |
200 | #if defined (SIGRETRACT) | |
201 | if (hostsig == SIGRETRACT) return TARGET_SIGNAL_RETRACT; | |
202 | #endif | |
203 | #if defined (SIGMSG) | |
204 | if (hostsig == SIGMSG) return TARGET_SIGNAL_MSG; | |
205 | #endif | |
206 | #if defined (SIGSOUND) | |
207 | if (hostsig == SIGSOUND) return TARGET_SIGNAL_SOUND; | |
208 | #endif | |
209 | #if defined (SIGSAK) | |
210 | if (hostsig == SIGSAK) return TARGET_SIGNAL_SAK; | |
211 | #endif | |
212 | return TARGET_SIGNAL_UNKNOWN; | |
213 | } | |
214 | ||
215 | int | |
216 | target_signal_to_host (oursig) | |
217 | enum target_signal oursig; | |
218 | { | |
219 | switch (oursig) | |
220 | { | |
221 | case TARGET_SIGNAL_0: return 0; | |
222 | ||
223 | #if defined (SIGHUP) | |
224 | case TARGET_SIGNAL_HUP: return SIGHUP; | |
225 | #endif | |
226 | #if defined (SIGINT) | |
227 | case TARGET_SIGNAL_INT: return SIGINT; | |
228 | #endif | |
229 | #if defined (SIGQUIT) | |
230 | case TARGET_SIGNAL_QUIT: return SIGQUIT; | |
231 | #endif | |
232 | #if defined (SIGILL) | |
233 | case TARGET_SIGNAL_ILL: return SIGILL; | |
234 | #endif | |
235 | #if defined (SIGTRAP) | |
236 | case TARGET_SIGNAL_TRAP: return SIGTRAP; | |
237 | #endif | |
238 | #if defined (SIGABRT) | |
239 | case TARGET_SIGNAL_ABRT: return SIGABRT; | |
240 | #endif | |
241 | #if defined (SIGEMT) | |
242 | case TARGET_SIGNAL_EMT: return SIGEMT; | |
243 | #endif | |
244 | #if defined (SIGFPE) | |
245 | case TARGET_SIGNAL_FPE: return SIGFPE; | |
246 | #endif | |
247 | #if defined (SIGKILL) | |
248 | case TARGET_SIGNAL_KILL: return SIGKILL; | |
249 | #endif | |
250 | #if defined (SIGBUS) | |
251 | case TARGET_SIGNAL_BUS: return SIGBUS; | |
252 | #endif | |
253 | #if defined (SIGSEGV) | |
254 | case TARGET_SIGNAL_SEGV: return SIGSEGV; | |
255 | #endif | |
256 | #if defined (SIGSYS) | |
257 | case TARGET_SIGNAL_SYS: return SIGSYS; | |
258 | #endif | |
259 | #if defined (SIGPIPE) | |
260 | case TARGET_SIGNAL_PIPE: return SIGPIPE; | |
261 | #endif | |
262 | #if defined (SIGALRM) | |
263 | case TARGET_SIGNAL_ALRM: return SIGALRM; | |
264 | #endif | |
265 | #if defined (SIGTERM) | |
266 | case TARGET_SIGNAL_TERM: return SIGTERM; | |
267 | #endif | |
268 | #if defined (SIGUSR1) | |
269 | case TARGET_SIGNAL_USR1: return SIGUSR1; | |
270 | #endif | |
271 | #if defined (SIGUSR2) | |
272 | case TARGET_SIGNAL_USR2: return SIGUSR2; | |
273 | #endif | |
274 | #if defined (SIGCHLD) || defined (SIGCLD) | |
275 | case TARGET_SIGNAL_CHLD: | |
276 | #if defined (SIGCHLD) | |
277 | return SIGCHLD; | |
278 | #else | |
279 | return SIGCLD; | |
280 | #endif | |
281 | #endif /* SIGCLD or SIGCHLD */ | |
282 | #if defined (SIGPWR) | |
283 | case TARGET_SIGNAL_PWR: return SIGPWR; | |
284 | #endif | |
285 | #if defined (SIGWINCH) | |
286 | case TARGET_SIGNAL_WINCH: return SIGWINCH; | |
287 | #endif | |
288 | #if defined (SIGURG) | |
289 | case TARGET_SIGNAL_URG: return SIGURG; | |
290 | #endif | |
291 | #if defined (SIGIO) | |
292 | case TARGET_SIGNAL_IO: return SIGIO; | |
293 | #endif | |
294 | #if defined (SIGPOLL) | |
295 | case TARGET_SIGNAL_POLL: return SIGPOLL; | |
296 | #endif | |
297 | #if defined (SIGSTOP) | |
298 | case TARGET_SIGNAL_STOP: return SIGSTOP; | |
299 | #endif | |
300 | #if defined (SIGTSTP) | |
301 | case TARGET_SIGNAL_TSTP: return SIGTSTP; | |
302 | #endif | |
303 | #if defined (SIGCONT) | |
304 | case TARGET_SIGNAL_CONT: return SIGCONT; | |
305 | #endif | |
306 | #if defined (SIGTTIN) | |
307 | case TARGET_SIGNAL_TTIN: return SIGTTIN; | |
308 | #endif | |
309 | #if defined (SIGTTOU) | |
310 | case TARGET_SIGNAL_TTOU: return SIGTTOU; | |
311 | #endif | |
312 | #if defined (SIGVTALRM) | |
313 | case TARGET_SIGNAL_VTALRM: return SIGVTALRM; | |
314 | #endif | |
315 | #if defined (SIGPROF) | |
316 | case TARGET_SIGNAL_PROF: return SIGPROF; | |
317 | #endif | |
318 | #if defined (SIGXCPU) | |
319 | case TARGET_SIGNAL_XCPU: return SIGXCPU; | |
320 | #endif | |
321 | #if defined (SIGXFSZ) | |
322 | case TARGET_SIGNAL_XFSZ: return SIGXFSZ; | |
323 | #endif | |
324 | #if defined (SIGWIND) | |
325 | case TARGET_SIGNAL_WIND: return SIGWIND; | |
326 | #endif | |
327 | #if defined (SIGPHONE) | |
328 | case TARGET_SIGNAL_PHONE: return SIGPHONE; | |
329 | #endif | |
330 | #if defined (SIGLOST) | |
331 | case TARGET_SIGNAL_LOST: return SIGLOST; | |
332 | #endif | |
333 | #if defined (SIGWAITING) | |
334 | case TARGET_SIGNAL_WAITING: return SIGWAITING; | |
335 | #endif | |
336 | #if defined (SIGLWP) | |
337 | case TARGET_SIGNAL_LWP: return SIGLWP; | |
338 | #endif | |
339 | #if defined (SIGDANGER) | |
340 | case TARGET_SIGNAL_DANGER: return SIGDANGER; | |
341 | #endif | |
342 | #if defined (SIGGRANT) | |
343 | case TARGET_SIGNAL_GRANT: return SIGGRANT; | |
344 | #endif | |
345 | #if defined (SIGRETRACT) | |
346 | case TARGET_SIGNAL_RETRACT: return SIGRETRACT; | |
347 | #endif | |
348 | #if defined (SIGMSG) | |
349 | case TARGET_SIGNAL_MSG: return SIGMSG; | |
350 | #endif | |
351 | #if defined (SIGSOUND) | |
352 | case TARGET_SIGNAL_SOUND: return SIGSOUND; | |
353 | #endif | |
354 | #if defined (SIGSAK) | |
355 | case TARGET_SIGNAL_SAK: return SIGSAK; | |
356 | #endif | |
357 | default: | |
358 | /* The user might be trying to do "signal SIGSAK" where this system | |
359 | doesn't have SIGSAK. */ | |
360 | warning ("Signal %s does not exist on this system.\n", | |
361 | target_signal_to_name (oursig)); | |
362 | return 0; | |
363 | } | |
364 | } | |
365 | ||
366 | /* Helper function for child_wait and the Lynx derivatives of child_wait. | |
367 | HOSTSTATUS is the waitstatus from wait() or the equivalent; store our | |
368 | translation of that in OURSTATUS. */ | |
369 | void | |
370 | store_waitstatus (ourstatus, hoststatus) | |
371 | struct target_waitstatus *ourstatus; | |
372 | int hoststatus; | |
373 | { | |
374 | if (WIFEXITED (hoststatus)) | |
375 | { | |
376 | ourstatus->kind = TARGET_WAITKIND_EXITED; | |
377 | ourstatus->value.integer = WEXITSTATUS (hoststatus); | |
378 | } | |
379 | else if (!WIFSTOPPED (hoststatus)) | |
380 | { | |
381 | ourstatus->kind = TARGET_WAITKIND_SIGNALLED; | |
382 | ourstatus->value.sig = target_signal_from_host (WTERMSIG (hoststatus)); | |
383 | } | |
384 | else | |
385 | { | |
386 | ourstatus->kind = TARGET_WAITKIND_STOPPED; | |
387 | ourstatus->value.sig = target_signal_from_host (WSTOPSIG (hoststatus)); | |
388 | } | |
389 | } | |
390 | ||
de43d7d0 SG |
391 | #ifndef CHILD_WAIT |
392 | ||
bd5635a1 | 393 | /* Wait for child to do something. Return pid of child, or -1 in case |
67ac9759 | 394 | of error; store status through argument pointer OURSTATUS. */ |
bd5635a1 | 395 | |
dcc8abce | 396 | static int |
67ac9759 | 397 | child_wait (pid, ourstatus) |
de43d7d0 | 398 | int pid; |
67ac9759 | 399 | struct target_waitstatus *ourstatus; |
bd5635a1 | 400 | { |
de43d7d0 | 401 | int save_errno; |
67ac9759 | 402 | int status; |
bd5635a1 RP |
403 | |
404 | do { | |
de43d7d0 SG |
405 | if (attach_flag) |
406 | set_sigint_trap(); /* Causes SIGINT to be passed on to the | |
407 | attached process. */ | |
67ac9759 | 408 | pid = wait (&status); |
de43d7d0 SG |
409 | save_errno = errno; |
410 | ||
411 | if (attach_flag) | |
412 | clear_sigint_trap(); | |
413 | ||
414 | if (pid == -1) | |
bd5635a1 | 415 | { |
de43d7d0 SG |
416 | if (save_errno == EINTR) |
417 | continue; | |
67ac9759 | 418 | fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n", |
de43d7d0 | 419 | safe_strerror (save_errno)); |
67ac9759 JK |
420 | /* Claim it exited with unknown signal. */ |
421 | ourstatus->kind = TARGET_WAITKIND_SIGNALLED; | |
422 | ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; | |
bd5635a1 RP |
423 | return -1; |
424 | } | |
425 | } while (pid != inferior_pid); /* Some other child died or stopped */ | |
67ac9759 | 426 | store_waitstatus (ourstatus, status); |
bd5635a1 RP |
427 | return pid; |
428 | } | |
de43d7d0 | 429 | #endif /* CHILD_WAIT */ |
bd5635a1 | 430 | |
836e343b | 431 | /* Attach to process PID, then initialize for debugging it. */ |
310cc570 RP |
432 | |
433 | static void | |
434 | child_attach (args, from_tty) | |
435 | char *args; | |
436 | int from_tty; | |
437 | { | |
310cc570 RP |
438 | if (!args) |
439 | error_no_arg ("process-id to attach"); | |
440 | ||
441 | #ifndef ATTACH_DETACH | |
442 | error ("Can't attach to a process on this machine."); | |
443 | #else | |
100f92e2 JK |
444 | { |
445 | char *exec_file; | |
446 | int pid; | |
310cc570 | 447 | |
100f92e2 | 448 | pid = atoi (args); |
310cc570 | 449 | |
100f92e2 JK |
450 | if (pid == getpid()) /* Trying to masturbate? */ |
451 | error ("I refuse to debug myself!"); | |
310cc570 | 452 | |
100f92e2 JK |
453 | if (from_tty) |
454 | { | |
455 | exec_file = (char *) get_exec_file (0); | |
310cc570 | 456 | |
100f92e2 | 457 | if (exec_file) |
67ac9759 | 458 | printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, |
100f92e2 JK |
459 | target_pid_to_str (pid)); |
460 | else | |
67ac9759 | 461 | printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid)); |
100f92e2 | 462 | |
67ac9759 | 463 | gdb_flush (gdb_stdout); |
100f92e2 | 464 | } |
310cc570 | 465 | |
100f92e2 JK |
466 | attach (pid); |
467 | inferior_pid = pid; | |
468 | push_target (&child_ops); | |
469 | } | |
310cc570 RP |
470 | #endif /* ATTACH_DETACH */ |
471 | } | |
472 | ||
3aa6856a JG |
473 | |
474 | /* Take a program previously attached to and detaches it. | |
475 | The program resumes execution and will no longer stop | |
476 | on signals, etc. We'd better not have left any breakpoints | |
477 | in the program or it'll die when it hits one. For this | |
478 | to work, it may be necessary for the process to have been | |
479 | previously attached. It *might* work if the program was | |
480 | started via the normal ptrace (PTRACE_TRACEME). */ | |
bd5635a1 RP |
481 | |
482 | static void | |
483 | child_detach (args, from_tty) | |
484 | char *args; | |
485 | int from_tty; | |
486 | { | |
bd5635a1 | 487 | #ifdef ATTACH_DETACH |
100f92e2 JK |
488 | { |
489 | int siggnal = 0; | |
490 | ||
491 | if (from_tty) | |
492 | { | |
493 | char *exec_file = get_exec_file (0); | |
494 | if (exec_file == 0) | |
495 | exec_file = ""; | |
67ac9759 | 496 | printf_unfiltered ("Detaching from program: %s %s\n", exec_file, |
100f92e2 | 497 | target_pid_to_str (inferior_pid)); |
67ac9759 | 498 | gdb_flush (gdb_stdout); |
100f92e2 JK |
499 | } |
500 | if (args) | |
501 | siggnal = atoi (args); | |
502 | ||
503 | detach (siggnal); | |
504 | inferior_pid = 0; | |
505 | unpush_target (&child_ops); | |
506 | } | |
bd5635a1 | 507 | #else |
100f92e2 | 508 | error ("This version of Unix does not support detaching a process."); |
bd5635a1 RP |
509 | #endif |
510 | } | |
511 | ||
512 | /* Get ready to modify the registers array. On machines which store | |
513 | individual registers, this doesn't need to do anything. On machines | |
514 | which store all the registers in one fell swoop, this makes sure | |
515 | that registers contains all the registers from the program being | |
516 | debugged. */ | |
517 | ||
dcc8abce | 518 | static void |
bd5635a1 RP |
519 | child_prepare_to_store () |
520 | { | |
521 | #ifdef CHILD_PREPARE_TO_STORE | |
522 | CHILD_PREPARE_TO_STORE (); | |
523 | #endif | |
524 | } | |
525 | ||
bd5635a1 RP |
526 | /* Print status information about what we're accessing. */ |
527 | ||
528 | static void | |
dcc8abce JG |
529 | child_files_info (ignore) |
530 | struct target_ops *ignore; | |
bd5635a1 | 531 | { |
67ac9759 | 532 | printf_unfiltered ("\tUsing the running image of %s %s.\n", |
de43d7d0 | 533 | attach_flag? "attached": "child", target_pid_to_str (inferior_pid)); |
bd5635a1 RP |
534 | } |
535 | ||
e1ce8aa5 | 536 | /* ARGSUSED */ |
70dcc196 JK |
537 | static void |
538 | child_open (arg, from_tty) | |
539 | char *arg; | |
540 | int from_tty; | |
541 | { | |
542 | error ("Use the \"run\" command to start a Unix child process."); | |
543 | } | |
544 | ||
de43d7d0 SG |
545 | /* Stub function which causes the inferior that runs it, to be ptrace-able |
546 | by its parent process. */ | |
547 | ||
548 | static void | |
549 | ptrace_me () | |
550 | { | |
551 | /* "Trace me, Dr. Memory!" */ | |
552 | call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0); | |
553 | } | |
554 | ||
555 | /* Stub function which causes the GDB that runs it, to start ptrace-ing | |
556 | the child process. */ | |
557 | ||
558 | static void | |
559 | ptrace_him (pid) | |
560 | int pid; | |
561 | { | |
562 | push_target (&child_ops); | |
67ac9759 JK |
563 | |
564 | #ifdef START_INFERIOR_TRAPS_EXPECTED | |
565 | startup_inferior (START_INFERIOR_TRAPS_EXPECTED); | |
566 | #else | |
567 | /* One trap to exec the shell, one to exec the program being debugged. */ | |
568 | startup_inferior (2); | |
569 | #endif | |
de43d7d0 SG |
570 | } |
571 | ||
310cc570 RP |
572 | /* Start an inferior Unix child process and sets inferior_pid to its pid. |
573 | EXEC_FILE is the file to run. | |
574 | ALLARGS is a string containing the arguments to the program. | |
575 | ENV is the environment vector to pass. Errors reported with error(). */ | |
576 | ||
310cc570 RP |
577 | static void |
578 | child_create_inferior (exec_file, allargs, env) | |
579 | char *exec_file; | |
580 | char *allargs; | |
581 | char **env; | |
582 | { | |
de43d7d0 SG |
583 | fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him); |
584 | /* We are at the first instruction we care about. */ | |
585 | /* Pedal to the metal... */ | |
67ac9759 | 586 | proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); |
310cc570 RP |
587 | } |
588 | ||
589 | static void | |
590 | child_mourn_inferior () | |
591 | { | |
592 | unpush_target (&child_ops); | |
593 | generic_mourn_inferior (); | |
594 | } | |
595 | ||
596 | static int | |
597 | child_can_run () | |
598 | { | |
599 | return(1); | |
600 | } | |
3aa6856a | 601 | \f |
bd5635a1 | 602 | struct target_ops child_ops = { |
dcc8abce JG |
603 | "child", /* to_shortname */ |
604 | "Unix child process", /* to_longname */ | |
605 | "Unix child process (started by the \"run\" command).", /* to_doc */ | |
606 | child_open, /* to_open */ | |
607 | 0, /* to_close */ | |
608 | child_attach, /* to_attach */ | |
609 | child_detach, /* to_detach */ | |
610 | child_resume, /* to_resume */ | |
611 | child_wait, /* to_wait */ | |
612 | fetch_inferior_registers, /* to_fetch_registers */ | |
613 | store_inferior_registers, /* to_store_registers */ | |
614 | child_prepare_to_store, /* to_prepare_to_store */ | |
615 | child_xfer_memory, /* to_xfer_memory */ | |
616 | child_files_info, /* to_files_info */ | |
617 | memory_insert_breakpoint, /* to_insert_breakpoint */ | |
618 | memory_remove_breakpoint, /* to_remove_breakpoint */ | |
619 | terminal_init_inferior, /* to_terminal_init */ | |
620 | terminal_inferior, /* to_terminal_inferior */ | |
621 | terminal_ours_for_output, /* to_terminal_ours_for_output */ | |
622 | terminal_ours, /* to_terminal_ours */ | |
623 | child_terminal_info, /* to_terminal_info */ | |
624 | kill_inferior, /* to_kill */ | |
625 | 0, /* to_load */ | |
626 | 0, /* to_lookup_symbol */ | |
627 | child_create_inferior, /* to_create_inferior */ | |
628 | child_mourn_inferior, /* to_mourn_inferior */ | |
310cc570 | 629 | child_can_run, /* to_can_run */ |
de43d7d0 | 630 | 0, /* to_notice_signals */ |
dcc8abce JG |
631 | process_stratum, /* to_stratum */ |
632 | 0, /* to_next */ | |
633 | 1, /* to_has_all_memory */ | |
634 | 1, /* to_has_memory */ | |
635 | 1, /* to_has_stack */ | |
636 | 1, /* to_has_registers */ | |
637 | 1, /* to_has_execution */ | |
638 | 0, /* sections */ | |
639 | 0, /* sections_end */ | |
640 | OPS_MAGIC /* to_magic */ | |
bd5635a1 RP |
641 | }; |
642 | ||
643 | void | |
644 | _initialize_inftarg () | |
645 | { | |
646 | add_target (&child_ops); | |
647 | } |