]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/qi/qi.c
cpu: make -p work with explicit service in dialstring (same as import)
[plan9front.git] / sys / src / cmd / qi / qi.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 "power.h"
8
9 char    *file = "q.out";
10 int     datasize;
11 ulong   textbase;
12 Biobuf  bp, bi;
13 Fhdr    fhdr;
14 ulong   bits[32];
15
16 void
17 main(int argc, char **argv)
18 {
19         int pid, i;
20
21         argc--;
22         argv++;
23
24         bioout = &bp;
25         bin = &bi;
26         Binit(bioout, 1, OWRITE);
27         Binit(bin, 0, OREAD);
28
29         if(argc) {
30                 pid = atoi(argv[0]);
31                 if(pid != 0) {
32                         procinit(pid);
33                         cmd();
34                 }
35                 file = argv[0];
36         }
37         argc--;
38         argv++;
39
40         text = open(file, OREAD);
41         if(text < 0)
42                 fatal(1, "open text '%s'", file);
43
44         Bprint(bioout, "qi\n");
45         inithdr(text);
46         initstk(argc, argv);
47
48         for(i=0; i<32; i++)
49                 bits[i] = 1L << (31-i);
50
51         fpreginit();
52         cmd();
53 }
54
55 /*
56  * we're rounding segment boundaries to the nearest 1MB on power now,
57  * and mach->pgsize is actually what to round segment boundaries up to.
58  */
59 #define SEGROUND mach->pgsize
60
61 void
62 initmap(void)
63 {
64
65         ulong t, d, b, bssend;
66         Segment *s;
67
68         t = (fhdr.txtaddr+fhdr.txtsz+(SEGROUND-1)) & ~(SEGROUND-1);
69         d = (t + fhdr.datsz + (SEGROUND-1)) & ~(SEGROUND-1);
70         bssend = t + fhdr.datsz + fhdr.bsssz;
71         b = (bssend + (SEGROUND-1)) & ~(SEGROUND-1);
72
73         s = &memory.seg[Text];
74         s->type = Text;
75         s->base = fhdr.txtaddr - fhdr.hdrsz;
76         s->end = t;
77         s->fileoff = fhdr.txtoff - fhdr.hdrsz;
78         s->fileend = s->fileoff + fhdr.txtsz;
79         s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
80
81         iprofsize = (s->end-s->base)/PROFGRAN;
82         iprof = emalloc(iprofsize*sizeof(long));
83         textbase = s->base;
84
85         s = &memory.seg[Data];
86         s->type = Data;
87         s->base = t;
88         s->end = t+(d-t);
89         s->fileoff = fhdr.datoff;
90         s->fileend = s->fileoff + fhdr.datsz;
91         datasize = fhdr.datsz;
92         s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
93
94         s = &memory.seg[Bss];
95         s->type = Bss;
96         s->base = d;
97         s->end = d+(b-d);
98         s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
99
100         s = &memory.seg[Stack];
101         s->type = Stack;
102         s->base = STACKTOP-STACKSIZE;
103         s->end = STACKTOP;
104         s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
105
106         reg.pc = fhdr.entry;
107 }
108
109 void
110 inithdr(int fd)
111 {
112         Symbol s;
113
114         extern Machdata powermach;
115
116         seek(fd, 0, 0);
117         if (!crackhdr(fd, &fhdr))
118                 fatal(0, "read text header");
119
120         if(fhdr.type != FPOWER)
121                 fatal(0, "bad magic number");
122
123         if(syminit(fd, &fhdr) < 0)
124                 fatal(0, "%r\n");
125         symmap = loadmap(symmap, fd, &fhdr);
126         if (mach->sbreg && lookup(0, mach->sbreg, &s))
127                 mach->sb = s.value;
128         machdata = &powermach;
129 }
130
131 ulong
132 greg(int f, ulong off)
133 {
134         int n;
135         ulong l;
136         uchar wd[BY2WD];
137         
138         seek(f, off, 0);
139         n = read(f, wd, BY2WD);
140         if(n != BY2WD)
141                 fatal(1, "read register");
142
143         l  = wd[0]<<24;
144         l |= wd[1]<<16;
145         l |= wd[2]<<8;
146         l |= wd[3];
147         return l;
148 }
149
150 ulong
151 roff[] = {
152         REGOFF(r0),
153         REGOFF(r1),     REGOFF(r2),     REGOFF(r3),
154         REGOFF(r4),     REGOFF(r5),     REGOFF(r6),
155         REGOFF(r7),     REGOFF(r8),     REGOFF(r9),
156         REGOFF(r10),    REGOFF(r11),    REGOFF(r12),
157         REGOFF(r13),    REGOFF(r14),    REGOFF(r15),
158         REGOFF(r16),    REGOFF(r17),    REGOFF(r18),
159         REGOFF(r19),    REGOFF(r20),    REGOFF(r21),
160         REGOFF(r22),    REGOFF(r23),    REGOFF(r24),
161         REGOFF(r25),    REGOFF(r26),    REGOFF(r27),
162         REGOFF(r28),    REGOFF(r29),    REGOFF(r30),
163         REGOFF(r31),
164 };
165
166 void
167 seginit(int fd, Segment *s, int idx, ulong vastart, ulong vaend)
168 {
169         int n;
170
171         while(vastart < vaend) {
172                 seek(fd, vastart, 0);
173                 s->table[idx] = emalloc(BY2PG);
174                 n = read(fd, s->table[idx], BY2PG);
175                 if(n != BY2PG)
176                         fatal(1, "data read");
177                 vastart += BY2PG;
178                 idx++;
179         }
180 }
181
182 void
183 procinit(int pid)
184 {
185         char *p;
186         Segment *s;
187         int n, m, sg, i;
188         ulong vastart, vaend;
189         char mfile[128], tfile[128], sfile[1024];
190
191         sprint(mfile, "/proc/%d/mem", pid);
192         sprint(tfile, "/proc/%d/text", pid);
193         sprint(sfile, "/proc/%d/segment", pid);
194
195         text = open(tfile, OREAD);
196         if(text < 0)
197                 fatal(1, "open text %s", tfile);
198         inithdr(text);
199
200         sg = open(sfile, OREAD);
201         if(sg < 0)
202                 fatal(1, "open text %s", sfile);
203
204         n = read(sg, sfile, sizeof(sfile));
205         if(n >= sizeof(sfile))
206                 fatal(0, "segment file buffer too small");
207         close(sg);
208
209         m = open(mfile, OREAD);
210         if(m < 0)
211                 fatal(1, "open %s", mfile);
212
213         initmap();
214
215         p = strstr(sfile, "Data");
216         if(p == 0)
217                 fatal(0, "no data");
218
219         vastart = strtoul(p+9, 0, 16);
220         vaend = strtoul(p+18, 0, 16);
221         s = &memory.seg[Data];
222         if(s->base != vastart || s->end != vaend) {
223                 s->base = vastart;
224                 s->end = vaend;
225                 free(s->table);
226                 s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
227         }
228         seginit(m, s, 0, vastart, vaend);
229         
230         p = strstr(sfile, "Bss");
231         if(p == 0)
232                 fatal(0, "no bss");
233
234         vastart = strtoul(p+9, 0, 16);
235         vaend = strtoul(p+18, 0, 16);
236         s = &memory.seg[Bss];
237         if(s->base != vastart || s->end != vaend) {
238                 s->base = vastart;
239                 s->end = vaend;
240                 free(s->table);
241                 s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
242         }
243         seginit(m, s, 0, vastart, vaend);
244
245         reg.pc = greg(m, REGOFF(pc));
246         reg.r[1] = greg(m, REGOFF(sp));
247         reg.r[2] = greg(m, REGOFF(r2));
248         reg.r[30] = greg(m, REGOFF(r30));
249         reg.r[31] = greg(m, REGOFF(r31));
250
251         for(i = 0; i < 32; i++)
252                 reg.r[i] = greg(m, roff[i-1]);
253
254         s = &memory.seg[Stack];
255         vastart = reg.r[1] & ~(BY2PG-1);
256         seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP);
257         close(m);
258         Bprint(bioout, "qi\n"); 
259 }
260
261 void
262 reset(void)
263 {
264         int i, l, m;
265         Segment *s;
266         Breakpoint *b;
267
268         memset(&reg, 0, sizeof(Registers));
269         fpreginit();
270         for(i = 0; i > Nseg; i++) {
271                 s = &memory.seg[i];
272                 l = ((s->end-s->base)/BY2PG)*sizeof(uchar*);
273                 for(m = 0; m < l; m++)
274                         if(s->table[m])
275                                 free(s->table[m]);
276                 free(s->table);
277         }
278         free(iprof);
279         memset(&memory, 0, sizeof(memory));
280
281         for(b = bplist; b; b = b->next)
282                 b->done = b->count;
283 }
284
285 void
286 initstk(int argc, char *argv[])
287 {
288         ulong size, sp, ap, tos;
289         int i;
290         char *p;
291
292         initmap();
293         tos = STACKTOP - sizeof(Tos)*2; /* we'll assume twice the host's is big enough */
294         sp = tos;
295         for (i = 0; i < sizeof(Tos)*2; i++)
296                 putmem_b(tos + i, 0);
297
298         /*
299          * pid is second word from end of tos and needs to be set for nsec().
300          * we know power is a 32-bit cpu, so we'll assume knowledge of the Tos
301          * struct for now, and use our pid.
302          */
303         putmem_w(tos + 4*4 + 2*sizeof(ulong) + 3*sizeof(uvlong), getpid());
304
305         /* Build exec stack */
306         size = strlen(file)+1+BY2WD+BY2WD+(BY2WD*2);    
307         for(i = 0; i < argc; i++)
308                 size += strlen(argv[i])+BY2WD+1;
309
310         sp -= size;
311         sp &= ~7;
312         reg.r[1] = sp;
313         reg.r[3] = tos;         /* Plan 9 profiling clock, etc. */
314
315         /* Push argc */
316         putmem_w(sp, argc+1);
317         sp += BY2WD;
318
319         /* Compute sizeof(argv) and push argv[0] */
320         ap = sp+((argc+1)*BY2WD)+BY2WD;
321         putmem_w(sp, ap);
322         sp += BY2WD;
323         
324         /* Build argv[0] string into stack */
325         for(p = file; *p; p++)
326                 putmem_b(ap++, *p);
327
328         putmem_b(ap++, '\0');
329
330         /* Loop through pushing the arguments */
331         for(i = 0; i < argc; i++) {
332                 putmem_w(sp, ap);
333                 sp += BY2WD;
334                 for(p = argv[i]; *p; p++)
335                         putmem_b(ap++, *p);
336                 putmem_b(ap++, '\0');
337         }
338         /* Null terminate argv */
339         putmem_w(sp, 0);
340
341 }
342
343 void
344 fatal(int syserr, char *fmt, ...)
345 {
346         char buf[ERRMAX], *s;
347         va_list ap;
348
349         va_start(ap, fmt);
350         vseprint(buf, buf+sizeof(buf), fmt, ap);
351         va_end(ap);
352         s = "qi: %s\n";
353         if(syserr)
354                 s = "qi: %s: %r\n";
355         fprint(2, s, buf);
356         exits(buf);
357 }
358
359 void
360 itrace(char *fmt, ...)
361 {
362         char buf[128];
363         va_list ap;
364
365         va_start(ap, fmt);
366         vseprint(buf, buf+sizeof(buf), fmt, ap);
367         va_end(ap);
368         Bprint(bioout, "%8lux %.8lux %s\n", reg.pc, reg.ir, buf);
369 Bflush(bioout);
370 }
371
372 void
373 dumpreg(void)
374 {
375         int i;
376
377         Bprint(bioout, "PC  #%-8lux SP  #%-8lux CR #%-8lux LR #%-8lux CTR #%-8lux XER #%-8lux\n",
378                                 reg.pc, reg.r[1], reg.cr, reg.lr, reg.ctr, reg.xer);
379
380         for(i = 0; i < 32; i++) {
381                 if((i%4) == 0 && i != 0)
382                         Bprint(bioout, "\n");
383                 Bprint(bioout, "R%-2d #%-8lux ", i, reg.r[i]);
384         }
385         Bprint(bioout, "\n");
386 }
387
388 void
389 dumpfreg(void)
390 {
391         dumpdreg();
392 }
393
394 void
395 dumpdreg(void)
396 {
397         int i;
398         char buf[64];
399         FPdbleword d;
400
401         i = 0;
402         while(i < 32) {
403                 d.x = reg.fd[i];
404                 ieeedftos(buf, sizeof(buf), d.hi, d.lo);
405                 Bprint(bioout, "F%-2d %s\t", i, buf);
406                 i++;
407                 d.x = reg.fd[i];
408                 ieeedftos(buf, sizeof(buf), d.hi, d.lo);
409                 Bprint(bioout, "\tF%-2d %s\n", i, buf);
410                 i++;
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 }