step toward darwin ffi: factor out macho code

R=r
DELTA=771  (374 added, 287 deleted, 110 changed)
OCL=35187
CL=35187
This commit is contained in:
Russ Cox 2009-09-30 17:33:39 -07:00
parent 399d23d4f4
commit 2157025ef0
12 changed files with 470 additions and 383 deletions

View File

@ -14,6 +14,7 @@ OFILES=\
enam.$O\ enam.$O\
go.$O\ go.$O\
list.$O\ list.$O\
macho.$O\
obj.$O\ obj.$O\
optab.$O\ optab.$O\
pass.$O\ pass.$O\
@ -23,6 +24,7 @@ HFILES=\
l.h\ l.h\
../6l/6.out.h\ ../6l/6.out.h\
../ld/elf.h\ ../ld/elf.h\
../ld/macho.h\
../6l/compat.h\ ../6l/compat.h\
@ -41,5 +43,5 @@ install: $(TARG)
cp $(TARG) $(GOBIN)/$(TARG) cp $(TARG) $(GOBIN)/$(TARG)
go.o: ../ld/go.c go.o: ../ld/go.c
elf.o: ../ld/elf.c elf.o: ../ld/elf.c
macho.o: ../ld/macho.c

View File

@ -30,6 +30,7 @@
#include "l.h" #include "l.h"
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/macho.h"
#define Dbufslop 100 #define Dbufslop 100
@ -422,13 +423,18 @@ asmb(void)
{ {
Prog *p; Prog *p;
int32 v, magic; int32 v, magic;
int a, nl, dynsym; int a, dynsym;
uchar *op1; uchar *op1;
vlong vl, va, startva, fo, w, symo; vlong vl, va, startva, fo, w, symo;
vlong symdatva = 0x99LL<<32; vlong symdatva = 0x99LL<<32;
ElfEhdr *eh; ElfEhdr *eh;
ElfPhdr *ph, *pph; ElfPhdr *ph, *pph;
ElfShdr *sh; ElfShdr *sh;
MachoHdr *mh;
MachoSect *msect;
MachoSeg *ms;
MachoDebug *md;
MachoLoad *ml;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime()); Bprint(&bso, "%5.2f asmb\n", cputime());
@ -602,71 +608,91 @@ asmb(void)
break; break;
case 6: case 6:
/* apple MACH */ /* apple MACH */
va = 4096; va = HEADR;
mh = getMachoHdr();
mh->cpu = MACHO_CPU_AMD64;
mh->subcpu = MACHO_SUBCPU_X86;
lputl(0xfeedfacf); /* 64-bit */ /* segment for zero page */
lputl((1<<24)|7); /* cputype - x86/ABI64 */ ms = newMachoSeg("__PAGEZERO", 0);
lputl(3); /* subtype - x86 */ ms->vsize = va;
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()-32); /* size of loads */
lputl(1); /* flags - no undefines */
lputl(0); /* reserved */
machseg("__PAGEZERO",
0,va, /* vaddr vsize */
0,0, /* fileoffset filesize */
0,0, /* protects */
0,0); /* sections flags */
/* text */
v = rnd(HEADR+textsize, INITRND); v = rnd(HEADR+textsize, INITRND);
machseg("__TEXT", ms = newMachoSeg("__TEXT", 1);
va, /* vaddr */ ms->vaddr = va;
v, /* vsize */ ms->vsize = v;
0,v, /* fileoffset filesize */ ms->filesize = v;
7,5, /* protects */ ms->prot1 = 7;
1,0); /* sections flags */ ms->prot2 = 5;
machsect("__text", "__TEXT",
va+HEADR,v-HEADR, /* addr size */
HEADR,0,0,0, /* offset align reloc nreloc */
0|0x400); /* flag - some instructions */
msect = newMachoSect(ms, "__text");
msect->addr = va+HEADR;
msect->size = v - HEADR;
msect->off = HEADR;
msect->flag = 0x400; /* flag - some instructions */
/* data */
w = datsize+bsssize; w = datsize+bsssize;
machseg("__DATA", ms = newMachoSeg("__DATA", 2);
va+v, /* vaddr */ ms->vaddr = va+v;
w, /* vsize */ ms->vsize = w;
v,datsize, /* fileoffset filesize */ ms->fileoffset = v;
7,3, /* protects */ ms->filesize = datsize;
2,0); /* sections flags */ ms->prot1 = 7;
machsect("__data", "__DATA", ms->prot2 = 3;
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(); msect = newMachoSect(ms, "__data");
machstack(entryvalue()); msect->addr = va+v;
msect->size = datsize;
msect->off = v;
if (!debug['s']) { msect = newMachoSect(ms, "__bss");
machseg("__SYMDAT", msect->addr = va+v+datsize;
symdatva, /* vaddr */ msect->size = bsssize;
8+symsize+lcsize, /* vsize */ msect->flag = 1; /* flag - zero fill */
symo, 8+symsize+lcsize, /* fileoffset filesize */
7, 5, /* protects */
0, 0); /* sections flags */
machsymseg(symo+8,symsize); /* fileoffset,filesize */ ml = newMachoLoad(5, 42+2); /* unix thread */
machsymseg(symo+8+symsize,lcsize); /* fileoffset,filesize */ ml->data[0] = 4; /* thread type */
ml->data[1] = 42; /* word count */
ml->data[2+32] = entryvalue(); /* start pc */
ml->data[2+32+1] = entryvalue()>>32;
if(!debug['d']) {
ml = newMachoLoad(2, 4); /* LC_SYMTAB */
USED(ml);
ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
USED(ml);
ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
ml->data[0] = 12; /* offset to string */
strcpy((char*)&ml->data[1], "/usr/lib/dyld");
} }
if(!debug['s']) {
ms = newMachoSeg("__SYMDAT", 1);
ms->vaddr = symdatva;
ms->vsize = 8+symsize+lcsize;
ms->fileoffset = symo;
ms->filesize = 8+symsize+lcsize;
ms->prot1 = 7;
ms->prot2 = 5;
md = newMachoDebug();
md->fileoffset = symo+8;
md->filesize = symsize;
md = newMachoDebug();
md->fileoffset = symo+8+symsize;
md->filesize = lcsize;
}
a = machowrite();
if(a > MACHORESERVE)
diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE);
break; break;
case 7: case 7:
/* elf amd-64 */ /* elf amd-64 */
@ -889,11 +915,8 @@ asmb(void)
a += elfwritehdr(); a += elfwritehdr();
a += elfwritephdrs(); a += elfwritephdrs();
a += elfwriteshdrs(); a += elfwriteshdrs();
if (a > ELFRESERVE) { if (a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE); diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
}
cflush();
break; break;
} }
cflush(); cflush();
@ -1079,122 +1102,3 @@ rnd(vlong v, vlong r)
return v; return v;
} }
void
machseg(char *name, vlong vaddr, vlong vsize, vlong foff, vlong fsize,
uint32 prot1, uint32 prot2, uint32 nsect, uint32 flag)
{
lputl(25); /* segment 64 */
lputl(72 + 80*nsect);
strnput(name, 16);
vputl(vaddr);
vputl(vsize);
vputl(foff);
vputl(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);
vputl(addr);
vputl(size);
lputl(off);
lputl(align);
lputl(reloc);
lputl(nreloc);
lputl(flag);
lputl(0); /* reserved */
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 a 6.out.
// The dynamic linker loads at 0x8fe00000, so if we want to
// be able to build >2GB binaries, we're going to need to move
// the text segment to 4G like Apple does.
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((42+4)*4); /* total byte count */
lputl(4); /* thread type */
lputl(42); /* word count */
for(i=0; i<32; i++)
lputl(0);
vputl(e);
for(i=0; i<8; i++)
lputl(0);
}
uint32
machheadr(void)
{
uint32 a;
a = 8; /* a.out header */
a += 18; /* page zero seg */
a += 18; /* text seg */
a += 20; /* text sect */
a += 18; /* data seg */
a += 20; /* data sect */
a += 20; /* bss sect */
a += 46; /* stack sect */
if (!debug['d']) {
a += 6; /* symtab */
a += 20; /* dysymtab */
a += 8; /* load dylinker */
}
if (!debug['s']) {
a += 18; /* symdat seg */
a += 4; /* symtab seg */
a += 4; /* lctab seg */
}
return a*4;
}

6
src/cmd/6l/macho.c Normal file
View File

@ -0,0 +1,6 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "l.h"
#include "../ld/macho.c"

View File

@ -31,6 +31,7 @@
#define EXTERN #define EXTERN
#include "l.h" #include "l.h"
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/macho.h"
#include <ar.h> #include <ar.h>
char *noname = "<none>"; char *noname = "<none>";
@ -188,7 +189,8 @@ main(int argc, char *argv[])
INITRND = 4096; INITRND = 4096;
break; break;
case 6: /* apple MACH */ case 6: /* apple MACH */
HEADR = machheadr(); machoinit();
HEADR = MACHORESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = 4096+HEADR; INITTEXT = 4096+HEADR;
if(INITDAT == -1) if(INITDAT == -1)

View File

@ -13,6 +13,7 @@ OFILES=\
elf.$O\ elf.$O\
enam.$O\ enam.$O\
list.$O\ list.$O\
macho.$O\
obj.$O\ obj.$O\
optab.$O\ optab.$O\
pass.$O\ pass.$O\
@ -23,6 +24,7 @@ HFILES=\
l.h\ l.h\
../8l/8.out.h\ ../8l/8.out.h\
../ld/elf.h\ ../ld/elf.h\
../ld/macho.h\
$(TARG): $(OFILES) $(TARG): $(OFILES)
@ -41,3 +43,4 @@ install: $(TARG)
go.o: ../ld/go.c go.o: ../ld/go.c
elf.o: ../ld/elf.c elf.o: ../ld/elf.c
macho.o: ../ld/macho.c

View File

@ -30,26 +30,12 @@
#include "l.h" #include "l.h"
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/macho.h"
#define Dbufslop 100 #define Dbufslop 100
char linuxdynld[] = "/lib/ld-linux.so.2"; char linuxdynld[] = "/lib/ld-linux.so.2";
uint32 symdatva = 0x99<<24; 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 int32
entryvalue(void) entryvalue(void)
@ -428,13 +414,18 @@ asmb(void)
{ {
Prog *p; Prog *p;
int32 v, magic; int32 v, magic;
int a, nl, dynsym; int a, dynsym;
uint32 va, fo, w, symo, startva; uint32 va, fo, w, symo, startva;
uchar *op1; uchar *op1;
ulong expectpc; ulong expectpc;
Elf64_Ehdr *eh; ElfEhdr *eh;
Elf64_Phdr *ph, *pph; ElfPhdr *ph, *pph;
Elf64_Shdr *sh; ElfShdr *sh;
MachoHdr *mh;
MachoSect *msect;
MachoSeg *ms;
MachoDebug *md;
MachoLoad *ml;
if(debug['v']) if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime()); Bprint(&bso, "%5.2f asmb\n", cputime());
@ -585,7 +576,7 @@ asmb(void)
break; break;
case 7: case 7:
case 8: case 8:
symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize; symo = rnd(HEADR+textsize, INITRND)+datsize;
symo = rnd(symo, INITRND); symo = rnd(symo, INITRND);
break; break;
} }
@ -750,69 +741,88 @@ asmb(void)
case 6: case 6:
/* apple MACH */ /* apple MACH */
va = 4096; va = HEADR;
mh = getMachoHdr();
mh->cpu = MACHO_CPU_386;
mh->subcpu = MACHO_SUBCPU_X86;
lputl(0xfeedface); /* 32-bit */ /* segment for zero page */
lputl(7); /* cputype - x86 */ ms = newMachoSeg("__PAGEZERO", 0);
lputl(3); /* subtype - x86 */ ms->vsize = va;
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 */
machseg("__PAGEZERO",
0,va, /* vaddr vsize */
0,0, /* fileoffset filesize */
0,0, /* protects */
0,0); /* sections flags */
/* text */
v = rnd(HEADR+textsize, INITRND); v = rnd(HEADR+textsize, INITRND);
machseg("__TEXT", ms = newMachoSeg("__TEXT", 1);
va, /* vaddr */ ms->vaddr = va;
v, /* vsize */ ms->vsize = v;
0,v, /* fileoffset filesize */ ms->filesize = v;
7,5, /* protects */ ms->prot1 = 7;
1,0); /* sections flags */ ms->prot2 = 5;
machsect("__text", "__TEXT",
va+HEADR,v-HEADR, /* addr size */
HEADR,0,0,0, /* offset align reloc nreloc */
0|0x400); /* flag - some instructions */
msect = newMachoSect(ms, "__text");
msect->addr = va+HEADR;
msect->size = v - HEADR;
msect->off = HEADR;
msect->flag = 0x400; /* flag - some instructions */
/* data */
w = datsize+bsssize; w = datsize+bsssize;
machseg("__DATA", ms = newMachoSeg("__DATA", 2);
va+v, /* vaddr */ ms->vaddr = va+v;
w, /* vsize */ ms->vsize = w;
v,datsize, /* fileoffset filesize */ ms->fileoffset = v;
7,3, /* protects */ ms->filesize = datsize;
2,0); /* sections flags */ ms->prot1 = 7;
machsect("__data", "__DATA", ms->prot2 = 3;
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(); msect = newMachoSect(ms, "__data");
machstack(entryvalue()); msect->addr = va+v;
msect->size = datsize;
msect->off = v;
if (!debug['s']) { msect = newMachoSect(ms, "__bss");
machseg("__SYMDAT", msect->addr = va+v+datsize;
symdatva, /* vaddr */ msect->size = bsssize;
8+symsize+lcsize, /* vsize */ msect->flag = 1; /* flag - zero fill */
symo, 8+symsize+lcsize, /* fileoffset filesize */
7, 5, /* protects */
0, 0); /* sections flags */
machsymseg(symo+8,symsize); /* fileoffset,filesize */ ml = newMachoLoad(5, 16+2); /* unix thread */
machsymseg(symo+8+symsize,lcsize); /* fileoffset,filesize */ ml->data[0] = 1; /* thread type */
ml->data[1] = 16; /* word count */
ml->data[2+10] = entryvalue(); /* start pc */
if(!debug['d']) {
ml = newMachoLoad(2, 4); /* LC_SYMTAB */
USED(ml);
ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
USED(ml);
ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
ml->data[0] = 12; /* offset to string */
strcpy((char*)&ml->data[1], "/usr/lib/dyld");
} }
if(!debug['s']) {
ms = newMachoSeg("__SYMDAT", 1);
ms->vaddr = symdatva;
ms->vsize = 8+symsize+lcsize;
ms->fileoffset = symo;
ms->filesize = 8+symsize+lcsize;
ms->prot1 = 7;
ms->prot2 = 5;
md = newMachoDebug();
md->fileoffset = symo+8;
md->filesize = symsize;
md = newMachoDebug();
md->fileoffset = symo+8+symsize;
md->filesize = lcsize;
}
a = machowrite();
if(a > MACHORESERVE)
diag("MACHORESERVE too small: %d > %d", a, MACHORESERVE);
break; break;
case 7: case 7:
@ -1242,129 +1252,3 @@ rnd(int32 v, int32 r)
v -= c; v -= c;
return v; 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;
}

View File

@ -371,6 +371,7 @@ Sym* lookup(char*, int);
void lput(int32); void lput(int32);
void lputl(int32); void lputl(int32);
void vputl(uvlong); void vputl(uvlong);
void strnput(char*, int);
void main(int, char*[]); void main(int, char*[]);
void mkfwd(void); void mkfwd(void);
void* mal(uint32); void* mal(uint32);

6
src/cmd/8l/macho.c Normal file
View File

@ -0,0 +1,6 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "l.h"
#include "../ld/macho.c"

View File

@ -31,6 +31,7 @@
#define EXTERN #define EXTERN
#include "l.h" #include "l.h"
#include "../ld/elf.h" #include "../ld/elf.h"
#include "../ld/macho.h"
#include <ar.h> #include <ar.h>
#ifndef DEFAULT #ifndef DEFAULT
@ -212,7 +213,8 @@ main(int argc, char *argv[])
Bprint(&bso, "HEADR = 0x%ld\n", HEADR); Bprint(&bso, "HEADR = 0x%ld\n", HEADR);
break; break;
case 6: /* apple MACH */ case 6: /* apple MACH */
HEADR = machheadr(); machoinit();
HEADR = MACHORESERVE;
if(INITTEXT == -1) if(INITTEXT == -1)
INITTEXT = 4096+HEADR; INITTEXT = 4096+HEADR;
if(INITDAT == -1) if(INITDAT == -1)

View File

@ -963,7 +963,7 @@ extern int numelfphdr;
extern int numelfshdr; extern int numelfshdr;
/* /*
* Total amount of ELF space to reserve at the start of the file * Total amount of space to reserve at the start of the file
* for Header, PHeaders, and SHeaders. * for Header, PHeaders, and SHeaders.
* May waste some. * May waste some.
*/ */

207
src/cmd/ld/macho.c Normal file
View File

@ -0,0 +1,207 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Mach-O file writing
// http://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
#include "../ld/macho.h"
static int macho64;
static MachoHdr hdr;
static MachoLoad load[16];
static MachoSeg seg[16];
static MachoDebug xdebug[16];
static int nload, nseg, ndebug, nsect;
void
machoinit(void)
{
switch(thechar) {
// 64-bit architectures
case '6':
macho64 = 1;
break;
// 32-bit architectures
default:
break;
}
}
MachoHdr*
getMachoHdr(void)
{
return &hdr;
}
MachoLoad*
newMachoLoad(uint32 type, uint32 ndata)
{
MachoLoad *l;
if(nload >= nelem(load)) {
diag("too many loads");
errorexit();
}
l = &load[nload++];
l->type = type;
l->ndata = ndata;
l->data = mal(ndata*4);
return l;
}
MachoSeg*
newMachoSeg(char *name, int msect)
{
MachoSeg *s;
if(nseg >= nelem(seg)) {
diag("too many segs");
errorexit();
}
s = &seg[nseg++];
s->name = name;
s->msect = msect;
s->sect = mal(msect*sizeof s->sect[0]);
return s;
}
MachoSect*
newMachoSect(MachoSeg *seg, char *name)
{
MachoSect *s;
if(seg->nsect >= seg->msect) {
diag("too many sects in segment %s", seg->name);
errorexit();
}
s = &seg->sect[seg->nsect++];
s->name = name;
nsect++;
return s;
}
MachoDebug*
newMachoDebug(void)
{
if(ndebug >= nelem(xdebug)) {
diag("too many debugs");
errorexit();
}
return &xdebug[ndebug++];
}
int
machowrite(void)
{
vlong o1;
int loadsize;
int i, j;
MachoSeg *s;
MachoSect *t;
MachoDebug *d;
MachoLoad *l;
o1 = Boffset(&bso);
loadsize = 4*4*ndebug;
for(i=0; i<nload; i++)
loadsize += 4*(load[i].ndata+2);
if(macho64) {
loadsize += 18*4*nseg;
loadsize += 20*4*nsect;
} else {
loadsize += 14*4*nseg;
loadsize += 17*4*nsect;
}
if(macho64)
LPUT(0xfeedfacf);
else
LPUT(0xfeedface);
LPUT(hdr.cpu);
LPUT(hdr.subcpu);
LPUT(2); /* file type - mach executable */
LPUT(nload+nseg+ndebug);
LPUT(loadsize);
LPUT(1); /* flags - no undefines */
if(macho64)
LPUT(0); /* reserved */
for(i=0; i<nseg; i++) {
s = &seg[i];
if(macho64) {
LPUT(25); /* segment 64 */
LPUT(72+80*s->nsect);
strnput(s->name, 16);
VPUT(s->vaddr);
VPUT(s->vsize);
VPUT(s->fileoffset);
VPUT(s->filesize);
LPUT(s->prot1);
LPUT(s->prot2);
LPUT(s->nsect);
LPUT(s->flag);
} else {
LPUT(1); /* segment 32 */
LPUT(56+68*s->nsect);
strnput(s->name, 16);
LPUT(s->vaddr);
LPUT(s->vsize);
LPUT(s->fileoffset);
LPUT(s->filesize);
LPUT(s->prot1);
LPUT(s->prot2);
LPUT(s->nsect);
LPUT(s->flag);
}
for(j=0; j<s->nsect; j++) {
t = &s->sect[j];
if(macho64) {
strnput(t->name, 16);
strnput(s->name, 16);
VPUT(t->addr);
VPUT(t->size);
LPUT(t->off);
LPUT(t->align);
LPUT(t->reloc);
LPUT(t->nreloc);
LPUT(t->flag);
LPUT(0); /* reserved */
LPUT(0); /* reserved */
LPUT(0); /* reserved */
} else {
strnput(t->name, 16);
strnput(s->name, 16);
LPUT(t->addr);
LPUT(t->size);
LPUT(t->off);
LPUT(t->align);
LPUT(t->reloc);
LPUT(t->nreloc);
LPUT(t->flag);
LPUT(0); /* reserved */
LPUT(0); /* reserved */
}
}
}
for(i=0; i<nload; i++) {
l = &load[i];
LPUT(l->type);
LPUT(4*(l->ndata+2));
for(j=0; j<l->ndata; j++)
LPUT(l->data[j]);
}
for(i=0; i<ndebug; i++) {
d = &xdebug[i];
LPUT(3); /* obsolete gdb debug info */
LPUT(16); /* size of symseg command */
LPUT(d->fileoffset);
LPUT(d->filesize);
}
return Boffset(&bso) - o1;
}

70
src/cmd/ld/macho.h Normal file
View File

@ -0,0 +1,70 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
typedef struct MachoHdr MachoHdr;
struct MachoHdr {
uint32 cpu;
uint32 subcpu;
};
typedef struct MachoSect MachoSect;
struct MachoSect {
char* name;
uint64 addr;
uint64 size;
uint32 off;
uint32 align;
uint32 reloc;
uint32 nreloc;
uint32 flag;
};
typedef struct MachoSeg MachoSeg;
struct MachoSeg {
char* name;
uint64 vsize;
uint64 vaddr;
uint64 fileoffset;
uint64 filesize;
uint32 prot1;
uint32 prot2;
uint32 nsect;
uint32 msect;
MachoSect *sect;
uint32 flag;
};
typedef struct MachoLoad MachoLoad;
struct MachoLoad {
uint32 type;
uint32 ndata;
uint32 *data;
};
typedef struct MachoDebug MachoDebug;
struct MachoDebug {
uint32 fileoffset;
uint32 filesize;
};
MachoHdr* getMachoHdr();
MachoSeg* newMachoSeg(char*, int);
MachoSect* newMachoSect(MachoSeg*, char*);
MachoLoad* newMachoLoad(uint32, uint32);
MachoDebug* newMachoDebug(void);
int machowrite(void);
void machoinit(void);
/*
* Total amount of space to reserve at the start of the file
* for Header, PHeaders, and SHeaders.
* May waste some.
*/
#define MACHORESERVE 4096
enum {
MACHO_CPU_AMD64 = (1<<24)|7,
MACHO_CPU_386 = 7,
MACHO_SUBCPU_X86 = 3,
};