]> Git Repo - binutils.git/blob - gdb/inflow.c
gdb-3.4
[binutils.git] / gdb / inflow.c
1 /* Low level interface to ptrace, for GDB when running under Unix.
2    Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 GDB is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 GDB is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GDB; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "param.h"
22 #include "frame.h"
23 #include "inferior.h"
24
25 #ifdef USG
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #endif
29
30 #include <stdio.h>
31 #include <sys/param.h>
32 #include <sys/dir.h>
33 #include <signal.h>
34
35 #ifdef HAVE_TERMIO
36 #include <termio.h>
37 #undef TIOCGETP
38 #define TIOCGETP TCGETA
39 #undef TIOCSETN
40 #define TIOCSETN TCSETA
41 #undef TIOCSETP
42 #define TIOCSETP TCSETAF
43 #define TERMINAL struct termio
44 #else
45 #include <sys/ioctl.h>
46 #include <fcntl.h>
47 #include <sgtty.h>
48 #define TERMINAL struct sgttyb
49 #endif
50
51 #ifdef SET_STACK_LIMIT_HUGE
52 #include <sys/time.h>
53 #include <sys/resource.h>
54 extern int original_stack_limit;
55 #endif /* SET_STACK_LIMIT_HUGE */
56
57 extern int errno;
58
59 /* Nonzero if we are debugging an attached outside process
60    rather than an inferior.  */
61
62 int attach_flag;
63
64 \f
65 /* Record terminal status separately for debugger and inferior.  */
66
67 static TERMINAL sg_inferior;
68 static TERMINAL sg_ours;
69
70 static int tflags_inferior;
71 static int tflags_ours;
72
73 #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
74 static struct tchars tc_inferior;
75 static struct tchars tc_ours;
76 #endif
77
78 #ifdef TIOCGLTC
79 static struct ltchars ltc_inferior;
80 static struct ltchars ltc_ours;
81 #endif
82
83 #ifdef TIOCLGET
84 static int lmode_inferior;
85 static int lmode_ours;
86 #endif
87
88 #ifdef TIOCGPGRP
89 static int pgrp_inferior;
90 static int pgrp_ours;
91 #else
92 static int (*sigint_ours) ();
93 static int (*sigquit_ours) ();
94 #endif /* TIOCGPGRP */
95
96 /* Copy of inferior_io_terminal when inferior was last started.  */
97 static char *inferior_thisrun_terminal;
98
99 static void terminal_ours_1 ();
100
101 /* Nonzero if our terminal settings are in effect.
102    Zero if the inferior's settings are in effect.  */
103 static int terminal_is_ours;
104
105 /* Initialize the terminal settings we record for the inferior,
106    before we actually run the inferior.  */
107
108 void
109 terminal_init_inferior ()
110 {
111   if (remote_debugging)
112     return;
113
114   sg_inferior = sg_ours;
115   tflags_inferior = tflags_ours;
116
117 #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
118   tc_inferior = tc_ours;
119 #endif
120
121 #ifdef TIOCGLTC
122   ltc_inferior = ltc_ours;
123 #endif
124
125 #ifdef TIOCLGET
126   lmode_inferior = lmode_ours;
127 #endif
128
129 #ifdef TIOCGPGRP
130   pgrp_inferior = inferior_pid;
131 #endif /* TIOCGPGRP */
132
133   terminal_is_ours = 1;
134 }
135
136 /* Put the inferior's terminal settings into effect.
137    This is preparation for starting or resuming the inferior.  */
138
139 void
140 terminal_inferior ()
141 {
142   if (remote_debugging)
143     return;
144
145   if (terminal_is_ours)   /*  && inferior_thisrun_terminal == 0) */
146     {
147       fcntl (0, F_SETFL, tflags_inferior);
148       fcntl (0, F_SETFL, tflags_inferior);
149       ioctl (0, TIOCSETN, &sg_inferior);
150
151 #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
152       ioctl (0, TIOCSETC, &tc_inferior);
153 #endif
154 #ifdef TIOCGLTC
155       ioctl (0, TIOCSLTC, &ltc_inferior);
156 #endif
157 #ifdef TIOCLGET
158       ioctl (0, TIOCLSET, &lmode_inferior);
159 #endif
160
161 #ifdef TIOCGPGRP
162       ioctl (0, TIOCSPGRP, &pgrp_inferior);
163 #else
164       sigint_ours = (int (*) ()) signal (SIGINT, SIG_IGN);
165       sigquit_ours = (int (*) ()) signal (SIGQUIT, SIG_IGN);
166 #endif /* TIOCGPGRP */
167     }
168   terminal_is_ours = 0;
169 }
170
171 /* Put some of our terminal settings into effect,
172    enough to get proper results from our output,
173    but do not change into or out of RAW mode
174    so that no input is discarded.
175
176    After doing this, either terminal_ours or terminal_inferior
177    should be called to get back to a normal state of affairs.  */
178
179 void
180 terminal_ours_for_output ()
181 {
182   if (remote_debugging)
183     return;
184
185   terminal_ours_1 (1);
186 }
187
188 /* Put our terminal settings into effect.
189    First record the inferior's terminal settings
190    so they can be restored properly later.  */
191
192 void
193 terminal_ours ()
194 {
195   if (remote_debugging)
196     return;
197
198   terminal_ours_1 (0);
199 }
200
201 static void
202 terminal_ours_1 (output_only)
203      int output_only;
204 {
205 #ifdef TIOCGPGRP
206   /* Ignore this signal since it will happen when we try to set the pgrp.  */
207   int (*osigttou) ();
208 #endif /* TIOCGPGRP */
209
210   if (!terminal_is_ours)  /*   && inferior_thisrun_terminal == 0)  */
211     {
212       terminal_is_ours = 1;
213
214 #ifdef TIOCGPGRP
215       osigttou = (int (*) ()) signal (SIGTTOU, SIG_IGN);
216
217       ioctl (0, TIOCGPGRP, &pgrp_inferior);
218       ioctl (0, TIOCSPGRP, &pgrp_ours);
219
220       signal (SIGTTOU, osigttou);
221 #else
222       signal (SIGINT, sigint_ours);
223       signal (SIGQUIT, sigquit_ours);
224 #endif /* TIOCGPGRP */
225
226       tflags_inferior = fcntl (0, F_GETFL, 0);
227       ioctl (0, TIOCGETP, &sg_inferior);
228
229 #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
230       ioctl (0, TIOCGETC, &tc_inferior);
231 #endif
232 #ifdef TIOCGLTC
233       ioctl (0, TIOCGLTC, &ltc_inferior);
234 #endif
235 #ifdef TIOCLGET
236       ioctl (0, TIOCLGET, &lmode_inferior);
237 #endif
238     }
239
240 #ifdef HAVE_TERMIO
241   sg_ours.c_lflag |= ICANON;
242   if (output_only && !(sg_inferior.c_lflag & ICANON))
243     sg_ours.c_lflag &= ~ICANON;
244 #else /* not HAVE_TERMIO */
245   sg_ours.sg_flags &= ~RAW & ~CBREAK;
246   if (output_only)
247     sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
248 #endif /* not HAVE_TERMIO */
249
250   fcntl (0, F_SETFL, tflags_ours);
251   fcntl (0, F_SETFL, tflags_ours);
252   ioctl (0, TIOCSETN, &sg_ours);
253
254 #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
255   ioctl (0, TIOCSETC, &tc_ours);
256 #endif
257 #ifdef TIOCGLTC
258   ioctl (0, TIOCSLTC, &ltc_ours);
259 #endif
260 #ifdef TIOCLGET
261   ioctl (0, TIOCLSET, &lmode_ours);
262 #endif
263
264 #ifdef HAVE_TERMIO
265   sg_ours.c_lflag |= ICANON;
266 #else /* not HAVE_TERMIO */
267   sg_ours.sg_flags &= ~RAW & ~CBREAK;
268 #endif /* not HAVE_TERMIO */
269 }
270
271 static void
272 term_status_command ()
273 {
274   register int i;
275
276   if (remote_debugging)
277     {
278       printf_filtered ("No terminal status when remote debugging.\n");
279       return;
280     }
281
282   printf_filtered ("Inferior's terminal status (currently saved by GDB):\n");
283
284 #ifdef HAVE_TERMIO
285
286   printf_filtered ("fcntl flags = 0x%x, c_iflag = 0x%x, c_oflag = 0x%x,\n",
287           tflags_inferior, sg_inferior.c_iflag, sg_inferior.c_oflag);
288   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
289           sg_inferior.c_cflag, sg_inferior.c_lflag, sg_inferior.c_line);
290   printf_filtered ("c_cc: ");
291   for (i = 0; (i < NCC); i += 1)
292     printf_filtered ("0x%x ", sg_inferior.c_cc[i]);
293   printf_filtered ("\n");
294
295 #else /* not HAVE_TERMIO */
296
297   printf_filtered ("fcntl flags = 0x%x, sgttyb.sg_flags = 0x%x, owner pid = %d.\n",
298           tflags_inferior, sg_inferior.sg_flags, pgrp_inferior);
299
300 #endif /* not HAVE_TERMIO */
301
302 #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
303   printf_filtered ("tchars: ");
304   for (i = 0; i < sizeof (struct tchars); i++)
305     printf_filtered ("0x%x ", ((char *)&tc_inferior)[i]);
306   printf_filtered ("\n");
307 #endif
308
309 #ifdef TIOCGLTC
310   printf_filtered ("ltchars: ");
311   for (i = 0; i < sizeof (struct ltchars); i++)
312     printf_filtered ("0x%x ", ((char *)&ltc_inferior)[i]);
313   printf_filtered ("\n");
314   ioctl (0, TIOCSLTC, &ltc_ours);
315 #endif
316   
317 #ifdef TIOCLGET
318   printf_filtered ("lmode:  %x\n", lmode_inferior);
319 #endif
320 }
321 \f
322 static void
323 new_tty (ttyname)
324      char *ttyname;
325 {
326   register int tty;
327   register int fd;
328
329 #ifdef TIOCNOTTY
330   /* Disconnect the child process from our controlling terminal.  */
331   tty = open("/dev/tty", O_RDWR);
332   if (tty > 0)
333     {
334       ioctl(tty, TIOCNOTTY, 0);
335       close(tty);
336     }
337 #endif
338
339   /* Now open the specified new terminal.  */
340
341   tty = open(ttyname, O_RDWR);
342   if (tty == -1)
343     _exit(1);
344
345   /* Avoid use of dup2; doesn't exist on all systems.  */
346   if (tty != 0)
347     { close (0); dup (tty); }
348   if (tty != 1)
349     { close (1); dup (tty); }
350   if (tty != 2)
351     { close (2); dup (tty); }
352   if (tty > 2)
353     close(tty);
354 }
355 \f
356 /* Start an inferior process and returns its pid.
357    ALLARGS is a string containing shell command to run the program.
358    ENV is the environment vector to pass.  */
359
360 #ifndef SHELL_FILE
361 #define SHELL_FILE "/bin/sh"
362 #endif
363
364 int
365 create_inferior (allargs, env)
366      char *allargs;
367      char **env;
368 {
369   int pid;
370   char *shell_command;
371   extern int sys_nerr;
372   extern char *sys_errlist[];
373   extern int errno;
374
375   /* If desired, concat something onto the front of ALLARGS.
376      SHELL_COMMAND is the result.  */
377 #ifdef SHELL_COMMAND_CONCAT
378   shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + strlen (allargs) + 1);
379   strcpy (shell_command, SHELL_COMMAND_CONCAT);
380   strcat (shell_command, allargs);
381 #else
382   shell_command = allargs;
383 #endif
384
385   /* exec is said to fail if the executable is open.  */
386   close_exec_file ();
387
388 #if defined(USG) && !defined(HAVE_VFORK)
389   pid = fork ();
390 #else
391   pid = vfork ();
392 #endif
393
394   if (pid < 0)
395     perror_with_name ("vfork");
396
397   if (pid == 0)
398     {
399 #ifdef TIOCGPGRP
400       /* Run inferior in a separate process group.  */
401       setpgrp (getpid (), getpid ());
402 #endif /* TIOCGPGRP */
403
404 #ifdef SET_STACK_LIMIT_HUGE
405       /* Reset the stack limit back to what it was.  */
406       {
407         struct rlimit rlim;
408
409         getrlimit (RLIMIT_STACK, &rlim);
410         rlim.rlim_cur = original_stack_limit;
411         setrlimit (RLIMIT_STACK, &rlim);
412       }
413 #endif /* SET_STACK_LIMIT_HUGE */
414
415
416       inferior_thisrun_terminal = inferior_io_terminal;
417       if (inferior_io_terminal != 0)
418         new_tty (inferior_io_terminal);
419
420 /* It seems that changing the signal handlers for the inferior after
421    a vfork also changes them for the superior.  See comments in
422    initialize_signals for how we get the right signal handlers
423    for the inferior.  */
424 /* Not needed on Sun, at least, and loses there
425    because it clobbers the superior.  */
426 /*???      signal (SIGQUIT, SIG_DFL);
427       signal (SIGINT, SIG_DFL);  */
428
429       call_ptrace (0);
430       execle (SHELL_FILE, "sh", "-c", shell_command, 0, env);
431
432       fprintf (stderr, "Cannot exec %s: %s.\n", SHELL_FILE,
433                errno < sys_nerr ? sys_errlist[errno] : "unknown error");
434       fflush (stderr);
435       _exit (0177);
436     }
437
438 #ifdef CREATE_INFERIOR_HOOK
439   CREATE_INFERIOR_HOOK (pid);
440 #endif  
441   return pid;
442 }
443
444 /* Kill the inferior process.  Make us have no inferior.  */
445
446 static void
447 kill_command ()
448 {
449   if (remote_debugging)
450     return;
451   if (inferior_pid == 0)
452     error ("The program is not being run.");
453   if (!query ("Kill the inferior process? "))
454     error ("Not confirmed.");
455   kill_inferior ();
456 }
457
458 void
459 inferior_died ()
460 {
461   inferior_pid = 0;
462   attach_flag = 0;
463   mark_breakpoints_out ();
464   select_frame ((FRAME) 0, -1);
465   reopen_exec_file ();
466   if (have_core_file_p ())
467     set_current_frame ( create_new_frame (read_register (FP_REGNUM),
468                                           read_pc ()));
469   else
470     set_current_frame (0);
471 }
472 \f
473 #if 0 
474 /* This function is just for testing, and on some systems (Sony NewsOS
475    3.2) <sys/user.h> also includes <sys/time.h> which leads to errors
476    (since on this system at least sys/time.h is not protected against
477    multiple inclusion).  */
478 static void
479 try_writing_regs_command ()
480 {
481   register int i;
482   register int value;
483   extern int errno;
484
485   if (inferior_pid == 0)
486     error ("There is no inferior process now.");
487
488   /* A Sun 3/50 or 3/60 (at least) running SunOS 4.0.3 will have a
489      kernel panic if we try to write past the end of the user area.
490      Presumably Sun will fix this bug (it has been reported), but it
491      is tacky to crash the system, so at least on SunOS4 we need to
492      stop writing when we hit the end of the user area.  */
493   for (i = 0; i < sizeof (struct user); i += 2)
494     {
495       QUIT;
496       errno = 0;
497       value = call_ptrace (3, inferior_pid, i, 0);
498       call_ptrace (6, inferior_pid, i, value);
499       if (errno == 0)
500         {
501           printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
502                   i, value, value);
503         }
504       else if ((i & 0377) == 0)
505         printf (" Failed at 0x%x.\n", i);
506     }
507 }
508 #endif
509 \f
510 void
511 _initialize_inflow ()
512 {
513   add_com ("term-status", class_obscure, term_status_command,
514            "Print info on inferior's saved terminal status.");
515
516 #if 0
517   add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
518            "Try writing all locations in inferior's system block.\n\
519 Report which ones can be written.");
520 #endif
521
522   add_com ("kill", class_run, kill_command,
523            "Kill execution of program being debugged.");
524
525   inferior_pid = 0;
526
527   ioctl (0, TIOCGETP, &sg_ours);
528   fcntl (0, F_GETFL, tflags_ours);
529
530 #if defined(TIOCGETC) && !defined(TIOCGETC_BROKEN)
531   ioctl (0, TIOCGETC, &tc_ours);
532 #endif
533 #ifdef TIOCGLTC
534   ioctl (0, TIOCGLTC, &ltc_ours);
535 #endif
536 #ifdef TIOCLGET
537   ioctl (0, TIOCLGET, &lmode_ours);
538 #endif
539
540 #ifdef TIOCGPGRP
541   ioctl (0, TIOCGPGRP, &pgrp_ours);
542 #endif /* TIOCGPGRP */
543
544   terminal_is_ours = 1;
545 }
546
This page took 0.083418 seconds and 4 git commands to generate.