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