summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-10-03 10:37:12 -0700
committerRuss Cox <rsc@golang.org>2009-10-03 10:37:12 -0700
commite7a28869ec5829d4e202b44797b748522a533b2a (patch)
tree7b69b0974f4999bac76d11abed2071a2dc9e97aa /src/cmd
parente6310aac93e28c68953277b30e2eaf8bdd9f106a (diff)
downloadgo-e7a28869ec5829d4e202b44797b748522a533b2a.tar.gz
8c, 8l dynamic loading support.
better mach binaries. cgo working on darwin+linux amd64+386. eliminated context switches - pi is 30x faster. add libcgo to build. on snow leopard: - non-cgo binaries work; all tests pass. - cgo binaries work on amd64 but not 386. R=r DELTA=2031 (1316 added, 626 deleted, 89 changed) OCL=35264 CL=35304
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/6l/asm.c101
-rw-r--r--src/cmd/6l/l.h4
-rw-r--r--src/cmd/6l/obj.c6
-rw-r--r--src/cmd/6l/pass.c10
-rw-r--r--src/cmd/6l/span.c11
-rw-r--r--src/cmd/8l/asm.c109
-rw-r--r--src/cmd/8l/l.h4
-rw-r--r--src/cmd/8l/obj.c21
-rw-r--r--src/cmd/8l/pass.c12
-rw-r--r--src/cmd/8l/span.c11
-rw-r--r--src/cmd/cgo/ast.go1
-rw-r--r--src/cmd/cgo/gcc.go16
-rw-r--r--src/cmd/cgo/main.go38
-rw-r--r--src/cmd/cgo/out.go2
-rw-r--r--src/cmd/ld/elf.h2
-rw-r--r--src/cmd/ld/macho.c321
-rw-r--r--src/cmd/ld/macho.h9
17 files changed, 474 insertions, 204 deletions
diff --git a/src/cmd/6l/asm.c b/src/cmd/6l/asm.c
index 5562ee4e3..a0f8524e7 100644
--- a/src/cmd/6l/asm.c
+++ b/src/cmd/6l/asm.c
@@ -425,16 +425,11 @@ asmb(void)
int32 v, magic;
int a, dynsym;
uchar *op1;
- vlong vl, va, startva, fo, w, symo;
+ vlong vl, va, startva, fo, w, symo, machlink;
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());
@@ -523,6 +518,10 @@ asmb(void)
datblk(v, datsize-v);
}
+ machlink = 0;
+ if(HEADTYPE == 6)
+ machlink = domacholink();
+
symsize = 0;
spsize = 0;
lcsize = 0;
@@ -539,7 +538,7 @@ asmb(void)
symo = HEADR+textsize+datsize;
break;
case 6:
- symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND);
+ symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND)+machlink;
break;
case 7:
symo = rnd(HEADR+textsize, INITRND)+datsize;
@@ -607,92 +606,8 @@ asmb(void)
lputb(lcsize); /* line offsets */
break;
case 6:
- /* apple MACH */
- va = HEADR;
- mh = getMachoHdr();
- mh->cpu = MACHO_CPU_AMD64;
- mh->subcpu = MACHO_SUBCPU_X86;
-
- /* 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;
- 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['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);
+ asmbmacho(symdatva, symo);
break;
-
case 7:
/* elf amd-64 */
@@ -965,6 +880,8 @@ datblk(int32 s, int32 n)
curp = p;
if(!p->from.sym->reachable)
diag("unreachable symbol in datblk - %s", p->from.sym->name);
+ if(p->from.sym->type == SMACHO)
+ continue;
l = p->from.sym->value + p->from.offset - s;
c = p->from.scale;
i = 0;
diff --git a/src/cmd/6l/l.h b/src/cmd/6l/l.h
index a1c2ec527..28c37a82c 100644
--- a/src/cmd/6l/l.h
+++ b/src/cmd/6l/l.h
@@ -160,6 +160,8 @@ enum
SIMPORT,
SEXPORT,
+ SMACHO,
+
NHASH = 10007,
NHUNK = 100000,
MINSIZ = 8,
@@ -362,6 +364,7 @@ EXTERN Prog undefp;
EXTERN vlong textstksiz;
EXTERN vlong textarg;
extern char thechar;
+EXTERN int dynptrsize;
#define UP (&undefp)
@@ -403,6 +406,7 @@ void dobss(void);
void dodata(void);
void doelf(void);
void doinit(void);
+void domacho(void);
void doprof1(void);
void doprof2(void);
void dostkoff(void);
diff --git a/src/cmd/6l/obj.c b/src/cmd/6l/obj.c
index ba2dec3b2..4b40cce61 100644
--- a/src/cmd/6l/obj.c
+++ b/src/cmd/6l/obj.c
@@ -191,12 +191,12 @@ main(int argc, char *argv[])
case 6: /* apple MACH */
machoinit();
HEADR = MACHORESERVE;
+ if(INITRND == -1)
+ INITRND = 4096;
if(INITTEXT == -1)
INITTEXT = 4096+HEADR;
if(INITDAT == -1)
INITDAT = 0;
- if(INITRND == -1)
- INITRND = 4096;
break;
case 7: /* elf64 executable */
elfinit();
@@ -393,6 +393,8 @@ main(int argc, char *argv[])
patch();
follow();
doelf();
+ if(HEADTYPE == 6)
+ domacho();
dodata();
dobss();
dostkoff();
diff --git a/src/cmd/6l/pass.c b/src/cmd/6l/pass.c
index c2f560500..2da88bac1 100644
--- a/src/cmd/6l/pass.c
+++ b/src/cmd/6l/pass.c
@@ -142,6 +142,11 @@ dobss(void)
Sym *s;
int32 t;
+ if(dynptrsize > 0) {
+ /* dynamic pointer section between data and bss */
+ datsize = rnd(datsize, 8);
+ }
+
/* now the bss */
bsssize = 0;
for(i=0; i<NHASH; i++)
@@ -154,12 +159,13 @@ dobss(void)
s->size = t;
if(t >= 8)
bsssize = rnd(bsssize, 8);
- s->value = bsssize + datsize;
+ s->value = bsssize + dynptrsize + datsize;
bsssize += t;
}
+
xdefine("data", SBSS, 0);
xdefine("edata", SBSS, datsize);
- xdefine("end", SBSS, bsssize + datsize);
+ xdefine("end", SBSS, dynptrsize + bsssize + datsize);
}
Prog*
diff --git a/src/cmd/6l/span.c b/src/cmd/6l/span.c
index f1eafff00..18bf8cc0c 100644
--- a/src/cmd/6l/span.c
+++ b/src/cmd/6l/span.c
@@ -237,6 +237,12 @@ asmsym(void)
putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype);
continue;
+ case SMACHO:
+ if(!s->reachable)
+ continue;
+ putsymb(s->name, 'D', s->value+INITDAT+datsize+bsssize, s->version, s->gotype);
+ continue;
+
case SBSS:
if(!s->reachable)
continue;
@@ -715,6 +721,11 @@ vaddr(Adr *a)
v += INITTEXT; /* TO DO */
v += s->value;
break;
+ case SMACHO:
+ if(!s->reachable)
+ sysfatal("unreachable symbol in vaddr - %s", s->name);
+ v += INITDAT + datsize + s->value;
+ break;
default:
if(!s->reachable)
diag("unreachable symbol in vaddr - %s", s->name);
diff --git a/src/cmd/8l/asm.c b/src/cmd/8l/asm.c
index 449467a5c..c70af7072 100644
--- a/src/cmd/8l/asm.c
+++ b/src/cmd/8l/asm.c
@@ -257,7 +257,7 @@ needlib(char *name)
Sym *s;
/* reuse hash code in symbol table */
- p = smprint(".elfload.%s", name);
+ p = smprint(".dynlib.%s", name);
s = lookup(p, 0);
if(s->type == 0) {
s->type = 100; // avoid SDATA, etc.
@@ -414,8 +414,8 @@ asmb(void)
{
Prog *p;
int32 v, magic;
- int a, dynsym;
- uint32 va, fo, w, symo, startva;
+ int a, i, dynsym;
+ uint32 va, fo, w, symo, startva, machlink;
uchar *op1;
ulong expectpc;
ElfEhdr *eh;
@@ -547,6 +547,10 @@ asmb(void)
datblk(v, datsize-v);
}
+ machlink = 0;
+ if(HEADTYPE == 6)
+ machlink = domacholink();
+
symsize = 0;
spsize = 0;
lcsize = 0;
@@ -572,7 +576,7 @@ asmb(void)
symo = HEADR+textsize+datsize;
break;
case 6:
- symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND);
+ symo = rnd(HEADR+textsize, INITRND)+rnd(datsize, INITRND)+machlink;
break;
case 7:
case 8:
@@ -740,89 +744,7 @@ asmb(void)
break;
case 6:
- /* apple MACH */
- va = HEADR;
- mh = getMachoHdr();
- mh->cpu = MACHO_CPU_386;
- mh->subcpu = MACHO_SUBCPU_X86;
-
- /* 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;
- 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['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);
+ asmbmacho(symdatva, symo);
break;
case 7:
@@ -963,6 +885,17 @@ asmb(void)
ph->type = PT_DYNAMIC;
ph->flags = PF_R + PF_W;
phsh(ph, sh);
+
+ /*
+ * Thread-local storage segment (really just size).
+ */
+ if(tlsoffset != 0) {
+ ph = newElfPhdr();
+ ph->type = PT_TLS;
+ ph->flags = PF_R;
+ ph->memsz = -tlsoffset;
+ ph->align = 4;
+ }
}
ph = newElfPhdr();
@@ -1105,6 +1038,8 @@ datblk(int32 s, int32 n)
curp = p;
if(!p->from.sym->reachable)
diag("unreachable symbol in datblk - %s", p->from.sym->name);
+ if(p->from.sym->type == SMACHO)
+ continue;
l = p->from.sym->value + p->from.offset - s;
c = p->from.scale;
i = 0;
diff --git a/src/cmd/8l/l.h b/src/cmd/8l/l.h
index cc5901fcb..1959b2c74 100644
--- a/src/cmd/8l/l.h
+++ b/src/cmd/8l/l.h
@@ -151,6 +151,8 @@ enum
SIMPORT,
SEXPORT,
+ SMACHO, /* pointer to mach-o imported symbol */
+
NHASH = 10007,
NHUNK = 100000,
MINSIZ = 4,
@@ -272,6 +274,7 @@ EXTERN Prog* curtext;
EXTERN Prog* datap;
EXTERN Prog* edatap;
EXTERN int32 datsize;
+EXTERN int32 dynptrsize;
EXTERN char debug[128];
EXTERN char literal[32];
EXTERN Prog* etextp;
@@ -311,6 +314,7 @@ EXTERN int version;
EXTERN Prog zprg;
EXTERN int dtype;
EXTERN char thechar;
+EXTERN int tlsoffset;
EXTERN Adr* reloca;
EXTERN int doexp, dlm;
diff --git a/src/cmd/8l/obj.c b/src/cmd/8l/obj.c
index 4b6532568..aa197be53 100644
--- a/src/cmd/8l/obj.c
+++ b/src/cmd/8l/obj.c
@@ -213,6 +213,11 @@ main(int argc, char *argv[])
Bprint(&bso, "HEADR = 0x%ld\n", HEADR);
break;
case 6: /* apple MACH */
+ /*
+ * OS X system constant - offset from %gs to our TLS.
+ * Explained in ../../libcgo/darwin_386.c.
+ */
+ tlsoffset = 0x468;
machoinit();
HEADR = MACHORESERVE;
if(INITTEXT == -1)
@@ -223,6 +228,13 @@ main(int argc, char *argv[])
INITRND = 4096;
break;
case 7: /* elf32 executable */
+ /*
+ * Linux ELF uses TLS offsets negative from %gs.
+ * Translate 0(GS) and 4(GS) into -8(GS) and -4(GS).
+ * Also known to ../../pkg/runtime/linux/386/sys.s
+ * and ../../libcgo/linux_386.c.
+ */
+ tlsoffset = -8;
elfinit();
HEADR = ELFRESERVE;
if(INITTEXT == -1)
@@ -373,6 +385,8 @@ main(int argc, char *argv[])
patch();
follow();
doelf();
+ if(HEADTYPE == 6)
+ domacho();
dodata();
dostkoff();
if(debug['p'])
@@ -592,11 +606,14 @@ zaddr(Biobuf *f, Adr *a, Sym *h[])
a->type = Bgetc(f);
if(t & T_GOTYPE)
a->gotype = h[Bgetc(f)];
+
+ t = a->type;
+ if(t == D_INDIR+D_GS)
+ a->offset += tlsoffset;
+
s = a->sym;
if(s == S)
return;
-
- t = a->type;
if(t != D_AUTO && t != D_PARAM) {
if(a->gotype)
s->gotype = a->gotype;
diff --git a/src/cmd/8l/pass.c b/src/cmd/8l/pass.c
index 7ce419e8f..c624f750a 100644
--- a/src/cmd/8l/pass.c
+++ b/src/cmd/8l/pass.c
@@ -125,6 +125,11 @@ dodata(void)
datsize += u;
}
+ if(dynptrsize > 0) {
+ /* dynamic pointer section between data and bss */
+ datsize = rnd(datsize, 4);
+ }
+
/* now the bss */
bsssize = 0;
for(i=0; i<NHASH; i++)
@@ -135,12 +140,13 @@ dodata(void)
continue;
t = s->value;
s->size = t;
- s->value = bsssize + datsize;
+ s->value = bsssize + dynptrsize + datsize;
bsssize += t;
}
+
xdefine("data", SBSS, 0);
xdefine("edata", SBSS, datsize);
- xdefine("end", SBSS, bsssize + datsize);
+ xdefine("end", SBSS, dynptrsize + bsssize + datsize);
}
Prog*
@@ -570,7 +576,7 @@ dostkoff(void)
p = appendp(p); // load g into CX
p->as = AMOVL;
p->from.type = D_INDIR+D_GS;
- p->from.offset = 0;
+ p->from.offset = tlsoffset + 0;
p->to.type = D_CX;
if(debug['K']) {
diff --git a/src/cmd/8l/span.c b/src/cmd/8l/span.c
index 71607fcf2..6f62f9b4d 100644
--- a/src/cmd/8l/span.c
+++ b/src/cmd/8l/span.c
@@ -219,6 +219,12 @@ asmsym(void)
putsymb(s->name, 'D', s->value+INITDAT, s->version, s->gotype);
continue;
+ case SMACHO:
+ if(!s->reachable)
+ continue;
+ putsymb(s->name, 'D', s->value+INITDAT+datsize+bsssize, s->version, s->gotype);
+ continue;
+
case SBSS:
if(!s->reachable)
continue;
@@ -611,6 +617,11 @@ vaddr(Adr *a)
sysfatal("unreachable symbol in vaddr - %s", s->name);
v += s->value;
break;
+ case SMACHO:
+ if(!s->reachable)
+ sysfatal("unreachable symbol in vaddr - %s", s->name);
+ v += INITDAT + datsize + s->value;
+ break;
default:
if(!s->reachable)
sysfatal("unreachable symbol in vaddr - %s", s->name);
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
index 9b122676c..57500680b 100644
--- a/src/cmd/cgo/ast.go
+++ b/src/cmd/cgo/ast.go
@@ -36,6 +36,7 @@ type Prog struct {
Vardef map[string]*Type;
Funcdef map[string]*FuncType;
PtrSize int64;
+ GccOptions []string;
}
// A Type collects information about a type in both the C and Go worlds.
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index e3f526845..f573b98cb 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -172,6 +172,17 @@ func (p *Prog) loadDebugInfo() {
p.Typedef = conv.typedef;
}
+func concat(a, b []string) []string {
+ c := make([]string, len(a)+len(b));
+ for i, s := range a {
+ c[i] = s;
+ }
+ for i, s := range b {
+ c[i+len(a)] = s;
+ }
+ return c;
+}
+
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
// returns the corresponding DWARF data and any messages
// printed to standard error.
@@ -182,7 +193,7 @@ func (p *Prog) gccDebug(stdin []byte) (*dwarf.Data, string) {
}
tmp := "_cgo_.o";
- _, stderr, ok := run(stdin, []string{
+ base := []string{
"gcc",
machine,
"-Wall", // many warnings
@@ -192,7 +203,8 @@ func (p *Prog) gccDebug(stdin []byte) (*dwarf.Data, string) {
"-c", // do not link
"-xc", // input language is C
"-", // read input from standard input
- });
+ };
+ _, stderr, ok := run(stdin, concat(base, p.GccOptions));
if !ok {
return nil, string(stderr);
}
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index b629f0a22..eb04fa77d 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -11,15 +11,13 @@
package main
import (
- "flag";
"fmt";
"go/ast";
"os";
)
func usage() {
- fmt.Fprint(os.Stderr, "usage: cgo file.cgo\n");
- flag.PrintDefaults();
+ fmt.Fprint(os.Stderr, "usage: cgo [compiler options] file.go\n");
}
var ptrSizeMap = map[string]int64 {
@@ -28,9 +26,24 @@ var ptrSizeMap = map[string]int64 {
"arm": 4
}
+var expandName = map[string]string {
+ "schar": "signed char",
+ "uchar": "unsigned char",
+ "ushort": "unsigned short",
+ "uint": "unsigned int",
+ "ulong": "unsigned long",
+ "longlong": "long long",
+ "ulonglong": "unsigned long long",
+}
+
func main() {
- flag.Usage = usage;
- flag.Parse();
+ args := os.Args;
+ if len(args) < 2 {
+ usage();
+ os.Exit(2);
+ }
+ gccOptions := args[1:len(args)-1];
+ input := args[len(args)-1];
arch := os.Getenv("GOARCH");
if arch == "" {
@@ -41,14 +54,17 @@ func main() {
fatal("unknown architecture %s", arch);
}
- args := flag.Args();
- if len(args) != 1 {
- usage();
- os.Exit(2);
+ p := openProg(input);
+ for _, cref := range p.Crefs {
+ // Convert C.ulong to C.unsigned long, etc.
+ if expand, ok := expandName[cref.Name]; ok {
+ cref.Name = expand;
+ }
}
- p := openProg(args[0]);
+
p.PtrSize = ptrSize;
p.Preamble = p.Preamble + "\n" + builtinProlog;
+ p.GccOptions = gccOptions;
p.loadDebugInfo();
p.Vardef = make(map[string]*Type);
p.Funcdef = make(map[string]*FuncType);
@@ -83,5 +99,5 @@ func main() {
}
p.PackagePath = p.Package;
- p.writeOutput(args[0]);
+ p.writeOutput(input);
}
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 91473abeb..d2eedc331 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -198,7 +198,7 @@ const cProlog = `
#include "cgocall.h"
#pragma dynld initcgo initcgo "%s/libcgo.so"
-#pragma dynld cgo cgo "%s/libcgo.so"
+#pragma dynld libcgo_thread_start libcgo_thread_start "%s/libcgo.so"
#pragma dynld _cgo_malloc _cgo_malloc "%s/libcgo.so"
#pragma dynld _cgo_free free "%s/libcgo.so"
diff --git a/src/cmd/ld/elf.h b/src/cmd/ld/elf.h
index cb4857248..e0c2bd1b6 100644
--- a/src/cmd/ld/elf.h
+++ b/src/cmd/ld/elf.h
@@ -243,7 +243,7 @@ typedef struct {
#define PT_NOTE 4 /* Auxiliary information. */
#define PT_SHLIB 5 /* Reserved (not used). */
#define PT_PHDR 6 /* Location of program header itself. */
-#define PT_TLS 7 /* Thread local storage segment */
+#define PT_TLS 7 /* Thread local storage segment */
#define PT_LOOS 0x60000000 /* First OS-specific. */
#define PT_HIOS 0x6fffffff /* Last OS-specific. */
#define PT_LOPROC 0x70000000 /* First processor-specific type. */
diff --git a/src/cmd/ld/macho.c b/src/cmd/ld/macho.c
index 159aceb9e..e4fe963ac 100644
--- a/src/cmd/ld/macho.c
+++ b/src/cmd/ld/macho.c
@@ -92,6 +92,22 @@ newMachoDebug(void)
return &xdebug[ndebug++];
}
+
+// Generic linking code.
+
+static uchar *linkdata;
+static uint32 nlinkdata;
+static uint32 mlinkdata;
+
+static uchar *strtab;
+static uint32 nstrtab;
+static uint32 mstrtab;
+
+static char **dylib;
+static int ndylib;
+
+static vlong linkoff;
+
int
machowrite(void)
{
@@ -205,3 +221,308 @@ machowrite(void)
return Boffset(&bso) - o1;
}
+
+static void*
+grow(uchar **dat, uint32 *ndat, uint32 *mdat, uint32 n)
+{
+ uchar *p;
+ uint32 old;
+
+ if(*ndat+n > *mdat) {
+ old = *mdat;
+ *mdat = (*ndat+n)*2 + 128;
+ *dat = realloc(*dat, *mdat);
+ if(*dat == 0) {
+ diag("out of memory");
+ errorexit();
+ }
+ memset(*dat+old, 0, *mdat-old);
+ }
+ p = *dat + *ndat;
+ *ndat += n;
+ return p;
+}
+
+static int
+needlib(char *name)
+{
+ char *p;
+ Sym *s;
+
+ /* reuse hash code in symbol table */
+ p = smprint(".machoload.%s", name);
+ s = lookup(p, 0);
+ if(s->type == 0) {
+ s->type = 100; // avoid SDATA, etc.
+ return 1;
+ }
+ return 0;
+}
+
+void
+domacho(void)
+{
+ int h, nsym, ptrsize;
+ char *p;
+ uchar *dat;
+ uint32 x;
+ Sym *s;
+
+ ptrsize = 4;
+ if(macho64)
+ ptrsize = 8;
+
+ // empirically, string table must begin with " \x00".
+ if(!debug['d'])
+ *(char*)grow(&strtab, &nstrtab, &mstrtab, 2) = ' ';
+
+ nsym = 0;
+ for(h=0; h<NHASH; h++) {
+ for(s=hash[h]; s!=S; s=s->link) {
+ if(!s->reachable || (s->type != SDATA && s->type != SBSS) || s->dynldname == nil)
+ continue;
+ if(debug['d']) {
+ diag("cannot use dynamic loading and -d");
+ errorexit();
+ }
+ s->type = SMACHO;
+ s->value = nsym*ptrsize;
+
+ /* symbol table entry - darwin still puts _ prefixes on all C symbols */
+ x = nstrtab;
+ p = grow(&strtab, &nstrtab, &mstrtab, 1+strlen(s->dynldname)+1);
+ *p++ = '_';
+ strcpy(p, s->dynldname);
+
+ dat = grow(&linkdata, &nlinkdata, &mlinkdata, 8+ptrsize);
+ dat[0] = x;
+ dat[1] = x>>8;
+ dat[2] = x>>16;
+ dat[3] = x>>24;
+ dat[4] = 0x01; // type: N_EXT - external symbol
+
+ if(needlib(s->dynldlib)) {
+ if(ndylib%32 == 0) {
+ dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
+ if(dylib == nil) {
+ diag("out of memory");
+ errorexit();
+ }
+ }
+ dylib[ndylib++] = s->dynldlib;
+ }
+ nsym++;
+ }
+ }
+
+ /*
+ * list of symbol table indexes.
+ * we don't take advantage of the opportunity
+ * to order the symbol table differently from
+ * this list, so it is boring: 0 1 2 3 4 ...
+ */
+ for(x=0; x<nsym; x++) {
+ dat = grow(&linkdata, &nlinkdata, &mlinkdata, 4);
+ dat[0] = x;
+ dat[1] = x>>8;
+ dat[2] = x>>16;
+ dat[3] = x>>24;
+ }
+
+ dynptrsize = nsym*ptrsize;
+}
+
+vlong
+domacholink(void)
+{
+ linkoff = 0;
+ if(nlinkdata > 0) {
+ linkoff = rnd(HEADR+textsize, INITRND) + rnd(datsize, INITRND);
+ seek(cout, linkoff, 0);
+ write(cout, linkdata, nlinkdata);
+ write(cout, strtab, nstrtab);
+ }
+ return rnd(nlinkdata+nstrtab, INITRND);
+}
+
+void
+asmbmacho(vlong symdatva, vlong symo)
+{
+ vlong v, w;
+ vlong va;
+ int a, i, ptrsize;
+ MachoHdr *mh;
+ MachoSect *msect;
+ MachoSeg *ms;
+ MachoDebug *md;
+ MachoLoad *ml;
+
+ /* apple MACH */
+ va = INITTEXT - HEADR;
+ mh = getMachoHdr();
+ switch(thechar){
+ default:
+ diag("unknown mach architecture");
+ errorexit();
+ case '6':
+ mh->cpu = MACHO_CPU_AMD64;
+ mh->subcpu = MACHO_SUBCPU_X86;
+ ptrsize = 8;
+ break;
+ case '8':
+ mh->cpu = MACHO_CPU_386;
+ mh->subcpu = MACHO_SUBCPU_X86;
+ ptrsize = 4;
+ break;
+ }
+
+ /* 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 = INITTEXT;
+ msect->size = textsize;
+ msect->off = INITTEXT - va;
+ msect->flag = 0x400; /* flag - some instructions */
+
+ /* data */
+ w = datsize+dynptrsize+bsssize;
+ ms = newMachoSeg("__DATA", 2+(dynptrsize>0));
+ 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;
+
+ if(dynptrsize > 0) {
+ msect = newMachoSect(ms, "__nl_symbol_ptr");
+ msect->addr = va+v+datsize;
+ msect->size = dynptrsize;
+ msect->align = 2;
+ msect->flag = 6; /* section with nonlazy symbol pointers */
+ /*
+ * The reserved1 field is supposed to be the index of
+ * the first entry in the list of symbol table indexes
+ * in isymtab for the symbols we need. We only use
+ * pointers, so we need the entire list, so the index
+ * here should be 0, which luckily is what the Mach-O
+ * writing code emits by default for this not really reserved field.
+ msect->reserved1 = 0; - first indirect symbol table entry we need
+ */
+ }
+
+ msect = newMachoSect(ms, "__bss");
+ msect->addr = va+v+datsize+dynptrsize;
+ msect->size = bsssize;
+ msect->flag = 1; /* flag - zero fill */
+
+ switch(thechar) {
+ default:
+ diag("unknown macho architecture");
+ errorexit();
+ case '6':
+ 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;
+ break;
+ case '8':
+ 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 */
+ break;
+ }
+
+ if(!debug['d']) {
+ int nsym;
+
+ nsym = dynptrsize/ptrsize;
+
+ ms = newMachoSeg("__LINKEDIT", 0);
+ ms->vaddr = va+v+rnd(datsize+dynptrsize+bsssize, INITRND);
+ ms->vsize = nlinkdata+nstrtab;
+ ms->fileoffset = linkoff;
+ ms->filesize = nlinkdata+nstrtab;
+ ms->prot1 = 7;
+ ms->prot2 = 3;
+
+ ml = newMachoLoad(2, 4); /* LC_SYMTAB */
+ ml->data[0] = linkoff; /* symoff */
+ ml->data[1] = nsym; /* nsyms */
+ ml->data[2] = linkoff + nlinkdata; /* stroff */
+ ml->data[3] = nstrtab; /* strsize */
+
+ ml = newMachoLoad(11, 18); /* LC_DYSYMTAB */
+ ml->data[0] = 0; /* ilocalsym */
+ ml->data[1] = 0; /* nlocalsym */
+ ml->data[2] = 0; /* iextdefsym */
+ ml->data[3] = 0; /* nextdefsym */
+ ml->data[4] = 0; /* iundefsym */
+ ml->data[5] = nsym; /* nundefsym */
+ ml->data[6] = 0; /* tocoffset */
+ ml->data[7] = 0; /* ntoc */
+ ml->data[8] = 0; /* modtaboff */
+ ml->data[9] = 0; /* nmodtab */
+ ml->data[10] = 0; /* extrefsymoff */
+ ml->data[11] = 0; /* nextrefsyms */
+ ml->data[12] = linkoff + nlinkdata - nsym*4; /* indirectsymoff */
+ ml->data[13] = nsym; /* nindirectsyms */
+ ml->data[14] = 0; /* extreloff */
+ ml->data[15] = 0; /* nextrel */
+ ml->data[16] = 0; /* locreloff */
+ ml->data[17] = 0; /* nlocrel */
+
+ ml = newMachoLoad(14, 6); /* LC_LOAD_DYLINKER */
+ ml->data[0] = 12; /* offset to string */
+ strcpy((char*)&ml->data[1], "/usr/lib/dyld");
+
+ for(i=0; i<ndylib; i++) {
+ ml = newMachoLoad(12, 4+(strlen(dylib[i])+1+7)/8*2); /* LC_LOAD_DYLIB */
+ ml->data[0] = 24; /* offset of string from beginning of load */
+ ml->data[1] = 0; /* time stamp */
+ ml->data[2] = 0; /* version */
+ ml->data[3] = 0; /* compatibility version */
+ strcpy((char*)&ml->data[4], dylib[i]);
+ }
+ }
+
+ 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);
+}
diff --git a/src/cmd/ld/macho.h b/src/cmd/ld/macho.h
index 747adac2d..a96b2a383 100644
--- a/src/cmd/ld/macho.h
+++ b/src/cmd/ld/macho.h
@@ -61,10 +61,17 @@ void machoinit(void);
* for Header, PHeaders, and SHeaders.
* May waste some.
*/
-#define MACHORESERVE 4096
+#define MACHORESERVE 3*1024
enum {
MACHO_CPU_AMD64 = (1<<24)|7,
MACHO_CPU_386 = 7,
MACHO_SUBCPU_X86 = 3,
+
+ MACHO32SYMSIZE = 12,
+ MACHO64SYMSIZE = 16,
};
+
+void domacho(void);
+vlong domacholink(void);
+void asmbmacho(vlong, vlong);