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