Commit | Line | Data |
---|---|---|
3aa6856a | 1 | /* Target-vector operations for controlling Unix child processes, for GDB. |
4ef1f467 DT |
2 | Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996 |
3 | Free Software Foundation, Inc. | |
bd5635a1 RP |
4 | Contributed by Cygnus Support. |
5 | ||
6 | This file is part of GDB. | |
7 | ||
dcc8abce | 8 | This program is free software; you can redistribute it and/or modify |
bd5635a1 | 9 | it under the terms of the GNU General Public License as published by |
dcc8abce JG |
10 | the Free Software Foundation; either version 2 of the License, or |
11 | (at your option) any later version. | |
bd5635a1 | 12 | |
dcc8abce | 13 | This program is distributed in the hope that it will be useful, |
bd5635a1 RP |
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 | |
dcc8abce | 19 | along with this program; if not, write to the Free Software |
4ef1f467 | 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
bd5635a1 | 21 | |
bd5635a1 | 22 | #include "defs.h" |
bd5635a1 RP |
23 | #include "frame.h" /* required by inferior.h */ |
24 | #include "inferior.h" | |
25 | #include "target.h" | |
bd5635a1 | 26 | #include "gdbcore.h" |
100f92e2 | 27 | #include "command.h" |
310cc570 | 28 | #include <signal.h> |
4ef1f467 DT |
29 | #include <sys/types.h> |
30 | #include <fcntl.h> | |
31 | ||
32 | #ifdef HAVE_WAIT_H | |
33 | # include <wait.h> | |
34 | #else | |
35 | # ifdef HAVE_SYS_WAIT_H | |
36 | # include <sys/wait.h> | |
37 | # endif | |
38 | #endif | |
39 | ||
40 | /* "wait.h" fills in the gaps left by <wait.h> */ | |
41 | #include "wait.h" | |
310cc570 | 42 | |
dcc8abce JG |
43 | static void |
44 | child_prepare_to_store PARAMS ((void)); | |
45 | ||
de43d7d0 | 46 | #ifndef CHILD_WAIT |
429f1c9f | 47 | static int child_wait PARAMS ((int, struct target_waitstatus *)); |
de43d7d0 | 48 | #endif /* CHILD_WAIT */ |
dcc8abce | 49 | |
429f1c9f | 50 | static void child_open PARAMS ((char *, int)); |
dcc8abce JG |
51 | |
52 | static void | |
53 | child_files_info PARAMS ((struct target_ops *)); | |
54 | ||
55 | static void | |
56 | child_detach PARAMS ((char *, int)); | |
bd5635a1 | 57 | |
310cc570 RP |
58 | static void |
59 | child_attach PARAMS ((char *, int)); | |
60 | ||
de43d7d0 SG |
61 | static void |
62 | ptrace_me PARAMS ((void)); | |
63 | ||
4ef1f467 | 64 | static int |
de43d7d0 SG |
65 | ptrace_him PARAMS ((int)); |
66 | ||
429f1c9f | 67 | static void child_create_inferior PARAMS ((char *, char *, char **)); |
310cc570 RP |
68 | |
69 | static void | |
70 | child_mourn_inferior PARAMS ((void)); | |
71 | ||
3aa6856a JG |
72 | static int |
73 | child_can_run PARAMS ((void)); | |
74 | ||
4ef1f467 DT |
75 | static int |
76 | proc_wait PARAMS ((int, int*)); | |
77 | ||
78 | static void | |
79 | child_stop PARAMS ((void)); | |
80 | ||
81 | #ifndef CHILD_THREAD_ALIVE | |
82 | static int child_thread_alive PARAMS ((int)); | |
83 | #endif | |
84 | ||
310cc570 RP |
85 | extern char **environ; |
86 | ||
bd5635a1 RP |
87 | /* Forward declaration */ |
88 | extern struct target_ops child_ops; | |
89 | ||
4ef1f467 DT |
90 | int child_suppress_run = 0; /* Non-zero if inftarg should pretend not to |
91 | be a runnable target. Used by targets | |
92 | that can sit atop inftarg, such as HPUX | |
93 | thread support. */ | |
94 | static int | |
95 | proc_wait (pid, status) | |
96 | int pid; | |
97 | int *status; | |
98 | { | |
99 | #ifndef __GO32__ | |
100 | return wait (status); | |
101 | #endif | |
102 | } | |
103 | ||
de43d7d0 SG |
104 | #ifndef CHILD_WAIT |
105 | ||
bd5635a1 | 106 | /* Wait for child to do something. Return pid of child, or -1 in case |
67ac9759 | 107 | of error; store status through argument pointer OURSTATUS. */ |
bd5635a1 | 108 | |
dcc8abce | 109 | static int |
67ac9759 | 110 | child_wait (pid, ourstatus) |
de43d7d0 | 111 | int pid; |
67ac9759 | 112 | struct target_waitstatus *ourstatus; |
bd5635a1 | 113 | { |
de43d7d0 | 114 | int save_errno; |
67ac9759 | 115 | int status; |
bd5635a1 RP |
116 | |
117 | do { | |
4ef1f467 DT |
118 | set_sigint_trap(); /* Causes SIGINT to be passed on to the |
119 | attached process. */ | |
429f1c9f JK |
120 | set_sigio_trap (); |
121 | ||
4ef1f467 | 122 | pid = proc_wait (inferior_pid, &status); |
de43d7d0 SG |
123 | save_errno = errno; |
124 | ||
429f1c9f JK |
125 | clear_sigio_trap (); |
126 | ||
4ef1f467 | 127 | clear_sigint_trap(); |
de43d7d0 SG |
128 | |
129 | if (pid == -1) | |
bd5635a1 | 130 | { |
de43d7d0 SG |
131 | if (save_errno == EINTR) |
132 | continue; | |
67ac9759 | 133 | fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n", |
de43d7d0 | 134 | safe_strerror (save_errno)); |
67ac9759 JK |
135 | /* Claim it exited with unknown signal. */ |
136 | ourstatus->kind = TARGET_WAITKIND_SIGNALLED; | |
137 | ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; | |
bd5635a1 RP |
138 | return -1; |
139 | } | |
140 | } while (pid != inferior_pid); /* Some other child died or stopped */ | |
67ac9759 | 141 | store_waitstatus (ourstatus, status); |
bd5635a1 RP |
142 | return pid; |
143 | } | |
de43d7d0 | 144 | #endif /* CHILD_WAIT */ |
bd5635a1 | 145 | |
4ef1f467 DT |
146 | #ifndef CHILD_THREAD_ALIVE |
147 | ||
148 | /* Check to see if the given thread is alive. | |
149 | ||
150 | FIXME: Is kill() ever the right way to do this? I doubt it, but | |
151 | for now we're going to try and be compatable with the old thread | |
152 | code. */ | |
153 | static int | |
154 | child_thread_alive (pid) | |
155 | int pid; | |
156 | { | |
157 | return (kill (pid, 0) != -1); | |
158 | } | |
159 | ||
160 | #endif | |
161 | ||
836e343b | 162 | /* Attach to process PID, then initialize for debugging it. */ |
310cc570 RP |
163 | |
164 | static void | |
165 | child_attach (args, from_tty) | |
166 | char *args; | |
167 | int from_tty; | |
168 | { | |
310cc570 RP |
169 | if (!args) |
170 | error_no_arg ("process-id to attach"); | |
171 | ||
172 | #ifndef ATTACH_DETACH | |
173 | error ("Can't attach to a process on this machine."); | |
174 | #else | |
100f92e2 JK |
175 | { |
176 | char *exec_file; | |
177 | int pid; | |
310cc570 | 178 | |
100f92e2 | 179 | pid = atoi (args); |
310cc570 | 180 | |
100f92e2 JK |
181 | if (pid == getpid()) /* Trying to masturbate? */ |
182 | error ("I refuse to debug myself!"); | |
310cc570 | 183 | |
100f92e2 JK |
184 | if (from_tty) |
185 | { | |
186 | exec_file = (char *) get_exec_file (0); | |
310cc570 | 187 | |
100f92e2 | 188 | if (exec_file) |
67ac9759 | 189 | printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, |
100f92e2 JK |
190 | target_pid_to_str (pid)); |
191 | else | |
67ac9759 | 192 | printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid)); |
100f92e2 | 193 | |
67ac9759 | 194 | gdb_flush (gdb_stdout); |
100f92e2 | 195 | } |
310cc570 | 196 | |
100f92e2 JK |
197 | attach (pid); |
198 | inferior_pid = pid; | |
199 | push_target (&child_ops); | |
200 | } | |
310cc570 RP |
201 | #endif /* ATTACH_DETACH */ |
202 | } | |
203 | ||
3aa6856a JG |
204 | |
205 | /* Take a program previously attached to and detaches it. | |
206 | The program resumes execution and will no longer stop | |
207 | on signals, etc. We'd better not have left any breakpoints | |
208 | in the program or it'll die when it hits one. For this | |
209 | to work, it may be necessary for the process to have been | |
210 | previously attached. It *might* work if the program was | |
211 | started via the normal ptrace (PTRACE_TRACEME). */ | |
bd5635a1 RP |
212 | |
213 | static void | |
214 | child_detach (args, from_tty) | |
215 | char *args; | |
216 | int from_tty; | |
217 | { | |
bd5635a1 | 218 | #ifdef ATTACH_DETACH |
100f92e2 JK |
219 | { |
220 | int siggnal = 0; | |
221 | ||
222 | if (from_tty) | |
223 | { | |
224 | char *exec_file = get_exec_file (0); | |
225 | if (exec_file == 0) | |
226 | exec_file = ""; | |
67ac9759 | 227 | printf_unfiltered ("Detaching from program: %s %s\n", exec_file, |
100f92e2 | 228 | target_pid_to_str (inferior_pid)); |
67ac9759 | 229 | gdb_flush (gdb_stdout); |
100f92e2 JK |
230 | } |
231 | if (args) | |
232 | siggnal = atoi (args); | |
233 | ||
234 | detach (siggnal); | |
235 | inferior_pid = 0; | |
236 | unpush_target (&child_ops); | |
237 | } | |
bd5635a1 | 238 | #else |
100f92e2 | 239 | error ("This version of Unix does not support detaching a process."); |
bd5635a1 RP |
240 | #endif |
241 | } | |
242 | ||
243 | /* Get ready to modify the registers array. On machines which store | |
244 | individual registers, this doesn't need to do anything. On machines | |
245 | which store all the registers in one fell swoop, this makes sure | |
246 | that registers contains all the registers from the program being | |
247 | debugged. */ | |
248 | ||
dcc8abce | 249 | static void |
bd5635a1 RP |
250 | child_prepare_to_store () |
251 | { | |
252 | #ifdef CHILD_PREPARE_TO_STORE | |
253 | CHILD_PREPARE_TO_STORE (); | |
254 | #endif | |
255 | } | |
256 | ||
bd5635a1 RP |
257 | /* Print status information about what we're accessing. */ |
258 | ||
259 | static void | |
dcc8abce JG |
260 | child_files_info (ignore) |
261 | struct target_ops *ignore; | |
bd5635a1 | 262 | { |
67ac9759 | 263 | printf_unfiltered ("\tUsing the running image of %s %s.\n", |
de43d7d0 | 264 | attach_flag? "attached": "child", target_pid_to_str (inferior_pid)); |
bd5635a1 RP |
265 | } |
266 | ||
e1ce8aa5 | 267 | /* ARGSUSED */ |
70dcc196 JK |
268 | static void |
269 | child_open (arg, from_tty) | |
270 | char *arg; | |
271 | int from_tty; | |
272 | { | |
273 | error ("Use the \"run\" command to start a Unix child process."); | |
274 | } | |
275 | ||
de43d7d0 SG |
276 | /* Stub function which causes the inferior that runs it, to be ptrace-able |
277 | by its parent process. */ | |
278 | ||
279 | static void | |
280 | ptrace_me () | |
281 | { | |
282 | /* "Trace me, Dr. Memory!" */ | |
283 | call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0); | |
284 | } | |
285 | ||
286 | /* Stub function which causes the GDB that runs it, to start ptrace-ing | |
287 | the child process. */ | |
288 | ||
4ef1f467 | 289 | static int |
de43d7d0 SG |
290 | ptrace_him (pid) |
291 | int pid; | |
292 | { | |
293 | push_target (&child_ops); | |
67ac9759 JK |
294 | |
295 | #ifdef START_INFERIOR_TRAPS_EXPECTED | |
296 | startup_inferior (START_INFERIOR_TRAPS_EXPECTED); | |
297 | #else | |
298 | /* One trap to exec the shell, one to exec the program being debugged. */ | |
299 | startup_inferior (2); | |
300 | #endif | |
4ef1f467 DT |
301 | |
302 | return pid; | |
de43d7d0 SG |
303 | } |
304 | ||
310cc570 RP |
305 | /* Start an inferior Unix child process and sets inferior_pid to its pid. |
306 | EXEC_FILE is the file to run. | |
307 | ALLARGS is a string containing the arguments to the program. | |
308 | ENV is the environment vector to pass. Errors reported with error(). */ | |
309 | ||
310cc570 RP |
310 | static void |
311 | child_create_inferior (exec_file, allargs, env) | |
312 | char *exec_file; | |
313 | char *allargs; | |
314 | char **env; | |
315 | { | |
429f1c9f | 316 | fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, NULL); |
de43d7d0 SG |
317 | /* We are at the first instruction we care about. */ |
318 | /* Pedal to the metal... */ | |
67ac9759 | 319 | proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0); |
310cc570 RP |
320 | } |
321 | ||
322 | static void | |
323 | child_mourn_inferior () | |
324 | { | |
4ef1f467 DT |
325 | /* FIXME: Should be in a header file */ |
326 | extern void proc_remove_foreign PARAMS ((int)); | |
327 | ||
310cc570 | 328 | unpush_target (&child_ops); |
4ef1f467 | 329 | proc_remove_foreign (inferior_pid); |
310cc570 RP |
330 | generic_mourn_inferior (); |
331 | } | |
332 | ||
333 | static int | |
334 | child_can_run () | |
335 | { | |
4ef1f467 DT |
336 | /* This variable is controlled by modules that sit atop inftarg that may layer |
337 | their own process structure atop that provided here. hpux-thread.c does | |
338 | this because of the Hpux user-mode level thread model. */ | |
339 | ||
340 | return !child_suppress_run; | |
341 | } | |
342 | ||
343 | /* Send a SIGINT to the process group. This acts just like the user typed a | |
344 | ^C on the controlling terminal. | |
345 | ||
346 | XXX - This may not be correct for all systems. Some may want to use | |
347 | killpg() instead of kill (-pgrp). */ | |
348 | ||
349 | static void | |
350 | child_stop () | |
351 | { | |
352 | extern pid_t inferior_process_group; | |
353 | ||
354 | kill (-inferior_process_group, SIGINT); | |
310cc570 | 355 | } |
3aa6856a | 356 | \f |
bd5635a1 | 357 | struct target_ops child_ops = { |
dcc8abce JG |
358 | "child", /* to_shortname */ |
359 | "Unix child process", /* to_longname */ | |
360 | "Unix child process (started by the \"run\" command).", /* to_doc */ | |
361 | child_open, /* to_open */ | |
362 | 0, /* to_close */ | |
363 | child_attach, /* to_attach */ | |
4ef1f467 DT |
364 | NULL, /* to_post_attach */ |
365 | NULL, /* to_require_attach */ | |
dcc8abce | 366 | child_detach, /* to_detach */ |
4ef1f467 | 367 | NULL, /* to_require_detach */ |
dcc8abce JG |
368 | child_resume, /* to_resume */ |
369 | child_wait, /* to_wait */ | |
4ef1f467 | 370 | NULL, /* to_post_wait */ |
dcc8abce JG |
371 | fetch_inferior_registers, /* to_fetch_registers */ |
372 | store_inferior_registers, /* to_store_registers */ | |
373 | child_prepare_to_store, /* to_prepare_to_store */ | |
374 | child_xfer_memory, /* to_xfer_memory */ | |
375 | child_files_info, /* to_files_info */ | |
376 | memory_insert_breakpoint, /* to_insert_breakpoint */ | |
377 | memory_remove_breakpoint, /* to_remove_breakpoint */ | |
378 | terminal_init_inferior, /* to_terminal_init */ | |
379 | terminal_inferior, /* to_terminal_inferior */ | |
380 | terminal_ours_for_output, /* to_terminal_ours_for_output */ | |
381 | terminal_ours, /* to_terminal_ours */ | |
382 | child_terminal_info, /* to_terminal_info */ | |
383 | kill_inferior, /* to_kill */ | |
384 | 0, /* to_load */ | |
385 | 0, /* to_lookup_symbol */ | |
386 | child_create_inferior, /* to_create_inferior */ | |
4ef1f467 DT |
387 | NULL, /* to_post_startup_inferior */ |
388 | NULL, /* to_acknowledge_created_inferior */ | |
389 | NULL, /* to_clone_and_follow_inferior */ | |
390 | NULL, /* to_post_follow_inferior_by_clone */ | |
391 | NULL, /* to_insert_fork_catchpoint */ | |
392 | NULL, /* to_remove_fork_catchpoint */ | |
393 | NULL, /* to_insert_vfork_catchpoint */ | |
394 | NULL, /* to_remove_vfork_catchpoint */ | |
395 | NULL, /* to_has_forked */ | |
396 | NULL, /* to_has_vforked */ | |
397 | NULL, /* to_can_follow_vfork_prior_to_exec */ | |
398 | NULL, /* to_post_follow_vfork */ | |
399 | NULL, /* to_insert_exec_catchpoint */ | |
400 | NULL, /* to_remove_exec_catchpoint */ | |
401 | NULL, /* to_has_execd */ | |
402 | NULL, /* to_reported_exec_events_per_exec_call */ | |
403 | NULL, /* to_has_syscall_event */ | |
404 | NULL, /* to_has_exited */ | |
dcc8abce | 405 | child_mourn_inferior, /* to_mourn_inferior */ |
310cc570 | 406 | child_can_run, /* to_can_run */ |
de43d7d0 | 407 | 0, /* to_notice_signals */ |
4ef1f467 DT |
408 | child_thread_alive, /* to_thread_alive */ |
409 | child_stop, /* to_stop */ | |
410 | NULL, /* to_enable_exception_callback */ | |
411 | NULL, /* to_get_current_exception_event */ | |
412 | NULL, /* to_pid_to_exec_file */ | |
413 | NULL, /* to_core_file_to_sym_file */ | |
dcc8abce JG |
414 | process_stratum, /* to_stratum */ |
415 | 0, /* to_next */ | |
416 | 1, /* to_has_all_memory */ | |
417 | 1, /* to_has_memory */ | |
418 | 1, /* to_has_stack */ | |
419 | 1, /* to_has_registers */ | |
420 | 1, /* to_has_execution */ | |
4ef1f467 DT |
421 | 0, /* to_sections */ |
422 | 0, /* to_sections_end */ | |
dcc8abce | 423 | OPS_MAGIC /* to_magic */ |
bd5635a1 RP |
424 | }; |
425 | ||
426 | void | |
427 | _initialize_inftarg () | |
428 | { | |
4ef1f467 DT |
429 | #ifdef HAVE_OPTIONAL_PROC_FS |
430 | char procname[32]; | |
431 | int fd; | |
432 | ||
433 | /* If we have an optional /proc filesystem (e.g. under OSF/1), | |
434 | don't add ptrace support if we can access the running GDB via /proc. */ | |
435 | #ifndef PROC_NAME_FMT | |
436 | #define PROC_NAME_FMT "/proc/%05d" | |
437 | #endif | |
438 | sprintf (procname, PROC_NAME_FMT, getpid ()); | |
439 | if ((fd = open (procname, O_RDONLY)) >= 0) | |
440 | { | |
441 | close (fd); | |
442 | return; | |
443 | } | |
444 | #endif | |
445 | ||
bd5635a1 RP |
446 | add_target (&child_ops); |
447 | } |