summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-09-30 17:33:39 -0700
committerRuss Cox <rsc@golang.org>2009-09-30 17:33:39 -0700
commit4097d029edf572ac446f4fae787b9a27eabb0200 (patch)
treea15f98dd881c534f8ae8e5b5228f62e3b4f0c4dc /src
parent64792af392839eb23fb2a420848a3f232adcc2ab (diff)
downloadgolang-4097d029edf572ac446f4fae787b9a27eabb0200.tar.gz
step toward darwin ffi: factor out macho code
R=r DELTA=771 (374 added, 287 deleted, 110 changed) OCL=35187 CL=35187
Diffstat (limited to 'src')
-rw-r--r--src/cmd/6l/Makefile4
-rw-r--r--src/cmd/6l/asm.c270
-rw-r--r--src/cmd/6l/macho.c6
-rw-r--r--src/cmd/6l/obj.c4
-rw-r--r--src/cmd/8l/Makefile3
-rw-r--r--src/cmd/8l/asm.c292
-rw-r--r--src/cmd/8l/l.h1
-rw-r--r--src/cmd/8l/macho.c6
-rw-r--r--src/cmd/8l/obj.c4
-rw-r--r--src/cmd/ld/elf.h2
-rw-r--r--src/cmd/ld/macho.c207
-rw-r--r--src/cmd/ld/macho.h70
12 files changed, 478 insertions, 391 deletions
diff --git a/src/cmd/6l/Makefile b/src/cmd/6l/Makefile
index 7952f754d..4821f9d91 100644
--- a/src/cmd/6l/Makefile
+++ b/src/cmd/6l/Makefile
@@ -14,6 +14,7 @@ OFILES=\
enam.$O\
go.$O\
list.$O\
+ macho.$O\
obj.$O\
optab.$O\
pass.$O\
@@ -23,6 +24,7 @@ HFILES=\
l.h\
../6l/6.out.h\
../ld/elf.h\
+ ../ld/macho.h\
../6l/compat.h\
@@ -41,5 +43,5 @@ install: $(TARG)
cp $(TARG) $(GOBIN)/$(TARG)
go.o: ../ld/go.c
-
elf.o: ../ld/elf.c
+macho.o: ../ld/macho.c
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 48a7bae4e..5562ee4e3 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -30,6 +30,7 @@
#include "l.h"
#include "../ld/elf.h"
+#include "../ld/macho.h"
#define Dbufslop 100
@@ -422,13 +423,18 @@ asmb(void)
{
Prog *p;
int32 v, magic;
- int a, nl, dynsym;
+ int a, dynsym;
uchar *op1;
vlong vl, va, startva, fo, w, symo;
vlong symdatva = 0x99LL<<32;
ElfEhdr *eh;
ElfPhdr *ph, *pph;
ElfShdr *sh;
+ MachoHdr *mh;
+ MachoSect *msect;
+ MachoSeg *ms;
+ MachoDebug *md;
+ MachoLoad *ml;
if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime());
@@ -602,71 +608,91 @@ asmb(void)
break;
case 6:
/* apple MACH */
- va = 4096;
-
- lputl(0xfeedfacf); /* 64-bit */
- lputl((1<<24)|7); /* cputype - x86/ABI64 */
- 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()-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 */
+ va = HEADR;
+ mh = getMachoHdr();
+ mh->cpu = MACHO_CPU_AMD64;
+ mh->subcpu = MACHO_SUBCPU_X86;
- 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 */
+ /* segment for zero page */
+ ms = newMachoSeg("__PAGEZERO", 0);
+ ms->vsize = va;
+ /* text */
+ v = rnd(HEADR+textsize, INITRND);
+ ms = newMachoSeg("__TEXT", 1);
+ ms->vaddr = va;
+ ms->vsize = v;
+ ms->filesize = v;
+ ms->prot1 = 7;
+ ms->prot2 = 5;
+
+ 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;
- 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());
+ ms = newMachoSeg("__DATA", 2);
+ ms->vaddr = va+v;
+ ms->vsize = w;
+ ms->fileoffset = v;
+ ms->filesize = datsize;
+ ms->prot1 = 7;
+ ms->prot2 = 3;
+
+ msect = newMachoSect(ms, "__data");
+ msect->addr = va+v;
+ msect->size = datsize;
+ msect->off = v;
+
+ msect = newMachoSect(ms, "__bss");
+ msect->addr = va+v+datsize;
+ msect->size = bsssize;
+ msect->flag = 1; /* flag - zero fill */
+
+ ml = newMachoLoad(5, 42+2); /* unix thread */
+ 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['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 */
+ 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;
+
case 7:
/* elf amd-64 */
@@ -889,11 +915,8 @@ asmb(void)
a += elfwritehdr();
a += elfwritephdrs();
a += elfwriteshdrs();
- if (a > ELFRESERVE) {
+ if (a > ELFRESERVE)
diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE);
- }
- cflush();
-
break;
}
cflush();
@@ -1079,122 +1102,3 @@ rnd(vlong v, vlong r)
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;
-}
diff --git a/src/cmd/6l/macho.c b/src/cmd/6l/macho.c
new file mode 100644
index 000000000..bafb0258c
--- /dev/null
+++ b/src/cmd/6l/macho.c
@@ -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"
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index 4c115b180..ba2dec3b2 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -31,6 +31,7 @@
#define EXTERN
#include "l.h"
#include "../ld/elf.h"
+#include "../ld/macho.h"
#include <ar.h>
char *noname = "<none>";
@@ -188,7 +189,8 @@ main(int argc, char *argv[])
INITRND = 4096;
break;
case 6: /* apple MACH */
- HEADR = machheadr();
+ machoinit();
+ HEADR = MACHORESERVE;
if(INITTEXT == -1)
INITTEXT = 4096+HEADR;
if(INITDAT == -1)
diff --git a/src/cmd/8l/Makefile b/src/cmd/8l/Makefile
index 21b589b13..e0ba629e6 100644
--- a/src/cmd/8l/Makefile
+++ b/src/cmd/8l/Makefile
@@ -13,6 +13,7 @@ OFILES=\
elf.$O\
enam.$O\
list.$O\
+ macho.$O\
obj.$O\
optab.$O\
pass.$O\
@@ -23,6 +24,7 @@ HFILES=\
l.h\
../8l/8.out.h\
../ld/elf.h\
+ ../ld/macho.h\
$(TARG): $(OFILES)
@@ -41,3 +43,4 @@ install: $(TARG)
go.o: ../ld/go.c
elf.o: ../ld/elf.c
+macho.o: ../ld/macho.c
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 627bd25e8..449467a5c 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -30,26 +30,12 @@
#include "l.h"
#include "../ld/elf.h"
+#include "../ld/macho.h"
#define Dbufslop 100
char linuxdynld[] = "/lib/ld-linux.so.2";
-
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)
@@ -428,13 +414,18 @@ asmb(void)
{
Prog *p;
int32 v, magic;
- int a, nl, dynsym;
+ int a, dynsym;
uint32 va, fo, w, symo, startva;
uchar *op1;
ulong expectpc;
- Elf64_Ehdr *eh;
- Elf64_Phdr *ph, *pph;
- Elf64_Shdr *sh;
+ ElfEhdr *eh;
+ ElfPhdr *ph, *pph;
+ ElfShdr *sh;
+ MachoHdr *mh;
+ MachoSect *msect;
+ MachoSeg *ms;
+ MachoDebug *md;
+ MachoLoad *ml;
if(debug['v'])
Bprint(&bso, "%5.2f asmb\n", cputime());
@@ -585,7 +576,7 @@ asmb(void)
break;
case 7:
case 8:
- symo = rnd(HEADR+textsize, INITRND)+datsize+strtabsize;
+ symo = rnd(HEADR+textsize, INITRND)+datsize;
symo = rnd(symo, INITRND);
break;
}
@@ -750,69 +741,88 @@ asmb(void)
case 6:
/* apple MACH */
- va = 4096;
-
- 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 */
-
- machseg("__PAGEZERO",
- 0,va, /* vaddr vsize */
- 0,0, /* fileoffset filesize */
- 0,0, /* protects */
- 0,0); /* sections flags */
+ va = HEADR;
+ mh = getMachoHdr();
+ mh->cpu = MACHO_CPU_386;
+ mh->subcpu = MACHO_SUBCPU_X86;
- 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 */
+ /* segment for zero page */
+ ms = newMachoSeg("__PAGEZERO", 0);
+ ms->vsize = va;
+ /* text */
+ v = rnd(HEADR+textsize, INITRND);
+ ms = newMachoSeg("__TEXT", 1);
+ ms->vaddr = va;
+ ms->vsize = v;
+ ms->filesize = v;
+ ms->prot1 = 7;
+ ms->prot2 = 5;
+
+ 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;
- 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());
+ ms = newMachoSeg("__DATA", 2);
+ ms->vaddr = va+v;
+ ms->vsize = w;
+ ms->fileoffset = v;
+ ms->filesize = datsize;
+ ms->prot1 = 7;
+ ms->prot2 = 3;
+
+ msect = newMachoSect(ms, "__data");
+ msect->addr = va+v;
+ msect->size = datsize;
+ msect->off = v;
+
+ msect = newMachoSect(ms, "__bss");
+ msect->addr = va+v+datsize;
+ msect->size = bsssize;
+ msect->flag = 1; /* flag - zero fill */
+
+ ml = newMachoLoad(5, 16+2); /* unix thread */
+ ml->data[0] = 1; /* thread type */
+ ml->data[1] = 16; /* word count */
+ ml->data[2+10] = entryvalue(); /* start pc */
- 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 */
+ 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;
case 7:
@@ -1242,129 +1252,3 @@ 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;
-}
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index ce28b1336..cc5901fcb 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -371,6 +371,7 @@ Sym* lookup(char*, int);
void lput(int32);
void lputl(int32);
void vputl(uvlong);
+void strnput(char*, int);
void main(int, char*[]);
void mkfwd(void);
void* mal(uint32);
diff --git a/src/cmd/8l/macho.c b/src/cmd/8l/macho.c
new file mode 100644
index 000000000..a4a4e6954
--- /dev/null
+++ b/src/cmd/8l/macho.c
@@ -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"
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 96099e77f..4b6532568 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -31,6 +31,7 @@
#define EXTERN
#include "l.h"
#include "../ld/elf.h"
+#include "../ld/macho.h"
#include <ar.h>
#ifndef DEFAULT
@@ -212,7 +213,8 @@ main(int argc, char *argv[])
Bprint(&bso, "HEADR = 0x%ld\n", HEADR);
break;
case 6: /* apple MACH */
- HEADR = machheadr();
+ machoinit();
+ HEADR = MACHORESERVE;
if(INITTEXT == -1)
INITTEXT = 4096+HEADR;
if(INITDAT == -1)
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index 0edadc43d..cb4857248 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -963,7 +963,7 @@ extern int numelfphdr;
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.
* May waste some.
*/
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
new file mode 100644
index 000000000..159aceb9e
--- /dev/null
+++ b/src/cmd/ld/macho.c
@@ -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;
+}
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
new file mode 100644
index 000000000..747adac2d
--- /dev/null
+++ b/src/cmd/ld/macho.h
@@ -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,
+};