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