Commit 7d443bb6 authored by Russ Cox's avatar Russ Cox

make 8l generate Darwin Mach-O and Linux ELF binaries

R=ken
OCL=26584
CL=26589
parent 997b6f9d
......@@ -32,6 +32,22 @@
#define Dbufslop 100
uint32 symdatva = 0x99<<24;
uint32 stroffset;
uint32 strtabsize;
uint32 machheadr(void);
uint32 elfheadr(void);
void elfphdr(int type, int flags, uint32 foff, uint32 vaddr, uint32 paddr, uint32 filesize, uint32 memsize, uint32 align);
void elfshdr(char *name, uint32 type, uint32 flags, uint32 addr, uint32 off, uint32 size, uint32 link, uint32 info, uint32 align, uint32 entsize);
int elfstrtable(void);
void machdylink(void);
uint32 machheadr(void);
void machsect(char *name, char *seg, vlong addr, vlong size, uint32 off, uint32 align, uint32 reloc, uint32 nreloc, uint32 flag);
void machseg(char *name, uint32 vaddr, uint32 vsize, uint32 foff, uint32 fsize, uint32 prot1, uint32 prot2, uint32 nsect, uint32 flag);
void machstack(vlong e);
void machsymseg(uint32 foffset, uint32 fsize);
int32
entryvalue(void)
{
......@@ -57,25 +73,64 @@ entryvalue(void)
}
void
wput(ushort w)
wputl(ushort w)
{
cput(w);
cput(w>>8);
}
void
wputb(ushort w)
wput(ushort w)
{
cput(w>>8);
cput(w);
}
void
lput(int32 l)
{
cput(l>>24);
cput(l>>16);
cput(l>>8);
cput(l);
}
void
lputl(int32 l)
{
cput(l);
cput(l>>8);
cput(l>>16);
cput(l>>24);
}
void
vputl(uvlong l)
{
lputl(l >> 32);
lputl(l);
}
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;
int32 v, magic;
int a;
int a, np, nl, ns;
uint32 va, fo, w, symo;
uchar *op1;
if(debug['v'])
......@@ -134,6 +189,23 @@ asmb(void)
case 4:
seek(cout, HEADR+rnd(textsize, INITRND), 0);
break;
case 6:
v = HEADR+textsize;
seek(cout, v, 0);
v = rnd(v, 4096) - v;
while(v > 0) {
cput(0);
v--;
}
cflush();
break;
case 7:
seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0);
strtabsize = elfstrtable();
cflush();
v = rnd(HEADR+textsize, INITRND);
seek(cout, v, 0);
break;
}
if(debug['v'])
......@@ -157,6 +229,7 @@ asmb(void)
symsize = 0;
spsize = 0;
lcsize = 0;
symo = 0;
if(!debug['s']) {
if(debug['v'])
Bprint(&bso, "%5.2f sym\n", cputime());
......@@ -175,8 +248,17 @@ asmb(void)
case 3:
case 4:
debug['s'] = 1;
symo = HEADR+textsize+datsize;
break;
case 6:
symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND);
break;
case 7:
symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize;
symo = rnd(symo, INITRND);
break;
}
seek(cout, symo+8, 0);
if(!debug['s'])
asmsym();
if(debug['v'])
......@@ -190,6 +272,10 @@ asmb(void)
if(dlm)
asmdyn();
cflush();
seek(cout, symo, 0);
lputl(symsize);
lputl(lcsize);
cflush();
}
else if(dlm){
seek(cout, HEADR+textsize+datsize, 0);
......@@ -311,45 +397,272 @@ asmb(void)
case 4:
/* fake MS-DOS .EXE */
v = rnd(HEADR+textsize, INITRND)+datsize;
wput(0x5A4D); /* 'MZ' */
wput(v % 512); /* bytes in last page */
wput(rnd(v, 512)/512); /* total number of pages */
wput(0x0000); /* number of reloc items */
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);
wput(v/16); /* size of header */
wput(0x0000); /* minimum allocation */
wput(0xFFFF); /* maximum allocation */
wput(0x0000); /* initial ss value */
wput(0x0100); /* initial sp value */
wput(0x0000); /* complemented checksum */
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();
wput(v); /* initial ip value (!) */
wput(0x0000); /* initial cs value */
wput(0x0000);
wput(0x0000);
wput(0x003E); /* reloc table offset */
wput(0x0000); /* overlay number */
wputl(v); /* initial ip value (!) */
wputl(0x0000); /* initial cs value */
wputl(0x0000);
wputl(0x0000);
wputl(0x003E); /* reloc table offset */
wputl(0x0000); /* overlay number */
break;
}
cflush();
}
case 6:
/* apple MACH */
va = 4096;
void
lput(int32 l)
{
cput(l>>24);
cput(l>>16);
cput(l>>8);
cput(l);
}
lputl(0xfeedface); /* 32-bit */
lputl(7); /* cputype - x86 */
lputl(3); /* subtype - x86 */
lputl(2); /* file type - mach executable */
nl = 4;
if (!debug['s'])
nl += 3;
if (!debug['d']) // -d = turn off "dynamic loader"
nl += 3;
lputl(nl); /* number of loads */
lputl(machheadr()-28); /* size of loads */
lputl(1); /* flags - no undefines */
void
lputl(int32 l)
{
cput(l);
cput(l>>8);
cput(l>>16);
cput(l>>24);
machseg("__PAGEZERO",
0,va, /* vaddr vsize */
0,0, /* fileoffset filesize */
0,0, /* protects */
0,0); /* sections flags */
v = rnd(HEADR+textsize, INITRND);
machseg("__TEXT",
va, /* vaddr */
v, /* vsize */
0,v, /* fileoffset filesize */
7,5, /* protects */
1,0); /* sections flags */
machsect("__text", "__TEXT",
va+HEADR,v-HEADR, /* addr size */
HEADR,0,0,0, /* offset align reloc nreloc */
0|0x400); /* flag - some instructions */
w = datsize+bsssize;
machseg("__DATA",
va+v, /* vaddr */
w, /* vsize */
v,datsize, /* fileoffset filesize */
7,3, /* protects */
2,0); /* sections flags */
machsect("__data", "__DATA",
va+v,datsize, /* addr size */
v,0,0,0, /* offset align reloc nreloc */
0); /* flag */
machsect("__bss", "__DATA",
va+v+datsize,bsssize, /* addr size */
0,0,0,0, /* offset align reloc nreloc */
1); /* flag - zero fill */
machdylink();
machstack(entryvalue());
if (!debug['s']) {
machseg("__SYMDAT",
symdatva, /* vaddr */
8+symsize+lcsize, /* vsize */
symo, 8+symsize+lcsize, /* fileoffset filesize */
7, 5, /* protects */
0, 0); /* sections flags */
machsymseg(symo+8,symsize); /* fileoffset,filesize */
machsymseg(symo+8+symsize,lcsize); /* fileoffset,filesize */
}
break;
case 7:
np = 3;
ns = 5;
if(!debug['s']) {
np++;
ns += 2;
}
/* ELF header */
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 = AMD64 */
lputl(1L); /* version = CURRENT */
lputl(entryvalue()); /* entry vaddr */
lputl(52L); /* offset to first phdr */
lputl(52L+32L*np); /* offset to first shdr */
lputl(0L); /* processor specific flags */
wputl(52L); /* Ehdr size */
wputl(32L); /* Phdr size */
wputl(np); /* # of Phdrs */
wputl(40L); /* Shdr size */
wputl(ns); /* # of Shdrs */
wputl(4); /* Shdr with strings */
/* prog headers */
fo = 0;
va = INITTEXT & ~((vlong)INITRND - 1);
w = HEADR+textsize;
elfphdr(1, /* text - type = PT_LOAD */
1L+4L, /* text - flags = PF_X+PF_R */
0, /* file offset */
va, /* vaddr */
va, /* paddr */
w, /* file size */
w, /* memory size */
INITRND); /* alignment */
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
w = datsize;
elfphdr(1, /* data - type = PT_LOAD */
2L+4L, /* data - flags = PF_W+PF_R */
fo, /* file offset */
va, /* vaddr */
va, /* paddr */
w, /* file size */
w+bsssize, /* memory size */
INITRND); /* alignment */
if(!debug['s']) {
elfphdr(1, /* data - type = PT_LOAD */
2L+4L, /* data - flags = PF_W+PF_R */
symo, /* file offset */
symdatva, /* vaddr */
symdatva, /* paddr */
8+symsize+lcsize, /* file size */
8+symsize+lcsize, /* memory size */
INITRND); /* alignment */
}
elfphdr(0x6474e551, /* gok - type = gok */
1L+2L+4L, /* gok - flags = PF_X+PF_W+PF_R */
0, /* file offset */
0, /* vaddr */
0, /* paddr */
0, /* file size */
0, /* memory size */
8); /* alignment */
/* segment headers */
elfshdr(nil, /* name */
0, /* type */
0, /* flags */
0, /* addr */
0, /* off */
0, /* size */
0, /* link */
0, /* info */
0, /* align */
0); /* entsize */
stroffset = 1; /* 0 means no name, so start at 1 */
fo = HEADR;
va = (INITTEXT & ~((vlong)INITRND - 1)) + HEADR;
w = textsize;
elfshdr(".text", /* name */
1, /* type */
6, /* flags */
va, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
8, /* align */
0); /* entsize */
fo = rnd(fo+w, INITRND);
va = rnd(va+w, INITRND);
w = datsize;
elfshdr(".data", /* name */
1, /* type */
3, /* flags */
va, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
8, /* align */
0); /* entsize */
fo += w;
va += w;
w = bsssize;
elfshdr(".bss", /* name */
8, /* type */
3, /* flags */
va, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
8, /* align */
0); /* entsize */
w = strtabsize;
elfshdr(".shstrtab", /* name */
3, /* type */
0, /* flags */
0, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
1, /* align */
0); /* entsize */
if (debug['s'])
break;
fo = symo+8;
w = symsize;
elfshdr(".gosymtab", /* name */
1, /* type 1 = SHT_PROGBITS */
0, /* flags */
0, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
1, /* align */
24); /* entsize */
fo += w;
w = lcsize;
elfshdr(".gopclntab", /* name */
1, /* type 1 = SHT_PROGBITS*/
0, /* flags */
0, /* addr */
fo, /* off */
w, /* size */
0, /* link */
0, /* info */
1, /* align */
24); /* entsize */
break;
}
cflush();
}
void
......@@ -530,3 +843,218 @@ rnd(int32 v, int32 r)
v -= c;
return v;
}
void
machseg(char *name, uint32 vaddr, uint32 vsize, uint32 foff, uint32 fsize,
uint32 prot1, uint32 prot2, uint32 nsect, uint32 flag)
{
lputl(1); /* segment 32 */
lputl(56 + 68*nsect);
strnput(name, 16);
lputl(vaddr);
lputl(vsize);
lputl(foff);
lputl(fsize);
lputl(prot1);
lputl(prot2);
lputl(nsect);
lputl(flag);
}
void
machsymseg(uint32 foffset, uint32 fsize)
{
lputl(3); /* obsolete gdb debug info */
lputl(16); /* size of symseg command */
lputl(foffset);
lputl(fsize);
}
void
machsect(char *name, char *seg, vlong addr, vlong size, uint32 off,
uint32 align, uint32 reloc, uint32 nreloc, uint32 flag)
{
strnput(name, 16);
strnput(seg, 16);
lputl(addr);
lputl(size);
lputl(off);
lputl(align);
lputl(reloc);
lputl(nreloc);
lputl(flag);
lputl(0); /* reserved */
lputl(0); /* reserved */
}
// Emit a section requesting the dynamic loader
// but giving it no work to do (an empty dynamic symbol table).
// This is enough to make the Apple tracing programs (like dtrace)
// accept the binary, so that one can run dtruss on an 8.out.
void
machdylink(void)
{
int i;
if(debug['d'])
return;
lputl(2); /* LC_SYMTAB */
lputl(24); /* byte count - 6 words*/
for(i=0; i<4; i++)
lputl(0);
lputl(11); /* LC_DYSYMTAB */
lputl(80); /* byte count - 20 words */
for(i=0; i<18; i++)
lputl(0);
lputl(14); /* LC_LOAD_DYLINKER */
lputl(32); /* byte count */
lputl(12); /* offset to string */
strnput("/usr/lib/dyld", 32-12);
}
void
machstack(vlong e)
{
int i;
lputl(5); /* unix thread */
lputl((16+4)*4); /* total byte count */
lputl(1); /* thread type - x86_THREAD_STATE32 */
lputl(16); /* word count */
for(i=0; i<16; i++) /* initial register set */
if(i == 10)
lputl(e);
else
lputl(0);
}
uint32
machheadr(void)
{
uint32 a;
enum {
Header = 28,
Seg = 56,
Sect = 68,
Symtab = 24,
Dysymtab = 80,
LoadDylinker = 32,
Stack = 80,
Symseg = 16,
};
a = Header; /* a.out header */
a += Seg; /* page zero seg */
a += Seg; /* text seg */
a += Sect; /* text sect */
a += Seg; /* data seg */
a += Sect; /* data sect */
a += Sect; /* bss sect */
if (!debug['d']) {
a += Symtab; /* symtab */
a += Dysymtab; /* dysymtab */
a += LoadDylinker; /* load dylinker */
}
a += Stack; /* stack sect */
if (!debug['s']) {
a += Seg; /* symdat seg */
a += Symseg; /* symtab seg */
a += Symseg; /* lctab seg */
}
return a;
}
uint32
elfheadr(void)
{
uint32 a;
a = 52; /* elf header */
a += 32; /* page zero seg */
a += 32; /* text seg */
a += 32; /* stack seg */
a += 40; /* nil sect */
a += 40; /* .text sect */
a += 40; /* .data seg */
a += 40; /* .bss sect */
a += 40; /* .shstrtab sect - strings for headers */
if (!debug['s']) {
a += 32; /* symdat seg */
a += 40; /* .gosymtab sect */
a += 40; /* .gopclntab sect */
}
return a;
}
void
elfphdr(int type, int flags, uint32 foff,
uint32 vaddr, uint32 paddr,
uint32 filesize, uint32 memsize, uint32 align)
{
lputl(type); /* text - type = PT_LOAD */
lputl(foff); /* file offset */
lputl(vaddr); /* vaddr */
lputl(paddr); /* paddr */
lputl(filesize); /* file size */
lputl(memsize); /* memory size */
lputl(flags); /* text - flags = PF_X+PF_R */
lputl(align); /* alignment */
}
void
elfshdr(char *name, uint32 type, uint32 flags, uint32 addr, uint32 off,
uint32 size, uint32 link, uint32 info, uint32 align, uint32 entsize)
{
lputl(stroffset);
lputl(type);
lputl(flags);
lputl(addr);
lputl(off);
lputl(size);
lputl(link);
lputl(info);
lputl(align);
lputl(entsize);
if(name != nil)
stroffset += strlen(name)+1;
}
int
putstrtab(char* name)
{
int w;
w = strlen(name)+1;
strnput(name, w);
return w;
}
int
elfstrtable(void)
{
int size;
size = 0;
size += putstrtab("");
size += putstrtab(".text");
size += putstrtab(".data");
size += putstrtab(".bss");
size += putstrtab(".shstrtab");
if (!debug['s']) {
size += putstrtab(".gosymtab");
size += putstrtab(".gopclntab");
}
return size;
}
......@@ -365,11 +365,19 @@ void span(void);
void undef(void);
void undefsym(Sym*);
int32 vaddr(Adr*);
void wputb(ushort);
void wput(ushort);
void xdefine(char*, int, int32);
void xfol(Prog*);
int zaddr(uchar*, Adr*, Sym*[]);
void zerosig(char*);
uint32 machheadr(void);
uint32 elfheadr(void);
void whatsys(void);
/* set by call to whatsys() */
extern char* goroot;
extern char* goarch;
extern char* goos;
#pragma varargck type "D" Adr*
#pragma varargck type "P" Prog*
......
......@@ -139,16 +139,22 @@ main(int argc, char *argv[])
diag("usage: 8l [-options] objects");
errorexit();
}
if(!debug['9'] && !debug['U'] && !debug['B'])
debug[DEFAULT] = 1;
whatsys(); // get goroot, goarch, goos
if(strcmp(goarch, thestring) != 0)
print("goarch is not known: %s\n", goarch);
if(HEADTYPE == -1) {
if(debug['U'])
HEADTYPE = 1;
if(debug['B'])
HEADTYPE = 2;
if(debug['9'])
HEADTYPE = 2;
HEADTYPE = 2;
if(strcmp(goos, "linux") == 0)
HEADTYPE = 7;
else
if(strcmp(goos, "darwin") == 0)
HEADTYPE = 6;
else
print("goos is not known: %sn", goos);
}
switch(HEADTYPE) {
default:
diag("unknown -H option");
......@@ -202,6 +208,24 @@ main(int argc, char *argv[])
if(debug['v'])
Bprint(&bso, "HEADR = 0x%ld\n", HEADR);
break;
case 6: /* apple MACH */
HEADR = machheadr();
if(INITTEXT == -1)
INITTEXT = 4096+HEADR;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 4096;
break;
case 7: /* elf32 executable */
HEADR = elfheadr();
if(INITTEXT == -1)
INITTEXT = 0x08048000+HEADR;
if(INITDAT == -1)
INITDAT = 0;
if(INITRND == -1)
INITRND = 4096;
break;
}
if(INITDAT != 0 && INITRND != 0)
print("warning: -D0x%lux is ignored because of -R0x%lux\n",
......@@ -294,19 +318,27 @@ main(int argc, char *argv[])
firstp = prg();
lastp = firstp;
if(INITENTRY == 0) {
INITENTRY = "_main";
if(debug['p'])
INITENTRY = "_mainp";
if(!debug['l'])
lookup(INITENTRY, 0)->type = SXREF;
} else
lookup(INITENTRY, 0)->type = SXREF;
if(INITENTRY == nil) {
INITENTRY = mal(strlen(goarch)+strlen(goos)+10);
sprint(INITENTRY, "_rt0_%s_%s", goarch, goos);
}
lookup(INITENTRY, 0)->type = SXREF;
if(!debug['l']) {
a = mal(strlen(goroot)+strlen(goarch)+strlen(goos)+20);
sprint(a, "%s/lib/rt0_%s_%s.%c", goroot, goarch, goos, thechar);
objfile(a);
}
while(*argv)
objfile(*argv++);
if(!debug['l'])
if(!debug['l']) {
loadlib();
a = mal(strlen(goroot)+strlen(goarch)+strlen(goos)+20);
sprint(a, "%s/lib/lib_%s_%s.a", goroot, goarch, goos);
objfile(a);
}
firstp = firstp->link;
if(firstp == P)
errorexit();
......
......@@ -1396,7 +1396,7 @@ asmdyn()
t++;
}
else if(c == 1){
wputb(ra);
wput(ra);
t += 2;
}
else{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment