#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#include <tos.h>#define Extern#include "sparc.h" char *file = "k.out";int datasize;ulong textbase;Biobuf bp, bi;Fhdr fhdr; voidmain(int argc, char **argv){ int pid; argc--; argv++; bioout = &bp; bin = &bi; Binit(bioout, 1, OWRITE); Binit(bin, 0, OREAD); if(argc) { pid = atoi(argv[0]); if(pid != 0) { procinit(pid); cmd(); } file = argv[0]; } argc--; argv++; text = open(file, OREAD); if(text < 0) fatal(1, "open text '%s'", file); Bprint(bioout, "ki\n"); inithdr(text); initstk(argc, argv); reg.fd[13] = 0.5; /* Normally initialised by the kernel */ reg.fd[12] = 0.0; reg.fd[14] = 1.0; reg.fd[15] = 2.0; cmd();} voidinitmap(void){ ulong t, d, b, bssend; Segment *s; t = (fhdr.txtaddr+fhdr.txtsz+(BY2PG-1)) & ~(BY2PG-1); d = (t + fhdr.datsz + (BY2PG-1)) & ~(BY2PG-1); bssend = t + fhdr.datsz + fhdr.bsssz; b = (bssend + (BY2PG-1)) & ~(BY2PG-1); s = &memory.seg[Text]; s->type = Text; s->base = fhdr.txtaddr - fhdr.hdrsz; s->end = t; s->fileoff = fhdr.txtoff - fhdr.hdrsz; s->fileend = s->fileoff + fhdr.txtsz; s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); iprof = emalloc(((s->end-s->base)/PROFGRAN)*sizeof(long)); textbase = s->base; s = &memory.seg[Data]; s->type = Data; s->base = t; s->end = t+(d-t); s->fileoff = fhdr.datoff; s->fileend = s->fileoff + fhdr.datsz; datasize = fhdr.datsz; s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); s = &memory.seg[Bss]; s->type = Bss; s->base = d; s->end = d+(b-d); s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); s = &memory.seg[Stack]; s->type = Stack; s->base = STACKTOP-STACKSIZE; s->end = STACKTOP; s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); reg.pc = fhdr.entry;} voidinithdr(int fd){ Symbol s; extern Machdata sparcmach; seek(fd, 0, 0); if (!crackhdr(fd, &fhdr)) fatal(0, "read text header"); if(fhdr.type != FSPARC) fatal(0, "bad magic number"); if(syminit(fd, &fhdr) < 0) fatal(0, "%r\n"); symmap = loadmap(symmap, fd, &fhdr); if (mach->sbreg && lookup(0, mach->sbreg, &s)) mach->sb = s.value; machdata = &sparcmach; asstype = ASUNSPARC;} ulonggreg(int f, ulong off){ int n; ulong l; uchar wd[BY2WD]; seek(f, off, 0); n = read(f, wd, BY2WD); if(n != BY2WD) fatal(1, "read register"); l = wd[0]<<24; l |= wd[1]<<16; l |= wd[2]<<8; l |= wd[3]; return l;} ulongroff[] = { REGOFF(r1), REGOFF(r2), REGOFF(r3), REGOFF(r4), REGOFF(r5), REGOFF(r6), REGOFF(r7), REGOFF(r8), REGOFF(r9), REGOFF(r10), REGOFF(r11), REGOFF(r12), REGOFF(r13), REGOFF(r14), REGOFF(r15), REGOFF(r16), REGOFF(r17), REGOFF(r18), REGOFF(r19), REGOFF(r20), REGOFF(r21), REGOFF(r22), REGOFF(r23), REGOFF(r24), REGOFF(r25), REGOFF(r26), REGOFF(r27), REGOFF(r28)}; voidseginit(int fd, Segment *s, int idx, ulong vastart, ulong vaend){ int n; while(vastart < vaend) { seek(fd, vastart, 0); s->table[idx] = emalloc(BY2PG); n = read(fd, s->table[idx], BY2PG); if(n != BY2PG) fatal(1, "data read"); vastart += BY2PG; idx++; }} voidprocinit(int pid){ char *p; Segment *s; int n, m, sg, i; ulong vastart, vaend; char mfile[128], tfile[128], sfile[1024]; sprint(mfile, "/proc/%d/mem", pid); sprint(tfile, "/proc/%d/text", pid); sprint(sfile, "/proc/%d/segment", pid); text = open(tfile, OREAD); if(text < 0) fatal(1, "open text %s", tfile); inithdr(text); sg = open(sfile, OREAD); if(sg < 0) fatal(1, "open text %s", sfile); n = read(sg, sfile, sizeof(sfile)); if(n >= sizeof(sfile)) fatal(0, "segment file buffer too small"); close(sg); m = open(mfile, OREAD); if(m < 0) fatal(1, "open %s", mfile); initmap(); p = strstr(sfile, "Data"); if(p == 0) fatal(0, "no data"); vastart = strtoul(p+9, 0, 16); vaend = strtoul(p+18, 0, 16); s = &memory.seg[Data]; if(s->base != vastart || s->end != vaend) { s->base = vastart; s->end = vaend; free(s->table); s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); } seginit(m, s, 0, vastart, vaend); p = strstr(sfile, "Bss"); if(p == 0) fatal(0, "no bss"); vastart = strtoul(p+9, 0, 16); vaend = strtoul(p+18, 0, 16); s = &memory.seg[Bss]; if(s->base != vastart || s->end != vaend) { s->base = vastart; s->end = vaend; free(s->table); s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*)); } seginit(m, s, 0, vastart, vaend); reg.pc = greg(m, REGOFF(pc)); reg.r[1] = greg(m, REGOFF(sp)); reg.r[30] = greg(m, REGOFF(r30)); reg.r[31] = greg(m, REGOFF(r31)); for(i = 1; i < 29; i++) reg.r[i] = greg(m, roff[i-1]); s = &memory.seg[Stack]; vastart = reg.r[1] & ~(BY2PG-1); seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP); close(m); Bprint(bioout, "ki\n"); } voidreset(void){ int i, l, m; Segment *s; Breakpoint *b; memset(®, 0, sizeof(Registers)); reg.fd[13] = 0.5; /* Normally initialised by the kernel */ reg.fd[12] = 0.0; reg.fd[14] = 1.0; reg.fd[15] = 2.0; for(i = 0; i > Nseg; i++) { s = &memory.seg[i]; l = ((s->end-s->base)/BY2PG)*sizeof(uchar*); for(m = 0; m < l; m++) if(s->table[m]) free(s->table[m]); free(s->table); } free(iprof); memset(&memory, 0, sizeof(memory)); for(b = bplist; b; b = b->next) b->done = b->count;} voidinitstk(int argc, char *argv[]){ ulong size, sp, ap, tos; int i; char *p; initmap(); tos = STACKTOP - sizeof(Tos)*2; /* we'll assume twice the host's is big enough */ sp = tos; for (i = 0; i < sizeof(Tos)*2; i++) putmem_b(tos + i, 0); /* * pid is second word from end of tos and needs to be set for nsec(). * we know sparc is a 32-bit cpu, so we'll assume knowledge of the Tos * struct for now, and use our pid. */ putmem_w(tos + 4*4 + 2*sizeof(ulong) + 3*sizeof(uvlong), getpid()); /* Build exec stack */ size = strlen(file)+1+BY2WD+BY2WD+(BY2WD*2); for(i = 0; i < argc; i++) size += strlen(argv[i])+BY2WD+1; sp -= size; sp &= ~7; reg.r[1] = sp; reg.r[7] = tos; /* Plan 9 profiling clock, etc. */ /* Push argc */ putmem_w(sp, argc+1); sp += BY2WD; /* Compute sizeof(argv) and push argv[0] */ ap = sp+((argc+1)*BY2WD)+BY2WD; putmem_w(sp, ap); sp += BY2WD; /* Build argv[0] string into stack */ for(p = file; *p; p++) putmem_b(ap++, *p); putmem_b(ap++, '\0'); /* Loop through pushing the arguments */ for(i = 0; i < argc; i++) { putmem_w(sp, ap); sp += BY2WD; for(p = argv[i]; *p; p++) putmem_b(ap++, *p); putmem_b(ap++, '\0'); } /* Null terminate argv */ putmem_w(sp, 0); } voidfatal(int syserr, char *fmt, ...){ char buf[ERRMAX], *s; va_list arg; va_start(arg, fmt); vseprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); s = "ki: %s\n"; if(syserr) s = "ki: %s: %r\n"; fprint(2, s, buf); exits(buf);} voiditrace(char *fmt, ...){ char buf[128]; va_list arg; va_start(arg, fmt); vseprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); Bprint(bioout, "%8lux %.8lux %s\n", reg.pc, reg.ir, buf); } voiddumpreg(void){ int i; Bprint(bioout, "PC #%-8lux SP #%-8lux Y #%-8lux PSR #%-8lux\n", reg.pc, reg.r[1], reg.Y, reg.psr); for(i = 0; i < 32; i++) { if((i%4) == 0 && i != 0) Bprint(bioout, "\n"); Bprint(bioout, "R%-2d #%-8lux ", i, reg.r[i]); } Bprint(bioout, "\n");} voiddumpfreg(void){ int i; char buf[64]; i = 0; while(i < 32) { ieeesftos(buf, sizeof(buf), reg.di[i]); Bprint(bioout, "F%-2d %s\t", i, buf); i++; ieeesftos(buf, sizeof(buf), reg.di[i]); Bprint(bioout, "\tF%-2d %s\n", i, buf); i++; }} voiddumpdreg(void){ int i; char buf[64]; i = 0; while(i < 32) { ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]); Bprint(bioout, "F%-2d %s\t", i, buf); i += 2; ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]); Bprint(bioout, "\tF%-2d %s\n", i, buf); i += 2; }} void *emalloc(ulong size){ void *a; a = malloc(size); if(a == 0) fatal(0, "no memory"); memset(a, 0, size); return a;} void *erealloc(void *a, ulong oldsize, ulong size){ void *n; n = malloc(size); if(n == 0) fatal(0, "no memory"); memset(n, 0, size); if(size > oldsize) size = oldsize; memmove(n, a, size); return n;} Mulumulu(ulong u1, ulong u2){ ulong lo1, lo2, hi1, hi2, lo, hi, t1, t2, t; lo1 = u1 & 0xffff; lo2 = u2 & 0xffff; hi1 = u1 >> 16; hi2 = u2 >> 16; lo = lo1 * lo2; t1 = lo1 * hi2; t2 = lo2 * hi1; hi = hi1 * hi2; t = lo; lo += t1 << 16; if(lo < t) hi++; t = lo; lo += t2 << 16; if(lo < t) hi++; hi += (t1 >> 16) + (t2 >> 16); return (Mulu){lo, hi};} Mulmul(long l1, long l2){ Mulu m; ulong t, lo, hi; int sign; sign = 0; if(l1 < 0){ sign ^= 1; l1 = -l1; } if(l2 < 0){ sign ^= 1; l2 = -l2; } m = mulu(l1, l2); lo = m.lo; hi = m.hi; if(sign){ t = lo = ~lo; hi = ~hi; lo++; if(lo < t) hi++; } return (Mul){lo, hi};}
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <mach.h>
#include <tos.h>
#define Extern
#include "sparc.h"
char *file = "k.out";
int datasize;
ulong textbase;
Biobuf bp, bi;
Fhdr fhdr;
void
main(int argc, char **argv)
{
int pid;
argc--;
argv++;
bioout = &bp;
bin = &bi;
Binit(bioout, 1, OWRITE);
Binit(bin, 0, OREAD);
if(argc) {
pid = atoi(argv[0]);
if(pid != 0) {
procinit(pid);
cmd();
}
file = argv[0];
}
argc--;
argv++;
text = open(file, OREAD);
if(text < 0)
fatal(1, "open text '%s'", file);
Bprint(bioout, "ki\n");
inithdr(text);
initstk(argc, argv);
reg.fd[13] = 0.5; /* Normally initialised by the kernel */
reg.fd[12] = 0.0;
reg.fd[14] = 1.0;
reg.fd[15] = 2.0;
cmd();
}
void
initmap(void)
{
ulong t, d, b, bssend;
Segment *s;
t = (fhdr.txtaddr+fhdr.txtsz+(BY2PG-1)) & ~(BY2PG-1);
d = (t + fhdr.datsz + (BY2PG-1)) & ~(BY2PG-1);
bssend = t + fhdr.datsz + fhdr.bsssz;
b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
s = &memory.seg[Text];
s->type = Text;
s->base = fhdr.txtaddr - fhdr.hdrsz;
s->end = t;
s->fileoff = fhdr.txtoff - fhdr.hdrsz;
s->fileend = s->fileoff + fhdr.txtsz;
s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
iprof = emalloc(((s->end-s->base)/PROFGRAN)*sizeof(long));
textbase = s->base;
s = &memory.seg[Data];
s->type = Data;
s->base = t;
s->end = t+(d-t);
s->fileoff = fhdr.datoff;
s->fileend = s->fileoff + fhdr.datsz;
datasize = fhdr.datsz;
s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
s = &memory.seg[Bss];
s->type = Bss;
s->base = d;
s->end = d+(b-d);
s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
s = &memory.seg[Stack];
s->type = Stack;
s->base = STACKTOP-STACKSIZE;
s->end = STACKTOP;
s->table = emalloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
reg.pc = fhdr.entry;
}
void
inithdr(int fd)
{
Symbol s;
extern Machdata sparcmach;
seek(fd, 0, 0);
if (!crackhdr(fd, &fhdr))
fatal(0, "read text header");
if(fhdr.type != FSPARC)
fatal(0, "bad magic number");
if(syminit(fd, &fhdr) < 0)
fatal(0, "%r\n");
symmap = loadmap(symmap, fd, &fhdr);
if (mach->sbreg && lookup(0, mach->sbreg, &s))
mach->sb = s.value;
machdata = &sparcmach;
asstype = ASUNSPARC;
}
ulong
greg(int f, ulong off)
{
int n;
ulong l;
uchar wd[BY2WD];
seek(f, off, 0);
n = read(f, wd, BY2WD);
if(n != BY2WD)
fatal(1, "read register");
l = wd[0]<<24;
l |= wd[1]<<16;
l |= wd[2]<<8;
l |= wd[3];
return l;
}
ulong
roff[] = {
REGOFF(r1), REGOFF(r2), REGOFF(r3),
REGOFF(r4), REGOFF(r5), REGOFF(r6),
REGOFF(r7), REGOFF(r8), REGOFF(r9),
REGOFF(r10), REGOFF(r11), REGOFF(r12),
REGOFF(r13), REGOFF(r14), REGOFF(r15),
REGOFF(r16), REGOFF(r17), REGOFF(r18),
REGOFF(r19), REGOFF(r20), REGOFF(r21),
REGOFF(r22), REGOFF(r23), REGOFF(r24),
REGOFF(r25), REGOFF(r26), REGOFF(r27),
REGOFF(r28)
};
void
seginit(int fd, Segment *s, int idx, ulong vastart, ulong vaend)
{
int n;
while(vastart < vaend) {
seek(fd, vastart, 0);
s->table[idx] = emalloc(BY2PG);
n = read(fd, s->table[idx], BY2PG);
if(n != BY2PG)
fatal(1, "data read");
vastart += BY2PG;
idx++;
}
}
void
procinit(int pid)
{
char *p;
Segment *s;
int n, m, sg, i;
ulong vastart, vaend;
char mfile[128], tfile[128], sfile[1024];
sprint(mfile, "/proc/%d/mem", pid);
sprint(tfile, "/proc/%d/text", pid);
sprint(sfile, "/proc/%d/segment", pid);
text = open(tfile, OREAD);
if(text < 0)
fatal(1, "open text %s", tfile);
inithdr(text);
sg = open(sfile, OREAD);
if(sg < 0)
fatal(1, "open text %s", sfile);
n = read(sg, sfile, sizeof(sfile));
if(n >= sizeof(sfile))
fatal(0, "segment file buffer too small");
close(sg);
m = open(mfile, OREAD);
if(m < 0)
fatal(1, "open %s", mfile);
initmap();
p = strstr(sfile, "Data");
if(p == 0)
fatal(0, "no data");
vastart = strtoul(p+9, 0, 16);
vaend = strtoul(p+18, 0, 16);
s = &memory.seg[Data];
if(s->base != vastart || s->end != vaend) {
s->base = vastart;
s->end = vaend;
free(s->table);
s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
}
seginit(m, s, 0, vastart, vaend);
p = strstr(sfile, "Bss");
if(p == 0)
fatal(0, "no bss");
vastart = strtoul(p+9, 0, 16);
vaend = strtoul(p+18, 0, 16);
s = &memory.seg[Bss];
if(s->base != vastart || s->end != vaend) {
s->base = vastart;
s->end = vaend;
free(s->table);
s->table = malloc(((s->end-s->base)/BY2PG)*sizeof(uchar*));
}
seginit(m, s, 0, vastart, vaend);
reg.pc = greg(m, REGOFF(pc));
reg.r[1] = greg(m, REGOFF(sp));
reg.r[30] = greg(m, REGOFF(r30));
reg.r[31] = greg(m, REGOFF(r31));
for(i = 1; i < 29; i++)
reg.r[i] = greg(m, roff[i-1]);
s = &memory.seg[Stack];
vastart = reg.r[1] & ~(BY2PG-1);
seginit(m, s, (vastart-s->base)/BY2PG, vastart, STACKTOP);
close(m);
Bprint(bioout, "ki\n");
}
void
reset(void)
{
int i, l, m;
Segment *s;
Breakpoint *b;
memset(®, 0, sizeof(Registers));
reg.fd[13] = 0.5; /* Normally initialised by the kernel */
reg.fd[12] = 0.0;
reg.fd[14] = 1.0;
reg.fd[15] = 2.0;
for(i = 0; i > Nseg; i++) {
s = &memory.seg[i];
l = ((s->end-s->base)/BY2PG)*sizeof(uchar*);
for(m = 0; m < l; m++)
if(s->table[m])
free(s->table[m]);
free(s->table);
}
free(iprof);
memset(&memory, 0, sizeof(memory));
for(b = bplist; b; b = b->next)
b->done = b->count;
}
void
initstk(int argc, char *argv[])
{
ulong size, sp, ap, tos;
int i;
char *p;
initmap();
tos = STACKTOP - sizeof(Tos)*2; /* we'll assume twice the host's is big enough */
sp = tos;
for (i = 0; i < sizeof(Tos)*2; i++)
putmem_b(tos + i, 0);
/*
* pid is second word from end of tos and needs to be set for nsec().
* we know sparc is a 32-bit cpu, so we'll assume knowledge of the Tos
* struct for now, and use our pid.
*/
putmem_w(tos + 4*4 + 2*sizeof(ulong) + 3*sizeof(uvlong), getpid());
/* Build exec stack */
size = strlen(file)+1+BY2WD+BY2WD+(BY2WD*2);
for(i = 0; i < argc; i++)
size += strlen(argv[i])+BY2WD+1;
sp -= size;
sp &= ~7;
reg.r[1] = sp;
reg.r[7] = tos; /* Plan 9 profiling clock, etc. */
/* Push argc */
putmem_w(sp, argc+1);
sp += BY2WD;
/* Compute sizeof(argv) and push argv[0] */
ap = sp+((argc+1)*BY2WD)+BY2WD;
putmem_w(sp, ap);
sp += BY2WD;
/* Build argv[0] string into stack */
for(p = file; *p; p++)
putmem_b(ap++, *p);
putmem_b(ap++, '\0');
/* Loop through pushing the arguments */
for(i = 0; i < argc; i++) {
putmem_w(sp, ap);
sp += BY2WD;
for(p = argv[i]; *p; p++)
putmem_b(ap++, *p);
putmem_b(ap++, '\0');
}
/* Null terminate argv */
putmem_w(sp, 0);
}
void
fatal(int syserr, char *fmt, ...)
{
char buf[ERRMAX], *s;
va_list arg;
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
s = "ki: %s\n";
if(syserr)
s = "ki: %s: %r\n";
fprint(2, s, buf);
exits(buf);
}
void
itrace(char *fmt, ...)
{
char buf[128];
va_list arg;
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
Bprint(bioout, "%8lux %.8lux %s\n", reg.pc, reg.ir, buf);
}
void
dumpreg(void)
{
int i;
Bprint(bioout, "PC #%-8lux SP #%-8lux Y #%-8lux PSR #%-8lux\n",
reg.pc, reg.r[1], reg.Y, reg.psr);
for(i = 0; i < 32; i++) {
if((i%4) == 0 && i != 0)
Bprint(bioout, "\n");
Bprint(bioout, "R%-2d #%-8lux ", i, reg.r[i]);
}
Bprint(bioout, "\n");
}
void
dumpfreg(void)
{
int i;
char buf[64];
i = 0;
while(i < 32) {
ieeesftos(buf, sizeof(buf), reg.di[i]);
Bprint(bioout, "F%-2d %s\t", i, buf);
i++;
ieeesftos(buf, sizeof(buf), reg.di[i]);
Bprint(bioout, "\tF%-2d %s\n", i, buf);
i++;
}
}
void
dumpdreg(void)
{
int i;
char buf[64];
i = 0;
while(i < 32) {
ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]);
Bprint(bioout, "F%-2d %s\t", i, buf);
i += 2;
ieeedftos(buf, sizeof(buf), reg.di[i] ,reg.di[i+1]);
Bprint(bioout, "\tF%-2d %s\n", i, buf);
i += 2;
}
}
void *
emalloc(ulong size)
{
void *a;
a = malloc(size);
if(a == 0)
fatal(0, "no memory");
memset(a, 0, size);
return a;
}
void *
erealloc(void *a, ulong oldsize, ulong size)
{
void *n;
n = malloc(size);
if(n == 0)
fatal(0, "no memory");
memset(n, 0, size);
if(size > oldsize)
size = oldsize;
memmove(n, a, size);
return n;
}
Mulu
mulu(ulong u1, ulong u2)
{
ulong lo1, lo2, hi1, hi2, lo, hi, t1, t2, t;
lo1 = u1 & 0xffff;
lo2 = u2 & 0xffff;
hi1 = u1 >> 16;
hi2 = u2 >> 16;
lo = lo1 * lo2;
t1 = lo1 * hi2;
t2 = lo2 * hi1;
hi = hi1 * hi2;
t = lo;
lo += t1 << 16;
if(lo < t)
hi++;
t = lo;
lo += t2 << 16;
if(lo < t)
hi++;
hi += (t1 >> 16) + (t2 >> 16);
return (Mulu){lo, hi};
}
Mul
mul(long l1, long l2)
{
Mulu m;
ulong t, lo, hi;
int sign;
sign = 0;
if(l1 < 0){
sign ^= 1;
l1 = -l1;
}
if(l2 < 0){
sign ^= 1;
l2 = -l2;
}
m = mulu(l1, l2);
lo = m.lo;
hi = m.hi;
if(sign){
t = lo = ~lo;
hi = ~hi;
lo++;
if(lo < t)
hi++;
}
return (Mul){lo, hi};
}