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