xref: /plan9/sys/src/cmd/db/trcrun.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * functions for running the debugged process
33e12c5d1SDavid du Colombier  */
43e12c5d1SDavid du Colombier 
53e12c5d1SDavid du Colombier #include "defs.h"
63e12c5d1SDavid du Colombier #include "fns.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier int child;
103e12c5d1SDavid du Colombier int msgfd = -1;
113e12c5d1SDavid du Colombier int notefd = -1;
123e12c5d1SDavid du Colombier int pcspid = -1;
133e12c5d1SDavid du Colombier int pcsactive = 0;
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier void
setpcs(void)163e12c5d1SDavid du Colombier setpcs(void)
173e12c5d1SDavid du Colombier {
183e12c5d1SDavid du Colombier 	char buf[128];
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier 	if(pid && pid != pcspid){
213e12c5d1SDavid du Colombier 		if(msgfd >= 0){
223e12c5d1SDavid du Colombier 			close(msgfd);
233e12c5d1SDavid du Colombier 			msgfd = -1;
243e12c5d1SDavid du Colombier 		}
253e12c5d1SDavid du Colombier 		if(notefd >= 0){
263e12c5d1SDavid du Colombier 			close(notefd);
273e12c5d1SDavid du Colombier 			notefd = -1;
283e12c5d1SDavid du Colombier 		}
293e12c5d1SDavid du Colombier 		pcspid = -1;
303e12c5d1SDavid du Colombier 		sprint(buf, "/proc/%d/ctl", pid);
313e12c5d1SDavid du Colombier 		msgfd = open(buf, OWRITE);
323e12c5d1SDavid du Colombier 		if(msgfd < 0)
333e12c5d1SDavid du Colombier 			error("can't open control file");
343e12c5d1SDavid du Colombier 		sprint(buf, "/proc/%d/note", pid);
353e12c5d1SDavid du Colombier 		notefd = open(buf, ORDWR);
363e12c5d1SDavid du Colombier 		if(notefd < 0)
373e12c5d1SDavid du Colombier 			error("can't open note file");
383e12c5d1SDavid du Colombier 		pcspid = pid;
393e12c5d1SDavid du Colombier 	}
403e12c5d1SDavid du Colombier }
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier void
msgpcs(char * msg)433e12c5d1SDavid du Colombier msgpcs(char *msg)
443e12c5d1SDavid du Colombier {
459a747e4fSDavid du Colombier 	char err[ERRMAX];
463e12c5d1SDavid du Colombier 
473e12c5d1SDavid du Colombier 	setpcs();
483e12c5d1SDavid du Colombier 	if(write(msgfd, msg, strlen(msg)) < 0 && !ending){
499a747e4fSDavid du Colombier 		errstr(err, sizeof err);
503e12c5d1SDavid du Colombier 		if(strcmp(err, "interrupted") != 0)
513e12c5d1SDavid du Colombier 			endpcs();
523e12c5d1SDavid du Colombier 		errors("can't write control file", err);
533e12c5d1SDavid du Colombier 	}
543e12c5d1SDavid du Colombier }
553e12c5d1SDavid du Colombier 
563e12c5d1SDavid du Colombier /*
573e12c5d1SDavid du Colombier  * empty the note buffer and toss pending breakpoint notes
583e12c5d1SDavid du Colombier  */
593e12c5d1SDavid du Colombier void
unloadnote(void)603e12c5d1SDavid du Colombier unloadnote(void)
613e12c5d1SDavid du Colombier {
629a747e4fSDavid du Colombier 	char err[ERRMAX];
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier 	setpcs();
653e12c5d1SDavid du Colombier 	for(; nnote<NNOTE; nnote++){
669a747e4fSDavid du Colombier 		switch(read(notefd, note[nnote], sizeof note[nnote])){
673e12c5d1SDavid du Colombier 		case -1:
689a747e4fSDavid du Colombier 			errstr(err, sizeof err);
693e12c5d1SDavid du Colombier 			if(strcmp(err, "interrupted") != 0)
703e12c5d1SDavid du Colombier 				endpcs();
713e12c5d1SDavid du Colombier 			errors("can't read note file", err);
723e12c5d1SDavid du Colombier 		case 0:
733e12c5d1SDavid du Colombier 			return;
743e12c5d1SDavid du Colombier 		}
759a747e4fSDavid du Colombier 		note[nnote][ERRMAX-1] = '\0';
763e12c5d1SDavid du Colombier 		if(strncmp(note[nnote], "sys: breakpoint", 15) == 0)
773e12c5d1SDavid du Colombier 			--nnote;
783e12c5d1SDavid du Colombier 	}
793e12c5d1SDavid du Colombier }
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier /*
823e12c5d1SDavid du Colombier  * reload the note buffer
833e12c5d1SDavid du Colombier  */
843e12c5d1SDavid du Colombier void
loadnote(void)853e12c5d1SDavid du Colombier loadnote(void)
863e12c5d1SDavid du Colombier {
873e12c5d1SDavid du Colombier 	int i;
889a747e4fSDavid du Colombier 	char err[ERRMAX];
893e12c5d1SDavid du Colombier 
903e12c5d1SDavid du Colombier 	setpcs();
913e12c5d1SDavid du Colombier 	for(i=0; i<nnote; i++){
923e12c5d1SDavid du Colombier 		if(write(notefd, note[i], strlen(note[i])) < 0){
939a747e4fSDavid du Colombier 			errstr(err, sizeof err);
943e12c5d1SDavid du Colombier 			if(strcmp(err, "interrupted") != 0)
953e12c5d1SDavid du Colombier 				endpcs();
963e12c5d1SDavid du Colombier 			errors("can't write note file", err);
973e12c5d1SDavid du Colombier 		}
983e12c5d1SDavid du Colombier 	}
993e12c5d1SDavid du Colombier 	nnote = 0;
1003e12c5d1SDavid du Colombier }
1013e12c5d1SDavid du Colombier 
1023e12c5d1SDavid du Colombier void
notes(void)1033e12c5d1SDavid du Colombier notes(void)
1043e12c5d1SDavid du Colombier {
1053e12c5d1SDavid du Colombier 	int n;
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier 	if(nnote == 0)
1083e12c5d1SDavid du Colombier 		return;
1093e12c5d1SDavid du Colombier 	dprint("notes:\n");
1103e12c5d1SDavid du Colombier 	for(n=0; n<nnote; n++)
1113e12c5d1SDavid du Colombier 		dprint("%d:\t%s\n", n, note[n]);
1123e12c5d1SDavid du Colombier }
1133e12c5d1SDavid du Colombier 
1143e12c5d1SDavid du Colombier void
killpcs(void)1153e12c5d1SDavid du Colombier killpcs(void)
1163e12c5d1SDavid du Colombier {
1173e12c5d1SDavid du Colombier 	msgpcs("kill");
1183e12c5d1SDavid du Colombier }
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier void
grab(void)1213e12c5d1SDavid du Colombier grab(void)
1223e12c5d1SDavid du Colombier {
1233e12c5d1SDavid du Colombier 	flush();
1243e12c5d1SDavid du Colombier 	msgpcs("stop");
1253e12c5d1SDavid du Colombier 	bpwait();
1263e12c5d1SDavid du Colombier }
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier void
ungrab(void)1293e12c5d1SDavid du Colombier ungrab(void)
1303e12c5d1SDavid du Colombier {
1313e12c5d1SDavid du Colombier 	msgpcs("start");
1323e12c5d1SDavid du Colombier }
1333e12c5d1SDavid du Colombier 
1343e12c5d1SDavid du Colombier void
doexec(void)1353e12c5d1SDavid du Colombier doexec(void)
1363e12c5d1SDavid du Colombier {
1373e12c5d1SDavid du Colombier 	char *argl[MAXARG];
1383e12c5d1SDavid du Colombier 	char args[LINSIZ];
1393e12c5d1SDavid du Colombier 	char *p;
1403e12c5d1SDavid du Colombier 	char **ap;
1413e12c5d1SDavid du Colombier 	char *thisarg;
1423e12c5d1SDavid du Colombier 
1433e12c5d1SDavid du Colombier 	ap = argl;
1443e12c5d1SDavid du Colombier 	p = args;
1453e12c5d1SDavid du Colombier 	*ap++ = symfil;
1463e12c5d1SDavid du Colombier 	for (rdc(); lastc != EOR;) {
1473e12c5d1SDavid du Colombier 		thisarg = p;
1483e12c5d1SDavid du Colombier 		if (lastc == '<' || lastc == '>') {
1493e12c5d1SDavid du Colombier 			*p++ = lastc;
1503e12c5d1SDavid du Colombier 			rdc();
1513e12c5d1SDavid du Colombier 		}
1523e12c5d1SDavid du Colombier 		while (lastc != EOR && lastc != SPC && lastc != TB) {
1533e12c5d1SDavid du Colombier 			*p++ = lastc;
1543e12c5d1SDavid du Colombier 			readchar();
1553e12c5d1SDavid du Colombier 		}
1563e12c5d1SDavid du Colombier 		if (lastc == SPC || lastc == TB)
1573e12c5d1SDavid du Colombier 			rdc();
1583e12c5d1SDavid du Colombier 		*p++ = 0;
1593e12c5d1SDavid du Colombier 		if (*thisarg == '<') {
1603e12c5d1SDavid du Colombier 			close(0);
1613e12c5d1SDavid du Colombier 			if (open(&thisarg[1], OREAD) < 0) {
1623e12c5d1SDavid du Colombier 				print("%s: cannot open\n", &thisarg[1]);
1633e12c5d1SDavid du Colombier 				_exits(0);
1643e12c5d1SDavid du Colombier 			}
1653e12c5d1SDavid du Colombier 		}
1663e12c5d1SDavid du Colombier 		else if (*thisarg == '>') {
1673e12c5d1SDavid du Colombier 			close(1);
1683e12c5d1SDavid du Colombier 			if (create(&thisarg[1], OWRITE, 0666) < 0) {
1693e12c5d1SDavid du Colombier 				print("%s: cannot create\n", &thisarg[1]);
1703e12c5d1SDavid du Colombier 				_exits(0);
1713e12c5d1SDavid du Colombier 			}
1723e12c5d1SDavid du Colombier 		}
1733e12c5d1SDavid du Colombier 		else
1743e12c5d1SDavid du Colombier 			*ap++ = thisarg;
1753e12c5d1SDavid du Colombier 	}
1763e12c5d1SDavid du Colombier 	*ap = 0;
1773e12c5d1SDavid du Colombier 	exec(symfil, argl);
1783e12c5d1SDavid du Colombier 	perror(symfil);
1793e12c5d1SDavid du Colombier }
1803e12c5d1SDavid du Colombier 
1813e12c5d1SDavid du Colombier char	procname[100];
1823e12c5d1SDavid du Colombier 
1833e12c5d1SDavid du Colombier void
startpcs(void)1843e12c5d1SDavid du Colombier startpcs(void)
1853e12c5d1SDavid du Colombier {
1863e12c5d1SDavid du Colombier 	if ((pid = fork()) == 0) {
1873e12c5d1SDavid du Colombier 		pid = getpid();
1883e12c5d1SDavid du Colombier 		msgpcs("hang");
1893e12c5d1SDavid du Colombier 		doexec();
1903e12c5d1SDavid du Colombier 		exits(0);
1913e12c5d1SDavid du Colombier 	}
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier 	if (pid == -1)
1943e12c5d1SDavid du Colombier 		error("can't fork");
1953e12c5d1SDavid du Colombier 	child++;
1963e12c5d1SDavid du Colombier 	sprint(procname, "/proc/%d/mem", pid);
1973e12c5d1SDavid du Colombier 	corfil = procname;
1983e12c5d1SDavid du Colombier 	msgpcs("waitstop");
1993e12c5d1SDavid du Colombier 	bpwait();
2003e12c5d1SDavid du Colombier 	if (adrflg)
201219b2ee8SDavid du Colombier 		rput(cormap, mach->pc, adrval);
2023e12c5d1SDavid du Colombier 	while (rdc() != EOR)
2033e12c5d1SDavid du Colombier 		;
2043e12c5d1SDavid du Colombier 	reread();
2053e12c5d1SDavid du Colombier }
2063e12c5d1SDavid du Colombier 
2073e12c5d1SDavid du Colombier void
runstep(uvlong loc,int keepnote)208*4de34a7eSDavid du Colombier runstep(uvlong loc, int keepnote)
2093e12c5d1SDavid du Colombier {
2103e12c5d1SDavid du Colombier 	int nfoll;
211*4de34a7eSDavid du Colombier 	uvlong foll[3];
2123e12c5d1SDavid du Colombier 	BKPT bkpt[3];
2133e12c5d1SDavid du Colombier 	int i;
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier 	if(machdata->foll == 0){
2163e12c5d1SDavid du Colombier 		dprint("stepping unimplemented; assuming not a branch\n");
2173e12c5d1SDavid du Colombier 		nfoll = 1;
2183e12c5d1SDavid du Colombier 		foll[0] = loc+mach->pcquant;
219219b2ee8SDavid du Colombier 	}else {
220219b2ee8SDavid du Colombier 		nfoll = machdata->foll(cormap, loc, rget, foll);
221219b2ee8SDavid du Colombier 		if (nfoll < 0)
222219b2ee8SDavid du Colombier 			error("%r");
223219b2ee8SDavid du Colombier 	}
2243e12c5d1SDavid du Colombier 	memset(bkpt, 0, sizeof bkpt);
2253e12c5d1SDavid du Colombier 	for(i=0; i<nfoll; i++){
2263e12c5d1SDavid du Colombier 		if(foll[i] == loc)
2273e12c5d1SDavid du Colombier 			error("can't single step: next instruction is dot");
2283e12c5d1SDavid du Colombier 		bkpt[i].loc = foll[i];
2293e12c5d1SDavid du Colombier 		bkput(&bkpt[i], 1);
2303e12c5d1SDavid du Colombier 	}
2313e12c5d1SDavid du Colombier 	runrun(keepnote);
2323e12c5d1SDavid du Colombier 	for(i=0; i<nfoll; i++)
2333e12c5d1SDavid du Colombier 		bkput(&bkpt[i], 0);
2343e12c5d1SDavid du Colombier }
2353e12c5d1SDavid du Colombier 
2363e12c5d1SDavid du Colombier void
bpwait(void)2373e12c5d1SDavid du Colombier bpwait(void)
2383e12c5d1SDavid du Colombier {
239219b2ee8SDavid du Colombier 	setcor();
2403e12c5d1SDavid du Colombier 	unloadnote();
2413e12c5d1SDavid du Colombier }
2423e12c5d1SDavid du Colombier 
2433e12c5d1SDavid du Colombier void
runrun(int keepnote)2443e12c5d1SDavid du Colombier runrun(int keepnote)
2453e12c5d1SDavid du Colombier {
2463e12c5d1SDavid du Colombier 	int on;
2473e12c5d1SDavid du Colombier 
2483e12c5d1SDavid du Colombier 	on = nnote;
2493e12c5d1SDavid du Colombier 	unloadnote();
2503e12c5d1SDavid du Colombier 	if(on != nnote){
2513e12c5d1SDavid du Colombier 		notes();
2523e12c5d1SDavid du Colombier 		error("not running: new notes pending");
2533e12c5d1SDavid du Colombier 	}
2543e12c5d1SDavid du Colombier 	if(keepnote)
2553e12c5d1SDavid du Colombier 		loadnote();
2563e12c5d1SDavid du Colombier 	else
2573e12c5d1SDavid du Colombier 		nnote = 0;
2583e12c5d1SDavid du Colombier 	flush();
2593e12c5d1SDavid du Colombier 	msgpcs("startstop");
2603e12c5d1SDavid du Colombier 	bpwait();
2613e12c5d1SDavid du Colombier }
2623e12c5d1SDavid du Colombier 
2633e12c5d1SDavid du Colombier void
bkput(BKPT * bp,int install)2643e12c5d1SDavid du Colombier bkput(BKPT *bp, int install)
2653e12c5d1SDavid du Colombier {
2663e12c5d1SDavid du Colombier 	char buf[256];
267*4de34a7eSDavid du Colombier 	ADDR loc;
268219b2ee8SDavid du Colombier 	int ret;
2693e12c5d1SDavid du Colombier 
2709a747e4fSDavid du Colombier 	errstr(buf, sizeof buf);
2713e12c5d1SDavid du Colombier 	if(machdata->bpfix)
2723e12c5d1SDavid du Colombier 		loc = (*machdata->bpfix)(bp->loc);
2733e12c5d1SDavid du Colombier 	else
2743e12c5d1SDavid du Colombier 		loc = bp->loc;
2753e12c5d1SDavid du Colombier 	if(install){
276219b2ee8SDavid du Colombier 		ret = get1(cormap, loc, bp->save, machdata->bpsize);
277219b2ee8SDavid du Colombier 		if (ret > 0)
278219b2ee8SDavid du Colombier 			ret = put1(cormap, loc, machdata->bpinst, machdata->bpsize);
2793e12c5d1SDavid du Colombier 	}else
280219b2ee8SDavid du Colombier 		ret = put1(cormap, loc, bp->save, machdata->bpsize);
281219b2ee8SDavid du Colombier 	if(ret < 0){
2829a747e4fSDavid du Colombier 		sprint(buf, "can't set breakpoint at %#llux: %r", bp->loc);
2833e12c5d1SDavid du Colombier 		print(buf);
2843e12c5d1SDavid du Colombier 		read(0, buf, 100);
2853e12c5d1SDavid du Colombier 	}
2863e12c5d1SDavid du Colombier }
287