file reorg, pathnames.h, paths.h
[unix-history] / usr / src / old / dbx / process.c
CommitLineData
2a24676e
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
9a3bab7a 6
2a24676e 7#ifndef lint
24350cae 8static char sccsid[] = "@(#)process.c 5.3 (Berkeley) %G%";
2a24676e 9#endif not lint
0022c355 10
24350cae 11static char rcsid[] = "$Header: process.c,v 1.4 88/01/10 00:49:31 donn Exp $";
9a3bab7a
ML
12
13/*
14 * Process management.
15 *
16 * This module contains the routines to manage the execution and
17 * tracing of the debuggee process.
18 */
19
20#include "defs.h"
21#include "process.h"
22#include "machine.h"
23#include "events.h"
24#include "tree.h"
8ee6535a 25#include "eval.h"
9a3bab7a
ML
26#include "operators.h"
27#include "source.h"
28#include "object.h"
29#include "mappings.h"
30#include "main.h"
31#include "coredump.h"
32#include <signal.h>
33#include <errno.h>
9a3bab7a
ML
34#include <sys/stat.h>
35
36#ifndef public
37
38typedef struct Process *Process;
39
40Process process;
41
8ee6535a
ML
42#define DEFSIG -1
43
9a3bab7a
ML
44#include "machine.h"
45
46#endif
47
48#define NOTSTARTED 1
49#define STOPPED 0177
50#define FINISHED 0
51
52/*
2fd0f574
SL
53 * A cache of the instruction segment is kept to reduce the number
54 * of system calls. Might be better just to read the entire
55 * code space into memory.
9a3bab7a
ML
56 */
57
24350cae 58#define CACHESIZE 1003
9a3bab7a
ML
59
60typedef struct {
61 Word addr;
62 Word val;
63} CacheWord;
64
65/*
66 * This structure holds the information we need from the user structure.
67 */
68
69struct Process {
70 int pid; /* process being traced */
5870175c
ML
71 int mask; /* process status word */
72 Word reg[NREG]; /* process' registers */
9a3bab7a
ML
73 Word oreg[NREG]; /* registers when process last stopped */
74 short status; /* either STOPPED or FINISHED */
75 short signo; /* signal that stopped process */
0022c355 76 short sigcode; /* extra signal information */
9a3bab7a
ML
77 int exitval; /* return value from exit() */
78 long sigset; /* bit array of traced signals */
24350cae 79 CacheWord word[CACHESIZE]; /* text segment cache */
5870175c 80 Ttyinfo ttyinfo; /* process' terminal characteristics */
2fd0f574 81 Address sigstatus; /* process' handler for current signal */
9a3bab7a
ML
82};
83
84/*
85 * These definitions are for the arguments to "pio".
86 */
87
88typedef enum { PREAD, PWRITE } PioOp;
89typedef enum { TEXTSEG, DATASEG } PioSeg;
90
91private struct Process pbuf;
92
0022c355 93#define MAXNCMDARGS 1000 /* maximum number of arguments to RUN */
9a3bab7a 94
ca69b757
ML
95extern int errno;
96
9a3bab7a
ML
97private Boolean just_started;
98private int argc;
99private String argv[MAXNCMDARGS];
100private String infile, outfile;
101
102/*
103 * Initialize process information.
104 */
105
106public process_init()
107{
24350cae
DS
108 register integer i;
109 char buf[10];
9a3bab7a
ML
110
111 process = &pbuf;
112 process->status = (coredump) ? STOPPED : NOTSTARTED;
113 setsigtrace();
24350cae
DS
114# if vax || tahoe
115 for (i = 0; i < NREG; i++) {
116 sprintf(buf, "$r%d", i);
117 defregname(identname(buf, false), i);
118 }
119# ifdef vax
120 defregname(identname("$ap", true), ARGP);
121# endif
122# else
123# ifdef mc68000
124 for (i = 0; i < 8; i++) {
125 sprintf(buf, "$d%d", i);
126 defregname(identname(buf, false), i);
127 sprintf(buf, "$a%d", i);
128 defregname(identname(buf, false), i + 8);
129 }
130# endif
131# endif
9a3bab7a
ML
132 defregname(identname("$fp", true), FRP);
133 defregname(identname("$sp", true), STKP);
134 defregname(identname("$pc", true), PROGCTR);
135 if (coredump) {
136 coredump_readin(process->mask, process->reg, process->signo);
4e067a2c 137 pc = process->reg[PROGCTR];
9a3bab7a 138 }
4e067a2c 139 arginit();
9a3bab7a
ML
140}
141
142/*
143 * Routines to get at process information from outside this module.
144 */
145
146public Word reg(n)
147Integer n;
148{
149 register Word w;
150
151 if (n == NREG) {
152 w = process->mask;
153 } else {
154 w = process->reg[n];
155 }
156 return w;
157}
158
159public setreg(n, w)
160Integer n;
161Word w;
162{
163 process->reg[n] = w;
164}
165
166/*
167 * Begin execution.
168 *
169 * We set a breakpoint at the end of the code so that the
170 * process data doesn't disappear after the program terminates.
171 */
172
173private Boolean remade();
174
175public start(argv, infile, outfile)
176String argv[];
177String infile, outfile;
178{
179 String pargv[4];
180 Node cond;
181
182 if (coredump) {
183 coredump = false;
184 fclose(corefile);
185 coredump_close();
186 }
187 if (argv == nil) {
188 argv = pargv;
189 pargv[0] = objname;
190 pargv[1] = nil;
191 } else {
192 argv[argc] = nil;
193 }
0022c355 194 pstart(process, argv, infile, outfile);
9a3bab7a
ML
195 if (remade(objname)) {
196 reinit(argv, infile, outfile);
197 }
9a3bab7a 198 if (process->status == STOPPED) {
24350cae 199 pc = CODESTART;
2fd0f574 200 setcurfunc(program);
9a3bab7a
ML
201 if (objsize != 0) {
202 cond = build(O_EQ, build(O_SYM, pcsym), build(O_LCON, lastaddr()));
203 event_once(cond, buildcmdlist(build(O_ENDX)));
204 }
205 }
206}
207
208/*
209 * Check to see if the object file has changed since the symbolic
210 * information last was read.
211 */
212
213private time_t modtime;
214
215private Boolean remade(filename)
216String filename;
217{
218 struct stat s;
219 Boolean b;
220
221 stat(filename, &s);
222 b = (Boolean) (modtime != 0 and modtime < s.st_mtime);
223 modtime = s.st_mtime;
224 return b;
225}
226
227/*
228 * Set up what signals we want to trace.
229 */
230
231private setsigtrace()
232{
233 register Integer i;
234 register Process p;
235
236 p = process;
237 for (i = 1; i <= NSIG; i++) {
238 psigtrace(p, i, true);
239 }
240 psigtrace(p, SIGHUP, false);
241 psigtrace(p, SIGKILL, false);
242 psigtrace(p, SIGALRM, false);
24350cae
DS
243# ifdef SIGTSTP
244 psigtrace(p, SIGTSTP, false);
245 psigtrace(p, SIGCONT, false);
246# endif
9a3bab7a 247 psigtrace(p, SIGCHLD, false);
ca6575f0 248 psigtrace(p, SIGWINCH, false);
9a3bab7a
ML
249}
250
251/*
252 * Initialize the argument list.
253 */
254
255public arginit()
256{
257 infile = nil;
258 outfile = nil;
259 argv[0] = objname;
260 argc = 1;
261}
262
263/*
264 * Add an argument to the list for the debuggee.
265 */
266
267public newarg(arg)
268String arg;
269{
270 if (argc >= MAXNCMDARGS) {
271 error("too many arguments");
272 }
273 argv[argc++] = arg;
274}
275
276/*
277 * Set the standard input for the debuggee.
278 */
279
280public inarg(filename)
281String filename;
282{
283 if (infile != nil) {
284 error("multiple input redirects");
285 }
286 infile = filename;
287}
288
289/*
290 * Set the standard output for the debuggee.
291 * Probably should check to avoid overwriting an existing file.
292 */
293
294public outarg(filename)
295String filename;
296{
297 if (outfile != nil) {
298 error("multiple output redirect");
299 }
300 outfile = filename;
301}
302
303/*
304 * Start debuggee executing.
305 */
306
307public run()
308{
309 process->status = STOPPED;
310 fixbps();
311 curline = 0;
312 start(argv, infile, outfile);
313 just_started = true;
314 isstopped = false;
8ee6535a 315 cont(0);
9a3bab7a
ML
316}
317
318/*
319 * Continue execution wherever we left off.
320 *
321 * Note that this routine never returns. Eventually bpact() will fail
322 * and we'll call printstatus or step will call it.
323 */
324
325typedef int Intfunc();
326
327private Intfunc *dbintr;
328private intr();
329
36fd36ba 330public cont(signo)
2fd0f574 331integer signo;
9a3bab7a 332{
2fd0f574
SL
333 integer s;
334
9a3bab7a
ML
335 dbintr = signal(SIGINT, intr);
336 if (just_started) {
337 just_started = false;
338 } else {
339 if (not isstopped) {
340 error("can't continue execution");
341 }
342 isstopped = false;
36fd36ba 343 stepover();
9a3bab7a 344 }
2fd0f574 345 s = signo;
9a3bab7a
ML
346 for (;;) {
347 if (single_stepping) {
348 printnews();
349 } else {
350 setallbps();
2fd0f574 351 resume(s);
9a3bab7a 352 unsetallbps();
2fd0f574 353 s = DEFSIG;
0022c355 354 if (not isbperr() or not bpact()) {
9a3bab7a
ML
355 printstatus();
356 }
357 }
36fd36ba 358 stepover();
9a3bab7a
ML
359 }
360 /* NOTREACHED */
361}
362
363/*
0022c355 364 * This routine is called if we get an interrupt while "running"
9a3bab7a
ML
365 * but actually in the debugger. Could happen, for example, while
366 * processing breakpoints.
367 *
368 * We basically just want to keep going; the assumption is
0022c355 369 * that when the process resumes it will get the interrupt,
9a3bab7a
ML
370 * which will then be handled.
371 */
372
373private intr()
374{
375 signal(SIGINT, intr);
376}
377
378public fixintr()
379{
380 signal(SIGINT, dbintr);
381}
382
383/*
384 * Resume execution.
385 */
386
36fd36ba
ML
387public resume(signo)
388int signo;
9a3bab7a
ML
389{
390 register Process p;
391
392 p = process;
36fd36ba 393 pcont(p, signo);
9a3bab7a 394 pc = process->reg[PROGCTR];
e0a80343 395 if (p->status != STOPPED) {
36fd36ba
ML
396 if (p->signo != 0) {
397 error("program terminated by signal %d", p->signo);
8ee6535a 398 } else if (not runfirst) {
0022c355
ML
399 if (p->exitval == 0) {
400 error("program exited");
401 } else {
402 error("program exited with code %d", p->exitval);
403 }
36fd36ba 404 }
e0a80343 405 }
9a3bab7a
ML
406}
407
408/*
409 * Continue execution up to the next source line.
410 *
411 * There are two ways to define the next source line depending on what
412 * is desired when a procedure or function call is encountered. Step
413 * stops at the beginning of the procedure or call; next skips over it.
414 */
415
416/*
417 * Stepc is what is called when the step command is given.
418 * It has to play with the "isstopped" information.
419 */
420
421public stepc()
422{
423 if (not isstopped) {
424 error("can't continue execution");
425 }
426 isstopped = false;
427 dostep(false);
428 isstopped = true;
429}
430
431public next()
432{
2fd0f574
SL
433 Address oldfrp, newfrp;
434
9a3bab7a
ML
435 if (not isstopped) {
436 error("can't continue execution");
437 }
438 isstopped = false;
2fd0f574
SL
439 oldfrp = reg(FRP);
440 do {
441 dostep(true);
442 pc = reg(PROGCTR);
443 newfrp = reg(FRP);
444 } while (newfrp < oldfrp and newfrp != 0);
9a3bab7a
ML
445 isstopped = true;
446}
447
2fd0f574
SL
448/*
449 * Continue execution until the current function returns, or,
450 * if the given argument is non-nil, until execution returns to
451 * somewhere within the given function.
452 */
453
454public rtnfunc (f)
455Symbol f;
456{
457 Address addr;
458 Symbol t;
459
460 if (not isstopped) {
461 error("can't continue execution");
462 } else if (f != nil and not isactive(f)) {
463 error("%s is not active", symname(f));
464 } else {
465 addr = return_addr();
466 if (addr == nil) {
467 error("no place to return to");
468 } else {
469 isstopped = false;
470 contto(addr);
471 if (f != nil) {
472 for (;;) {
473 t = whatblock(pc);
474 addr = return_addr();
475 if (t == f or addr == nil) break;
476 contto(addr);
477 }
478 }
0022c355 479 if (not bpact()) {
2fd0f574
SL
480 isstopped = true;
481 printstatus();
482 }
483 }
484 }
485}
486
36fd36ba
ML
487/*
488 * Single-step over the current machine instruction.
489 *
490 * If we're single-stepping by source line we want to step to the
491 * next source line. Otherwise we're going to continue so there's
492 * no reason to do all the work necessary to single-step to the next
493 * source line.
494 */
495
2fd0f574 496public stepover()
9a3bab7a 497{
36fd36ba
ML
498 Boolean b;
499
2fd0f574
SL
500 if (traceexec) {
501 printf("!! stepping over 0x%x\n", process->reg[PROGCTR]);
502 }
36fd36ba
ML
503 if (single_stepping) {
504 dostep(false);
505 } else {
506 b = inst_tracing;
507 inst_tracing = true;
508 dostep(false);
509 inst_tracing = b;
510 }
2fd0f574
SL
511 if (traceexec) {
512 printf("!! stepped over to 0x%x\n", process->reg[PROGCTR]);
513 }
9a3bab7a
ML
514}
515
516/*
0022c355
ML
517 * Resume execution up to the given address. We can either ignore
518 * breakpoints (stepto) or catch them (contto).
9a3bab7a
ML
519 */
520
521public stepto(addr)
522Address addr;
523{
2fd0f574
SL
524 xto(addr, false);
525}
526
527private contto (addr)
528Address addr;
529{
530 xto(addr, true);
531}
532
533private xto (addr, catchbps)
534Address addr;
535boolean catchbps;
536{
537 Address curpc;
538
539 if (catchbps) {
540 stepover();
541 }
542 curpc = process->reg[PROGCTR];
543 if (addr != curpc) {
544 if (traceexec) {
545 printf("!! stepping from 0x%x to 0x%x\n", curpc, addr);
546 }
547 if (catchbps) {
548 setallbps();
549 }
550 setbp(addr);
551 resume(DEFSIG);
552 unsetbp(addr);
553 if (catchbps) {
554 unsetallbps();
555 }
556 if (not isbperr()) {
557 printstatus();
558 }
9a3bab7a
ML
559 }
560}
561
562/*
563 * Print the status of the process.
564 * This routine does not return.
565 */
566
24350cae 567public printstatus ()
9a3bab7a 568{
ca69b757
ML
569 int status;
570
b0edae1c
ML
571 if (process->status == FINISHED) {
572 exit(0);
9a3bab7a 573 } else {
24350cae
DS
574 if (runfirst) {
575 fprintf(stderr, "\nEntering debugger ...\n");
576 printheading();
577 init();
578 }
2fd0f574 579 setcurfunc(whatblock(pc));
b0edae1c
ML
580 getsrcpos();
581 if (process->signo == SIGINT) {
582 isstopped = true;
583 printerror();
584 } else if (isbperr() and isstopped) {
585 printf("stopped ");
86d0cc79
ML
586 printloc();
587 putchar('\n');
b0edae1c 588 if (curline > 0) {
b0edae1c
ML
589 printlines(curline, curline);
590 } else {
b0edae1c
ML
591 printinst(pc, pc);
592 }
593 erecover();
9a3bab7a 594 } else {
b0edae1c 595 fixintr();
9a3bab7a
ML
596 isstopped = true;
597 printerror();
598 }
599 }
600}
601
86d0cc79
ML
602/*
603 * Print out the current location in the debuggee.
604 */
605
606public printloc()
607{
608 printf("in ");
609 printname(stdout, curfunc);
610 putchar(' ');
8ee6535a 611 if (curline > 0 and not useInstLoc) {
86d0cc79
ML
612 printsrcpos();
613 } else {
8ee6535a
ML
614 useInstLoc = false;
615 curline = 0;
86d0cc79
ML
616 printf("at 0x%x", pc);
617 }
618}
619
9a3bab7a
ML
620/*
621 * Some functions for testing the state of the process.
622 */
623
624public Boolean notstarted(p)
625Process p;
626{
627 return (Boolean) (p->status == NOTSTARTED);
628}
629
630public Boolean isfinished(p)
631Process p;
632{
633 return (Boolean) (p->status == FINISHED);
634}
635
636/*
0022c355
ML
637 * Predicate to test if the reason the process stopped was because
638 * of a breakpoint. If so, as a side effect clear the local copy of
639 * signal handler associated with process. We must do this so as to
640 * not confuse future stepping or continuing by possibly concluding
641 * the process should continue with a SIGTRAP handler.
9a3bab7a
ML
642 */
643
0022c355
ML
644public boolean isbperr()
645{
646 Process p;
647 boolean b;
648
649 p = process;
650 if (p->status == STOPPED and p->signo == SIGTRAP) {
651 b = true;
652 p->sigstatus = 0;
653 } else {
654 b = false;
655 }
656 return b;
657}
658
659/*
660 * Return the signal number that stopped the process.
661 */
662
663public integer errnum (p)
9a3bab7a
ML
664Process p;
665{
666 return p->signo;
667}
668
0022c355
ML
669/*
670 * Return the signal code associated with the signal.
671 */
672
673public integer errcode (p)
57a9bb29
SL
674Process p;
675{
676 return p->sigcode;
677}
678
9a3bab7a
ML
679/*
680 * Return the termination code of the process.
681 */
682
0022c355 683public integer exitcode (p)
9a3bab7a
ML
684Process p;
685{
686 return p->exitval;
687}
688
689/*
690 * These routines are used to access the debuggee process from
691 * outside this module.
692 *
693 * They invoke "pio" which eventually leads to a call to "ptrace".
8ee6535a
ML
694 * The system generates an I/O error when a ptrace fails. During reads
695 * these are ignored, during writes they are reported as an error, and
696 * for anything else they cause a fatal error.
9a3bab7a
ML
697 */
698
699extern Intfunc *onsyserr();
700
701private badaddr;
8ee6535a 702private read_err(), write_err();
9a3bab7a
ML
703
704/*
705 * Read from the process' instruction area.
706 */
707
708public iread(buff, addr, nbytes)
709char *buff;
710Address addr;
711int nbytes;
712{
713 Intfunc *f;
714
8ee6535a 715 f = onsyserr(EIO, read_err);
9a3bab7a
ML
716 badaddr = addr;
717 if (coredump) {
718 coredump_readtext(buff, addr, nbytes);
719 } else {
720 pio(process, PREAD, TEXTSEG, buff, addr, nbytes);
721 }
722 onsyserr(EIO, f);
723}
724
725/*
726 * Write to the process' instruction area, usually in order to set
727 * or unset a breakpoint.
728 */
729
730public iwrite(buff, addr, nbytes)
731char *buff;
732Address addr;
733int nbytes;
734{
735 Intfunc *f;
736
737 if (coredump) {
738 error("no process to write to");
739 }
8ee6535a 740 f = onsyserr(EIO, write_err);
9a3bab7a
ML
741 badaddr = addr;
742 pio(process, PWRITE, TEXTSEG, buff, addr, nbytes);
743 onsyserr(EIO, f);
744}
745
746/*
747 * Read for the process' data area.
748 */
749
750public dread(buff, addr, nbytes)
751char *buff;
752Address addr;
753int nbytes;
754{
755 Intfunc *f;
756
9a3bab7a
ML
757 badaddr = addr;
758 if (coredump) {
0022c355 759 f = onsyserr(EFAULT, read_err);
9a3bab7a 760 coredump_readdata(buff, addr, nbytes);
0022c355 761 onsyserr(EFAULT, f);
9a3bab7a 762 } else {
0022c355 763 f = onsyserr(EIO, read_err);
9a3bab7a 764 pio(process, PREAD, DATASEG, buff, addr, nbytes);
0022c355 765 onsyserr(EIO, f);
9a3bab7a 766 }
9a3bab7a
ML
767}
768
769/*
770 * Write to the process' data area.
771 */
772
773public dwrite(buff, addr, nbytes)
774char *buff;
775Address addr;
776int nbytes;
777{
778 Intfunc *f;
779
780 if (coredump) {
781 error("no process to write to");
782 }
8ee6535a 783 f = onsyserr(EIO, write_err);
9a3bab7a
ML
784 badaddr = addr;
785 pio(process, PWRITE, DATASEG, buff, addr, nbytes);
786 onsyserr(EIO, f);
787}
788
789/*
8ee6535a
ML
790 * Trap for errors in reading or writing to a process.
791 * The current approach is to "ignore" read errors and complain
792 * bitterly about write errors.
9a3bab7a
ML
793 */
794
8ee6535a 795private read_err()
9a3bab7a 796{
ae743e15 797 /*
8ee6535a 798 * Ignore.
ae743e15 799 */
9a3bab7a
ML
800}
801
8ee6535a
ML
802private write_err()
803{
804 error("can't write to process (address 0x%x)", badaddr);
805}
806
9a3bab7a
ML
807/*
808 * Ptrace interface.
809 */
810
9a3bab7a 811#define WMASK (~(sizeof(Word) - 1))
24350cae 812#define cachehash(addr) ((unsigned) ((addr >> 2) % CACHESIZE))
9a3bab7a
ML
813
814#define FIRSTSIG SIGINT
815#define LASTSIG SIGQUIT
816#define ischild(pid) ((pid) == 0)
0022c355 817#define traceme() ptrace(0, 0, 0, 0)
9a3bab7a
ML
818#define setrep(n) (1 << ((n)-1))
819#define istraced(p) (p->sigset&setrep(p->signo))
820
0022c355
ML
821/*
822 * Ptrace options (specified in first argument).
823 */
824
825#define UREAD 3 /* read from process's user structure */
826#define UWRITE 6 /* write to process's user structure */
827#define IREAD 1 /* read from process's instruction space */
828#define IWRITE 4 /* write to process's instruction space */
829#define DREAD 2 /* read from process's data space */
830#define DWRITE 5 /* write to process's data space */
831#define CONT 7 /* continue stopped process */
832#define SSTEP 9 /* continue for approximately one instruction */
833#define PKILL 8 /* terminate the process */
834
24350cae
DS
835#ifdef IRIS
836# define readreg(p, r) ptrace(10, p->pid, r, 0)
837# define writereg(p, r, v) ptrace(11, p->pid, r, v)
838#else
839# define readreg(p, r) ptrace(UREAD, p->pid, regloc(r), 0);
840# define writereg(p, r, v) ptrace(UWRITE, p->pid, regloc(r), v);
841#endif
842
9a3bab7a
ML
843/*
844 * Start up a new process by forking and exec-ing the
845 * given argument list, returning when the process is loaded
846 * and ready to execute. The PROCESS information (pointed to
847 * by the first argument) is appropriately filled.
848 *
849 * If the given PROCESS structure is associated with an already running
850 * process, we terminate it.
851 */
852
853/* VARARGS2 */
854private pstart(p, argv, infile, outfile)
855Process p;
856String argv[];
857String infile;
858String outfile;
859{
860 int status;
9a3bab7a 861
2fd0f574
SL
862 if (p->pid != 0) {
863 pterm(p);
0022c355 864 cacheflush(p);
9a3bab7a 865 }
0022c355 866 fflush(stdout);
9a3bab7a 867 psigtrace(p, SIGTRAP, true);
24350cae
DS
868# ifdef IRIS
869 p->pid = fork();
870# else
871 p->pid = vfork();
872# endif
ca69b757 873 if (p->pid == -1) {
9a3bab7a
ML
874 panic("can't fork");
875 }
876 if (ischild(p->pid)) {
0022c355 877 nocatcherrs();
9a3bab7a
ML
878 traceme();
879 if (infile != nil) {
2fd0f574 880 infrom(infile);
9a3bab7a
ML
881 }
882 if (outfile != nil) {
2fd0f574 883 outto(outfile);
9a3bab7a 884 }
e0a80343 885 execv(argv[0], argv);
86d0cc79 886 _exit(1);
9a3bab7a
ML
887 }
888 pwait(p->pid, &status);
889 getinfo(p, status);
890 if (p->status != STOPPED) {
0022c355
ML
891 beginerrmsg();
892 fprintf(stderr, "warning: cannot execute %s\n", argv[0]);
893 } else {
894 ptraced(p->pid);
9a3bab7a
ML
895 }
896}
897
2fd0f574
SL
898/*
899 * Terminate a ptrace'd process.
900 */
901
902public pterm (p)
903Process p;
904{
905 integer status;
906
907 if (p != nil and p->pid != 0) {
0022c355 908 ptrace(PKILL, p->pid, 0, 0);
2fd0f574
SL
909 pwait(p->pid, &status);
910 unptraced(p->pid);
911 }
912}
913
9a3bab7a 914/*
36fd36ba
ML
915 * Continue a stopped process. The first argument points to a Process
916 * structure. Before the process is restarted it's user area is modified
917 * according to the values in the structure. When this routine finishes,
9a3bab7a
ML
918 * the structure has the new values from the process's user area.
919 *
920 * Pcont terminates when the process stops with a signal pending that
921 * is being traced (via psigtrace), or when the process terminates.
922 */
923
36fd36ba 924private pcont(p, signo)
9a3bab7a 925Process p;
36fd36ba 926int signo;
9a3bab7a 927{
2fd0f574 928 int s, status;
9a3bab7a
ML
929
930 if (p->pid == 0) {
0022c355 931 error("program is not active");
9a3bab7a 932 }
2fd0f574 933 s = signo;
9a3bab7a 934 do {
2fd0f574
SL
935 setinfo(p, s);
936 if (traceexec) {
937 printf("!! pcont from 0x%x with signal %d (%d)\n",
938 p->reg[PROGCTR], s, p->signo);
939 fflush(stdout);
940 }
9a3bab7a 941 sigs_off();
0022c355 942 if (ptrace(CONT, p->pid, p->reg[PROGCTR], p->signo) < 0) {
ca69b757 943 panic("error %d trying to continue process", errno);
9a3bab7a
ML
944 }
945 pwait(p->pid, &status);
946 sigs_on();
947 getinfo(p, status);
0022c355
ML
948 if (p->status == STOPPED and traceexec and not istraced(p)) {
949 printf("!! ignored signal %d at 0x%x\n",
950 p->signo, p->reg[PROGCTR]);
2fd0f574
SL
951 fflush(stdout);
952 }
953 s = p->signo;
9a3bab7a 954 } while (p->status == STOPPED and not istraced(p));
2fd0f574
SL
955 if (traceexec) {
956 printf("!! pcont to 0x%x on signal %d\n", p->reg[PROGCTR], p->signo);
957 fflush(stdout);
958 }
9a3bab7a
ML
959}
960
961/*
962 * Single step as best ptrace can.
963 */
964
2fd0f574 965public pstep(p, signo)
9a3bab7a 966Process p;
2fd0f574 967integer signo;
9a3bab7a 968{
0022c355 969 int s, status;
9a3bab7a 970
0022c355
ML
971 s = signo;
972 do {
973 setinfo(p, s);
974 if (traceexec) {
975 printf("!! pstep from 0x%x with signal %d (%d)\n",
976 p->reg[PROGCTR], s, p->signo);
977 fflush(stdout);
978 }
979 sigs_off();
980 if (ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo) < 0) {
981 panic("error %d trying to step process", errno);
982 }
983 pwait(p->pid, &status);
984 sigs_on();
985 getinfo(p, status);
24350cae
DS
986# if mc68000 || m68000
987 if (p->status == STOPPED and p->signo == SIGTRAP) {
988 p->reg[PROGCTR] += 2;
989 }
990# endif
0022c355
ML
991 if (p->status == STOPPED and traceexec and not istraced(p)) {
992 printf("!! pstep ignored signal %d at 0x%x\n",
993 p->signo, p->reg[PROGCTR]);
994 fflush(stdout);
995 }
996 s = p->signo;
997 } while (p->status == STOPPED and not istraced(p));
2fd0f574 998 if (traceexec) {
0022c355
ML
999 printf("!! pstep to 0x%x on signal %d\n",
1000 p->reg[PROGCTR], p->signo);
2fd0f574
SL
1001 fflush(stdout);
1002 }
1003 if (p->status != STOPPED) {
0022c355
ML
1004 if (p->exitval == 0) {
1005 error("program exited\n");
1006 } else {
1007 error("program exited with code %d\n", p->exitval);
1008 }
2fd0f574 1009 }
9a3bab7a
ML
1010}
1011
1012/*
1013 * Return from execution when the given signal is pending.
1014 */
1015
1016public psigtrace(p, sig, sw)
1017Process p;
1018int sig;
1019Boolean sw;
1020{
1021 if (sw) {
1022 p->sigset |= setrep(sig);
1023 } else {
1024 p->sigset &= ~setrep(sig);
1025 }
1026}
1027
1028/*
1029 * Don't catch any signals.
1030 * Particularly useful when letting a process finish uninhibited.
1031 */
1032
1033public unsetsigtraces(p)
1034Process p;
1035{
1036 p->sigset = 0;
1037}
1038
1039/*
1040 * Turn off attention to signals not being caught.
1041 */
1042
1043private Intfunc *sigfunc[NSIG];
1044
1045private sigs_off()
1046{
1047 register int i;
1048
1049 for (i = FIRSTSIG; i < LASTSIG; i++) {
1050 if (i != SIGKILL) {
1051 sigfunc[i] = signal(i, SIG_IGN);
1052 }
1053 }
1054}
1055
1056/*
1057 * Turn back on attention to signals.
1058 */
1059
1060private sigs_on()
1061{
1062 register int i;
1063
1064 for (i = FIRSTSIG; i < LASTSIG; i++) {
1065 if (i != SIGKILL) {
1066 signal(i, sigfunc[i]);
1067 }
1068 }
1069}
1070
1071/*
1072 * Get process information from user area.
1073 */
1074
24350cae 1075private getinfo (p, status)
9a3bab7a
ML
1076register Process p;
1077register int status;
1078{
1079 register int i;
2fd0f574 1080 Address addr;
9a3bab7a
ML
1081
1082 p->signo = (status&0177);
1083 p->exitval = ((status >> 8)&0377);
1084 if (p->signo != STOPPED) {
1085 p->status = FINISHED;
8ee6535a 1086 p->pid = 0;
2fd0f574 1087 p->reg[PROGCTR] = 0;
9a3bab7a
ML
1088 } else {
1089 p->status = p->signo;
1090 p->signo = p->exitval;
1091 p->exitval = 0;
24350cae
DS
1092# ifdef IRIS
1093 p->mask = readreg(p, RPS);
1094# else
1095 p->sigcode = ptrace(UREAD, p->pid, &((struct user *)0)->u_code, 0);
1096 p->mask = readreg(p, PS);
1097# endif
9a3bab7a 1098 for (i = 0; i < NREG; i++) {
24350cae 1099 p->reg[i] = readreg(p, rloc[i]);
9a3bab7a
ML
1100 p->oreg[i] = p->reg[i];
1101 }
24350cae
DS
1102# ifdef mc68000
1103 if (p->status == STOPPED and p->signo == SIGTRAP and
1104 p->reg[PROGCTR] > CODESTART
1105 ) {
1106 p->reg[PROGCTR] -= 2;
1107 }
1108# endif
5870175c 1109 savetty(stdout, &(p->ttyinfo));
2fd0f574 1110 addr = (Address) &(((struct user *) 0)->u_signal[p->signo]);
0022c355 1111 p->sigstatus = (Address) ptrace(UREAD, p->pid, addr, 0);
9a3bab7a
ML
1112 }
1113}
1114
1115/*
1116 * Set process's user area information from given process structure.
1117 */
1118
24350cae 1119private setinfo (p, signo)
9a3bab7a 1120register Process p;
36fd36ba 1121int signo;
9a3bab7a
ML
1122{
1123 register int i;
1124 register int r;
1125
8ee6535a 1126 if (signo == DEFSIG) {
2fd0f574 1127 if (istraced(p) and (p->sigstatus == 0 or p->sigstatus == 1)) {
8ee6535a
ML
1128 p->signo = 0;
1129 }
1130 } else {
36fd36ba 1131 p->signo = signo;
9a3bab7a
ML
1132 }
1133 for (i = 0; i < NREG; i++) {
1134 if ((r = p->reg[i]) != p->oreg[i]) {
24350cae 1135 writereg(p, rloc[i], r);
9a3bab7a
ML
1136 }
1137 }
5870175c 1138 restoretty(stdout, &(p->ttyinfo));
9a3bab7a
ML
1139}
1140
2fd0f574
SL
1141/*
1142 * Return the address associated with the current signal.
1143 * (Plus two since the address points to the beginning of a procedure).
1144 */
1145
1146public Address usignal (p)
1147Process p;
1148{
1149 Address r;
1150
1151 r = p->sigstatus;
1152 if (r != 0 and r != 1) {
24350cae 1153 r += FUNCOFFSET;
2fd0f574
SL
1154 }
1155 return r;
1156}
1157
9a3bab7a
ML
1158/*
1159 * Structure for reading and writing by words, but dealing with bytes.
1160 */
1161
1162typedef union {
1163 Word pword;
1164 Byte pbyte[sizeof(Word)];
1165} Pword;
1166
1167/*
1168 * Read (write) from (to) the process' address space.
1169 * We must deal with ptrace's inability to look anywhere other
1170 * than at a word boundary.
1171 */
1172
1173private Word fetch();
1174private store();
1175
1176private pio(p, op, seg, buff, addr, nbytes)
1177Process p;
1178PioOp op;
1179PioSeg seg;
1180char *buff;
1181Address addr;
1182int nbytes;
1183{
1184 register int i;
1185 register Address newaddr;
1186 register char *cp;
1187 char *bufend;
1188 Pword w;
1189 Address wordaddr;
1190 int byteoff;
1191
1192 if (p->status != STOPPED) {
1193 error("program is not active");
1194 }
1195 cp = buff;
1196 newaddr = addr;
1197 wordaddr = (newaddr&WMASK);
1198 if (wordaddr != newaddr) {
1199 w.pword = fetch(p, seg, wordaddr);
1200 for (i = newaddr - wordaddr; i < sizeof(Word) and nbytes > 0; i++) {
1201 if (op == PREAD) {
1202 *cp++ = w.pbyte[i];
1203 } else {
1204 w.pbyte[i] = *cp++;
1205 }
1206 nbytes--;
1207 }
1208 if (op == PWRITE) {
1209 store(p, seg, wordaddr, w.pword);
1210 }
1211 newaddr = wordaddr + sizeof(Word);
1212 }
1213 byteoff = (nbytes&(~WMASK));
1214 nbytes -= byteoff;
1215 bufend = cp + nbytes;
ca6575f0
SL
1216#ifdef tahoe
1217 if (((int)cp)&WMASK) {
1218 /*
1219 * Must copy a byte at a time, buffer not word addressable.
1220 */
1221 while (cp < bufend) {
1222 if (op == PREAD) {
1223 w.pword = fetch(p, seg, newaddr);
1224 for (i = 0; i < sizeof(Word); i++)
1225 *cp++ = w.pbyte[i];
1226 } else {
1227 for (i = 0; i < sizeof(Word); i++)
1228 w.pbyte[i] = *cp++;
1229 store(p, seg, newaddr, w.pword);
1230 }
1231 newaddr += sizeof(Word);
1232 }
1233 } else {
1234 /*
1235 * Buffer, word aligned, act normally...
1236 */
1237#endif
9a3bab7a
ML
1238 while (cp < bufend) {
1239 if (op == PREAD) {
1240 *((Word *) cp) = fetch(p, seg, newaddr);
1241 } else {
1242 store(p, seg, newaddr, *((Word *) cp));
1243 }
1244 cp += sizeof(Word);
1245 newaddr += sizeof(Word);
1246 }
ca6575f0
SL
1247#ifdef tahoe
1248 }
1249#endif
9a3bab7a
ML
1250 if (byteoff > 0) {
1251 w.pword = fetch(p, seg, newaddr);
1252 for (i = 0; i < byteoff; i++) {
1253 if (op == PREAD) {
1254 *cp++ = w.pbyte[i];
1255 } else {
1256 w.pbyte[i] = *cp++;
1257 }
1258 }
1259 if (op == PWRITE) {
1260 store(p, seg, newaddr, w.pword);
1261 }
1262 }
1263}
1264
1265/*
1266 * Get a word from a process at the given address.
1267 * The address is assumed to be on a word boundary.
1268 *
1269 * A simple cache scheme is used to avoid redundant ptrace calls
1270 * to the instruction space since it is assumed to be pure.
1271 *
1272 * It is necessary to use a write-through scheme so that
1273 * breakpoints right next to each other don't interfere.
1274 */
1275
1276private Integer nfetchs, nreads, nwrites;
1277
1278private Word fetch(p, seg, addr)
1279Process p;
1280PioSeg seg;
1281register int addr;
1282{
1283 register CacheWord *wp;
1284 register Word w;
1285
1286 switch (seg) {
1287 case TEXTSEG:
1288 ++nfetchs;
1289 wp = &p->word[cachehash(addr)];
1290 if (addr == 0 or wp->addr != addr) {
1291 ++nreads;
0022c355 1292 w = ptrace(IREAD, p->pid, addr, 0);
9a3bab7a
ML
1293 wp->addr = addr;
1294 wp->val = w;
1295 } else {
1296 w = wp->val;
1297 }
1298 break;
1299
1300 case DATASEG:
0022c355 1301 w = ptrace(DREAD, p->pid, addr, 0);
9a3bab7a
ML
1302 break;
1303
1304 default:
1305 panic("fetch: bad seg %d", seg);
1306 /* NOTREACHED */
1307 }
1308 return w;
1309}
1310
1311/*
1312 * Put a word into the process' address space at the given address.
1313 * The address is assumed to be on a word boundary.
1314 */
1315
1316private store(p, seg, addr, data)
1317Process p;
1318PioSeg seg;
1319int addr;
1320Word data;
1321{
1322 register CacheWord *wp;
1323
1324 switch (seg) {
1325 case TEXTSEG:
1326 ++nwrites;
1327 wp = &p->word[cachehash(addr)];
1328 wp->addr = addr;
1329 wp->val = data;
0022c355 1330 ptrace(IWRITE, p->pid, addr, data);
9a3bab7a
ML
1331 break;
1332
1333 case DATASEG:
0022c355 1334 ptrace(DWRITE, p->pid, addr, data);
9a3bab7a
ML
1335 break;
1336
1337 default:
1338 panic("store: bad seg %d", seg);
1339 /* NOTREACHED */
1340 }
1341}
1342
0022c355
ML
1343/*
1344 * Flush the instruction cache associated with a process.
1345 */
1346
1347private cacheflush (p)
1348Process p;
1349{
1350 bzero(p->word, sizeof(p->word));
1351}
1352
9a3bab7a
ML
1353public printptraceinfo()
1354{
1355 printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites);
1356}
1357
1358/*
2fd0f574
SL
1359 * Redirect input.
1360 * Assuming this is called from a child, we should be careful to avoid
1361 * (possibly) shared standard I/O buffers.
1362 */
1363
1364private infrom (filename)
1365String filename;
1366{
1367 Fileid in;
1368
1369 in = open(filename, 0);
1370 if (in == -1) {
1371 write(2, "can't read ", 11);
1372 write(2, filename, strlen(filename));
1373 write(2, "\n", 1);
1374 _exit(1);
1375 }
1376 fswap(0, in);
1377}
1378
1379/*
1380 * Redirect standard output.
1381 * Same assumptions as for "infrom" above.
1382 */
1383
1384private outto (filename)
1385String filename;
1386{
1387 Fileid out;
1388
1389 out = creat(filename, 0666);
1390 if (out == -1) {
1391 write(2, "can't write ", 12);
1392 write(2, filename, strlen(filename));
1393 write(2, "\n", 1);
1394 _exit(1);
1395 }
1396 fswap(1, out);
1397}
1398
1399/*
1400 * Swap file numbers, useful for redirecting standard input or output.
9a3bab7a
ML
1401 */
1402
1403private fswap(oldfd, newfd)
2fd0f574
SL
1404Fileid oldfd;
1405Fileid newfd;
9a3bab7a
ML
1406{
1407 if (oldfd != newfd) {
1408 close(oldfd);
1409 dup(newfd);
1410 close(newfd);
1411 }
1412}
f7adfe8e 1413
f7adfe8e 1414/*
0022c355 1415 * Signal name manipulation.
f7adfe8e 1416 */
0022c355
ML
1417
1418private String signames[NSIG] = {
1419 0,
1420 "HUP", "INT", "QUIT", "ILL", "TRAP",
1421 "IOT", "EMT", "FPE", "KILL", "BUS",
1422 "SEGV", "SYS", "PIPE", "ALRM", "TERM",
1423 0, "STOP", "TSTP", "CONT", "CHLD",
1424 "TTIN", "TTOU", "TINT", "XCPU", "XFSZ",
ca6575f0 1425 "VTALRM", "PROF", "WINCH", "USR1", "USR2"
f7adfe8e
SL
1426};
1427
1428/*
0022c355
ML
1429 * Get the signal number associated with a given name.
1430 * The name is first translated to upper case if necessary.
f7adfe8e 1431 */
0022c355
ML
1432
1433public integer siglookup (s)
f7adfe8e
SL
1434String s;
1435{
0022c355
ML
1436 register char *p, *q;
1437 char buf[100];
1438 integer i;
1439
1440 p = s;
1441 q = buf;
1442 while (*p != '\0') {
1443 if (*p >= 'a' and *p <= 'z') {
1444 *q = (*p - 'a') + 'A';
1445 } else {
1446 *q = *p;
1447 }
1448 ++p;
1449 ++q;
1450 }
1451 *q = '\0';
1452 p = buf;
1453 if (buf[0] == 'S' and buf[1] == 'I' and buf[2] == 'G') {
1454 p += 3;
1455 }
1456 i = 1;
1457 for (;;) {
1458 if (i >= sizeof(signames) div sizeof(signames[0])) {
1459 error("signal \"%s\" unknown", s);
1460 i = 0;
1461 break;
1462 }
1463 if (signames[i] != nil and streq(signames[i], p)) {
1464 break;
1465 }
1466 ++i;
1467 }
1468 return i;
f7adfe8e
SL
1469}
1470
1471/*
0022c355
ML
1472 * Print all signals being ignored by the debugger.
1473 * These signals are auotmatically
f7adfe8e
SL
1474 * passed on to the debugged process.
1475 */
0022c355
ML
1476
1477public printsigsignored (p)
57a9bb29 1478Process p;
f7adfe8e 1479{
57a9bb29 1480 printsigs(~p->sigset);
f7adfe8e
SL
1481}
1482
1483/*
1484 * Print all signals being intercepted by
1485 * the debugger for the specified process.
1486 */
0022c355 1487
57a9bb29
SL
1488public printsigscaught(p)
1489Process p;
f7adfe8e 1490{
57a9bb29 1491 printsigs(p->sigset);
f7adfe8e
SL
1492}
1493
0022c355
ML
1494private printsigs (set)
1495integer set;
57a9bb29 1496{
0022c355
ML
1497 integer s;
1498 char separator[2];
1499
1500 separator[0] = '\0';
1501 for (s = 1; s < sizeof(signames) div sizeof(signames[0]); s++) {
1502 if (set & setrep(s)) {
1503 if (signames[s] != nil) {
1504 printf("%s%s", separator, signames[s]);
1505 separator[0] = ' ';
1506 separator[1] = '\0';
1507 }
57a9bb29 1508 }
0022c355
ML
1509 }
1510 if (separator[0] == ' ') {
57a9bb29 1511 putchar('\n');
57a9bb29
SL
1512 }
1513}