This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / gdb / inftarg.c
1 /* Target-vector operations for controlling Unix child processes, for GDB.
2    Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
3    Contributed by Cygnus Support.
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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "defs.h"
22 #include "frame.h"  /* required by inferior.h */
23 #include "inferior.h"
24 #include "target.h"
25 #include "wait.h"
26 #include "gdbcore.h"
27 #include "command.h"
28 #include <signal.h>
29
30 static void
31 child_prepare_to_store PARAMS ((void));
32
33 #ifndef CHILD_WAIT
34 static int child_wait PARAMS ((int, struct target_waitstatus *));
35 #endif /* CHILD_WAIT */
36
37 static void child_open PARAMS ((char *, int));
38
39 static void
40 child_files_info PARAMS ((struct target_ops *));
41
42 static void
43 child_detach PARAMS ((char *, int));
44
45 static void
46 child_attach PARAMS ((char *, int));
47
48 static void
49 ptrace_me PARAMS ((void));
50
51 static void
52 ptrace_him PARAMS ((int));
53
54 static void child_create_inferior PARAMS ((char *, char *, char **));
55
56 static void
57 child_mourn_inferior PARAMS ((void));
58
59 static int
60 child_can_run PARAMS ((void));
61
62 extern char **environ;
63
64 /* Forward declaration */
65 extern struct target_ops child_ops;
66
67 #ifndef CHILD_WAIT
68
69 /* Wait for child to do something.  Return pid of child, or -1 in case
70    of error; store status through argument pointer OURSTATUS.  */
71
72 static int
73 child_wait (pid, ourstatus)
74      int pid;
75      struct target_waitstatus *ourstatus;
76 {
77   int save_errno;
78   int status;
79
80   do {
81     if (attach_flag)
82       set_sigint_trap();        /* Causes SIGINT to be passed on to the
83                                    attached process. */
84     set_sigio_trap ();
85
86     pid = wait (&status);
87     save_errno = errno;
88
89     clear_sigio_trap ();
90
91     if (attach_flag)
92       clear_sigint_trap();
93
94     if (pid == -1)
95       {
96         if (save_errno == EINTR)
97           continue;
98         fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
99                  safe_strerror (save_errno));
100         /* Claim it exited with unknown signal.  */
101         ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
102         ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
103         return -1;
104       }
105   } while (pid != inferior_pid); /* Some other child died or stopped */
106   store_waitstatus (ourstatus, status);
107   return pid;
108 }
109 #endif /* CHILD_WAIT */
110
111 /* Attach to process PID, then initialize for debugging it.  */
112
113 static void
114 child_attach (args, from_tty)
115      char *args;
116      int from_tty;
117 {
118   if (!args)
119     error_no_arg ("process-id to attach");
120
121 #ifndef ATTACH_DETACH
122   error ("Can't attach to a process on this machine.");
123 #else
124   {
125     char *exec_file;
126     int pid;
127
128     pid = atoi (args);
129
130     if (pid == getpid())                /* Trying to masturbate? */
131       error ("I refuse to debug myself!");
132
133     if (from_tty)
134       {
135         exec_file = (char *) get_exec_file (0);
136
137         if (exec_file)
138           printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
139                   target_pid_to_str (pid));
140         else
141           printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
142
143         gdb_flush (gdb_stdout);
144       }
145
146     attach (pid);
147     inferior_pid = pid;
148     push_target (&child_ops);
149   }
150 #endif  /* ATTACH_DETACH */
151 }
152
153
154 /* Take a program previously attached to and detaches it.
155    The program resumes execution and will no longer stop
156    on signals, etc.  We'd better not have left any breakpoints
157    in the program or it'll die when it hits one.  For this
158    to work, it may be necessary for the process to have been
159    previously attached.  It *might* work if the program was
160    started via the normal ptrace (PTRACE_TRACEME).  */
161
162 static void
163 child_detach (args, from_tty)
164      char *args;
165      int from_tty;
166 {
167 #ifdef ATTACH_DETACH
168   {
169     int siggnal = 0;
170
171     if (from_tty)
172       {
173         char *exec_file = get_exec_file (0);
174         if (exec_file == 0)
175           exec_file = "";
176         printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
177                 target_pid_to_str (inferior_pid));
178         gdb_flush (gdb_stdout);
179       }
180     if (args)
181       siggnal = atoi (args);
182
183     detach (siggnal);
184     inferior_pid = 0;
185     unpush_target (&child_ops);
186   }
187 #else
188   error ("This version of Unix does not support detaching a process.");
189 #endif
190 }
191
192 /* Get ready to modify the registers array.  On machines which store
193    individual registers, this doesn't need to do anything.  On machines
194    which store all the registers in one fell swoop, this makes sure
195    that registers contains all the registers from the program being
196    debugged.  */
197
198 static void
199 child_prepare_to_store ()
200 {
201 #ifdef CHILD_PREPARE_TO_STORE
202   CHILD_PREPARE_TO_STORE ();
203 #endif
204 }
205
206 /* Print status information about what we're accessing.  */
207
208 static void
209 child_files_info (ignore)
210      struct target_ops *ignore;
211 {
212   printf_unfiltered ("\tUsing the running image of %s %s.\n",
213           attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
214 }
215
216 /* ARGSUSED */
217 static void
218 child_open (arg, from_tty)
219      char *arg;
220      int from_tty;
221 {
222   error ("Use the \"run\" command to start a Unix child process.");
223 }
224
225 /* Stub function which causes the inferior that runs it, to be ptrace-able
226    by its parent process.  */
227
228 static void
229 ptrace_me ()
230 {
231   /* "Trace me, Dr. Memory!" */
232   call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
233 }
234
235 /* Stub function which causes the GDB that runs it, to start ptrace-ing
236    the child process.  */
237
238 static void
239 ptrace_him (pid)
240      int pid;
241 {
242   push_target (&child_ops);
243
244 #ifdef START_INFERIOR_TRAPS_EXPECTED
245   startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
246 #else
247   /* One trap to exec the shell, one to exec the program being debugged.  */
248   startup_inferior (2);
249 #endif
250 }
251
252 /* Start an inferior Unix child process and sets inferior_pid to its pid.
253    EXEC_FILE is the file to run.
254    ALLARGS is a string containing the arguments to the program.
255    ENV is the environment vector to pass.  Errors reported with error().  */
256
257 static void
258 child_create_inferior (exec_file, allargs, env)
259      char *exec_file;
260      char *allargs;
261      char **env;
262 {
263   fork_inferior (exec_file, allargs, env, ptrace_me, ptrace_him, NULL);
264   /* We are at the first instruction we care about.  */
265   /* Pedal to the metal... */
266   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
267 }
268
269 static void
270 child_mourn_inferior ()
271 {
272   unpush_target (&child_ops);
273   generic_mourn_inferior ();
274 }
275
276 static int
277 child_can_run ()
278 {
279   return(1);
280 }
281 \f
282 struct target_ops child_ops = {
283   "child",                      /* to_shortname */
284   "Unix child process",         /* to_longname */
285   "Unix child process (started by the \"run\" command).",       /* to_doc */
286   child_open,                   /* to_open */
287   0,                            /* to_close */
288   child_attach,                 /* to_attach */
289   child_detach,                 /* to_detach */
290   child_resume,                 /* to_resume */
291   child_wait,                   /* to_wait */
292   fetch_inferior_registers,     /* to_fetch_registers */
293   store_inferior_registers,     /* to_store_registers */
294   child_prepare_to_store,       /* to_prepare_to_store */
295   child_xfer_memory,            /* to_xfer_memory */
296   child_files_info,             /* to_files_info */
297   memory_insert_breakpoint,     /* to_insert_breakpoint */
298   memory_remove_breakpoint,     /* to_remove_breakpoint */
299   terminal_init_inferior,       /* to_terminal_init */
300   terminal_inferior,            /* to_terminal_inferior */
301   terminal_ours_for_output,     /* to_terminal_ours_for_output */
302   terminal_ours,                /* to_terminal_ours */
303   child_terminal_info,          /* to_terminal_info */
304   kill_inferior,                /* to_kill */
305   0,                            /* to_load */
306   0,                            /* to_lookup_symbol */
307   child_create_inferior,        /* to_create_inferior */
308   child_mourn_inferior,         /* to_mourn_inferior */
309   child_can_run,                /* to_can_run */
310   0,                            /* to_notice_signals */
311   process_stratum,              /* to_stratum */
312   0,                            /* to_next */
313   1,                            /* to_has_all_memory */
314   1,                            /* to_has_memory */
315   1,                            /* to_has_stack */
316   1,                            /* to_has_registers */
317   1,                            /* to_has_execution */
318   0,                            /* sections */
319   0,                            /* sections_end */
320   OPS_MAGIC                     /* to_magic */
321 };
322
323 void
324 _initialize_inftarg ()
325 {
326   add_target (&child_ops);
327 }