xref: /plan9/sys/src/cmd/ki/cmd.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1 #include <u.h>
2 #include <libc.h>
3 #include <ctype.h>
4 #include <bio.h>
5 #include <mach.h>
6 #define Extern extern
7 #include "sparc.h"
8 
9 char	buf[128], lastcmd[128];
10 char	fmt = 'X';
11 int	width = 60;
12 int	inc;
13 
14 ulong	expr(char*);
15 ulong	expr1(char*);
16 char*	term(char*, ulong*);
17 
18 char *
nextc(char * p)19 nextc(char *p)
20 {
21 	while(*p && (*p == ' ' || *p == '\t') && *p != '\n')
22 		p++;
23 
24 	if(*p == '\n')
25 		*p = '\0';
26 
27 	return p;
28 }
29 
30 char *
numsym(char * addr,ulong * val)31 numsym(char *addr, ulong *val)
32 {
33 	char tsym[128], *t;
34 	static char *delim = "`'<>/\\@*|-~+-/=?\n";
35 	Symbol s;
36 	char c;
37 
38 	t = tsym;
39 	while(c = *addr) {
40 		if(strchr(delim, c))
41 			break;
42 		*t++ = c;
43 		addr++;
44 	}
45 	t[0] = '\0';
46 
47 	if(strcmp(tsym, ".") == 0) {
48 		*val = dot;
49 		return addr;
50 	}
51 
52 	if(lookup(0, tsym, &s))
53 		*val = s.value;
54 	else {
55 		if(tsym[0] == '#')
56 			*val = strtoul(tsym+1, 0, 16);
57 		else
58 			*val = strtoul(tsym, 0, 0);
59 	}
60 	return addr;
61 }
62 
63 ulong
expr(char * addr)64 expr(char *addr)
65 {
66 	ulong t, t2;
67 	char op;
68 
69 	if(*addr == '\0')
70 		return dot;
71 
72 	addr = numsym(addr, &t);
73 
74 	if(*addr == '\0')
75 		return t;
76 
77 	addr = nextc(addr);
78 	op = *addr++;
79 	numsym(addr, &t2);
80 	switch(op) {
81 	default:
82 		Bprint(bioout, "expr syntax\n");
83 		return 0;
84 	case '+':
85 		t += t2;
86 		break;
87 	case '-':
88 		t -= t2;
89 		break;
90 	case '%':
91 		t /= t2;
92 		break;
93 	case '&':
94 		t &= t2;
95 		break;
96 	case '|':
97 		t |= t2;
98 		break;
99 	}
100 
101 	return t;
102 }
103 
104 int
buildargv(char * str,char ** args,int max)105 buildargv(char *str, char **args, int max)
106 {
107 	int na = 0;
108 
109 	while (na < max) {
110 		while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0')
111 			str++;
112 
113 		if(*str == '\0')
114 			return na;
115 
116 		args[na++] = str;
117 		while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0')
118 			str++;
119 
120 		if(*str == '\n')
121 			*str = '\0';
122 
123 		if(*str == '\0')
124 			break;
125 
126 		*str++ = '\0';
127 	}
128 	return na;
129 }
130 
131 void
colon(char * addr,char * cp)132 colon(char *addr, char *cp)
133 {
134 	int argc;
135 	char *argv[100];
136 	char tbuf[512];
137 
138 	cp = nextc(cp);
139 	switch(*cp) {
140 	default:
141 		Bprint(bioout, "?\n");
142 		return;
143 	case 'b':
144 		breakpoint(addr, cp+1);
145 		return;
146 
147 	case 'd':
148 		delbpt(addr);
149 		return;
150 
151 	/* These fall through to print the stopped address */
152 	case 'r':
153 		reset();
154 		argc = buildargv(cp+1, argv, 100);
155 		initstk(argc, argv);
156 		count = 0;
157 		atbpt = 0;
158 		run();
159 		break;
160 	case 'c':
161 		count = 0;
162 		atbpt = 0;
163 		run();
164 		break;
165 	case 's':
166 		cp = nextc(cp+1);
167 		count = 0;
168 		if(*cp)
169 			count = strtoul(cp, 0, 0);
170 		if(count == 0)
171 			count = 1;
172 		atbpt = 0;
173 		run();
174 		break;
175 	}
176 
177 	dot = reg.pc;
178 	Bprint(bioout, "%s at #%lux ", atbpt ? "breakpoint" : "stopped", dot);
179 	symoff(tbuf, sizeof(tbuf), dot, CTEXT);
180 	Bprint(bioout, tbuf);
181 	if(fmt == 'z')
182 		printsource(dot);
183 
184 	Bprint(bioout, "\n");
185 }
186 
187 
188 void
dollar(char * cp)189 dollar(char *cp)
190 {
191 	cp = nextc(cp);
192 	switch(*cp) {
193 	default:
194 		Bprint(bioout, "?\n");
195 		break;
196 
197 	case 'c':
198 	case 'C':
199 		stktrace(*cp);
200 		break;
201 
202 	case 'b':
203 		dobplist();
204 		break;
205 
206 	case 'r':
207 		dumpreg();
208 		break;
209 
210 	case 'R':
211 		dumpreg();
212 		/* fall through */
213 
214 	case 'f':
215 		dumpfreg();
216 		break;
217 
218 	case 'F':
219 		dumpdreg();
220 		break;
221 
222 	case 'q':
223 		exits(0);
224 		break;
225 
226 	case 'Q':
227 		isum();
228 		segsum();
229 		break;
230 
231 	case 't':
232 		cp++;
233 		switch(*cp) {
234 		default:
235 			Bprint(bioout, ":t[0sic]\n");
236 			break;
237 		case '\0':
238 			trace = 1;
239 			break;
240 		case '0':
241 			trace = 0;
242 			sysdbg = 0;
243 			calltree = 0;
244 			break;
245 		case 's':
246 			sysdbg = 1;
247 			break;
248 		case 'i':
249 			trace = 1;
250 			break;
251 		case 'c':
252 			calltree = 1;
253 			break;
254 		}
255 		break;
256 
257 	case 'i':
258 		cp++;
259 		switch(*cp) {
260 		default:
261 			Bprint(bioout, "$i[isa]\n");
262 			break;
263 		case 'i':
264 			isum();
265 			break;
266 		case 's':
267 			segsum();
268 			break;
269 		case 'a':
270 			isum();
271 			segsum();
272 			iprofile();
273 			break;
274 		case 'p':
275 			iprofile();
276 			break;
277 		}
278 	}
279 }
280 
281 int
pfmt(char fmt,int mem,ulong val)282 pfmt(char fmt, int mem, ulong val)
283 {
284 	int c, i;
285 	Symbol s;
286 	char *p, ch, str[1024];
287 
288 	c = 0;
289 	switch(fmt) {
290 	default:
291 		Bprint(bioout, "bad modifier\n");
292 		return 0;
293 	case 'o':
294 		c = Bprint(bioout, "%-4lo ", mem ? (ushort)getmem_2(dot) : val);
295 		inc = 2;
296 		break;
297 
298 	case 'O':
299 		c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val);
300 		inc = 4;
301 		break;
302 
303 	case 'q':
304 		c = Bprint(bioout, "%-4lo ", mem ? (short)getmem_2(dot) : val);
305 		inc = 2;
306 		break;
307 
308 	case 'Q':
309 		c = Bprint(bioout, "%-8lo ", mem ? (long)getmem_4(dot) : val);
310 		inc = 4;
311 		break;
312 
313 	case 'd':
314 		c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val);
315 		inc = 2;
316 		break;
317 
318 
319 	case 'D':
320 		c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val);
321 		inc = 4;
322 		break;
323 
324 	case 'x':
325 		c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val);
326 		inc = 2;
327 		break;
328 
329 	case 'X':
330 		c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val);
331 		inc = 4;
332 		break;
333 
334 	case 'u':
335 		c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val);
336 		inc = 2;
337 		break;
338 
339 	case 'U':
340 		c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val);
341 		inc = 4;
342 		break;
343 
344 	case 'b':
345 		c = Bprint(bioout, "%-3d ", (int)(mem ? getmem_b(dot) : val));
346 		inc = 1;
347 		break;
348 
349 	case 'c':
350 		c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val));
351 		inc = 1;
352 		break;
353 
354 	case 'C':
355 		ch = mem ? getmem_b(dot) : val;
356 		if(isprint(ch))
357 			c = Bprint(bioout, "%c ", ch);
358 		else
359 			c = Bprint(bioout, "\\x%.2x ", ch);
360 		inc = 1;
361 		break;
362 
363 	case 's':
364 		i = 0;
365 		while(ch = getmem_b(dot+i))
366 			str[i++] = ch;
367 		str[i] = '\0';
368 		dot += i;
369 		c = Bprint(bioout, "%s", str);
370 		inc = 0;
371 		break;
372 
373 	case 'S':
374 		i = 0;
375 		while(ch = getmem_b(dot+i))
376 			str[i++] = ch;
377 		str[i] = '\0';
378 		dot += i;
379 		for(p = str; *p; p++)
380 			if(isprint(*p))
381 				c += Bprint(bioout, "%c", *p);
382 			else
383 				c += Bprint(bioout, "\\x%.2ux", *p);
384 		inc = 0;
385 		break;
386 
387 	case 'Y':
388 		p = ctime(mem ? getmem_b(dot) : val);
389 		p[30] = '\0';
390 		c = Bprint(bioout, "%s", p);
391 		inc = 4;
392 		break;
393 
394 	case 'a':
395 		symoff(str, sizeof(str), dot, CTEXT);
396 		Bprint(bioout, "%s", str);
397 		inc = 0;
398 		break;
399 
400 	case 'e':
401 		for (i = 0; globalsym(&s, i); i++)
402 			Bprint(bioout, "%-15s #%lux\n", s.name,	getmem_4(s.value));
403 		inc = 0;
404 		break;
405 
406 	case 'I':
407 	case 'i':
408 		inc = machdata->das(symmap, dot, fmt, str, sizeof(str));
409 		if (inc < 0) {
410 			Bprint(bioout, "ki: %r\n");
411 			return 0;
412 		}
413 		c = Bprint(bioout, "\t%s", str);
414 		break;
415 
416 	case 'n':
417 		c = width+1;
418 		inc = 0;
419 		break;
420 
421 	case '-':
422 		c = 0;
423 		inc = -1;
424 		break;
425 
426 	case '+':
427 		c = 0;
428 		inc = 1;
429 		break;
430 
431 	case '^':
432 		c = 0;
433 		if(inc > 0)
434 			inc = -inc;
435 		break;
436 
437 	case 'z':
438 		if (findsym(dot, CTEXT, &s))
439 			Bprint(bioout, "  %s() ", s.name);
440 		printsource(dot);
441 		inc = 0;
442 		break;
443 	}
444 	return c;
445 }
446 
447 void
eval(char * addr,char * p)448 eval(char *addr, char *p)
449 {
450 	ulong val;
451 
452 	val = expr(addr);
453 	p = nextc(p);
454 	if(*p == '\0') {
455 		p[0] = fmt;
456 		p[1] = '\0';
457 	}
458 	pfmt(*p, 0, val);
459 	Bprint(bioout, "\n");
460 }
461 
462 void
quesie(char * p)463 quesie(char *p)
464 {
465 	int c, count, i;
466 	char tbuf[512];
467 
468 	c = 0;
469 	symoff(tbuf, sizeof(tbuf), dot, CTEXT);
470 	Bprint(bioout, "%s?\t", tbuf);
471 
472 	while(*p) {
473 		p = nextc(p);
474 		if(*p == '"') {
475 			for(p++; *p && *p != '"'; p++) {
476 				Bputc(bioout, *p);
477 				c++;
478 			}
479 			if(*p)
480 				p++;
481 			continue;
482 		}
483 		count = 0;
484 		while(*p >= '0' && *p <= '9')
485 			count = count*10 + (*p++ - '0');
486 		if(count == 0)
487 			count = 1;
488 		p = nextc(p);
489 		if(*p == '\0') {
490 			p[0] = fmt;
491 			p[1] = '\0';
492 		}
493 		for(i = 0; i < count; i++) {
494 			c += pfmt(*p, 1, 0);
495 			dot += inc;
496 			if(c > width) {
497 				Bprint(bioout, "\n");
498 				symoff(tbuf, sizeof(tbuf), dot, CTEXT);
499 				Bprint(bioout, "%s?\t", tbuf);
500 				c = 0;
501 			}
502 		}
503 		fmt = *p++;
504 		p = nextc(p);
505 	}
506 	Bprint(bioout, "\n");
507 }
508 
509 void
catcher(void * a,char * msg)510 catcher(void *a, char *msg)
511 {
512 	USED(a);
513 	if(strcmp(msg, "interrupt") != 0)
514 		noted(NDFLT);
515 
516 	count = 1;
517 	print("ki\n");
518 	noted(NCONT);
519 }
520 
521 void
setreg(char * addr,char * cp)522 setreg(char *addr, char *cp)
523 {
524 	int rn;
525 
526 	dot = expr(addr);
527 	cp = nextc(cp);
528 	if(strcmp(cp, "pc") == 0) {
529 		reg.pc = dot;
530 		return;
531 	}
532 	if(strcmp(cp, "sp") == 0) {
533 		reg.r[1] = dot;
534 		return;
535 	}
536 	if(strcmp(cp, "y") == 0) {
537 		reg.Y = dot;
538 		return;
539 	}
540 	if(strcmp(cp, "psr") == 0) {
541 		reg.psr = dot;
542 		return;
543 	}
544 	if(*cp++ == 'r') {
545 		rn = strtoul(cp, 0, 10);
546 		if(rn > 0 && rn < 32) {
547 			reg.r[rn] = dot;
548 			return;
549 		}
550 	}
551 	Bprint(bioout, "bad register\n");
552 }
553 
554 void
cmd(void)555 cmd(void)
556 {
557 	char *p, *a, *cp, *gotint;
558 	char addr[128];
559 	static char *cmdlet = ":$?/=>";
560 	int n, i;
561 
562 	notify(catcher);
563 
564 	dot = reg.pc;
565 	setjmp(errjmp);
566 
567 	for(;;) {
568 		Bflush(bioout);
569 		p = buf;
570 		n = 0;
571 		for(;;) {
572 			i = Bgetc(bin);
573 			if(i < 0)
574 				exits(0);
575 			*p++ = i;
576 			n++;
577 			if(i == '\n')
578 				break;
579 		}
580 
581 		if(buf[0] == '\n')
582 			strcpy(buf, lastcmd);
583 		else {
584 			buf[n-1] = '\0';
585 			strcpy(lastcmd, buf);
586 		}
587 		p = buf;
588 		a = addr;
589 
590 		for(;;) {
591 			p = nextc(p);
592 			if(*p == 0 || strchr(cmdlet, *p))
593 				break;
594 			*a++ = *p++;
595 		}
596 
597 		*a = '\0';
598 		cmdcount = 1;
599 		cp = strchr(addr, ',');
600 		if(cp != 0) {
601 			if(cp[1] == '#')
602 				cmdcount = strtoul(cp+2, &gotint, 16);
603 			else
604 				cmdcount = strtoul(cp+1, &gotint, 0);
605 			*cp = '\0';
606 		}
607 
608 		switch(*p) {
609 		case '$':
610 			dollar(p+1);
611 			break;
612 		case ':':
613 			colon(addr, p+1);
614 			break;
615 		case '/':
616 		case '?':
617 			dot = expr(addr);
618 			for(i = 0; i < cmdcount; i++)
619 				quesie(p+1);
620 			break;
621 		case '=':
622 			eval(addr, p+1);
623 			break;
624 		case '>':
625 			setreg(addr, p+1);
626 			break;
627 		default:
628 			Bprint(bioout, "?\n");
629 			break;
630 		}
631 	}
632 }
633