xref: /plan9-contrib/sys/src/cmd/qi/qi.c (revision bb43afe423a7a925fe6bf0f50e9f0e6b24a63d80)
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(&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
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