1 /*
2  *
3  *	debugger
4  *
5  */
6 
7 #include "defs.h"
8 #include "fns.h"
9 
10 char	BADEQ[] = "unexpected `='";
11 
12 BOOL	executing;
13 extern	char	*lp;
14 
15 char	eqformat[ARB] = "z";
16 char	stformat[ARB] = "zMi";
17 
18 ADDR	ditto;
19 
20 ADDR	dot;
21 WORD	dotinc;
22 WORD	adrval, cntval, loopcnt;
23 int	adrflg, cntflg;
24 
25 /* command decoding */
26 
27 int
command(char * buf,int defcom)28 command(char *buf, int defcom)
29 {
30 	char	*reg;
31 	char	savc;
32 	char	*savlp=lp;
33 	char	savlc = lastc;
34 	char	savpc = peekc;
35 	static char lastcom = '=', savecom = '=';
36 
37 	if (defcom == 0)
38 		defcom = lastcom;
39 	if (buf) {
40 		if (*buf==EOR)
41 			return(FALSE);
42 		clrinp();
43 		lp=buf;
44 	}
45 	do {
46 		adrflg=expr(0);		/* first address */
47 		if (adrflg){
48 			dot=expv;
49 			ditto=expv;
50 		}
51 		adrval=dot;
52 
53 		if (rdc()==',' && expr(0)) {	/* count */
54 			cntflg=TRUE;
55 			cntval=expv;
56 		} else {
57 			cntflg=FALSE;
58 			cntval=1;
59 			reread();
60 		}
61 
62 		if (!eol(rdc()))
63 			lastcom=lastc;		/* command */
64 		else {
65 			if (adrflg==0)
66 				dot=inkdot(dotinc);
67 			reread();
68 			lastcom=defcom;
69 		}
70 		switch(lastcom) {
71 		case '/':
72 		case '=':
73 		case '?':
74 			savecom = lastcom;
75 			acommand(lastcom);
76 			break;
77 
78 		case '>':
79 			lastcom = savecom;
80 			savc=rdc();
81 			if (reg=regname(savc))
82 				rput(correg, reg, dot);
83 			else
84 				error("bad variable");
85 			break;
86 
87 		case '!':
88 			lastcom=savecom;
89 			shell();
90 			break;
91 
92 		case '$':
93 			lastcom=savecom;
94 			printdollar(nextchar());
95 			break;
96 
97 		case ':':
98 			if (!executing) {
99 				executing=TRUE;
100 				subpcs(nextchar());
101 				executing=FALSE;
102 				lastcom=savecom;
103 			}
104 			break;
105 
106 		case 0:
107 			prints(DBNAME);
108 			break;
109 
110 		default:
111 			error("bad command");
112 		}
113 		flushbuf();
114 	} while (rdc()==';');
115 	if (buf == 0)
116 		reread();
117 	else {
118 		clrinp();
119 		lp=savlp;
120 		lastc = savlc;
121 		peekc = savpc;
122 	}
123 
124 	if(adrflg)
125 		return dot;
126 	return 1;
127 }
128 
129 /*
130  * [/?][wml]
131  */
132 
133 void
acommand(int pc)134 acommand(int pc)
135 {
136 	int eqcom;
137 	Map *map;
138 	char *fmt;
139 	char buf[512];
140 
141 	if (pc == '=') {
142 		eqcom = 1;
143 		fmt = eqformat;
144 		map = dotmap;
145 	} else {
146 		eqcom = 0;
147 		fmt = stformat;
148 		if (pc == '/')
149 			map = cormap;
150 		else
151 			map = symmap;
152 	}
153 	if (!map) {
154 		sprint(buf, "no map for %c", pc);
155 		error(buf);
156 	}
157 
158 	switch (rdc())
159 	{
160 	case 'm':
161 		if (eqcom)
162 			error(BADEQ);
163 		cmdmap(map);
164 		break;
165 
166 	case 'L':
167 	case 'l':
168 		if (eqcom)
169 			error(BADEQ);
170 		cmdsrc(lastc, map);
171 		break;
172 
173 	case 'W':
174 	case 'w':
175 		if (eqcom)
176 			error(BADEQ);
177 		cmdwrite(lastc, map);
178 		break;
179 
180 	default:
181 		reread();
182 		getformat(fmt);
183 		scanform(cntval, !eqcom, fmt, map, eqcom);
184 	}
185 }
186 
187 void
cmdsrc(int c,Map * map)188 cmdsrc(int c, Map *map)
189 {
190 	u32int w;
191 	long locval, locmsk;
192 	ADDR savdot;
193 	ushort sh;
194 	char buf[512];
195 	int ret;
196 
197 	if (c == 'L')
198 		dotinc = 4;
199 	else
200 		dotinc = 2;
201 	savdot=dot;
202 	expr(1);
203 	locval=expv;
204 	if (expr(0))
205 		locmsk=expv;
206 	else
207 		locmsk = ~0;
208 	if (c == 'L')
209 		while ((ret = get4(map, dot, &w)) > 0 &&  (w&locmsk) != locval)
210 			dot = inkdot(dotinc);
211 	else
212 		while ((ret = get2(map, dot, &sh)) > 0 && (sh&locmsk) != locval)
213 			dot = inkdot(dotinc);
214 	if (ret < 0) {
215 		dot=savdot;
216 		error("%r");
217 	}
218 	symoff(buf, 512, dot, CANY);
219 	dprint(buf);
220 }
221 
222 static char badwrite[] = "can't write process memory or text image";
223 
224 void
cmdwrite(int wcom,Map * map)225 cmdwrite(int wcom, Map *map)
226 {
227 	ADDR savdot;
228 	char *format;
229 	int pass;
230 
231 	if (wcom == 'w')
232 		format = "x";
233 	else
234 		format = "X";
235 	expr(1);
236 	pass = 0;
237 	do {
238 		pass++;
239 		savdot=dot;
240 		exform(1, 1, format, map, 0, pass);
241 		dot=savdot;
242 		if (wcom == 'W') {
243 			if (put4(map, dot, expv) <= 0)
244 				error(badwrite);
245 		} else {
246 			if (put2(map, dot, expv) <= 0)
247 				error(badwrite);
248 		}
249 		savdot=dot;
250 		dprint("=%8t");
251 		exform(1, 0, format, map, 0, pass);
252 		newline();
253 	} while (expr(0));
254 	dot=savdot;
255 }
256 
257 /*
258  * collect a register name; return register offset
259  * this is not what i'd call a good division of labour
260  */
261 
262 char *
regname(int regnam)263 regname(int regnam)
264 {
265 	static char buf[64];
266 	char *p;
267 	int c;
268 
269 	p = buf;
270 	*p++ = regnam;
271 	while (isalnum(c = readchar())) {
272 		if (p >= buf+sizeof(buf)-1)
273 			error("register name too long");
274 		*p++ = c;
275 	}
276 	*p = 0;
277 	reread();
278 	return (buf);
279 }
280 
281 /*
282  * shell escape
283  */
284 
285 void
shell(void)286 shell(void)
287 {
288 	int	rc, unixpid;
289 	char *argp = lp;
290 
291 	while (lastc!=EOR)
292 		rdc();
293 	if ((unixpid=fork())==0) {
294 		*lp=0;
295 		execl("/bin/rc", "rc", "-c", argp, 0);
296 		exits("execl");				/* botch */
297 	} else if (unixpid == -1) {
298 		error("cannot fork");
299 	} else {
300 		mkfault = 0;
301 		while ((rc = waitpid()) != unixpid){
302 			if(rc == -1 && mkfault){
303 				mkfault = 0;
304 				continue;
305 			}
306 			break;
307 		}
308 		prints("!");
309 		reread();
310 	}
311 }
312