xref: /csrg-svn/old/adb/adb.hp300/runpcs.c (revision 59805)
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