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