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