xref: /plan9/sys/src/cmd/qi/qi.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #define Extern
6 #include "power.h"
7 
8 char	*file = "q.out";
9 int	datasize;
10 ulong	textbase;
11 Biobuf	bp, bi;
12 Fhdr	fhdr;
13 ulong	bits[32];
14 
15 void
16 main(int argc, char **argv)
17 {
18 	int pid, i;
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, "qi\n");
44 	inithdr(text);
45 	initstk(argc, argv);
46 
47 	for(i=0; i<32; i++)
48 		bits[i] = 1L << (31-i);
49 
50 	reg.fd[27] = 4503601774854144.0;
51 	reg.fd[29] = 0.5;	/* Normally initialised by the kernel */
52 	reg.fd[28] = 0.0;
53 	reg.fd[30] = 1.0;
54 	reg.fd[31] = 2.0;
55 	cmd();
56 }
57 
58 void
59 initmap(void)
60 {
61 
62 	ulong t, d, b, bssend;
63 	Segment *s;
64 
65 	t = (fhdr.txtaddr+fhdr.txtsz+(BY2PG-1)) & ~(BY2PG-1);
66 	d = (t + fhdr.datsz + (BY2PG-1)) & ~(BY2PG-1);
67 	bssend = t + fhdr.datsz + fhdr.bsssz;
68 	b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
69 
70 	s = &memory.seg[Text];
71 	s->type = Text;
72 	s->base = fhdr.txtaddr - fhdr.hdrsz;
73 	s->end = t;
74 	s->fileoff = fhdr.txtoff - fhdr.hdrsz;
75 	s->fileend = s->fileoff + fhdr.txtsz;
76 	s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
77 
78 	iprofsize = (s->end-s->base)/PROFGRAN;
79 	iprof = emalloc(iprofsize*sizeof(long));
80 	textbase = s->base;
81 
82 	s = &memory.seg[Data];
83 	s->type = Data;
84 	s->base = t;
85 	s->end = t+(d-t);
86 	s->fileoff = fhdr.datoff;
87 	s->fileend = s->fileoff + fhdr.datsz;
88 	datasize = fhdr.datsz;
89 	s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
90 
91 	s = &memory.seg[Bss];
92 	s->type = Bss;
93 	s->base = d;
94 	s->end = d+(b-d);
95 	s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
96 
97 	s = &memory.seg[Stack];
98 	s->type = Stack;
99 	s->base = STACKTOP-STACKSIZE;
100 	s->end = STACKTOP;
101 	s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
102 
103 	reg.pc = fhdr.entry;
104 }
105 
106 void
107 inithdr(int fd)
108 {
109 	Symbol s;
110 
111 	extern Machdata powermach;
112 
113 	seek(fd, 0, 0);
114 	if (!crackhdr(fd, &fhdr))
115 		fatal(0, "read text header");
116 
117 	if(fhdr.type != FPOWER)
118 		fatal(0, "bad magic number");
119 
120 	if(syminit(fd, &fhdr) < 0)
121 		fatal(0, "%r\n");
122 	symmap = loadmap(symmap, fd, &fhdr);
123 	if (mach->sbreg && lookup(0, mach->sbreg, &s))
124 		mach->sb = s.value;
125 	machdata = &powermach;
126 }
127 
128 ulong
129 greg(int f, ulong off)
130 {
131 	int n;
132 	ulong l;
133 	uchar wd[BY2WD];
134 
135 	seek(f, off, 0);
136 	n = read(f, wd, BY2WD);
137 	if(n != BY2WD)
138 		fatal(1, "read register");
139 
140 	l  = wd[0]<<24;
141 	l |= wd[1]<<16;
142 	l |= wd[2]<<8;
143 	l |= wd[3];
144 	return l;
145 }
146 
147 ulong
148 roff[] = {
149 	REGOFF(r0),
150 	REGOFF(r1),	REGOFF(r2),	REGOFF(r3),
151 	REGOFF(r4),	REGOFF(r5),	REGOFF(r6),
152 	REGOFF(r7),	REGOFF(r8),	REGOFF(r9),
153 	REGOFF(r10),	REGOFF(r11),	REGOFF(r12),
154 	REGOFF(r13),	REGOFF(r14),	REGOFF(r15),
155 	REGOFF(r16),	REGOFF(r17),	REGOFF(r18),
156 	REGOFF(r19),	REGOFF(r20),	REGOFF(r21),
157 	REGOFF(r22),	REGOFF(r23),	REGOFF(r24),
158 	REGOFF(r25),	REGOFF(r26),	REGOFF(r27),
159 	REGOFF(r28),	REGOFF(r29),	REGOFF(r30),
160 	REGOFF(r31),
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 
212 	p = strstr(sfile, "Data");
213 	if(p == 0)
214 		fatal(0, "no data");
215 
216 	vastart = strtoul(p+9, 0, 16);
217 	vaend = strtoul(p+18, 0, 16);
218 	s = &memory.seg[Data];
219 	if(s->base != vastart || s->end != vaend) {
220 		s->base = vastart;
221 		s->end = vaend;
222 		free(s->table);
223 		s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
224 	}
225 	seginit(m, s, 0, vastart, vaend);
226 
227 	p = strstr(sfile, "Bss");
228 	if(p == 0)
229 		fatal(0, "no bss");
230 
231 	vastart = strtoul(p+9, 0, 16);
232 	vaend = strtoul(p+18, 0, 16);
233 	s = &memory.seg[Bss];
234 	if(s->base != vastart || s->end != vaend) {
235 		s->base = vastart;
236 		s->end = vaend;
237 		free(s->table);
238 		s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
239 	}
240 	seginit(m, s, 0, vastart, vaend);
241 
242 	reg.pc = greg(m, REGOFF(pc));
243 	reg.r[1] = greg(m, REGOFF(sp));
244 	reg.r[2] = greg(m, REGOFF(r2));
245 	reg.r[30] = greg(m, REGOFF(r30));
246 	reg.r[31] = greg(m, REGOFF(r31));
247 
248 	for(i = 0; i < 32; i++)
249 		reg.r[i] = greg(m, roff[i-1]);
250 
251 	s = &memory.seg[Stack];
252 	vastart = reg.r[1] & ~(BY2PG-1);
253 	seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP);
254 	close(m);
255 	Bprint(bioout, "qi\n");
256 }
257 
258 void
259 reset(void)
260 {
261 	int i, l, m;
262 	Segment *s;
263 	Breakpoint *b;
264 
265 	memset(&reg, 0, sizeof(Registers));
266 	reg.fd[27] = 4503601774854144.0;
267 	reg.fd[29] = 0.5;	/* Normally initialised by the kernel */
268 	reg.fd[28] = 0.0;
269 	reg.fd[30] = 1.0;
270 	reg.fd[31] = 2.0;
271 	for(i = 0; i > Nseg; i++) {
272 		s = &memory.seg[i];
273 		l = ((s->end-s->base)/BY2PG)*sizeof(uchar*);
274 		for(m = 0; m < l; m++)
275 			if(s->table[m])
276 				free(s->table[m]);
277 		free(s->table);
278 	}
279 	free(iprof);
280 	memset(&memory, 0, sizeof(memory));
281 
282 	for(b = bplist; b; b = b->next)
283 		b->done = b->count;
284 }
285 
286 void
287 initstk(int argc, char *argv[])
288 {
289 	ulong size, sp, ap;
290 	int i;
291 	char *p;
292 
293 	initmap();
294 	sp = STACKTOP - 4;
295 
296 	/* Build exec stack */
297 	size = strlen(file)+1+BY2WD+BY2WD+(BY2WD*2);
298 	for(i = 0; i < argc; i++)
299 		size += strlen(argv[i])+BY2WD+1;
300 
301 	sp -= size;
302 	sp &= ~7;
303 	reg.r[1] = sp;
304 	reg.r[3] = STACKTOP-4;	/* Plan 9 profiling clock */
305 
306 	/* Push argc */
307 	putmem_w(sp, argc+1);
308 	sp += BY2WD;
309 
310 	/* Compute sizeof(argv) and push argv[0] */
311 	ap = sp+((argc+1)*BY2WD)+BY2WD;
312 	putmem_w(sp, ap);
313 	sp += BY2WD;
314 
315 	/* Build argv[0] string into stack */
316 	for(p = file; *p; p++)
317 		putmem_b(ap++, *p);
318 
319 	putmem_b(ap++, '\0');
320 
321 	/* Loop through pushing the arguments */
322 	for(i = 0; i < argc; i++) {
323 		putmem_w(sp, ap);
324 		sp += BY2WD;
325 		for(p = argv[i]; *p; p++)
326 			putmem_b(ap++, *p);
327 		putmem_b(ap++, '\0');
328 	}
329 	/* Null terminate argv */
330 	putmem_w(sp, 0);
331 
332 }
333 
334 void
335 fatal(int syserr, char *fmt, ...)
336 {
337 	char buf[ERRMAX], *s;
338 	va_list ap;
339 
340 	va_start(ap, fmt);
341 	vseprint(buf, buf+sizeof(buf), fmt, ap);
342 	va_end(ap);
343 	s = "qi: %s\n";
344 	if(syserr)
345 		s = "qi: %s: %r\n";
346 	fprint(2, s, buf);
347 	exits(buf);
348 }
349 
350 void
351 itrace(char *fmt, ...)
352 {
353 	char buf[128];
354 	va_list ap;
355 
356 	va_start(ap, fmt);
357 	vseprint(buf, buf+sizeof(buf), fmt, ap);
358 	va_end(ap);
359 	Bprint(bioout, "%8lux %.8lux %s\n", reg.pc, reg.ir, buf);
360 }
361 
362 void
363 dumpreg(void)
364 {
365 	int i;
366 
367 	Bprint(bioout, "PC  #%-8lux SP  #%-8lux CR #%-8lux LR #%-8lux CTR #%-8lux XER #%-8lux\n",
368 				reg.pc, reg.r[1], reg.cr, reg.lr, reg.ctr, reg.xer);
369 
370 	for(i = 0; i < 32; i++) {
371 		if((i%4) == 0 && i != 0)
372 			Bprint(bioout, "\n");
373 		Bprint(bioout, "R%-2d #%-8lux ", i, reg.r[i]);
374 	}
375 	Bprint(bioout, "\n");
376 }
377 
378 void
379 dumpfreg(void)
380 {
381 	dumpdreg();
382 }
383 
384 void
385 dumpdreg(void)
386 {
387 	int i;
388 	char buf[64];
389 
390 	i = 0;
391 	while(i < 32) {
392 		ieeedftos(buf, sizeof(buf), (ulong)(reg.dv[i]>>32), (ulong)reg.dv[i]);
393 		Bprint(bioout, "F%-2d %s\t", i, buf);
394 		i++;
395 		ieeedftos(buf, sizeof(buf), (ulong)(reg.dv[i]>>32), (ulong)reg.dv[i]);
396 		Bprint(bioout, "\tF%-2d %s\n", i, buf);
397 		i++;
398 	}
399 }
400 
401 void *
402 emalloc(ulong size)
403 {
404 	void *a;
405 
406 	a = malloc(size);
407 	if(a == 0)
408 		fatal(0, "no memory");
409 
410 	memset(a, 0, size);
411 	return a;
412 }
413 
414 void *
415 erealloc(void *a, ulong oldsize, ulong size)
416 {
417 	void *n;
418 
419 	n = malloc(size);
420 	if(n == 0)
421 		fatal(0, "no memory");
422 	memset(n, 0, size);
423 	if(size > oldsize)
424 		size = oldsize;
425 	memmove(n, a, size);
426 	return n;
427 }
428