159794Shibler #ifndef lint
259794Shibler static char sccsid[] = "@(#)runpcs.c 4.6 4/25/85";
359794Shibler #endif
459794Shibler /*
559794Shibler *
659794Shibler * UNIX debugger
759794Shibler *
859794Shibler */
959794Shibler
1059794Shibler #include "defs.h"
1159794Shibler #include <sys/wait.h>
1259794Shibler
1359794Shibler extern MAP txtmap;
1459794Shibler
1559794Shibler MSG NOFORK;
1659794Shibler MSG ENDPCS;
1759794Shibler MSG BADWAIT;
1859794Shibler
1959794Shibler CHAR *lp;
2059794Shibler ADDR sigint;
2159794Shibler ADDR sigqit;
2259794Shibler
2359794Shibler /* breakpoints */
2459794Shibler BKPTR bkpthead;
2559794Shibler
2659794Shibler extern REGLIST reglist[];
2759794Shibler extern INT nregs;
2859794Shibler
2959794Shibler CHAR lastc;
3059794Shibler
3159794Shibler INT fcor;
3259794Shibler INT fsym;
3359794Shibler STRING errflg;
3459794Shibler int errno;
3559794Shibler INT signo;
3659794Shibler INT sigcode;
3759794Shibler
3859794Shibler L_INT dot;
3959794Shibler STRING symfil;
4059794Shibler INT wtflag;
4159794Shibler INT pid;
4259794Shibler L_INT expv;
4359794Shibler INT adrflg;
4459794Shibler L_INT loopcnt;
4559794Shibler
4659794Shibler
4759794Shibler
4859794Shibler
4959794Shibler
5059794Shibler /* service routines for sub process control */
5159794Shibler
getsig(sig)5259794Shibler getsig(sig)
5359794Shibler { return(expr(0) ? expv : sig);
5459794Shibler }
5559794Shibler
5659794Shibler ADDR userpc = 1;
5759794Shibler
runpcs(runmode,execsig)5859794Shibler runpcs(runmode,execsig)
5959794Shibler {
6059794Shibler INT rc;
6159794Shibler REG BKPTR bkpt;
6259794Shibler IF adrflg THEN userpc=dot; FI
6359794Shibler printf("%s: running\n", symfil);
6459794Shibler
6559794Shibler WHILE --loopcnt>=0
6659794Shibler DO
6759794Shibler #ifdef DEBUG
6859794Shibler printf("\ncontinue %x %d\n",userpc,execsig);
6959794Shibler #endif
7059794Shibler IF runmode==SINGLE
7159794Shibler THEN delbp(); /* hardware handles single-stepping */
7259794Shibler ELSE /* continuing from a breakpoint is hard */
7359794Shibler IF bkpt=scanbkpt(userpc)
7459794Shibler THEN execbkpt(bkpt,execsig); execsig=0;
7559794Shibler FI
7659794Shibler setbp();
7759794Shibler FI
7859794Shibler ptrace(runmode,pid,userpc,execsig);
7959794Shibler bpwait(); chkerr(); execsig=0; delbp(); readregs();
8059794Shibler
8159794Shibler IF signo==0
8259794Shibler ANDF runmode != SINGLE
8359794Shibler #ifdef mc68000
8459794Shibler ANDF (bkpt=scanbkpt(userpc - 2)) /* argh */
8559794Shibler #else
8659794Shibler ANDF (bkpt=scanbkpt(userpc))
8759794Shibler #endif
8859794Shibler THEN /* stopped by BPT instruction */
8959794Shibler #ifdef DEBUG
9059794Shibler printf("\n BPT code; '%s'%o'%o'%d",
9159794Shibler bkpt->comm,bkpt->comm[0],EOR,bkpt->flag);
9259794Shibler #endif
9359794Shibler dot=bkpt->loc;
9459794Shibler userpc = dot;
9559794Shibler *(ADDR *)(((ADDR)&u)+PC-getradj(1)) = userpc;
9659794Shibler IF bkpt->flag==BKPTEXEC
9759794Shibler ORF ((bkpt->flag=BKPTEXEC)
9859794Shibler ANDF bkpt->comm[0]!=EOR
9959794Shibler ANDF command(bkpt->comm,':')
10059794Shibler ANDF --bkpt->count)
10159794Shibler THEN execbkpt(bkpt,execsig); execsig=0; loopcnt++;
10259794Shibler ELSE bkpt->count=bkpt->initcnt; rc=1;
10359794Shibler FI
10459794Shibler ELSE execsig=signo; rc=0;
10559794Shibler FI
10659794Shibler OD
10759794Shibler return(rc);
10859794Shibler }
10959794Shibler
11059794Shibler #define BPOUT 0
11159794Shibler #define BPIN 1
11259794Shibler INT bpstate = BPOUT;
11359794Shibler
endpcs()11459794Shibler endpcs()
11559794Shibler {
11659794Shibler REG BKPTR bkptr;
11759794Shibler IF pid
11859794Shibler THEN ptrace(PT_KILL,pid,0,0); pid=0; userpc=1;
11959794Shibler FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
12059794Shibler DO IF bkptr->flag
12159794Shibler THEN bkptr->flag=BKPTSET;
12259794Shibler FI
12359794Shibler OD
12459794Shibler FI
12559794Shibler bpstate=BPOUT;
12659794Shibler }
12759794Shibler
12859794Shibler #ifdef VFORK
nullsig()12959794Shibler nullsig()
13059794Shibler {
13159794Shibler
13259794Shibler }
13359794Shibler #endif
13459794Shibler
setup()13559794Shibler setup()
13659794Shibler {
13759794Shibler close(fsym); fsym = -1;
13859794Shibler #ifndef VFORK
13959794Shibler IF (pid = fork()) == 0
14059794Shibler #else
14159794Shibler IF (pid = vfork()) == 0
14259794Shibler #endif
14359794Shibler THEN ptrace(PT_TRACE_ME,0,0,0);
14459794Shibler #ifdef VFORK
14559794Shibler signal(SIGTRAP,nullsig);
14659794Shibler #endif
14759794Shibler signal(SIGINT,sigint); signal(SIGQUIT,sigqit);
14859794Shibler doexec(); exit(0);
14959794Shibler ELIF pid == -1
15059794Shibler THEN error(NOFORK);
15159794Shibler ELSE bpwait(); readregs(); lp[0]=EOR; lp[1]=0;
15259794Shibler fsym=open(symfil,wtflag);
15359794Shibler IF errflg
15459794Shibler THEN printf("%s: cannot execute\n",symfil);
15559794Shibler endpcs(); error(0);
15659794Shibler FI
15759794Shibler FI
15859794Shibler bpstate=BPOUT;
15959794Shibler }
16059794Shibler
execbkpt(bkptr,execsig)16159794Shibler execbkpt(bkptr,execsig)
16259794Shibler BKPTR bkptr;
16359794Shibler {
16459794Shibler #ifdef DEBUG
16559794Shibler printf("exbkpt: %d\n",bkptr->count);
16659794Shibler #endif
16759794Shibler delbp();
16859794Shibler ptrace(PT_STEP,pid,bkptr->loc,execsig);
16959794Shibler bkptr->flag=BKPTSET;
17059794Shibler bpwait(); chkerr(); readregs();
17159794Shibler }
17259794Shibler
17359794Shibler
doexec()17459794Shibler doexec()
17559794Shibler {
17659794Shibler STRING argl[MAXARG];
17759794Shibler CHAR args[LINSIZ];
17859794Shibler STRING p, *ap, filnam;
17959794Shibler extern STRING environ;
18059794Shibler ap=argl; p=args;
18159794Shibler *ap++=symfil;
18259794Shibler REP IF rdc()==EOR THEN break; FI
18359794Shibler *ap = p;
18459794Shibler /*
18559794Shibler * First thing is to look for direction characters
18659794Shibler * and get filename. Do not use up the args for filenames.
18759794Shibler * Then get rid of spaces before next args.
18859794Shibler */
18959794Shibler IF lastc=='<'
19059794Shibler THEN REP readchar(); PER lastc==SP ORF lastc==TB DONE
19159794Shibler filnam = p;
19259794Shibler WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='>'
19359794Shibler DO *p++=lastc; readchar(); OD
19459794Shibler *p = 0;
19559794Shibler close(0);
19659794Shibler IF open(filnam,0)<0
19759794Shibler THEN printf("%s: cannot open\n",filnam); _exit(0);
19859794Shibler FI
19959794Shibler p = *ap;
20059794Shibler ELIF lastc=='>'
20159794Shibler THEN REP readchar(); PER lastc==SP ORF lastc==TB DONE
20259794Shibler filnam = p;
20359794Shibler WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='<'
20459794Shibler DO *p++=lastc; readchar(); OD
20559794Shibler *p = '\0';
20659794Shibler close(1);
20759794Shibler IF creat(filnam,0666)<0
20859794Shibler THEN printf("%s: cannot create\n",filnam); _exit(0);
20959794Shibler FI
21059794Shibler p = *ap;
21159794Shibler ELSE
21259794Shibler WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='>' ANDF lastc!='<'
21359794Shibler DO *p++=lastc; readchar(); OD
21459794Shibler *p++ = '\0';
21559794Shibler ap++;
21659794Shibler FI
21759794Shibler PER lastc!=EOR DONE
21859794Shibler *ap++=0;
21959794Shibler exect(symfil, argl, environ);
22059794Shibler perror(symfil);
22159794Shibler }
22259794Shibler
scanbkpt(adr)22359794Shibler BKPTR scanbkpt(adr)
22459794Shibler ADDR adr;
22559794Shibler {
22659794Shibler REG BKPTR bkptr;
22759794Shibler FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
22859794Shibler DO IF bkptr->flag ANDF bkptr->loc==adr
22959794Shibler THEN break;
23059794Shibler FI
23159794Shibler OD
23259794Shibler return(bkptr);
23359794Shibler }
23459794Shibler
delbp()23559794Shibler delbp()
23659794Shibler {
23759794Shibler REG ADDR a;
23859794Shibler REG BKPTR bkptr;
23959794Shibler IF bpstate!=BPOUT
24059794Shibler THEN
24159794Shibler FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
24259794Shibler DO IF bkptr->flag
24359794Shibler THEN a=bkptr->loc;
24459794Shibler IF a < txtmap.e1 THEN
24559794Shibler ptrace(PT_WRITE_I,pid,a,bkptr->ins);
24659794Shibler ELSE
24759794Shibler ptrace(PT_WRITE_D,pid,a,bkptr->ins);
24859794Shibler FI
24959794Shibler FI
25059794Shibler OD
25159794Shibler bpstate=BPOUT;
25259794Shibler FI
25359794Shibler }
25459794Shibler
25559794Shibler #ifdef pdp11
25659794Shibler help -- I left my architecture manual at home
25759794Shibler #endif
25859794Shibler
25959794Shibler #ifdef vax
26059794Shibler #define SETBP(ins) (BPT | ((ins) &~ 0xFF))
26159794Shibler #endif
26259794Shibler
26359794Shibler #ifdef mc68000
26459794Shibler #define SETBP(ins) ((BPT << 16) | ((ins) & 0xFFFF))
26559794Shibler #endif
26659794Shibler
26759794Shibler #if !pdp11 && !vax && !mc68000
26859794Shibler
269*59805Shibler edit this file to handle your machines breakpoint indication
27059794Shibler
27159794Shibler #endif
27259794Shibler
27359794Shibler setbp()
27459794Shibler {
27559794Shibler REG ADDR a;
27659794Shibler REG BKPTR bkptr;
27759794Shibler
27859794Shibler IF bpstate!=BPIN
27959794Shibler THEN
28059794Shibler FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt
28159794Shibler DO IF bkptr->flag
28259794Shibler THEN a = bkptr->loc;
28359794Shibler IF a < txtmap.e1 THEN
28459794Shibler bkptr->ins = ptrace(PT_READ_I, pid, a, 0);
28559794Shibler ptrace(PT_WRITE_I, pid, a, SETBP(bkptr->ins));
28659794Shibler ELSE
28759794Shibler bkptr->ins = ptrace(PT_READ_D, pid, a, 0);
28859794Shibler ptrace(PT_WRITE_D, pid, a, SETBP(bkptr->ins));
28959794Shibler FI
29059794Shibler IF errno
29159794Shibler THEN prints("cannot set breakpoint: ");
29259794Shibler psymoff(bkptr->loc,ISYM,"\n");
29359794Shibler FI
29459794Shibler FI
29559794Shibler OD
29659794Shibler bpstate=BPIN;
29759794Shibler FI
29859794Shibler }
29959794Shibler
bpwait()30059794Shibler bpwait()
30159794Shibler {
30259794Shibler REG ADDR w;
30359794Shibler union wait stat;
30459794Shibler
30559794Shibler signal(SIGINT, 1);
30659794Shibler WHILE (w = wait(&stat))!=pid ANDF w != -1 DONE
30759794Shibler signal(SIGINT,sigint);
30859794Shibler IF w == -1
30959794Shibler THEN pid=0;
31059794Shibler errflg=BADWAIT;
31159794Shibler ELIF !WIFSTOPPED(stat)
31259794Shibler THEN sigcode = 0;
31359794Shibler IF signo = stat.w_termsig
31459794Shibler THEN sigprint();
31559794Shibler FI
31659794Shibler IF stat.w_coredump
31759794Shibler THEN prints(" - core dumped");
31859794Shibler close(fcor);
31959794Shibler setcor();
32059794Shibler FI
32159794Shibler pid=0;
32259794Shibler errflg=ENDPCS;
32359794Shibler ELSE signo = stat.w_stopsig;
32459794Shibler sigcode = ptrace(PT_READ_U, pid, &((struct user *)0)->u_code, 0);
32559794Shibler IF signo!=SIGTRAP
32659794Shibler THEN sigprint();
32759794Shibler ELSE signo=0;
32859794Shibler FI
32959794Shibler flushbuf();
33059794Shibler FI
33159794Shibler }
33259794Shibler
readregs()33359794Shibler readregs()
33459794Shibler {
33559794Shibler /*get REG values from pcs*/
33659794Shibler REG i;
33759794Shibler L_INT radj = getradj(1);
33859794Shibler L_INT offset;
33959794Shibler
34059794Shibler FOR i=nregs; --i>=0;
34159794Shibler DO IF (offset = reglist[i].roffs) >= sizeof (struct user)
34259794Shibler THEN offset -= radj;
34359794Shibler FI
34459794Shibler *(ADDR *)(((ADDR)&u) + offset) =
34559794Shibler ptrace(PT_READ_U, pid, offset, 0);
34659794Shibler #ifdef hp300
34759794Shibler /* XXX: 68881/68882 FP regs are 3 longwords */
34859794Shibler IF reglist[i].rtype == XPFLOAT
34959794Shibler THEN offset += sizeof (ADDR);
35059794Shibler *(ADDR *)(((ADDR)&u) + offset) =
35159794Shibler ptrace(PT_READ_U, pid, offset, 0);
35259794Shibler offset += sizeof (ADDR);
35359794Shibler *(ADDR *)(((ADDR)&u) + offset) =
35459794Shibler ptrace(PT_READ_U, pid, offset, 0);
35559794Shibler FI
35659794Shibler #endif
35759794Shibler OD
35859794Shibler userpc= *(ADDR *)(((ADDR)&u) + PC - radj);
35959794Shibler }
36059794Shibler
36159794Shibler #ifdef hp300
36259794Shibler L_INT
getradj(running)36359794Shibler getradj(running)
36459794Shibler INT running;
36559794Shibler {
36659794Shibler L_INT radj;
36759794Shibler
36859794Shibler /* this code assumes that u_ap always points to u_arg */
36959794Shibler IF running
37059794Shibler THEN u.u_ar0 = (int *) ptrace(PT_READ_U, pid,
37159794Shibler (ADDR)&u.u_ar0 - (ADDR) &u, 0);
37259794Shibler #if 0
37359794Shibler u.u_ap = (int *) ptrace(PT_READ_U, pid,
37459794Shibler (ADDR)&u.u_ap - (ADDR) &u, 0);
37559794Shibler #endif
37659794Shibler IF u.u_ar0 == -1
37759794Shibler #if 0
37859794Shibler ORF u.u_ap == -1
37959794Shibler #endif
38059794Shibler THEN endpcs();
38159794Shibler error("can't read from running process");
38259794Shibler return (0);
38359794Shibler FI
38459794Shibler FI
38559794Shibler IF !kcore
38659794Shibler THEN
38759794Shibler #if 0
38859794Shibler radj = (ADDR) &u.u_arg - (ADDR) &u; /* offset of u_arg */
38959794Shibler radj = (ADDR) u.u_ap - radj; /* address of u */
39059794Shibler #endif
39159794Shibler radj = (ADDR) 0xfff00000;
39259794Shibler radj = (ADDR) u.u_ar0 - radj; /* offset of d0 */
39359794Shibler radj = D0 - radj; /* difference from expected offset */
39459794Shibler ELSE
39559794Shibler radj = 0;
39659794Shibler FI
39759794Shibler return (radj);
39859794Shibler }
39959794Shibler #endif
400