added 5e (not finished)
parent
fcf30f314b
commit
2acb5433d8
|
@ -0,0 +1,76 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
Process **PP;
|
||||
|
||||
static int nflag;
|
||||
|
||||
void
|
||||
dump(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 16; i++) {
|
||||
print("R%2d %.8ux", i, P->R[i]);
|
||||
if((i % 4) == 3) print("\n");
|
||||
else print("\t");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
adjustns(void)
|
||||
{
|
||||
if(bind("/arm/bin", "/bin", MREPL) < 0)
|
||||
sysfatal("bind: %r");
|
||||
if(bind("/rc/bin", "/bin", MAFTER) < 0)
|
||||
sysfatal("bind: %r");
|
||||
putenv("cputype", "arm");
|
||||
putenv("objtype", "arm");
|
||||
}
|
||||
|
||||
void
|
||||
cleanup(void)
|
||||
{
|
||||
if(P == nil)
|
||||
return;
|
||||
|
||||
freesegs();
|
||||
fddecref(P->fd);
|
||||
free(P);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: 5e [ -n ] text [ args ]\n");
|
||||
exits(nil);
|
||||
}
|
||||
|
||||
void
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
ARGBEGIN {
|
||||
case 'n': nflag++; break;
|
||||
default: usage();
|
||||
} ARGEND;
|
||||
if(argc < 1)
|
||||
usage();
|
||||
if(_nprivates < 1)
|
||||
sysfatal("we don't have privates");
|
||||
if(rfork(RFREND | RFNAMEG | RFENVG) < 0)
|
||||
sysfatal("rfork: %r");
|
||||
atexit(cleanup);
|
||||
if(nflag)
|
||||
adjustns();
|
||||
initproc();
|
||||
if(loadtext(argv[0], argc, argv) < 0)
|
||||
sysfatal("%r");
|
||||
for(;;) {
|
||||
if(ultraverbose)
|
||||
dump();
|
||||
step();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,472 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <bio.h>
|
||||
#include <mach.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
enum {
|
||||
fI = 1<<25,
|
||||
fP = 1<<24,
|
||||
fLi = 1<<24,
|
||||
fU = 1<<23,
|
||||
fB = 1<<22,
|
||||
fW = 1<<21,
|
||||
fL = 1<<20,
|
||||
fS = 1<<20,
|
||||
fSg = 1<<6,
|
||||
fH = 1<<5,
|
||||
};
|
||||
|
||||
static void
|
||||
invalid(u32int instr)
|
||||
{
|
||||
sysfatal("undefined instruction %8ux @ %8ux", instr, P->R[15] - 4);
|
||||
}
|
||||
|
||||
static u32int
|
||||
doshift(u32int instr)
|
||||
{
|
||||
ulong amount, val;
|
||||
|
||||
if((instr & (1<<4)) && (instr & (1<<7)))
|
||||
invalid(instr);
|
||||
|
||||
if(instr & (1<<4))
|
||||
amount = P->R[(instr >> 8) & 15];
|
||||
else
|
||||
amount = (instr >> 7) & 31;
|
||||
val = P->R[instr & 15];
|
||||
switch((instr >> 5) & 3) {
|
||||
case 0:
|
||||
return val << amount;
|
||||
case 1:
|
||||
return val >> amount;
|
||||
case 2:
|
||||
return ((long) val) >> amount;
|
||||
case 3:
|
||||
return (val >> amount) | (val << (32 - amount));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
single(u32int instr)
|
||||
{
|
||||
long offset;
|
||||
u32int addr;
|
||||
u32int *Rn, *Rd;
|
||||
void *targ;
|
||||
Segment *seg;
|
||||
|
||||
if(instr & fI) {
|
||||
if(instr & (1<<4))
|
||||
invalid(instr);
|
||||
offset = doshift(instr);
|
||||
} else
|
||||
offset = instr & ((1<<12) - 1);
|
||||
if(!(instr & fU))
|
||||
offset = - offset;
|
||||
Rn = P->R + ((instr >> 16) & 15);
|
||||
Rd = P->R + ((instr >> 12) & 15);
|
||||
if((instr & (fW | fP)) == fW)
|
||||
invalid(instr);
|
||||
if(Rn == P->R + 15) {
|
||||
if(instr & fW)
|
||||
invalid(instr);
|
||||
addr = P->R[15] + 4;
|
||||
}
|
||||
else
|
||||
addr = *Rn;
|
||||
if(instr & fP)
|
||||
addr += offset;
|
||||
targ = vaddr(addr, &seg);
|
||||
switch(instr & (fB | fL)) {
|
||||
case 0:
|
||||
*(u32int*) targ = *Rd;
|
||||
break;
|
||||
case fB:
|
||||
*(u8int*) targ = *Rd;
|
||||
break;
|
||||
case fL:
|
||||
*Rd = *(u32int*) targ;
|
||||
break;
|
||||
case fB | fL:
|
||||
*Rd = *(u8int*) targ;
|
||||
break;
|
||||
}
|
||||
if(Rd == P->R + 15 && !(instr & fL)) {
|
||||
if(instr & fB)
|
||||
*(u8int*) targ += 8;
|
||||
else
|
||||
*(u32int*) targ += 8;
|
||||
}
|
||||
segunlock(seg);
|
||||
if(!(instr & fP))
|
||||
addr += offset;
|
||||
if((instr & fW) || !(instr & fP))
|
||||
*Rn = addr;
|
||||
}
|
||||
|
||||
static void
|
||||
swap(u32int instr)
|
||||
{
|
||||
u32int *Rm, *Rn, *Rd, *targ, tmp;
|
||||
Segment *seg;
|
||||
|
||||
Rm = P->R + (instr & 15);
|
||||
Rd = P->R + ((instr >> 12) & 15);
|
||||
Rn = P->R + ((instr >> 16) & 15);
|
||||
if(Rm == P->R + 15 || Rd == P->R + 15 || Rn == P->R + 15)
|
||||
invalid(instr);
|
||||
targ = (u32int *) vaddr(*Rn, &seg);
|
||||
lock(&seg->lock);
|
||||
if(instr & fB) {
|
||||
tmp = *(u8int*) targ;
|
||||
*(u8int*) targ = *Rm;
|
||||
*Rd = tmp;
|
||||
} else {
|
||||
tmp = *targ;
|
||||
*targ = *Rm;
|
||||
*Rd = tmp;
|
||||
}
|
||||
unlock(&seg->lock);
|
||||
segunlock(seg);
|
||||
}
|
||||
|
||||
static u32int
|
||||
add(u32int a, u32int b, u8int type, u8int *carry, u8int *overflow)
|
||||
{
|
||||
u32int res1;
|
||||
u64int res2;
|
||||
|
||||
if(type) {
|
||||
res2 = (u64int)a - b + *carry - 1;
|
||||
res1 = res2;
|
||||
if(((a ^ b) & (1<<31)) && !((b ^ res1) & (1<<31))) *overflow = 1;
|
||||
if(res2 & 0x100000000LL) *carry = 0;
|
||||
else *carry = 1;
|
||||
} else {
|
||||
res2 = (u64int)a + b + *carry;
|
||||
res1 = res2;
|
||||
if(!((a ^ b) & (1<<31)) && ((b ^ res1) & (1<<31))) *overflow = 1;
|
||||
if(res2 & 0x100000000LL) *carry = 1;
|
||||
else *carry = 0;
|
||||
}
|
||||
return res1;
|
||||
}
|
||||
|
||||
static void
|
||||
alu(u32int instr)
|
||||
{
|
||||
u32int Rn, *Rd, operand, shift, result, op;
|
||||
u8int carry, overflow;
|
||||
|
||||
Rn = P->R[(instr >> 16) & 15];
|
||||
Rd = P->R + ((instr >> 12) & 15);
|
||||
if(((instr >> 16) & 15) == 15) {
|
||||
Rn += 4;
|
||||
if(!(instr & fI) && (instr & (1<<4)))
|
||||
Rn += 4;
|
||||
}
|
||||
if(Rd == P->R + 15 && (instr & fS))
|
||||
invalid(instr);
|
||||
if(instr & fI) {
|
||||
operand = instr & 0xFF;
|
||||
shift = ((instr >> 8) & 15) << 1;
|
||||
operand = (operand >> shift) | (operand << (32 - shift));
|
||||
} else
|
||||
operand = doshift(instr);
|
||||
op = (instr >> 21) & 15;
|
||||
carry = 0;
|
||||
if(op >= 8 && op <= 11 && !(instr & fS))
|
||||
sysfatal("no PSR transfers plz");
|
||||
if(op >= 5 && op < 8) {
|
||||
if(P->CPSR & flC)
|
||||
carry = 1;
|
||||
} else {
|
||||
if(op != 4 && op != 5 && op != 11)
|
||||
carry = 1;
|
||||
}
|
||||
overflow = 0;
|
||||
switch(op) {
|
||||
case 0: case 8: result = Rn & operand; break;
|
||||
case 1: case 9: result = Rn ^ operand; break;
|
||||
case 2: case 6: case 10: result = add(Rn, operand, 1, &carry, &overflow); break;
|
||||
case 3: case 7: result = add(operand, Rn, 1, &carry, &overflow); break;
|
||||
case 4: case 5: case 11: result = add(operand, Rn, 0, &carry, &overflow); break;
|
||||
case 12: result = Rn | operand; break;
|
||||
case 13: result = operand; break;
|
||||
case 14: result = Rn & ~operand; break;
|
||||
case 15: result = ~operand; break;
|
||||
default: result = 0; /* never happens */
|
||||
}
|
||||
if(instr & fS) {
|
||||
P->CPSR &= ~FLAGS;
|
||||
if(result == 0)
|
||||
P->CPSR |= flZ;
|
||||
if(result & (1<<31))
|
||||
P->CPSR |= flN;
|
||||
if(carry && op > 1 && op < 12)
|
||||
P->CPSR |= flC;
|
||||
if(overflow)
|
||||
P->CPSR |= flV;
|
||||
}
|
||||
if(op < 8 || op >= 12)
|
||||
*Rd = result;
|
||||
}
|
||||
|
||||
static void
|
||||
branch(u32int instr)
|
||||
{
|
||||
long offset;
|
||||
|
||||
offset = instr & ((1<<24) - 1);
|
||||
if(offset & (1<<23))
|
||||
offset |= ~((1 << 24) - 1);
|
||||
offset *= 4;
|
||||
if(instr & fLi)
|
||||
P->R[14] = P->R[15];
|
||||
P->R[15] += offset + 4;
|
||||
}
|
||||
|
||||
static void
|
||||
halfword(u32int instr)
|
||||
{
|
||||
u32int offset, target, *Rn, *Rd;
|
||||
Segment *seg;
|
||||
|
||||
if(instr & (1<<22)) {
|
||||
offset = (instr & 15) | ((instr >> 4) & 0xF0);
|
||||
} else {
|
||||
if((instr & 15) == 15)
|
||||
invalid(instr);
|
||||
offset = P->R[instr & 15];
|
||||
}
|
||||
if(!(instr & fU))
|
||||
offset = - offset;
|
||||
if(!(instr & fP) && (instr & fW))
|
||||
invalid(instr);
|
||||
Rn = P->R + ((instr >> 16) & 15);
|
||||
Rd = P->R + ((instr >> 12) & 15);
|
||||
if(Rn == P->R + 15 || Rd == P->R + 15)
|
||||
sysfatal("R15 in halfword");
|
||||
target = *Rn;
|
||||
if(instr & fP)
|
||||
target += offset;
|
||||
switch(instr & (fSg | fH | fL)) {
|
||||
case fSg: *(u8int*) vaddr(target, &seg) = *Rd; break;
|
||||
case fSg | fL: *Rd = (long) *(char*) vaddr(target, &seg); break;
|
||||
case fH: case fSg | fH: *(u16int*) vaddr(target, &seg) = *Rd; break;
|
||||
case fH | fL: *Rd = *(u16int*) vaddr(target, &seg); break;
|
||||
case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, &seg); break;
|
||||
}
|
||||
segunlock(seg);
|
||||
if(!(instr & fP))
|
||||
target += offset;
|
||||
if(!(instr & fP) || (instr & fW))
|
||||
*Rn = target;
|
||||
}
|
||||
|
||||
static void
|
||||
block(u32int instr)
|
||||
{
|
||||
int i;
|
||||
u32int targ, *Rn;
|
||||
Segment *seg;
|
||||
|
||||
if(instr & (1<<22))
|
||||
invalid(instr);
|
||||
Rn = P->R + ((instr >> 16) & 15);
|
||||
if(Rn == P->R + 15 || instr & (1<<15))
|
||||
sysfatal("R15 block");
|
||||
targ = *Rn;
|
||||
if(instr & fU) {
|
||||
for(i = 0; i < 16; i++) {
|
||||
if(!(instr & (1<<i)))
|
||||
continue;
|
||||
if(instr & fP)
|
||||
targ += 4;
|
||||
if(instr & fL)
|
||||
P->R[i] = *(u32int*) vaddr(targ, &seg);
|
||||
else
|
||||
*(u32int*) vaddr(targ, &seg) = P->R[i];
|
||||
segunlock(seg);
|
||||
if(!(instr & fP))
|
||||
targ += 4;
|
||||
}
|
||||
} else {
|
||||
for(i = 15; i >= 0; i--) {
|
||||
if(!(instr & (1<<i)))
|
||||
continue;
|
||||
if(instr & fP)
|
||||
targ -= 4;
|
||||
if(instr & fL)
|
||||
P->R[i] = *(u32int*) vaddr(targ, &seg);
|
||||
else
|
||||
*(u32int*) vaddr(targ, &seg) = P->R[i];
|
||||
segunlock(seg);
|
||||
if(!(instr & fP))
|
||||
targ -= 4;
|
||||
}
|
||||
}
|
||||
if(instr & fW)
|
||||
*Rn = targ;
|
||||
}
|
||||
|
||||
static void
|
||||
multiply(u32int instr)
|
||||
{
|
||||
u32int *Rd, *Rn, *Rs, *Rm, res;
|
||||
|
||||
Rm = P->R + (instr & 15);
|
||||
Rs = P->R + ((instr >> 8) & 15);
|
||||
Rn = P->R + ((instr >> 12) & 15);
|
||||
Rd = P->R + ((instr >> 16) & 15);
|
||||
if(Rd == Rm || Rm == P->R + 15 || Rs == P->R + 15 || Rn == P->R + 15 || Rd == P->R + 15)
|
||||
invalid(instr);
|
||||
res = *Rm * *Rs;
|
||||
if(instr & (1<<21))
|
||||
res += *Rn;
|
||||
*Rd = res;
|
||||
if(instr & (1<<20)) {
|
||||
P->CPSR &= ~(flN | flZ);
|
||||
if(res & (1<<31))
|
||||
P->CPSR |= flN;
|
||||
if(res == 0)
|
||||
P->CPSR |= flZ;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
multiplylong(u32int instr)
|
||||
{
|
||||
u32int *RdH, *RdL, *Rs, *Rm;
|
||||
u64int res;
|
||||
|
||||
Rm = P->R + (instr & 15);
|
||||
Rs = P->R + ((instr >> 8) & 15);
|
||||
RdL = P->R + ((instr >> 12) & 15);
|
||||
RdH = P->R + ((instr >> 16) & 15);
|
||||
if(RdL == RdH || RdH == Rm || RdL == Rm || Rm == P->R + 15 || Rs == P->R + 15 || RdL == P->R + 15 || RdH == P->R + 15)
|
||||
invalid(instr);
|
||||
if(instr & (1<<22)) {
|
||||
res = *Rs;
|
||||
res *= *Rm;
|
||||
} else
|
||||
res = ((vlong)*(int*)Rs) * *(int*)Rm;
|
||||
if(instr & (1<<21)) {
|
||||
res += *RdL;
|
||||
res += ((uvlong)*RdH) << 32;
|
||||
}
|
||||
*RdL = res;
|
||||
*RdH = res >> 32;
|
||||
if(instr & (1<<20)) {
|
||||
P->CPSR &= ~FLAGS;
|
||||
if(res == 0)
|
||||
P->CPSR |= flN;
|
||||
if(res & (1LL<<63))
|
||||
P->CPSR |= flV;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
singleex(u32int instr)
|
||||
{
|
||||
u32int *Rn, *Rd, *Rm, *targ;
|
||||
Segment *seg;
|
||||
|
||||
Rd = P->R + ((instr >> 12) & 15);
|
||||
Rn = P->R + ((instr >> 16) & 15);
|
||||
if(Rd == P->R + 15 || Rn == P->R + 15)
|
||||
invalid(instr);
|
||||
if(instr & fS) {
|
||||
targ = vaddr(*Rn, &seg);
|
||||
lock(&seg->lock);
|
||||
*Rd = *targ;
|
||||
segunlock(seg);
|
||||
} else {
|
||||
Rm = P->R + (instr & 15);
|
||||
if(Rm == P->R + 15)
|
||||
invalid(instr);
|
||||
targ = vaddr(*Rn, &seg);
|
||||
if(canlock(&seg->lock)) {
|
||||
*Rd = 1;
|
||||
} else {
|
||||
*targ = *Rd;
|
||||
unlock(&seg->lock);
|
||||
*Rd = 0;
|
||||
}
|
||||
segunlock(seg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
step(void)
|
||||
{
|
||||
u32int instr;
|
||||
Segment *seg;
|
||||
|
||||
instr = *(u32int*) vaddr(P->R[15], &seg);
|
||||
segunlock(seg);
|
||||
if(fulltrace) {
|
||||
print("%d ", P->pid);
|
||||
if(havesymbols) {
|
||||
Symbol s;
|
||||
char buf[512];
|
||||
|
||||
if(findsym(P->R[15], CTEXT, &s) >= 0)
|
||||
print("%s ", s.name);
|
||||
if(fileline(buf, 512, P->R[15]) >= 0)
|
||||
print("%s ", buf);
|
||||
}
|
||||
print("%.8ux %.8ux %c%c%c%c\n", P->R[15], instr,
|
||||
(P->CPSR & flZ) ? 'Z' : ' ',
|
||||
(P->CPSR & flC) ? 'C' : ' ',
|
||||
(P->CPSR & flN) ? 'N' : ' ',
|
||||
(P->CPSR & flV) ? 'V' : ' '
|
||||
);
|
||||
}
|
||||
P->R[15] += 4;
|
||||
switch(instr >> 28) {
|
||||
case 0x0: if(!(P->CPSR & flZ)) return; break;
|
||||
case 0x1: if(P->CPSR & flZ) return; break;
|
||||
case 0x2: if(!(P->CPSR & flC)) return; break;
|
||||
case 0x3: if(P->CPSR & flC) return; break;
|
||||
case 0x4: if(!(P->CPSR & flN)) return; break;
|
||||
case 0x5: if(P->CPSR & flN) return; break;
|
||||
case 0x6: if(!(P->CPSR & flV)) return; break;
|
||||
case 0x7: if(P->CPSR & flV) return; break;
|
||||
case 0x8: if(!(P->CPSR & flC) || (P->CPSR & flZ)) return; break;
|
||||
case 0x9: if((P->CPSR & flC) && !(P->CPSR & flZ)) return; break;
|
||||
case 0xA: if(!(P->CPSR & flN) != !(P->CPSR & flV)) return; break;
|
||||
case 0xB: if(!(P->CPSR & flN) == !(P->CPSR & flV)) return; break;
|
||||
case 0xC: if((P->CPSR & flZ) || !(P->CPSR & flN) != !(P->CPSR & flV)) return; break;
|
||||
case 0xD: if(!(P->CPSR & flZ) && !(P->CPSR & flN) == !(P->CPSR & flV)) return; break;
|
||||
case 0xE: break;
|
||||
default: sysfatal("condition code %x not implemented", instr >> 28);
|
||||
}
|
||||
if((instr & 0x0FB00FF0) == 0x01000090)
|
||||
swap(instr);
|
||||
else if((instr & 0x0FE000F0) == 0x01800090)
|
||||
singleex(instr);
|
||||
else if((instr & 0x0FC000F0) == 0x90)
|
||||
multiply(instr);
|
||||
else if((instr & 0x0F8000F0) == 0x800090)
|
||||
multiplylong(instr);
|
||||
else if((instr & ((1<<26) | (1<<27))) == (1 << 26))
|
||||
single(instr);
|
||||
else if((instr & 0x0E000090) == 0x90 && (instr & 0x60))
|
||||
halfword(instr);
|
||||
else if((instr & ((1<<26) | (1<<27))) == 0)
|
||||
alu(instr);
|
||||
else if((instr & (7<<25)) == (5 << 25))
|
||||
branch(instr);
|
||||
else if((instr & (15<<24)) == (15 << 24))
|
||||
syscall();
|
||||
else if((instr & (7<<25)) == (4 << 25))
|
||||
block(instr);
|
||||
else
|
||||
invalid(instr);
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
typedef struct Process Process;
|
||||
typedef struct Segment Segment;
|
||||
typedef struct Fdtable Fdtable;
|
||||
typedef struct Fd Fd;
|
||||
|
||||
enum {
|
||||
STACKTOP = 0x80000000UL,
|
||||
STACKSIZE = 0x10000,
|
||||
|
||||
FDBLOCK = 16,
|
||||
SEGNUM = 8,
|
||||
|
||||
flN = 1<<31,
|
||||
flZ = 1<<30,
|
||||
flC = 1<<29,
|
||||
flV = 1<<28,
|
||||
FLAGS = flN | flZ | flC | flV,
|
||||
};
|
||||
|
||||
enum {
|
||||
SEGTEXT,
|
||||
SEGDATA,
|
||||
SEGBSS,
|
||||
SEGSTACK,
|
||||
};
|
||||
|
||||
struct Process {
|
||||
Segment* S[SEGNUM];
|
||||
u32int R[16]; /* general purpose registers / PC (R15) */
|
||||
u32int CPSR; /* status register */
|
||||
char errbuf[ERRMAX];
|
||||
Fd *fd;
|
||||
int pid;
|
||||
};
|
||||
|
||||
extern void **_privates;
|
||||
extern int _nprivates;
|
||||
#define P (*(Process**)_privates)
|
||||
|
||||
enum {
|
||||
SEGFLLOCK = 1,
|
||||
};
|
||||
|
||||
struct Segment {
|
||||
Ref;
|
||||
int flags;
|
||||
RWLock rw; /* lock for SEGLOCK segments */
|
||||
Lock lock; /* atomic accesses */
|
||||
u32int start, size;
|
||||
void *data;
|
||||
Ref *ref;
|
||||
};
|
||||
|
||||
struct Fd {
|
||||
RWLock;
|
||||
Ref ref;
|
||||
u8int *fds;
|
||||
int nfds;
|
||||
};
|
||||
|
||||
#define fulltrace 0
|
||||
#define havesymbols 0
|
||||
#define ultraverbose 0
|
||||
#define systrace 0
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
void *emalloc(u32int);
|
||||
void *emallocz(u32int);
|
||||
void *erealloc(void *, u32int);
|
||||
void initproc(void);
|
||||
int loadtext(char *, int, char **);
|
||||
Segment *newseg(u32int, u32int, int);
|
||||
void *vaddr(u32int, Segment **);
|
||||
void *vaddrnol(u32int);
|
||||
void step(void);
|
||||
void syscall(void);
|
||||
void cherrstr(char *, ...);
|
||||
u32int noteerr(u32int, u32int);
|
||||
void freesegs(void);
|
||||
Fd *newfd(void);
|
||||
Fd *copyfd(Fd *);
|
||||
void fddecref(Fd *);
|
||||
int iscexec(Fd *, int);
|
||||
void setcexec(Fd *, int, int);
|
||||
void cleanup(void);
|
||||
void segunlock(Segment *);
|
||||
void *copyifnec(u32int, int, int *);
|
||||
void *bufifnec(u32int, int, int *);
|
||||
void copyback(u32int, int, void *);
|
|
@ -0,0 +1,7 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG=5e
|
||||
OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O
|
||||
HFILES=dat.h fns.h
|
||||
|
||||
</sys/src/cmd/mkone
|
|
@ -0,0 +1,244 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include <bio.h>
|
||||
#include <mach.h>
|
||||
#include <ctype.h>
|
||||
#include <tos.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
void
|
||||
initproc(void)
|
||||
{
|
||||
P = emallocz(sizeof(Process));
|
||||
P->pid = getpid();
|
||||
P->fd = newfd();
|
||||
}
|
||||
|
||||
static void
|
||||
initstack(int argc, char **argv)
|
||||
{
|
||||
ulong tos, sp, ap, size, i, len;
|
||||
|
||||
tos = STACKTOP - sizeof(Tos) * 2;
|
||||
sp = tos;
|
||||
|
||||
size = 8;
|
||||
for(i = 0; i < argc; i++)
|
||||
size += strlen(argv[i]) + 5;
|
||||
|
||||
sp -= size;
|
||||
sp &= ~7;
|
||||
P->R[0] = tos;
|
||||
P->R[1] = STACKTOP - 4;
|
||||
P->R[13] = sp;
|
||||
|
||||
*(ulong *) vaddrnol(sp) = argc;
|
||||
sp += 4;
|
||||
ap = sp + (argc + 1) * 4;
|
||||
for(i = 0; i < argc; i++) {
|
||||
*(ulong *) vaddrnol(sp) = ap;
|
||||
sp += 4;
|
||||
len = strlen(argv[i]) + 1;
|
||||
memcpy(vaddrnol(ap), argv[i], len);
|
||||
ap += len;
|
||||
}
|
||||
*(ulong *) vaddrnol(sp) = 0;
|
||||
|
||||
((Tos *) vaddrnol(tos))->pid = getpid();
|
||||
}
|
||||
|
||||
static int
|
||||
loadscript(int fd, char *file, int argc, char **argv)
|
||||
{
|
||||
char buf[513], *p, **q, **nargv;
|
||||
int rc, nargc, i;
|
||||
|
||||
seek(fd, 0, 0);
|
||||
rc = readn(fd, buf, 512);
|
||||
if(rc <= 0)
|
||||
goto invalid;
|
||||
close(fd);
|
||||
buf[rc] = 0;
|
||||
p = strchr(buf, '\n');
|
||||
if(p == nil)
|
||||
goto invalid;
|
||||
*p = 0;
|
||||
while(isspace(*--p))
|
||||
*p = 0;
|
||||
nargc = 0;
|
||||
p = buf + 2;
|
||||
while(*p) {
|
||||
while(*p && isspace(*p))
|
||||
p++;
|
||||
nargc++;
|
||||
while(*p && !isspace(*p))
|
||||
p++;
|
||||
}
|
||||
if(nargc == 0)
|
||||
goto invalid;
|
||||
nargv = emallocz(sizeof(char *) * (nargc + argc));
|
||||
q = nargv;
|
||||
p = buf + 2;
|
||||
while(*p) {
|
||||
while(*p && isspace(*p))
|
||||
p++;
|
||||
*(p-1) = 0;
|
||||
*q++ = p;
|
||||
while(*p && !isspace(*p))
|
||||
p++;
|
||||
}
|
||||
*q++ = file;
|
||||
for(i = 1; i < argc; i++)
|
||||
*q++ = argv[i];
|
||||
rc = loadtext(*nargv, argc + nargc, nargv);
|
||||
free(nargv);
|
||||
return rc;
|
||||
|
||||
invalid:
|
||||
werrstr("exec header invalid");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
loadtext(char *file, int argc, char **argv)
|
||||
{
|
||||
int fd, i;
|
||||
Fhdr fp;
|
||||
Segment *text, *data, *bss, *stack;
|
||||
char buf[2];
|
||||
|
||||
fd = open(file, OREAD);
|
||||
if(fd < 0) return -1;
|
||||
if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!')
|
||||
return loadscript(fd, file, argc, argv);
|
||||
seek(fd, 0, 0);
|
||||
if(crackhdr(fd, &fp) == 0) {
|
||||
werrstr("exec header invalid");
|
||||
return -1;
|
||||
}
|
||||
if(fp.magic != E_MAGIC) {
|
||||
werrstr("exec header invalid");
|
||||
return -1;
|
||||
}
|
||||
freesegs();
|
||||
memset(P->R, 0, sizeof(P->R));
|
||||
P->CPSR = 0;
|
||||
text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
|
||||
data = newseg(fp.dataddr, fp.datsz, SEGDATA);
|
||||
bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
|
||||
stack = newseg(STACKTOP - STACKSIZE, STACKSIZE, SEGSTACK);
|
||||
seek(fd, fp.txtoff - fp.hdrsz, 0);
|
||||
if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
|
||||
sysfatal("%r");
|
||||
seek(fd, fp.datoff, 0);
|
||||
if(readn(fd, data->data, fp.datsz) < fp.datsz)
|
||||
sysfatal("%r");
|
||||
memset(bss->data, 0, bss->size);
|
||||
memset(stack->data, 0, stack->size);
|
||||
P->R[15] = fp.entry;
|
||||
if(havesymbols && syminit(fd, &fp) < 0)
|
||||
fprint(2, "initializing symbol table: %r\n");
|
||||
close(fd);
|
||||
for(i = 0; i < P->fd->nfds * 8; i++)
|
||||
if(iscexec(P->fd, i))
|
||||
close(i);
|
||||
wlock(P->fd);
|
||||
free(P->fd->fds);
|
||||
P->fd->fds = nil;
|
||||
P->fd->nfds = 0;
|
||||
wunlock(P->fd);
|
||||
initstack(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cherrstr(char *str, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start(va, str);
|
||||
vsnprint(P->errbuf, ERRMAX, str, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
u32int
|
||||
noteerr(u32int x, u32int y)
|
||||
{
|
||||
if(((int)x) >= ((int)y))
|
||||
return x;
|
||||
rerrstr(P->errbuf, ERRMAX);
|
||||
return x;
|
||||
}
|
||||
|
||||
Fd *
|
||||
newfd(void)
|
||||
{
|
||||
Fd *fd;
|
||||
|
||||
fd = emallocz(sizeof(*fd));
|
||||
incref(&fd->ref);
|
||||
return fd;
|
||||
}
|
||||
|
||||
Fd *
|
||||
copyfd(Fd *old)
|
||||
{
|
||||
Fd *new;
|
||||
|
||||
rlock(old);
|
||||
new = newfd();
|
||||
if(old->nfds > 0) {
|
||||
new->nfds = old->nfds;
|
||||
new->fds = emalloc(old->nfds);
|
||||
memcpy(new->fds, old->fds, old->nfds);
|
||||
}
|
||||
runlock(old);
|
||||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
fddecref(Fd *fd)
|
||||
{
|
||||
if(decref(&fd->ref) == 0) {
|
||||
free(fd->fds);
|
||||
free(fd);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iscexec(Fd *fd, int n)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = 0;
|
||||
rlock(fd);
|
||||
if(n / 8 < fd->nfds)
|
||||
r = (fd->fds[n / 8] & (1 << (n % 8))) != 0;
|
||||
runlock(fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
setcexec(Fd *fd, int n, int status)
|
||||
{
|
||||
int old;
|
||||
|
||||
wlock(fd);
|
||||
if(n / 8 >= fd->nfds) {
|
||||
if(status == 0) {
|
||||
wunlock(fd);
|
||||
return;
|
||||
}
|
||||
old = fd->nfds;
|
||||
fd->nfds = (n / 8) + 1;
|
||||
fd->fds = erealloc(fd->fds, fd->nfds);
|
||||
memset(fd->fds + old, 0, fd->nfds - old);
|
||||
}
|
||||
if(status == 0)
|
||||
fd->fds[n / 8] &= ~(1 << (n % 8));
|
||||
else
|
||||
fd->fds[n / 8] |= (1 << (n % 8));
|
||||
wunlock(fd);
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
Segment *
|
||||
newseg(u32int start, u32int size, int idx)
|
||||
{
|
||||
Segment *s;
|
||||
|
||||
s = emallocz(sizeof *s);
|
||||
incref(s);
|
||||
s->start = start;
|
||||
s->size = size;
|
||||
s->ref = emalloc(size + sizeof(Ref));
|
||||
memset(s->ref, 0, sizeof(Ref));
|
||||
incref(s->ref);
|
||||
s->data = s->ref + 1;
|
||||
if(idx == SEGBSS)
|
||||
s->flags = SEGFLLOCK;
|
||||
P->S[idx] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
freesegs(void)
|
||||
{
|
||||
Segment **s;
|
||||
|
||||
for(s = P->S; s < P->S + SEGNUM; s++) {
|
||||
if(*s == nil)
|
||||
continue;
|
||||
if(decref((*s)->ref) == 0)
|
||||
free((*s)->ref);
|
||||
if(decref(*s) == 0)
|
||||
free(*s);
|
||||
*s = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
vaddr(u32int addr, Segment **seg)
|
||||
{
|
||||
Segment **ss, *s;
|
||||
|
||||
for(ss = P->S; ss < P->S + SEGNUM; ss++) {
|
||||
if(*ss == nil)
|
||||
continue;
|
||||
s = *ss;
|
||||
if(addr >= s->start && addr < s->start + s->size) {
|
||||
if(s->flags & SEGFLLOCK)
|
||||
rlock(&s->rw);
|
||||
*seg = s;
|
||||
return (char *)s->data + (addr - s->start);
|
||||
}
|
||||
}
|
||||
sysfatal("fault %.8ux @ %.8ux", addr, P->R[15]);
|
||||
return nil;
|
||||
}
|
||||
|
||||
void *
|
||||
vaddrnol(u32int addr)
|
||||
{
|
||||
Segment *seg;
|
||||
void *ret;
|
||||
|
||||
ret = vaddr(addr, &seg);
|
||||
segunlock(seg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* might be made a macro for hurr durr performance */
|
||||
void
|
||||
segunlock(Segment *s)
|
||||
{
|
||||
if(s->flags & SEGFLLOCK)
|
||||
runlock(&s->rw);
|
||||
}
|
||||
|
||||
void *
|
||||
copyifnec(u32int addr, int len, int *copied)
|
||||
{
|
||||
void *targ, *ret;
|
||||
Segment *seg;
|
||||
|
||||
targ = vaddr(addr, &seg);
|
||||
if((seg->flags & SEGFLLOCK) == 0) {
|
||||
*copied = 0;
|
||||
return targ;
|
||||
}
|
||||
if(len < 0)
|
||||
len = strlen(targ) + 1;
|
||||
ret = emalloc(len);
|
||||
memcpy(ret, targ, len);
|
||||
segunlock(seg);
|
||||
*copied = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
bufifnec(u32int addr, int len, int *buffered)
|
||||
{
|
||||
void *targ;
|
||||
Segment *seg;
|
||||
|
||||
targ = vaddr(addr, &seg);
|
||||
if((seg->flags & SEGFLLOCK) == 0) {
|
||||
*buffered = 0;
|
||||
return targ;
|
||||
}
|
||||
segunlock(seg);
|
||||
*buffered = 1;
|
||||
return emalloc(len);
|
||||
}
|
||||
|
||||
void
|
||||
copyback(u32int addr, int len, void *data)
|
||||
{
|
||||
void *targ;
|
||||
Segment *seg;
|
||||
|
||||
if(len <= 0)
|
||||
return;
|
||||
targ = vaddr(addr, &seg);
|
||||
memmove(targ, data, len);
|
||||
segunlock(seg);
|
||||
free(data);
|
||||
}
|
|
@ -0,0 +1,576 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include </sys/src/libc/9syscall/sys.h>
|
||||
|
||||
static u32int
|
||||
arg(int n)
|
||||
{
|
||||
/* no locking necessary, since we're on the stack */
|
||||
return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n);
|
||||
}
|
||||
|
||||
static u64int
|
||||
argv(int n)
|
||||
{
|
||||
return arg(n) | ((u64int)arg(n+1) << 32);
|
||||
}
|
||||
|
||||
static void
|
||||
sysopen(void)
|
||||
{
|
||||
u32int name, flags;
|
||||
char *namet;
|
||||
int fd, copied;
|
||||
|
||||
name = arg(0);
|
||||
flags = arg(1);
|
||||
namet = copyifnec(name, -1, &copied);
|
||||
if(systrace)
|
||||
fprint(2, "open(%#ux=\"%s\", %#o)\n", name, namet, flags);
|
||||
fd = open(namet, flags);
|
||||
if(copied)
|
||||
free(namet);
|
||||
if(fd < 0) {
|
||||
noteerr(0, 1);
|
||||
P->R[0] = fd;
|
||||
return;
|
||||
}
|
||||
setcexec(P->fd, fd, flags & OCEXEC);
|
||||
P->R[0] = fd;
|
||||
}
|
||||
|
||||
static void
|
||||
syscreate(void)
|
||||
{
|
||||
u32int name, flags, perm;
|
||||
char *namet;
|
||||
int fd, copied;
|
||||
|
||||
name = arg(0);
|
||||
flags = arg(1);
|
||||
perm = arg(2);
|
||||
namet = copyifnec(name, -1, &copied);
|
||||
if(systrace)
|
||||
fprint(2, "create(%#ux=\"%s\", %#o, %o)\n", name, namet, flags, perm);
|
||||
fd = create(namet, flags, perm);
|
||||
if(copied)
|
||||
free(namet);
|
||||
if(fd < 0) {
|
||||
noteerr(0, 1);
|
||||
P->R[0] = fd;
|
||||
return;
|
||||
}
|
||||
setcexec(P->fd, fd, flags & OCEXEC);
|
||||
P->R[0] = fd;
|
||||
}
|
||||
|
||||
static void
|
||||
sysclose(void)
|
||||
{
|
||||
u32int fd;
|
||||
|
||||
fd = arg(0);
|
||||
if(systrace)
|
||||
fprint(2, "close(%d)\n", fd);
|
||||
P->R[0] = noteerr(close(fd), 0);
|
||||
if((fd & (1<<31)) == 0)
|
||||
setcexec(P->fd, fd, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
syspread(void)
|
||||
{
|
||||
int buffered;
|
||||
u32int fd, size, buf;
|
||||
u64int off;
|
||||
void *targ;
|
||||
|
||||
fd = arg(0);
|
||||
buf = arg(1);
|
||||
size = arg(2);
|
||||
off = argv(3);
|
||||
if(systrace)
|
||||
fprint(2, "pread(%d, %#ux, %ud, %#ullx)\n", fd, buf, size, off);
|
||||
targ = bufifnec(buf, size, &buffered);
|
||||
P->R[0] = noteerr(pread(fd, targ, size, off), size);
|
||||
if(buffered)
|
||||
copyback(buf, P->R[0], targ);
|
||||
}
|
||||
|
||||
static void
|
||||
syspwrite(void)
|
||||
{
|
||||
u32int fd, size, buf;
|
||||
u64int off;
|
||||
int copied;
|
||||
void *buft;
|
||||
|
||||
fd = arg(0);
|
||||
buf = arg(1);
|
||||
size = arg(2);
|
||||
off = argv(3);
|
||||
buft = copyifnec(buf, size, &copied);
|
||||
if(systrace)
|
||||
fprint(2, "pwrite(%d, %#ux, %ud, %#ullx)\n", fd, buf, size, off);
|
||||
P->R[0] = noteerr(pwrite(fd, buft, size, off), size);
|
||||
if(copied)
|
||||
free(buft);
|
||||
}
|
||||
|
||||
static void
|
||||
sysseek(void)
|
||||
{
|
||||
u32int fd, type;
|
||||
vlong n, *ret;
|
||||
Segment *seg;
|
||||
|
||||
ret = vaddr(arg(0), &seg);
|
||||
fd = arg(1);
|
||||
n = argv(2);
|
||||
type = arg(4);
|
||||
if(systrace)
|
||||
fprint(2, "seek(%d, %lld, %d)\n", fd, n, type);
|
||||
*ret = seek(fd, n, type);
|
||||
if(*ret < 0) noteerr(0, 1);
|
||||
segunlock(seg);
|
||||
}
|
||||
|
||||
static void
|
||||
sysfd2path(void)
|
||||
{
|
||||
u32int fd, buf, nbuf;
|
||||
void *buft;
|
||||
int buffered;
|
||||
|
||||
fd = arg(0);
|
||||
buf = arg(1);
|
||||
nbuf = arg(2);
|
||||
buft = bufifnec(buf, nbuf, &buffered);
|
||||
if(systrace)
|
||||
fprint(2, "fd2path(%d, %#ux, %d)\n", fd, buf, nbuf);
|
||||
P->R[0] = noteerr(fd2path(fd, buft, nbuf), 0);
|
||||
if(buffered)
|
||||
copyback(buf, nbuf, buft);
|
||||
}
|
||||
|
||||
static void
|
||||
sysstat(void)
|
||||
{
|
||||
u32int name, edir, nedir;
|
||||
char *namet;
|
||||
void *edirt;
|
||||
int copied, buffered;
|
||||
|
||||
name = arg(0);
|
||||
namet = copyifnec(name, -1, &copied);
|
||||
edir = arg(1);
|
||||
nedir = arg(2);
|
||||
edirt = bufifnec(edir, nedir, &buffered);
|
||||
if(systrace)
|
||||
fprint(2, "stat(%#ux=\"%s\", %#ux, %ud)\n", name, namet, edir, nedir);
|
||||
P->R[0] = noteerr(stat(namet, edirt, nedir), nedir);
|
||||
if(copied)
|
||||
free(namet);
|
||||
if(buffered)
|
||||
copyback(edir, P->R[0], edirt);
|
||||
}
|
||||
|
||||
static void
|
||||
sysfstat(void)
|
||||
{
|
||||
u32int fd, edir, nedir;
|
||||
void *edirt;
|
||||
int buffered;
|
||||
|
||||
fd = arg(0);
|
||||
edir = arg(1);
|
||||
nedir = arg(2);
|
||||
edirt = bufifnec(edir, nedir, &buffered);
|
||||
if(systrace)
|
||||
fprint(2, "fstat(%d, %#ux, %d)\n", fd, edir, nedir);
|
||||
P->R[0] = noteerr(fstat(fd, edirt, nedir), nedir);
|
||||
if(buffered)
|
||||
copyback(edir, P->R[0], edirt);
|
||||
}
|
||||
|
||||
static void
|
||||
sysexits(void)
|
||||
{
|
||||
if(arg(0) == 0)
|
||||
exits(nil);
|
||||
else
|
||||
exits(vaddrnol(arg(0)));
|
||||
}
|
||||
|
||||
static void
|
||||
sysbrk(void)
|
||||
{
|
||||
ulong v;
|
||||
Segment *s;
|
||||
|
||||
v = arg(0);
|
||||
if(v >= P->S[SEGSTACK]->start)
|
||||
sysfatal("bss > stack, wtf?");
|
||||
if(v < P->S[SEGBSS]->start)
|
||||
sysfatal("bss length < 0, wtf?");
|
||||
s = P->S[SEGBSS];
|
||||
wlock(&s->rw);
|
||||
s->ref = realloc(s->ref, v - s->start + 4);
|
||||
if(s->ref == nil)
|
||||
sysfatal("error reallocating");
|
||||
s->data = s->ref + 1;
|
||||
if(s->size < v - s->start)
|
||||
memset((char*)s->data + s->size, 0, v - s->start - s->size);
|
||||
s->size = v - s->start;
|
||||
P->R[0] = 0;
|
||||
wunlock(&s->rw);
|
||||
}
|
||||
|
||||
static void
|
||||
syserrstr(void)
|
||||
{
|
||||
char buf[ERRMAX], *srct;
|
||||
u32int src, len;
|
||||
int copied;
|
||||
|
||||
src = arg(0);
|
||||
len = arg(1);
|
||||
srct = copyifnec(src, len, &copied);
|
||||
strcpy(buf, P->errbuf);
|
||||
utfecpy(P->errbuf, P->errbuf + ERRMAX, srct);
|
||||
utfecpy(srct, srct + len, buf);
|
||||
if(copied)
|
||||
copyback(src, len, srct);
|
||||
P->R[0] = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
syschdir(void)
|
||||
{
|
||||
u32int dir;
|
||||
char *dirt;
|
||||
int copied;
|
||||
|
||||
dir = arg(0);
|
||||
dirt = copyifnec(dir, -1, &copied);
|
||||
if(systrace)
|
||||
fprint(2, "chdir(%#ux=\"%s\")\n", dir, dirt);
|
||||
P->R[0] = noteerr(chdir(dirt), 0);
|
||||
if(copied)
|
||||
free(dirt);
|
||||
}
|
||||
|
||||
static void
|
||||
sysnotify(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
sysrfork(void)
|
||||
{
|
||||
u32int flags;
|
||||
int rc, i;
|
||||
Process *p;
|
||||
Segment *s, *t;
|
||||
Fd *old;
|
||||
enum {
|
||||
RFORKPASS = RFENVG | RFCENVG | RFNOTEG | RFNOMNT | RFNAMEG | RFCNAMEG | RFNOWAIT | RFREND | RFFDG | RFCFDG,
|
||||
RFORKHANDLED = RFPROC | RFMEM,
|
||||
};
|
||||
|
||||
flags = arg(0);
|
||||
if(systrace)
|
||||
fprint(2, "rfork(%#o)\n", flags);
|
||||
if(flags & ~(RFORKPASS | RFORKHANDLED))
|
||||
sysfatal("rfork with unhandled flags %#o", flags & ~(RFORKPASS | RFORKHANDLED));
|
||||
if((flags & RFPROC) == 0) {
|
||||
if(flags & RFFDG) {
|
||||
old = P->fd;
|
||||
P->fd = copyfd(P->fd);
|
||||
fddecref(old);
|
||||
}
|
||||
if(flags & RFCFDG) {
|
||||
old = P->fd;
|
||||
P->fd = newfd();
|
||||
fddecref(old);
|
||||
}
|
||||
P->R[0] = noteerr(rfork(flags & RFORKPASS), 0);
|
||||
return;
|
||||
}
|
||||
p = emallocz(sizeof(Process));
|
||||
memcpy(p, P, sizeof(Process));
|
||||
for(i = 0; i < SEGNUM; i++) {
|
||||
s = p->S[i];
|
||||
if(s == nil)
|
||||
continue;
|
||||
if((flags & RFMEM) == 0 && i != SEGTEXT || i == SEGSTACK) {
|
||||
t = emallocz(sizeof(Segment));
|
||||
incref(t);
|
||||
t->size = s->size;
|
||||
t->start = s->start;
|
||||
t->ref = emalloc(sizeof(Ref) + s->size);
|
||||
memset(t->ref, 0, sizeof(Ref));
|
||||
incref(t->ref);
|
||||
t->data = t->ref + 1;
|
||||
memcpy(t->data, s->data, s->size);
|
||||
p->S[i] = t;
|
||||
} else {
|
||||
incref(s);
|
||||
incref(s->ref);
|
||||
}
|
||||
}
|
||||
|
||||
if(flags & RFFDG)
|
||||
p->fd = copyfd(P->fd);
|
||||
else if(flags & RFCFDG)
|
||||
p->fd = newfd();
|
||||
else
|
||||
incref(&P->fd->ref);
|
||||
|
||||
rc = rfork(RFPROC | RFMEM | (flags & RFORKPASS));
|
||||
if(rc < 0)
|
||||
sysfatal("rfork: %r");
|
||||
if(rc == 0) {
|
||||
P = p;
|
||||
atexit(cleanup);
|
||||
P->pid = getpid();
|
||||
}
|
||||
P->R[0] = rc;
|
||||
}
|
||||
|
||||
static void
|
||||
sysexec(void)
|
||||
{
|
||||
u32int name, argv, *argvt;
|
||||
char *namet, **argvv;
|
||||
int i, argc, rc;
|
||||
Segment *seg1, *seg2;
|
||||
|
||||
name = arg(0);
|
||||
argv = arg(1);
|
||||
namet = strdup(vaddr(name, &seg1));
|
||||
segunlock(seg1);
|
||||
argvt = vaddr(argv, &seg1);
|
||||
if(systrace)
|
||||
fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv);
|
||||
for(argc = 0; argvt[argc]; argc++)
|
||||
;
|
||||
argvv = emalloc(sizeof(char *) * argc);
|
||||
for(i = 0; i < argc; i++) {
|
||||
argvv[i] = strdup(vaddr(argvt[i], &seg2));
|
||||
segunlock(seg2);
|
||||
}
|
||||
segunlock(seg1);
|
||||
rc = loadtext(namet, argc, argvv);
|
||||
for(i = 0; i < argc; i++)
|
||||
free(argvv[i]);
|
||||
free(argvv);
|
||||
if(rc < 0)
|
||||
P->R[0] = noteerr(rc, 0);
|
||||
free(namet);
|
||||
}
|
||||
|
||||
static void
|
||||
sysawait(void)
|
||||
{
|
||||
u32int s, n;
|
||||
void *st;
|
||||
int buffered;
|
||||
|
||||
s = arg(0);
|
||||
n = arg(1);
|
||||
st = bufifnec(s, n, &buffered);
|
||||
if(systrace)
|
||||
fprint(2, "await(%#ux, %d)\n", s, n);
|
||||
P->R[0] = noteerr(await(st, n), 0);
|
||||
if(buffered)
|
||||
copyback(s, P->R[0], st);
|
||||
}
|
||||
|
||||
static void
|
||||
syspipe(void)
|
||||
{
|
||||
u32int fd, *fdt;
|
||||
int buffered;
|
||||
|
||||
fd = arg(0);
|
||||
if(systrace)
|
||||
fprint(2, "pipe(%#ux)\n", fd);
|
||||
fdt = bufifnec(fd, 8, &buffered);
|
||||
P->R[0] = noteerr(pipe((int *) fdt), 0);
|
||||
if(buffered)
|
||||
copyback(fd, 8, fdt);
|
||||
}
|
||||
|
||||
static void
|
||||
sysdup(void)
|
||||
{
|
||||
u32int oldfd, newfd;
|
||||
|
||||
oldfd = arg(0);
|
||||
newfd = arg(1);
|
||||
if(systrace)
|
||||
fprint(2, "dup(%d, %d)\n", oldfd, newfd);
|
||||
P->R[0] = noteerr(dup(oldfd, newfd), 0);
|
||||
}
|
||||
|
||||
static void
|
||||
syssleep(void)
|
||||
{
|
||||
u32int n;
|
||||
|
||||
n = arg(0);
|
||||
if(systrace)
|
||||
fprint(2, "sleep(%d)\n", n);
|
||||
P->R[0] = noteerr(sleep(n), 0);
|
||||
}
|
||||
|
||||
static void
|
||||
sysrendezvous(void)
|
||||
{
|
||||
u32int tag, value;
|
||||
|
||||
tag = arg(0);
|
||||
value = arg(1);
|
||||
if(systrace)
|
||||
fprint(2, "rendezvous(%#ux, %#ux)\n", tag, value);
|
||||
P->R[0] = (u32int) rendezvous((void *) tag, (void *) value);
|
||||
if(P->R[0] == ~0)
|
||||
noteerr(0, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
sysmount(void)
|
||||
{
|
||||
u32int fd, afd, old, flag, aname;
|
||||
char *oldt, *anamet;
|
||||
int copiedold, copiedaname;
|
||||
|
||||
fd = arg(0);
|
||||
afd = arg(1);
|
||||
old = arg(2);
|
||||
flag = arg(3);
|
||||
aname = arg(4);
|
||||
oldt = copyifnec(old, -1, &copiedold);
|
||||
if(aname) {
|
||||
anamet = copyifnec(aname, -1, &copiedaname);
|
||||
if(systrace)
|
||||
fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, %#x=\"%s\")\n", fd, afd, old, oldt, flag, aname, anamet);
|
||||
} else {
|
||||
anamet = nil;
|
||||
copiedaname = 0;
|
||||
if(systrace)
|
||||
fprint(2, "mount(%d, %d, %#x=\"%s\", %#o, nil)\n", fd, afd, old, oldt, flag);
|
||||
}
|
||||
P->R[0] = noteerr(mount(fd, afd, oldt, flag, anamet), 0);
|
||||
if(copiedold)
|
||||
free(oldt);
|
||||
if(copiedaname)
|
||||
free(anamet);
|
||||
}
|
||||
|
||||
static void
|
||||
sysbind(void)
|
||||
{
|
||||
u32int name, old, flags;
|
||||
char *namet, *oldt;
|
||||
int copiedname, copiedold;
|
||||
|
||||
name = arg(0);
|
||||
old = arg(1);
|
||||
flags = arg(2);
|
||||
namet = copyifnec(name, -1, &copiedname);
|
||||
oldt = copyifnec(old, -1, &copiedold);
|
||||
if(systrace)
|
||||
fprint(2, "bind(%#ux=\"%s\", %#ux=\"%s\", %#o)\n", name, namet, old, oldt, flags);
|
||||
P->R[0] = noteerr(bind(namet, oldt, flags), 0);
|
||||
if(copiedname)
|
||||
free(namet);
|
||||
if(copiedold)
|
||||
free(oldt);
|
||||
}
|
||||
|
||||
static void
|
||||
sysunmount(void)
|
||||
{
|
||||
u32int name, old;
|
||||
char *namet, *oldt;
|
||||
int copiedname, copiedold;
|
||||
|
||||
name = arg(0);
|
||||
old = arg(1);
|
||||
oldt = copyifnec(old, -1, &copiedold);
|
||||
if(name == 0) {
|
||||
namet = nil;
|
||||
copiedname = 0;
|
||||
if(systrace)
|
||||
fprint(2, "unmount(nil, %#ux=\"%s\")\n", old, oldt);
|
||||
P->R[0] = noteerr(unmount(nil, oldt), 0);
|
||||
} else {
|
||||
namet = copyifnec(name, -1, &copiedname);
|
||||
if(systrace)
|
||||
fprint(2, "unmount(%#ux=\"%s\", %#ux=\"%s\")\n", name, namet, old, oldt);
|
||||
P->R[0] = noteerr(unmount(namet, oldt), 0);
|
||||
}
|
||||
if(copiedold)
|
||||
free(oldt);
|
||||
if(copiedname)
|
||||
free(namet);
|
||||
}
|
||||
|
||||
static void
|
||||
sysremove(void)
|
||||
{
|
||||
u32int file;
|
||||
char *filet;
|
||||
int copied;
|
||||
|
||||
file = arg(0);
|
||||
filet = copyifnec(file, -1, &copied);
|
||||
if(systrace)
|
||||
fprint(2, "remove(%#ux=\"%s\")\n", file, filet);
|
||||
P->R[0] = noteerr(remove(filet), 0);
|
||||
if(copied)
|
||||
free(filet);
|
||||
}
|
||||
|
||||
void
|
||||
syscall(void)
|
||||
{
|
||||
u32int n;
|
||||
static void (*calls[])(void) = {
|
||||
[EXITS] sysexits,
|
||||
[CLOSE] sysclose,
|
||||
[OPEN] sysopen,
|
||||
[CREATE] syscreate,
|
||||
[PREAD] syspread,
|
||||
[PWRITE] syspwrite,
|
||||
[BRK_] sysbrk,
|
||||
[ERRSTR] syserrstr,
|
||||
[STAT] sysstat,
|
||||
[FSTAT] sysfstat,
|
||||
[SEEK] sysseek,
|
||||
[CHDIR] syschdir,
|
||||
[FD2PATH] sysfd2path,
|
||||
[NOTIFY] sysnotify,
|
||||
[RFORK] sysrfork,
|
||||
[EXEC] sysexec,
|
||||
[AWAIT] sysawait,
|
||||
[PIPE] syspipe,
|
||||
[SLEEP] syssleep,
|
||||
[RENDEZVOUS] sysrendezvous,
|
||||
[BIND] sysbind,
|
||||
[UNMOUNT] sysunmount,
|
||||
[DUP] sysdup,
|
||||
[MOUNT] sysmount,
|
||||
[REMOVE] sysremove,
|
||||
};
|
||||
|
||||
n = P->R[0];
|
||||
if(n >= nelem(calls) || calls[n] == nil)
|
||||
sysfatal("no such syscall %d @ %#ux", n, P->R[15] - 4);
|
||||
calls[n]();
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <thread.h>
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
void *
|
||||
emalloc(u32int size)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = malloc(size);
|
||||
if(v == nil)
|
||||
sysfatal("%r");
|
||||
return v;
|
||||
}
|
||||
|
||||
void *
|
||||
emallocz(u32int size)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = emalloc(size);
|
||||
memset(v, 0, size);
|
||||
return v;
|
||||
}
|
||||
|
||||
void *
|
||||
erealloc(void *old, u32int size)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = realloc(old, size);
|
||||
if(v == nil)
|
||||
sysfatal("%r");
|
||||
return v;
|
||||
}
|
Loading…
Reference in New Issue