]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/RCS/inflow.c,v
gdb-2.4+.aux.coff
[thirdparty/binutils-gdb.git] / gdb / RCS / inflow.c,v
CommitLineData
7b4ac7e1 1head 1.2;
2access ;
3symbols RMS-has:1.2;
4locks ; strict;
5comment @ * @;
6
7
81.2
9date 88.01.26.05.07.38; author gnu; state Exp;
10branches ;
11next 1.1;
12
131.1
14date 88.01.21.05.04.57; author gnu; state Exp;
15branches ;
16next ;
17
18
19desc
20@From RMS's development sources on wheaties, 20Jan88
21@
22
23
241.2
25log
26@Major Sys V tty changes, and a few changes to try to find the registers
27in the upage (untested yet).
28@
29text
30@/* Low level interface to ptrace, for GDB when running under Unix.
31 Copyright (C) 1986, 1987 Free Software Foundation, Inc.
32
33GDB is distributed in the hope that it will be useful, but WITHOUT ANY
34WARRANTY. No author or distributor accepts responsibility to anyone
35for the consequences of using it or for whether it serves any
36particular purpose or works at all, unless he says so in writing.
37Refer to the GDB General Public License for full details.
38
39Everyone is granted permission to copy, modify and redistribute GDB,
40but only under the conditions described in the GDB General Public
41License. A copy of this license is supposed to have been given to you
42along with GDB so you can know your rights and responsibilities. It
43should be in a file named COPYING. Among other things, the copyright
44notice and this notice must be preserved on all copies.
45
46In other words, go ahead and share GDB, but don't try to stop
47anyone else from sharing it farther. Help stamp out software hoarding!
48*/
49
50#include "defs.h"
51#include "initialize.h"
52#include "param.h"
53#include "frame.h"
54#include "inferior.h"
55
56#include <stdio.h>
57#include <sys/types.h>
58#include <sys/param.h>
59#include <sys/dir.h>
60#include <signal.h>
61#include <sys/ioctl.h>
62#include <sgtty.h>
63#include <fcntl.h>
64
65#ifdef mac_aux
66#include <sys/seg.h>
67#include <sys/mmu.h>
68#include <sys/signal.h>
69#include <sys/time.h>
70#include <sys/user.h>
71#else
72#include <sys/user.h>
73#endif /* mac_aux */
74
75
76#ifdef UMAX_PTRACE
77#include <a.out.h>
78#endif
79
80#ifdef NEW_SUN_PTRACE
81#include <sys/ptrace.h>
82#include <machine/reg.h>
83#endif
84
85#ifdef SYSV_TTYS
86#include <termio.h>
87#endif
88
89extern int errno;
90
91/* Nonzero if we are debugging an attached outside process
92 rather than an inferior. */
93
94static int attach_flag;
95
96#define UPAGE_MASK 0x00003FFF
97
98START_FILE
99\f
100/* Record terminal status separately for debugger and inferior. */
101
102#ifdef SYSV_TTYS
103static struct termio ti_inferior;
104#else
105static struct sgttyb sg_inferior;
106static struct tchars tc_inferior;
107static struct ltchars ltc_inferior;
108static int lmode_inferior;
109#endif
110static int tflags_inferior;
111static int pgrp_inferior;
112
113#ifdef SYSV_TTYS
114static struct termio ti_ours;
115#else
116static struct sgttyb sg_ours;
117static struct tchars tc_ours;
118static struct ltchars ltc_ours;
119static int lmode_ours;
120#endif
121static int tflags_ours;
122static int pgrp_ours;
123
124/* Copy of inferior_io_terminal when inferior was last started. */
125static char *inferior_thisrun_terminal;
126
127static void terminal_ours_1 ();
128
129/* Nonzero if our terminal settings are in effect.
130 Zero if the inferior's settings are in effect. */
131static int terminal_is_ours;
132
133/* Initialize the terminal settings we record for the inferior,
134 before we actually run the inferior. */
135
136void
137terminal_init_inferior ()
138{
139
140#ifdef SYSV_TTYS
141 ti_inferior = ti_ours;
142#else
143 sg_inferior = sg_ours;
144 tc_inferior = tc_ours;
145 ltc_inferior = ltc_ours;
146 lmode_inferior = lmode_ours;
147#endif
148 tflags_inferior = tflags_ours;
149 pgrp_inferior = inferior_pid;
150
151 terminal_is_ours = 1;
152}
153
154/* Put the inferior's terminal settings into effect.
155 This is preparation for starting or resuming the inferior. */
156
157void
158terminal_inferior ()
159{
160 if (terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
161 {
162 fcntl (0, F_SETFL, tflags_inferior);
163 fcntl (0, F_SETFL, tflags_inferior);
164#ifdef SYSV_TTYS
165 ioctl (0, TCSETA, &ti_inferior);
166#else
167 ioctl (0, TIOCSETN, &sg_inferior);
168 ioctl (0, TIOCSETC, &tc_inferior);
169 ioctl (0, TIOCSLTC, &ltc_inferior);
170 ioctl (0, TIOCLSET, &lmode_inferior);
171#endif
172 ioctl (0, TIOCSPGRP, &pgrp_inferior);
173 }
174 terminal_is_ours = 0;
175}
176
177/* Put some of our terminal settings into effect,
178 enough to get proper results from our output,
179 but do not change into or out of RAW mode
180 so that no input is discarded.
181
182 After doing this, either terminal_ours or terminal_inferior
183 should be called to get back to a normal state of affairs. */
184
185void
186terminal_ours_for_output ()
187{
188 terminal_ours_1 (1);
189}
190
191/* Put our terminal settings into effect.
192 First record the inferior's terminal settings
193 so they can be restored properly later. */
194
195void
196terminal_ours ()
197{
198 terminal_ours_1 (0);
199}
200
201static void
202terminal_ours_1 (output_only)
203 int output_only;
204{
205 /* Ignore this signal since it will happen when we try to set the pgrp. */
206 int (*osigttou) ();
207
208 if (!terminal_is_ours) /* && inferior_thisrun_terminal == 0) */
209 {
210 terminal_is_ours = 1;
211
212 osigttou = signal (SIGTTOU, SIG_IGN);
213
214 ioctl (0, TIOCGPGRP, &pgrp_inferior);
215 ioctl (0, TIOCSPGRP, &pgrp_ours);
216
217 signal (SIGTTOU, osigttou);
218
219 tflags_inferior = fcntl (0, F_GETFL, 0);
220#ifdef SYSV_TTYS
221 ioctl (0, TCGETA, &ti_inferior);
222#else
223 ioctl (0, TIOCGETP, &sg_inferior);
224 ioctl (0, TIOCGETC, &tc_inferior);
225 ioctl (0, TIOCGLTC, &ltc_inferior);
226 ioctl (0, TIOCLGET, &lmode_inferior);
227#endif
228 }
229
230 fcntl (0, F_SETFL, tflags_ours);
231 fcntl (0, F_SETFL, tflags_ours);
232
233
234#ifdef SYSV_TTYS
235 ti_ours.c_lflag |= ICANON | ISIG;
236 if (output_only)
237 ti_ours.c_lflag &= ~((ICANON|ISIG)&ti_inferior.c_lflag);
238 ioctl (0, TCSETA, &ti_ours);
239 ti_ours.c_lflag |= ICANON | ISIG;
240#else
241 sg_ours.sg_flags &= ~RAW & ~CBREAK;
242 if (output_only)
243 sg_ours.sg_flags |= (RAW | CBREAK) & sg_inferior.sg_flags;
244 ioctl (0, TIOCSETN, &sg_ours);
245 ioctl (0, TIOCSETC, &tc_ours);
246 ioctl (0, TIOCSLTC, &ltc_ours);
247 ioctl (0, TIOCLSET, &lmode_ours);
248 sg_ours.sg_flags &= ~RAW & ~CBREAK;
249#endif
250}
251
252static void
253term_status_command ()
254{
255 register int i;
256 printf ("Inferior's terminal status (currently saved by GDB):\n");
257#ifdef SYSV_TTYS
258 printf ("fcntl flags = 0x%x, owner pid = %d.\n",
259 tflags_inferior, pgrp_inferior);
260 printf ("iflag = 0x%04x, oflag = 0x%04x, cflag = 0x%04x, lflag = 0x%04x\n",
261 ti_inferior.c_iflag, ti_inferior.c_oflag,
262 ti_inferior.c_cflag, ti_inferior.c_lflag);
263 printf ("line discipline = %d\n", ti_inferior.c_line);
264 printf ("control chars: ");
265 for (i = 0; i < NCC; i++)
266 printf ("0x%x ", ti_inferior.c_cc[i]);
267 printf ("\n");
268#else
269 printf ("fcntl flags = 0x%x, lmode = 0x%x,\nsgttyb.sg_flags = 0x%x, owner pid = %d.\n",
270 tflags_inferior, lmode_inferior,
271 sg_inferior.sg_flags, pgrp_inferior);
272 printf ("tchars: ");
273 for (i = 0; i < sizeof (struct tchars); i++)
274 printf ("0x%x ", ((char *)&tc_inferior)[i]);
275 printf ("\n");
276 printf ("ltchars: ");
277 for (i = 0; i < sizeof (struct ltchars); i++)
278 printf ("0x%x ", ((char *)&ltc_inferior)[i]);
279 printf ("\n");
280#endif
281}
282\f
283static void
284new_tty (ttyname)
285 char *ttyname;
286{
287 register int tty;
288 register int fd;
289
290#if 0
291 /* I think it is better not to do this. Then C-z on the GDB terminal
292 will still stop the program, while C-z on the data terminal
293 will be input. */
294
295 /* Disconnect the child process from our controlling terminal. */
296 tty = open("/dev/tty", O_RDWR);
297 if (tty > 0)
298 {
299 ioctl(tty, TIOCNOTTY, 0);
300 close(tty);
301 }
302#endif
303 /* Now open the specified new terminal. */
304
305 tty = open(ttyname, O_RDWR);
306 if (tty == -1)
307 _exit(1);
308
309 dup2(tty, 0);
310 dup2(tty, 1);
311 dup2(tty, 2);
312 close(tty);
313}
314\f
315/* Start an inferior process and returns its pid.
316 ALLARGS is a vector of program-name and args.
317 ENV is the environment vector to pass. */
318
319int
320create_inferior (allargs, env)
321 char **allargs;
322 char **env;
323{
324 int pid;
325 extern int sys_nerr;
326 extern char *sys_errlist[];
327 extern int errno;
328
329 /* exec is said to fail if the executable is open. */
330 close_exec_file ();
331
332 pid = vfork ();
333 if (pid < 0)
334 perror_with_name ("vfork");
335
336 if (pid == 0)
337 {
338 /* Run inferior in a separate process group. */
339 setpgrp (getpid (), getpid ());
340
341 inferior_thisrun_terminal = inferior_io_terminal;
342 if (inferior_io_terminal != 0)
343 new_tty (inferior_io_terminal);
344
345/* Not needed on Sun, at least, and loses there
346 because it clobbers the superior. */
347/*??? signal (SIGQUIT, SIG_DFL);
348 signal (SIGINT, SIG_DFL); */
349
350 ptrace (0);
351 execle ("/bin/sh", "sh", "-c", allargs, 0, env);
352
353 fprintf (stderr, "Cannot exec /bin/sh: %s.\n",
354 errno < sys_nerr ? sys_errlist[errno] : "unknown error");
355 fflush (stderr);
356 _exit (0177);
357 }
358 return pid;
359}
360
361/* Kill the inferior process. Make us have no inferior. */
362
363static void
364kill_command ()
365{
366 if (inferior_pid == 0)
367 error ("The program is not being run.");
368 if (!query ("Kill the inferior process? "))
369 error ("Not confirmed.");
370 kill_inferior ();
371}
372
373kill_inferior ()
374{
375 if (inferior_pid == 0)
376 return;
377 ptrace (8, inferior_pid, 0, 0);
378 wait (0);
379 inferior_died ();
380}
381
382inferior_died ()
383{
384 inferior_pid = 0;
385 attach_flag = 0;
386 mark_breakpoints_out ();
387 reopen_exec_file ();
388 if (have_core_file_p ())
389 set_current_frame (read_register (FP_REGNUM));
390}
391
392/* Resume execution of the inferior process.
393 If STEP is nonzero, single-step it.
394 If SIGNAL is nonzero, give it that signal. */
395
396void
397resume (step, signal)
398 int step;
399 int signal;
400{
401 errno = 0;
402 ptrace (step ? 9 : 7, inferior_pid, 1, signal);
403 if (errno)
404 perror_with_name ("ptrace");
405}
406\f
407#ifdef NEW_SUN_PTRACE
408
409/* Start debugging the process whose number is PID. */
410
411attach (pid)
412 int pid;
413{
414 errno = 0;
415 ptrace (PTRACE_ATTACH, pid, 0, 0);
416 if (errno)
417 perror_with_name ("ptrace");
418 attach_flag = 1;
419 return pid;
420}
421
422/* Stop debugging the process whose number is PID
423 and continue it with signal number SIGNAL.
424 SIGNAL = 0 means just continue it. */
425
426void
427detach (signal)
428 int signal;
429{
430 errno = 0;
431 ptrace (PTRACE_DETACH, inferior_pid, 1, signal);
432 if (errno)
433 perror_with_name ("ptrace");
434 attach_flag = 0;
435}
436#endif
437\f
438#ifdef NEW_SUN_PTRACE
439
440void
441fetch_inferior_registers ()
442{
443 struct regs inferior_registers;
444 struct fp_status inferior_fp_registers;
445 extern char registers[];
446
447 ptrace (PTRACE_GETREGS, inferior_pid, &inferior_registers);
448 ptrace (PTRACE_GETFPREGS, inferior_pid, &inferior_fp_registers);
449
450 bcopy (&inferior_registers, registers, 16 * 4);
451 bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
452 sizeof inferior_fp_registers.fps_regs);
453 *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
454 *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
455 bcopy (&inferior_fp_registers.fps_control,
456 &registers[REGISTER_BYTE (FPC_REGNUM)],
457 sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
458}
459
460/* Store our register values back into the inferior.
461 If REGNO is -1, do this for all registers.
462 Otherwise, REGNO specifies which register (so we can save time). */
463
464store_inferior_registers (regno)
465 int regno;
466{
467 struct regs inferior_registers;
468 struct fp_status inferior_fp_registers;
469 extern char registers[];
470
471 bcopy (registers, &inferior_registers, 16 * 4);
472 bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
473 sizeof inferior_fp_registers.fps_regs);
474 inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
475 inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
476 bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
477 &inferior_fp_registers.fps_control,
478 sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
479
480 ptrace (PTRACE_SETREGS, inferior_pid, &inferior_registers);
481 ptrace (PTRACE_SETFPREGS, inferior_pid, &inferior_fp_registers);
482}
483
484#else
485
486void
487fetch_inferior_registers ()
488{
489 register int regno;
490 register unsigned int regaddr;
491 char buf[MAX_REGISTER_RAW_SIZE];
492 register int i;
493
494#ifdef UMAX_PTRACE
495 unsigned int offset = 0;
496#else
497 struct user u;
498 unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
499 offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
500#endif
501
502 for (regno = 0; regno < NUM_REGS; regno++)
503 {
504 regaddr = register_addr (regno, offset);
505 for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
506 {
507 *(int *) &buf[i] = ptrace (3, inferior_pid, regaddr, 0);
508 regaddr += sizeof (int);
509 }
510 supply_register (regno, buf);
511 }
512}
513
514/* Store our register values back into the inferior.
515 If REGNO is -1, do this for all registers.
516 Otherwise, REGNO specifies which register (so we can save time). */
517
518store_inferior_registers (regno)
519 int regno;
520{
521 register unsigned int regaddr;
522 char buf[80];
523
524#ifdef UMAX_PTRACE
525 unsigned int offset = 0;
526#else
527 struct user u;
528 unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
529 offset = ptrace (3, inferior_pid, offset, 0) & UPAGE_MASK;
530#endif
531
532 if (regno >= 0)
533 {
534 regaddr = register_addr (regno, offset);
535 errno = 0;
536 ptrace (6, inferior_pid, regaddr, read_register (regno));
537 if (errno != 0)
538 {
539 sprintf (buf, "writing register number %d", regno);
540 perror_with_name (buf);
541 }
542 }
543 else for (regno = 0; regno < NUM_REGS; regno++)
544 {
545 regaddr = register_addr (regno, offset);
546 errno = 0;
547 ptrace (6, inferior_pid, regaddr, read_register (regno));
548 if (errno != 0)
549 {
550 sprintf (buf, "writing register number %d", regno);
551 perror_with_name (buf);
552 }
553 }
554}
555
556#endif /* not NEW_SUN_PTRACE */
557\f
558/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
559 in the NEW_SUN_PTRACE case.
560 It ought to be straightforward. But it appears that writing did
561 not write the data that I specified. I cannot understand where
562 it got the data that it actually did write. */
563
564/* Copy LEN bytes from inferior's memory starting at MEMADDR
565 to debugger memory starting at MYADDR. */
566
567read_inferior_memory (memaddr, myaddr, len)
568 CORE_ADDR memaddr;
569 char *myaddr;
570 int len;
571{
572 register int i;
573 /* Round starting address down to longword boundary. */
574 register CORE_ADDR addr = memaddr & - sizeof (int);
575 /* Round ending address up; get number of longwords that makes. */
576 register int count
577 = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
578 /* Allocate buffer of that many longwords. */
579 register int *buffer = (int *) alloca (count * sizeof (int));
580
581 /* Read all the longwords */
582 for (i = 0; i < count; i++, addr += sizeof (int))
583 buffer[i] = ptrace (1, inferior_pid, addr, 0);
584
585 /* Copy appropriate bytes out of the buffer. */
586 bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
587}
588
589/* Copy LEN bytes of data from debugger memnory at MYADDR
590 to inferior's memory at MEMADDR.
591 On failure (cannot write the inferior)
592 returns the value of errno. */
593
594int
595write_inferior_memory (memaddr, myaddr, len)
596 CORE_ADDR memaddr;
597 char *myaddr;
598 int len;
599{
600 register int i;
601 /* Round starting address down to longword boundary. */
602 register CORE_ADDR addr = memaddr & - sizeof (int);
603 /* Round ending address up; get number of longwords that makes. */
604 register int count
605 = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
606 /* Allocate buffer of that many longwords. */
607 register int *buffer = (int *) alloca (count * sizeof (int));
608 extern int errno;
609
610 /* Fill start and end extra bytes of buffer with existing memory data. */
611
612 buffer[0] = ptrace (1, inferior_pid, addr, 0);
613 if (count > 1)
614 buffer[count - 1]
615 = ptrace (1, inferior_pid,
616 addr + (count - 1) * sizeof (int), 0);
617
618 /* Copy data to be written over corresponding part of buffer */
619
620 bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
621
622 /* Write the entire buffer. */
623
624 for (i = 0; i < count; i++, addr += sizeof (int))
625 {
626 errno = 0;
627 ptrace (4, inferior_pid, addr, buffer[i]);
628 if (errno)
629 return errno;
630 }
631
632 return 0;
633}
634\f
635static void
636try_writing_regs_command ()
637{
638 register int i;
639 register int value;
640 extern int errno;
641
642 if (inferior_pid == 0)
643 error ("The program is not being run.");
644
645 for (i = 0; ; i += 2)
646 {
647 QUIT;
648 errno = 0;
649 value = ptrace (3, inferior_pid, i, 0);
650 ptrace (6, inferior_pid, i, value);
651 if (errno == 0)
652 {
653 printf (" Succeeded with address 0x%x; value 0x%x (%d).\n",
654 i, value, value);
655 }
656 else if ((i & 0377) == 0)
657 printf (" Failed at 0x%x.\n", i);
658 }
659}
660\f
661static
662initialize ()
663{
664 add_com ("term-status", class_obscure, term_status_command,
665 "Print info on inferior's saved terminal status.");
666
667 add_com ("try-writing-regs", class_obscure, try_writing_regs_command,
668 "Try writing all locations in inferior's system block.\n\
669Report which ones can be written.");
670
671 add_com ("kill", class_run, kill_command,
672 "Kill execution of program being debugged.");
673
674 inferior_pid = 0;
675
676#ifdef SYSV_TTYS
677 ioctl (0, TCGETA, &ti_ours);
678#else
679 ioctl (0, TIOCGETP, &sg_ours);
680 ioctl (0, TIOCGETC, &tc_ours);
681 ioctl (0, TIOCGLTC, &ltc_ours);
682 ioctl (0, TIOCLGET, &lmode_ours);
683#endif
684 fcntl (0, F_GETFL, tflags_ours);
685 ioctl (0, TIOCGPGRP, &pgrp_ours);
686
687 terminal_is_ours = 1;
688}
689
690END_FILE
691@
692
693
6941.1
695log
696@Initial revision
697@
698text
699@d28 1
700a30 1
701#include <sys/user.h>
702d36 11
703d56 4
704d67 2
705d73 3
706d80 1
707d84 3
708d91 1
709d110 4
710d118 1
711d135 3
712d142 1
713d191 3
714d198 1
715d201 11
716a214 3
717
718 fcntl (0, F_SETFL, tflags_ours);
719 fcntl (0, F_SETFL, tflags_ours);
720d220 1
721d228 12
722d251 1
723d470 1
724a470 1
725 offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
726d500 1
727a500 1
728 offset = ptrace (3, inferior_pid, offset, 0) - KERNEL_U_ADDR;
729d647 3
730d654 1
731@