1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #include <tos.h>
6 #define Extern
7 #include "mips.h"
8
9 char *file = "v.out";
10 int datasize;
11 ulong textbase;
12 Biobuf bp, bi;
13 Fhdr fhdr;
14
15 void
main(int argc,char ** argv)16 main(int argc, char **argv)
17 {
18 int pid;
19
20 argc--;
21 argv++;
22
23 bioout = &bp;
24 bin = &bi;
25 Binit(bioout, 1, OWRITE);
26 Binit(bin, 0, OREAD);
27
28 tlb.on = 1;
29 tlb.tlbsize = 24;
30
31 if(argc) {
32 pid = atoi(argv[0]);
33 if(pid != 0) {
34 procinit(pid);
35 cmd();
36 }
37 file = argv[0];
38 }
39 argc--;
40 argv++;
41
42 text = open(file, OREAD);
43 if(text < 0)
44 fatal(1, "open text '%s'", file);
45
46 Bprint(bioout, "vi\n");
47 inithdr(text);
48 initstk(argc, argv);
49
50 reg.fd[dreg(24)] = 0.0; /* Normally initialised by the kernel */
51 reg.ft[24] = FPd;
52 reg.fd[dreg(26)] = 0.5;
53 reg.ft[26] = FPd;
54 reg.fd[dreg(28)] = 1.0;
55 reg.ft[28] = FPd;
56 reg.fd[dreg(30)] = 2.0;
57 reg.ft[30] = FPd;
58 cmd();
59 }
60
61 void
initmap()62 initmap()
63 {
64 ulong t, d, b, bssend;
65 Segment *s;
66
67 t = (fhdr.txtaddr+fhdr.txtsz+(BY2PG-1)) & ~(BY2PG-1);
68 d = (t + fhdr.datsz + (BY2PG-1)) & ~(BY2PG-1);
69 bssend = t + fhdr.datsz + fhdr.bsssz;
70 b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
71
72 s = &memory.seg[Text];
73 s->type = Text;
74 s->base = fhdr.txtaddr - fhdr.hdrsz;
75 s->end = t;
76 s->fileoff = fhdr.txtoff - fhdr.hdrsz;
77 s->fileend = s->fileoff + fhdr.txtsz;
78 s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
79
80 iprof = emalloc(((s->end-s->base)/PROFGRAN)*sizeof(long));
81 textbase = s->base;
82
83 s = &memory.seg[Data];
84 s->type = Data;
85 s->base = t;
86 s->end = t+(d-t);
87 s->fileoff = fhdr.datoff;
88 s->fileend = s->fileoff + fhdr.datsz;
89 datasize = fhdr.datsz;
90 s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
91
92 s = &memory.seg[Bss];
93 s->type = Bss;
94 s->base = d;
95 s->end = d+(b-d);
96 s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
97
98 s = &memory.seg[Stack];
99 s->type = Stack;
100 s->base = STACKTOP-STACKSIZE;
101 s->end = STACKTOP;
102 s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
103
104 reg.pc = fhdr.entry;
105 }
106
107 void
inithdr(int fd)108 inithdr(int fd)
109 {
110 Symbol s;
111
112 extern Machdata mipsmach;
113
114 seek(fd, 0, 0);
115 if (!crackhdr(fd, &fhdr))
116 fatal(0, "read text header");
117
118 if(fhdr.type != FMIPS && fhdr.type != FMIPS2BE)
119 fatal(0, "bad magic number: %d %d", fhdr.type, FMIPS);
120
121 if (syminit(fd, &fhdr) < 0)
122 fatal(0, "%r\n");
123
124 symmap = loadmap(symmap, fd, &fhdr);
125 if (mach->sbreg && lookup(0, mach->sbreg, &s))
126 mach->sb = s.value;
127 machdata = &mipsmach;
128 }
129
130 ulong
greg(int f,ulong off)131 greg(int f, ulong off)
132 {
133 int n;
134 ulong l;
135 uchar wd[BY2WD];
136
137 seek(f, off, 0);
138 n = read(f, wd, BY2WD);
139 if(n != BY2WD)
140 fatal(1, "read register");
141
142 l = wd[0]<<24;
143 l |= wd[1]<<16;
144 l |= wd[2]<<8;
145 l |= wd[3];
146 return l;
147 }
148
149 ulong
150 roff[] = {
151 REGOFF(r1), REGOFF(r2), REGOFF(r3),
152 REGOFF(r4), REGOFF(r5), REGOFF(r6),
153 REGOFF(r7), REGOFF(r8), REGOFF(r9),
154 REGOFF(r10), REGOFF(r11), REGOFF(r12),
155 REGOFF(r13), REGOFF(r14), REGOFF(r15),
156 REGOFF(r16), REGOFF(r17), REGOFF(r18),
157 REGOFF(r19), REGOFF(r20), REGOFF(r21),
158 REGOFF(r22), REGOFF(r23), REGOFF(r24),
159 REGOFF(r25), REGOFF(r26), REGOFF(r27),
160 REGOFF(r28)
161 };
162
163 void
seginit(int fd,Segment * s,int idx,ulong vastart,ulong vaend)164 seginit(int fd, Segment *s, int idx, ulong vastart, ulong vaend)
165 {
166 int n;
167
168 while(vastart < vaend) {
169 seek(fd, vastart, 0);
170 s->table[idx] = emalloc(BY2PG);
171 n = read(fd, s->table[idx], BY2PG);
172 if(n != BY2PG)
173 fatal(1, "data read");
174 vastart += BY2PG;
175 idx++;
176 }
177 }
178
179 void
procinit(int pid)180 procinit(int pid)
181 {
182 char *p;
183 Segment *s;
184 int n, m, sg, i;
185 ulong vastart, vaend;
186 char mfile[128], tfile[128], sfile[1024];
187
188 sprint(mfile, "/proc/%d/mem", pid);
189 sprint(tfile, "/proc/%d/text", pid);
190 sprint(sfile, "/proc/%d/segment", pid);
191
192 text = open(tfile, OREAD);
193 if(text < 0)
194 fatal(1, "open text %s", tfile);
195 inithdr(text);
196
197 sg = open(sfile, OREAD);
198 if(sg < 0)
199 fatal(1, "open text %s", sfile);
200
201 n = read(sg, sfile, sizeof(sfile));
202 if(n >= sizeof(sfile))
203 fatal(0, "segment file buffer too small");
204 close(sg);
205
206 m = open(mfile, OREAD);
207 if(m < 0)
208 fatal(1, "open %s", mfile);
209
210 initmap();
211 p = strstr(sfile, "Data");
212 if(p == 0)
213 fatal(0, "no data");
214
215 vastart = strtoul(p+9, 0, 16);
216 vaend = strtoul(p+18, 0, 16);
217 s = &memory.seg[Data];
218 if(s->base != vastart || s->end != vaend) {
219 s->base = vastart;
220 s->end = vaend;
221 free(s->table);
222 s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
223 }
224 seginit(m, s, 0, vastart, vaend);
225
226 p = strstr(sfile, "Bss");
227 if(p == 0)
228 fatal(0, "no bss");
229
230 vastart = strtoul(p+9, 0, 16);
231 vaend = strtoul(p+18, 0, 16);
232 s = &memory.seg[Bss];
233 if(s->base != vastart || s->end != vaend) {
234 s->base = vastart;
235 s->end = vaend;
236 free(s->table);
237 s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
238 }
239 seginit(m, s, 0, vastart, vaend);
240
241 reg.pc = greg(m, REGOFF(pc));
242 reg.r[29] = greg(m, REGOFF(sp));
243 reg.r[30] = greg(m, REGOFF(r30));
244 reg.r[31] = greg(m, REGOFF(r31));
245
246 reg.mhi = greg(m, REGOFF(hi));
247 reg.mlo = greg(m, REGOFF(lo));
248
249 for(i = 1; i < 29; i++)
250 reg.r[i] = greg(m, roff[i-1]);
251
252 s = &memory.seg[Stack];
253 vastart = reg.r[29] & ~(BY2PG-1);
254 seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP);
255 close(m);
256 Bprint(bioout, "vi\n");
257 }
258
259 void
reset(void)260 reset(void)
261 {
262 int i, l, m;
263 Segment *s;
264 Breakpoint *b;
265
266 memset(®, 0, sizeof(Registers));
267 reg.fd[dreg(24)] = 0.0; /* Normally initialised by the kernel */
268 reg.ft[24] = FPd;
269 reg.fd[dreg(26)] = 0.5;
270 reg.ft[26] = FPd;
271 reg.fd[dreg(28)] = 1.0;
272 reg.ft[28] = FPd;
273 reg.fd[dreg(30)] = 2.0;
274 reg.ft[30] = FPd;
275
276 for(i = 0; i > Nseg; i++) {
277 s = &memory.seg[i];
278 l = ((s->end-s->base)/BY2PG)*sizeof(uchar*);
279 for(m = 0; m < l; m++)
280 if(s->table[m])
281 free(s->table[m]);
282 free(s->table);
283 }
284 free(iprof);
285 memset(&memory, 0, sizeof(memory));
286
287 for(b = bplist; b; b = b->next)
288 b->done = b->count;
289 }
290
291 void
initstk(int argc,char * argv[])292 initstk(int argc, char *argv[])
293 {
294 ulong size;
295 ulong sp, ap, tos;
296 int i;
297 char *p;
298
299 initmap();
300 tos = STACKTOP - sizeof(Tos)*2; /* we'll assume twice the host's is big enough */
301 sp = tos;
302 for (i = 0; i < sizeof(Tos)*2; i++)
303 putmem_b(tos + i, 0);
304
305 /*
306 * pid is second word from end of tos and needs to be set for nsec().
307 * we know mips is a 32-bit cpu, so we'll assume knowledge of the Tos
308 * struct for now, and use our pid.
309 */
310 putmem_w(tos + 4*4 + 2*sizeof(ulong) + 3*sizeof(uvlong), getpid());
311
312 /* Build exec stack */
313 size = strlen(file)+1+BY2WD+BY2WD+BY2WD;
314 for(i = 0; i < argc; i++)
315 size += strlen(argv[i])+BY2WD+1;
316
317 sp -= size;
318 sp &= ~3;
319 reg.r[29] = sp;
320 reg.r[1] = tos; /* Plan 9 profiling clock, etc. */
321
322 /* Push argc */
323 putmem_w(sp, argc+1);
324 sp += BY2WD;
325
326 /* Compute sizeof(argv) and push argv[0] */
327 ap = sp+((argc+1)*BY2WD)+BY2WD;
328 putmem_w(sp, ap);
329 sp += BY2WD;
330
331 /* Build argv[0] string into stack */
332 for(p = file; *p; p++)
333 putmem_b(ap++, *p);
334
335 putmem_b(ap++, '\0');
336
337 /* Loop through pushing the arguments */
338 for(i = 0; i < argc; i++) {
339 putmem_w(sp, ap);
340 sp += BY2WD;
341 for(p = argv[i]; *p; p++)
342 putmem_b(ap++, *p);
343 putmem_b(ap++, '\0');
344 }
345 /* Null terminate argv */
346 putmem_w(sp, 0);
347
348 }
349
350 void
fatal(int syserr,char * fmt,...)351 fatal(int syserr, char *fmt, ...)
352 {
353 char buf[ERRMAX], *s;
354 va_list arg;
355
356 va_start(arg, fmt);
357 vseprint(buf, buf+sizeof(buf), fmt, arg);
358 va_end(arg);
359 s = "vi: %s\n";
360 if(syserr)
361 s = "vi: %s: %r\n";
362 fprint(2, s, buf);
363 exits(buf);
364 }
365
366 void
itrace(char * fmt,...)367 itrace(char *fmt, ...)
368 {
369 char buf[128];
370 va_list arg;
371
372 va_start(arg, fmt);
373 vseprint(buf, buf+sizeof(buf), fmt, arg);
374 va_end(arg);
375 Bprint(bioout, "%8lux %.8lux %s\n", reg.pc, reg.ir, buf);
376 }
377
378 void
dumpreg(void)379 dumpreg(void)
380 {
381 int i;
382
383 Bprint(bioout, "PC #%-8lux SP #%-8lux HI #%-8lux LO #%-8lux\n",
384 reg.pc, reg.r[29], reg.mhi, reg.mlo);
385
386 for(i = 0; i < 32; i++) {
387 if((i%4) == 0 && i != 0)
388 Bprint(bioout, "\n");
389 Bprint(bioout, "R%-2d #%-8lux ", i, reg.r[i]);
390 }
391 Bprint(bioout, "\n");
392 }
393
394 void
dumpfreg(void)395 dumpfreg(void)
396 {
397 int i;
398 char buf[64];
399
400 i = 0;
401 while(i < 32) {
402 ieeesftos(buf, sizeof(buf), reg.di[i]);
403 Bprint(bioout, "F%-2d %s\t", i, buf);
404 i++;
405
406 ieeesftos(buf, sizeof(buf), reg.di[i]);
407 Bprint(bioout, "\t\t\tF%-2d %s\n", i, buf);
408 i++;
409 }
410 }
411
412 void
dumpdreg(void)413 dumpdreg(void)
414 {
415 int i;
416 char buf[64];
417
418 i = 0;
419 while(i < 32) {
420 if(reg.ft[i] == FPd)
421 ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]);
422 else
423 ieeedftos(buf, sizeof(buf), reg.di[i+1] ,reg.di[i]);
424 Bprint(bioout, "F%-2d %s\t\t\t", i, buf);
425 i += 2;
426
427 if(reg.ft[i] == FPd)
428 ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]);
429 else
430 ieeedftos(buf, sizeof(buf), reg.di[i+1] ,reg.di[i]);
431 Bprint(bioout, "F%-2d %s\n", i, buf);
432 i += 2;
433 }
434 }
435
436 void *
emalloc(ulong size)437 emalloc(ulong size)
438 {
439 void *a;
440
441 a = malloc(size);
442 if(a == 0)
443 fatal(0, "no memory");
444
445 memset(a, 0, size);
446 return a;
447 }
448
449 void *
erealloc(void * a,ulong oldsize,ulong size)450 erealloc(void *a, ulong oldsize, ulong size)
451 {
452 void *n;
453
454 n = malloc(size);
455 if(n == 0)
456 fatal(0, "no memory");
457 memset(n, 0, size);
458 if(size > oldsize)
459 size = oldsize;
460 memmove(n, a, size);
461 return n;
462 }
463
464 Mulu
mulu(ulong u1,ulong u2)465 mulu(ulong u1, ulong u2)
466 {
467 ulong lo1, lo2, hi1, hi2, lo, hi, t1, t2, t;
468
469 lo1 = u1 & 0xffff;
470 lo2 = u2 & 0xffff;
471 hi1 = u1 >> 16;
472 hi2 = u2 >> 16;
473
474 lo = lo1 * lo2;
475 t1 = lo1 * hi2;
476 t2 = lo2 * hi1;
477 hi = hi1 * hi2;
478 t = lo;
479 lo += t1 << 16;
480 if(lo < t)
481 hi++;
482 t = lo;
483 lo += t2 << 16;
484 if(lo < t)
485 hi++;
486 hi += (t1 >> 16) + (t2 >> 16);
487 return (Mulu){lo, hi};
488 }
489
490 Mul
mul(long l1,long l2)491 mul(long l1, long l2)
492 {
493 Mulu m;
494 ulong t, lo, hi;
495 int sign;
496
497 sign = 0;
498 if(l1 < 0){
499 sign ^= 1;
500 l1 = -l1;
501 }
502 if(l2 < 0){
503 sign ^= 1;
504 l2 = -l2;
505 }
506 m = mulu(l1, l2);
507 lo = m.lo;
508 hi = m.hi;
509 if(sign){
510 t = lo = ~lo;
511 hi = ~hi;
512 lo++;
513 if(lo < t)
514 hi++;
515 }
516 return (Mul){lo, hi};
517 }
518
519