]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vi/vi.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / vi / vi.c
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
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
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
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
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
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
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
260 reset(void)
261 {
262         int i, l, m;
263         Segment *s;
264         Breakpoint *b;
265
266         memset(&reg, 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
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
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
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
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
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
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 *
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 *
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
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
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