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
main(int argc,char ** argv)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
initmap(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
inithdr(int fd)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
greg(int f,ulong off)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
seginit(int fd,Segment * s,int idx,ulong vastart,ulong vaend)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
procinit(int pid)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
reset(void)262 reset(void)
263 {
264 int i, l, m;
265 Segment *s;
266 Breakpoint *b;
267
268 memset(®, 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
initstk(int argc,char * argv[])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
fatal(int syserr,char * fmt,...)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
itrace(char * fmt,...)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
dumpreg(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
dumpfreg(void)389 dumpfreg(void)
390 {
391 dumpdreg();
392 }
393
394 void
dumpdreg(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 *
emalloc(ulong size)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 *
erealloc(void * a,ulong oldsize,ulong size)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