555 lines
12 KiB
C
555 lines
12 KiB
C
#include "l.h"
|
|
|
|
#define Dbufslop 100
|
|
|
|
#define PADDR(a) ((ulong)(a) & ~0xF0000000)
|
|
|
|
long
|
|
entryvalue(void)
|
|
{
|
|
char *a;
|
|
Sym *s;
|
|
|
|
a = INITENTRY;
|
|
if(*a >= '0' && *a <= '9')
|
|
return atolwhex(a);
|
|
s = lookup(a, 0);
|
|
if(s->type == 0)
|
|
return INITTEXT;
|
|
switch(s->type) {
|
|
case STEXT:
|
|
break;
|
|
case SDATA:
|
|
if(dlm)
|
|
return s->value+INITDAT;
|
|
default:
|
|
diag("entry not text: %s", s->name);
|
|
}
|
|
return s->value;
|
|
}
|
|
|
|
void
|
|
wputl(ushort w)
|
|
{
|
|
cput(w);
|
|
cput(w>>8);
|
|
}
|
|
|
|
void
|
|
wput(ushort w)
|
|
{
|
|
cput(w>>8);
|
|
cput(w);
|
|
}
|
|
|
|
void
|
|
lput(long l)
|
|
{
|
|
cput(l>>24);
|
|
cput(l>>16);
|
|
cput(l>>8);
|
|
cput(l);
|
|
}
|
|
|
|
void
|
|
lputl(long l)
|
|
{
|
|
cput(l);
|
|
cput(l>>8);
|
|
cput(l>>16);
|
|
cput(l>>24);
|
|
}
|
|
|
|
void
|
|
strnput(char *s, int n)
|
|
{
|
|
for(; *s && n > 0; s++){
|
|
cput(*s);
|
|
n--;
|
|
}
|
|
while(n > 0){
|
|
cput(0);
|
|
n--;
|
|
}
|
|
}
|
|
|
|
void
|
|
asmb(void)
|
|
{
|
|
Prog *p;
|
|
long v, magic;
|
|
int a;
|
|
uchar *op1;
|
|
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f asmb\n", cputime());
|
|
Bflush(&bso);
|
|
|
|
seek(cout, HEADR, 0);
|
|
pc = INITTEXT;
|
|
curp = firstp;
|
|
for(p = firstp; p != P; p = p->link) {
|
|
if(p->as == ATEXT)
|
|
curtext = p;
|
|
if(p->pc != pc) {
|
|
if(!debug['a'])
|
|
print("%P\n", curp);
|
|
diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME);
|
|
pc = p->pc;
|
|
}
|
|
curp = p;
|
|
asmins(p);
|
|
if(cbc < sizeof(and))
|
|
cflush();
|
|
a = (andptr - and);
|
|
if(debug['a']) {
|
|
Bprint(&bso, pcstr, pc);
|
|
for(op1 = and; op1 < andptr; op1++)
|
|
Bprint(&bso, "%.2ux", *op1 & 0xff);
|
|
Bprint(&bso, "\t%P\n", curp);
|
|
}
|
|
if(dlm) {
|
|
if(p->as == ATEXT)
|
|
reloca = nil;
|
|
else if(reloca != nil)
|
|
diag("reloc failure: %P", curp);
|
|
}
|
|
memmove(cbp, and, a);
|
|
cbp += a;
|
|
pc += a;
|
|
cbc -= a;
|
|
}
|
|
cflush();
|
|
switch(HEADTYPE) {
|
|
default:
|
|
diag("unknown header type %ld", HEADTYPE);
|
|
case 0:
|
|
seek(cout, rnd(HEADR+textsize, 8192), 0);
|
|
break;
|
|
case 1:
|
|
textsize = rnd(HEADR+textsize, 4096)-HEADR;
|
|
seek(cout, textsize+HEADR, 0);
|
|
break;
|
|
case 2:
|
|
case 5:
|
|
seek(cout, HEADR+textsize, 0);
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
seek(cout, HEADR+rnd(textsize, INITRND), 0);
|
|
break;
|
|
}
|
|
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f datblk\n", cputime());
|
|
Bflush(&bso);
|
|
|
|
if(dlm){
|
|
char buf[8];
|
|
|
|
write(cout, buf, INITDAT-textsize);
|
|
textsize = INITDAT;
|
|
}
|
|
|
|
for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) {
|
|
if(datsize-v > sizeof(buf)-Dbufslop)
|
|
datblk(v, sizeof(buf)-Dbufslop);
|
|
else
|
|
datblk(v, datsize-v);
|
|
}
|
|
|
|
symsize = 0;
|
|
spsize = 0;
|
|
lcsize = 0;
|
|
if(!debug['s']) {
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f sym\n", cputime());
|
|
Bflush(&bso);
|
|
switch(HEADTYPE) {
|
|
default:
|
|
case 0:
|
|
seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0);
|
|
break;
|
|
case 1:
|
|
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
|
|
break;
|
|
case 2:
|
|
case 5:
|
|
seek(cout, HEADR+textsize+datsize, 0);
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
debug['s'] = 1;
|
|
break;
|
|
}
|
|
if(!debug['s'])
|
|
asmsym();
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f sp\n", cputime());
|
|
Bflush(&bso);
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f pc\n", cputime());
|
|
Bflush(&bso);
|
|
if(!debug['s'])
|
|
asmlc();
|
|
if(dlm)
|
|
asmdyn();
|
|
cflush();
|
|
}
|
|
else if(dlm){
|
|
seek(cout, HEADR+textsize+datsize, 0);
|
|
asmdyn();
|
|
cflush();
|
|
}
|
|
if(debug['v'])
|
|
Bprint(&bso, "%5.2f headr\n", cputime());
|
|
Bflush(&bso);
|
|
seek(cout, 0L, 0);
|
|
switch(HEADTYPE) {
|
|
default:
|
|
case 0: /* garbage */
|
|
lput(0x160L<<16); /* magic and sections */
|
|
lput(0L); /* time and date */
|
|
lput(rnd(HEADR+textsize, 4096)+datsize);
|
|
lput(symsize); /* nsyms */
|
|
lput((0x38L<<16)|7L); /* size of optional hdr and flags */
|
|
lput((0413<<16)|0437L); /* magic and version */
|
|
lput(rnd(HEADR+textsize, 4096));/* sizes */
|
|
lput(datsize);
|
|
lput(bsssize);
|
|
lput(entryvalue()); /* va of entry */
|
|
lput(INITTEXT-HEADR); /* va of base of text */
|
|
lput(INITDAT); /* va of base of data */
|
|
lput(INITDAT+datsize); /* va of base of bss */
|
|
lput(~0L); /* gp reg mask */
|
|
lput(0L);
|
|
lput(0L);
|
|
lput(0L);
|
|
lput(0L);
|
|
lput(~0L); /* gp value ?? */
|
|
break;
|
|
case 1: /* unix coff */
|
|
/*
|
|
* file header
|
|
*/
|
|
lputl(0x0004014c); /* 4 sections, magic */
|
|
lputl(0); /* unix time stamp */
|
|
lputl(0); /* symbol table */
|
|
lputl(0); /* nsyms */
|
|
lputl(0x0003001c); /* flags, sizeof a.out header */
|
|
/*
|
|
* a.out header
|
|
*/
|
|
lputl(0x10b); /* magic, version stamp */
|
|
lputl(rnd(textsize, INITRND)); /* text sizes */
|
|
lputl(datsize); /* data sizes */
|
|
lputl(bsssize); /* bss sizes */
|
|
lput(entryvalue()); /* va of entry */
|
|
lputl(INITTEXT); /* text start */
|
|
lputl(INITDAT); /* data start */
|
|
/*
|
|
* text section header
|
|
*/
|
|
strnput(".text", 8);
|
|
lputl(HEADR); /* pa */
|
|
lputl(HEADR); /* va */
|
|
lputl(textsize); /* text size */
|
|
lputl(HEADR); /* file offset */
|
|
lputl(0); /* relocation */
|
|
lputl(0); /* line numbers */
|
|
lputl(0); /* relocation, line numbers */
|
|
lputl(0x20); /* flags text only */
|
|
/*
|
|
* data section header
|
|
*/
|
|
strnput(".data", 8);
|
|
lputl(INITDAT); /* pa */
|
|
lputl(INITDAT); /* va */
|
|
lputl(datsize); /* data size */
|
|
lputl(HEADR+textsize); /* file offset */
|
|
lputl(0); /* relocation */
|
|
lputl(0); /* line numbers */
|
|
lputl(0); /* relocation, line numbers */
|
|
lputl(0x40); /* flags data only */
|
|
/*
|
|
* bss section header
|
|
*/
|
|
strnput(".bss", 8);
|
|
lputl(INITDAT+datsize); /* pa */
|
|
lputl(INITDAT+datsize); /* va */
|
|
lputl(bsssize); /* bss size */
|
|
lputl(0); /* file offset */
|
|
lputl(0); /* relocation */
|
|
lputl(0); /* line numbers */
|
|
lputl(0); /* relocation, line numbers */
|
|
lputl(0x80); /* flags bss only */
|
|
/*
|
|
* comment section header
|
|
*/
|
|
strnput(".comment", 8);
|
|
lputl(0); /* pa */
|
|
lputl(0); /* va */
|
|
lputl(symsize+lcsize); /* comment size */
|
|
lputl(HEADR+textsize+datsize); /* file offset */
|
|
lputl(HEADR+textsize+datsize); /* offset of syms */
|
|
lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */
|
|
lputl(0); /* relocation, line numbers */
|
|
lputl(0x200); /* flags comment only */
|
|
break;
|
|
case 2: /* plan9 */
|
|
magic = 4*11*11+7;
|
|
if(dlm)
|
|
magic |= 0x80000000;
|
|
lput(magic); /* magic */
|
|
lput(textsize); /* sizes */
|
|
lput(datsize);
|
|
lput(bsssize);
|
|
lput(symsize); /* nsyms */
|
|
lput(entryvalue()); /* va of entry */
|
|
lput(spsize); /* sp offsets */
|
|
lput(lcsize); /* line offsets */
|
|
break;
|
|
case 3:
|
|
/* MS-DOS .COM */
|
|
break;
|
|
case 4:
|
|
/* fake MS-DOS .EXE */
|
|
v = rnd(HEADR+textsize, INITRND)+datsize;
|
|
wputl(0x5A4D); /* 'MZ' */
|
|
wputl(v % 512); /* bytes in last page */
|
|
wputl(rnd(v, 512)/512); /* total number of pages */
|
|
wputl(0x0000); /* number of reloc items */
|
|
v = rnd(HEADR-(INITTEXT & 0xFFFF), 16);
|
|
wputl(v/16); /* size of header */
|
|
wputl(0x0000); /* minimum allocation */
|
|
wputl(0xFFFF); /* maximum allocation */
|
|
wputl(0x0000); /* initial ss value */
|
|
wputl(0x0100); /* initial sp value */
|
|
wputl(0x0000); /* complemented checksum */
|
|
v = entryvalue();
|
|
wputl(v); /* initial ip value (!) */
|
|
wputl(0x0000); /* initial cs value */
|
|
wputl(0x0000);
|
|
wputl(0x0000);
|
|
wputl(0x003E); /* reloc table offset */
|
|
wputl(0x0000); /* overlay number */
|
|
break;
|
|
case 5:
|
|
strnput("\177ELF", 4); /* e_ident */
|
|
cput(1); /* class = 32 bit */
|
|
cput(1); /* data = LSB */
|
|
cput(1); /* version = CURRENT */
|
|
strnput("", 9);
|
|
wputl(2); /* type = EXEC */
|
|
wputl(3); /* machine = 386 */
|
|
lputl(1L); /* version = CURRENT */
|
|
lputl(PADDR(entryvalue())); /* entry vaddr */
|
|
lputl(52L); /* offset to first phdr */
|
|
lputl(0L); /* offset to first shdr */
|
|
lputl(0L); /* flags = 386 */
|
|
wputl(52); /* Ehdr size */
|
|
wputl(32); /* Phdr size */
|
|
wputl(3); /* # of Phdrs */
|
|
wputl(0); /* Shdr size */
|
|
wputl(0); /* # of Shdrs */
|
|
wputl(0); /* Shdr string size */
|
|
|
|
lputl(1L); /* text - type = PT_LOAD */
|
|
lputl(HEADR); /* file offset */
|
|
lputl(INITTEXT); /* vaddr */
|
|
lputl(PADDR(INITTEXT)); /* paddr */
|
|
lputl(textsize); /* file size */
|
|
lputl(textsize); /* memory size */
|
|
lputl(0x05L); /* protections = RX */
|
|
lputl(INITRND); /* alignment */
|
|
|
|
lputl(1L); /* data - type = PT_LOAD */
|
|
lputl(HEADR+textsize); /* file offset */
|
|
lputl(INITDAT); /* vaddr */
|
|
lputl(PADDR(INITDAT)); /* paddr */
|
|
lputl(datsize); /* file size */
|
|
lputl(datsize+bsssize); /* memory size */
|
|
lputl(0x06L); /* protections = RW */
|
|
lputl(INITRND); /* alignment */
|
|
|
|
lputl(0L); /* data - type = PT_NULL */
|
|
lputl(HEADR+textsize+datsize); /* file offset */
|
|
lputl(0L);
|
|
lputl(0L);
|
|
lputl(symsize); /* symbol table size */
|
|
lputl(lcsize); /* line number size */
|
|
lputl(0x04L); /* protections = R */
|
|
lputl(0x04L); /* alignment */
|
|
break;
|
|
}
|
|
cflush();
|
|
}
|
|
|
|
void
|
|
cflush(void)
|
|
{
|
|
int n;
|
|
|
|
n = sizeof(buf.cbuf) - cbc;
|
|
if(n)
|
|
write(cout, buf.cbuf, n);
|
|
cbp = buf.cbuf;
|
|
cbc = sizeof(buf.cbuf);
|
|
}
|
|
|
|
void
|
|
datblk(long s, long n)
|
|
{
|
|
Prog *p;
|
|
char *cast;
|
|
long l, fl, j;
|
|
int i, c;
|
|
|
|
memset(buf.dbuf, 0, n+Dbufslop);
|
|
for(p = datap; p != P; p = p->link) {
|
|
curp = p;
|
|
l = p->from.sym->value + p->from.offset - s;
|
|
c = p->from.scale;
|
|
i = 0;
|
|
if(l < 0) {
|
|
if(l+c <= 0)
|
|
continue;
|
|
while(l < 0) {
|
|
l++;
|
|
i++;
|
|
}
|
|
}
|
|
if(l >= n)
|
|
continue;
|
|
if(p->as != AINIT && p->as != ADYNT) {
|
|
for(j=l+(c-i)-1; j>=l; j--)
|
|
if(buf.dbuf[j]) {
|
|
print("%P\n", p);
|
|
diag("multiple initialization");
|
|
break;
|
|
}
|
|
}
|
|
switch(p->to.type) {
|
|
case D_FCONST:
|
|
switch(c) {
|
|
default:
|
|
case 4:
|
|
fl = ieeedtof(&p->to.ieee);
|
|
cast = (char*)&fl;
|
|
if(debug['a'] && i == 0) {
|
|
Bprint(&bso, pcstr, l+s+INITDAT);
|
|
for(j=0; j<c; j++)
|
|
Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff);
|
|
Bprint(&bso, "\t%P\n", curp);
|
|
}
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[fnuxi4[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 8:
|
|
cast = (char*)&p->to.ieee;
|
|
if(debug['a'] && i == 0) {
|
|
Bprint(&bso, pcstr, l+s+INITDAT);
|
|
for(j=0; j<c; j++)
|
|
Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff);
|
|
Bprint(&bso, "\t%P\n", curp);
|
|
}
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[fnuxi8[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case D_SCONST:
|
|
if(debug['a'] && i == 0) {
|
|
Bprint(&bso, pcstr, l+s+INITDAT);
|
|
for(j=0; j<c; j++)
|
|
Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff);
|
|
Bprint(&bso, "\t%P\n", curp);
|
|
}
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = p->to.scon[i];
|
|
l++;
|
|
}
|
|
break;
|
|
default:
|
|
fl = p->to.offset;
|
|
if(p->to.type == D_ADDR) {
|
|
if(p->to.index != D_STATIC && p->to.index != D_EXTERN)
|
|
diag("DADDR type%P", p);
|
|
if(p->to.sym) {
|
|
if(p->to.sym->type == SUNDEF)
|
|
ckoff(p->to.sym, fl);
|
|
fl += p->to.sym->value;
|
|
if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF)
|
|
fl += INITDAT;
|
|
if(dlm)
|
|
dynreloc(p->to.sym, l+s+INITDAT, 1);
|
|
}
|
|
}
|
|
cast = (char*)&fl;
|
|
switch(c) {
|
|
default:
|
|
diag("bad nuxi %d %d\n%P", c, i, curp);
|
|
break;
|
|
case 1:
|
|
if(debug['a'] && i == 0) {
|
|
Bprint(&bso, pcstr, l+s+INITDAT);
|
|
for(j=0; j<c; j++)
|
|
Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff);
|
|
Bprint(&bso, "\t%P\n", curp);
|
|
}
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi1[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 2:
|
|
if(debug['a'] && i == 0) {
|
|
Bprint(&bso, pcstr, l+s+INITDAT);
|
|
for(j=0; j<c; j++)
|
|
Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff);
|
|
Bprint(&bso, "\t%P\n", curp);
|
|
}
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi2[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
case 4:
|
|
if(debug['a'] && i == 0) {
|
|
Bprint(&bso, pcstr, l+s+INITDAT);
|
|
for(j=0; j<c; j++)
|
|
Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff);
|
|
Bprint(&bso, "\t%P\n", curp);
|
|
}
|
|
for(; i<c; i++) {
|
|
buf.dbuf[l] = cast[inuxi4[i]];
|
|
l++;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
write(cout, buf.dbuf, n);
|
|
}
|
|
|
|
long
|
|
rnd(long v, long r)
|
|
{
|
|
long c;
|
|
|
|
if(r <= 0)
|
|
return v;
|
|
v += r - 1;
|
|
c = v % r;
|
|
if(c < 0)
|
|
c += r;
|
|
v -= c;
|
|
return v;
|
|
}
|