496 lines
8.7 KiB
C
496 lines
8.7 KiB
C
#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};
|
|
}
|