mirror of
https://github.com/golang/go
synced 2024-11-12 09:20:22 -07:00
cmd/ld: host linking support for linux/amd64
Still to do: non-linux and non-amd64. It may work on other ELF-based amd64 systems too, but untested. "go test -ldflags -hostobj $GOROOT/misc/cgo/test" passes. Much may yet change, but this seems a reasonable checkpoint. R=iant CC=golang-dev https://golang.org/cl/7369057
This commit is contained in:
parent
8aafb44b0b
commit
60f783d92b
@ -125,7 +125,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
// Handle relocations found in ELF object files.
|
// Handle relocations found in ELF object files.
|
||||||
case 256 + R_ARM_PLT32:
|
case 256 + R_ARM_PLT32:
|
||||||
r->type = D_CALL;
|
r->type = D_CALL;
|
||||||
if(targ->dynimpname != nil && !targ->dynexport) {
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic)) {
|
||||||
addpltsym(targ);
|
addpltsym(targ);
|
||||||
r->sym = lookup(".plt", 0);
|
r->sym = lookup(".plt", 0);
|
||||||
r->add = braddoff(r->add, targ->plt / 4);
|
r->add = braddoff(r->add, targ->plt / 4);
|
||||||
@ -138,7 +138,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_ARM_GOT32: // R_ARM_GOT_BREL
|
case 256 + R_ARM_GOT32: // R_ARM_GOT_BREL
|
||||||
if(targ->dynimpname == nil || targ->dynexport) {
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic)) {
|
||||||
addgotsyminternal(targ);
|
addgotsyminternal(targ);
|
||||||
} else {
|
} else {
|
||||||
addgotsym(targ);
|
addgotsym(targ);
|
||||||
@ -149,7 +149,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_ARM_GOT_PREL: // GOT(S) + A - P
|
case 256 + R_ARM_GOT_PREL: // GOT(S) + A - P
|
||||||
if(targ->dynimpname == nil || targ->dynexport) {
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic)) {
|
||||||
addgotsyminternal(targ);
|
addgotsyminternal(targ);
|
||||||
} else {
|
} else {
|
||||||
addgotsym(targ);
|
addgotsym(targ);
|
||||||
@ -171,7 +171,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
|
|
||||||
case 256 + R_ARM_CALL:
|
case 256 + R_ARM_CALL:
|
||||||
r->type = D_CALL;
|
r->type = D_CALL;
|
||||||
if(targ->dynimpname != nil && !targ->dynexport) {
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic)) {
|
||||||
addpltsym(targ);
|
addpltsym(targ);
|
||||||
r->sym = lookup(".plt", 0);
|
r->sym = lookup(".plt", 0);
|
||||||
r->add = braddoff(r->add, targ->plt / 4);
|
r->add = braddoff(r->add, targ->plt / 4);
|
||||||
@ -184,7 +184,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_ARM_ABS32:
|
case 256 + R_ARM_ABS32:
|
||||||
if(targ->dynimpname != nil && !targ->dynexport)
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ->name);
|
diag("unexpected R_ARM_ABS32 relocation for dynamic symbol %s", targ->name);
|
||||||
r->type = D_ADDR;
|
r->type = D_ADDR;
|
||||||
return;
|
return;
|
||||||
@ -201,7 +201,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
case 256 + R_ARM_PC24:
|
case 256 + R_ARM_PC24:
|
||||||
case 256 + R_ARM_JUMP24:
|
case 256 + R_ARM_JUMP24:
|
||||||
r->type = D_CALL;
|
r->type = D_CALL;
|
||||||
if(targ->dynimpname != nil && !targ->dynexport) {
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic)) {
|
||||||
addpltsym(targ);
|
addpltsym(targ);
|
||||||
r->sym = lookup(".plt", 0);
|
r->sym = lookup(".plt", 0);
|
||||||
r->add = braddoff(r->add, targ->plt / 4);
|
r->add = braddoff(r->add, targ->plt / 4);
|
||||||
@ -210,7 +210,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle references to ELF symbols from our own object files.
|
// Handle references to ELF symbols from our own object files.
|
||||||
if(targ->dynimpname == nil || targ->dynexport)
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(r->type) {
|
switch(r->type) {
|
||||||
@ -464,7 +464,7 @@ adddynsym(Sym *s)
|
|||||||
|
|
||||||
/* type */
|
/* type */
|
||||||
t = STB_GLOBAL << 4;
|
t = STB_GLOBAL << 4;
|
||||||
if(s->dynexport && (s->type&SMASK) == STEXT)
|
if((s->cgoexport & CgoExportDynamic) && (s->type&SMASK) == STEXT)
|
||||||
t |= STT_FUNC;
|
t |= STT_FUNC;
|
||||||
else
|
else
|
||||||
t |= STT_OBJECT;
|
t |= STT_OBJECT;
|
||||||
@ -472,7 +472,7 @@ adddynsym(Sym *s)
|
|||||||
adduint8(d, 0);
|
adduint8(d, 0);
|
||||||
|
|
||||||
/* shndx */
|
/* shndx */
|
||||||
if(!s->dynexport && s->dynimpname != nil)
|
if(!(s->cgoexport & CgoExportDynamic) && s->dynimpname != nil)
|
||||||
adduint16(d, SHN_UNDEF);
|
adduint16(d, SHN_UNDEF);
|
||||||
else {
|
else {
|
||||||
switch(s->type) {
|
switch(s->type) {
|
||||||
|
@ -137,7 +137,7 @@ struct Sym
|
|||||||
short version;
|
short version;
|
||||||
uchar dupok;
|
uchar dupok;
|
||||||
uchar reachable;
|
uchar reachable;
|
||||||
uchar dynexport;
|
uchar cgoexport;
|
||||||
uchar leaf;
|
uchar leaf;
|
||||||
int32 dynid;
|
int32 dynid;
|
||||||
int32 plt;
|
int32 plt;
|
||||||
|
@ -82,6 +82,7 @@ main(int argc, char *argv[])
|
|||||||
INITRND = -1;
|
INITRND = -1;
|
||||||
INITENTRY = 0;
|
INITENTRY = 0;
|
||||||
LIBINITENTRY = 0;
|
LIBINITENTRY = 0;
|
||||||
|
linkmode = LinkInternal; // TODO: LinkAuto once everything works.
|
||||||
nuxiinit();
|
nuxiinit();
|
||||||
|
|
||||||
p = getgoarm();
|
p = getgoarm();
|
||||||
@ -126,6 +127,7 @@ main(int argc, char *argv[])
|
|||||||
flagcount("v", "print link trace", &debug['v']);
|
flagcount("v", "print link trace", &debug['v']);
|
||||||
flagcount("w", "disable DWARF generation", &debug['w']);
|
flagcount("w", "disable DWARF generation", &debug['w']);
|
||||||
flagcount("shared", "generate shared object", &flag_shared);
|
flagcount("shared", "generate shared object", &flag_shared);
|
||||||
|
// TODO: link mode flag
|
||||||
|
|
||||||
flagparse(&argc, &argv, usage);
|
flagparse(&argc, &argv, usage);
|
||||||
|
|
||||||
@ -268,6 +270,7 @@ main(int argc, char *argv[])
|
|||||||
reloc();
|
reloc();
|
||||||
asmb();
|
asmb();
|
||||||
undef();
|
undef();
|
||||||
|
hostlink();
|
||||||
|
|
||||||
if(debug['c'])
|
if(debug['c'])
|
||||||
print("ARM size = %d\n", armsize);
|
print("ARM size = %d\n", armsize);
|
||||||
|
@ -131,7 +131,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
|
|
||||||
// Handle relocations found in ELF object files.
|
// Handle relocations found in ELF object files.
|
||||||
case 256 + R_X86_64_PC32:
|
case 256 + R_X86_64_PC32:
|
||||||
if(targ->dynimpname != nil && !targ->dynexport)
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name);
|
diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ->name);
|
||||||
if(targ->type == 0 || targ->type == SXREF)
|
if(targ->type == 0 || targ->type == SXREF)
|
||||||
diag("unknown symbol %s in pcrel", targ->name);
|
diag("unknown symbol %s in pcrel", targ->name);
|
||||||
@ -142,7 +142,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
case 256 + R_X86_64_PLT32:
|
case 256 + R_X86_64_PLT32:
|
||||||
r->type = D_PCREL;
|
r->type = D_PCREL;
|
||||||
r->add += 4;
|
r->add += 4;
|
||||||
if(targ->dynimpname != nil && !targ->dynexport) {
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic)) {
|
||||||
addpltsym(targ);
|
addpltsym(targ);
|
||||||
r->sym = lookup(".plt", 0);
|
r->sym = lookup(".plt", 0);
|
||||||
r->add += targ->plt;
|
r->add += targ->plt;
|
||||||
@ -150,7 +150,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_X86_64_GOTPCREL:
|
case 256 + R_X86_64_GOTPCREL:
|
||||||
if(targ->dynimpname == nil || targ->dynexport) {
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic)) {
|
||||||
// have symbol
|
// have symbol
|
||||||
if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
|
if(r->off >= 2 && s->p[r->off-2] == 0x8b) {
|
||||||
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
||||||
@ -171,7 +171,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_X86_64_64:
|
case 256 + R_X86_64_64:
|
||||||
if(targ->dynimpname != nil && !targ->dynexport)
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name);
|
diag("unexpected R_X86_64_64 relocation for dynamic symbol %s", targ->name);
|
||||||
r->type = D_ADDR;
|
r->type = D_ADDR;
|
||||||
return;
|
return;
|
||||||
@ -182,12 +182,12 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0:
|
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 0:
|
||||||
// TODO: What is the difference between all these?
|
// TODO: What is the difference between all these?
|
||||||
r->type = D_ADDR;
|
r->type = D_ADDR;
|
||||||
if(targ->dynimpname != nil && !targ->dynexport)
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected reloc for dynamic symbol %s", targ->name);
|
diag("unexpected reloc for dynamic symbol %s", targ->name);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1:
|
case 512 + MACHO_X86_64_RELOC_BRANCH*2 + 1:
|
||||||
if(targ->dynimpname != nil && !targ->dynexport) {
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic)) {
|
||||||
addpltsym(targ);
|
addpltsym(targ);
|
||||||
r->sym = lookup(".plt", 0);
|
r->sym = lookup(".plt", 0);
|
||||||
r->add = targ->plt;
|
r->add = targ->plt;
|
||||||
@ -201,12 +201,12 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1:
|
case 512 + MACHO_X86_64_RELOC_SIGNED_2*2 + 1:
|
||||||
case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
|
case 512 + MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
|
||||||
r->type = D_PCREL;
|
r->type = D_PCREL;
|
||||||
if(targ->dynimpname != nil && !targ->dynexport)
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name);
|
diag("unexpected pc-relative reloc for dynamic symbol %s", targ->name);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
|
case 512 + MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
|
||||||
if(targ->dynimpname == nil || targ->dynexport) {
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic)) {
|
||||||
// have symbol
|
// have symbol
|
||||||
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
// turn MOVQ of GOT entry into LEAQ of symbol itself
|
||||||
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
||||||
@ -219,7 +219,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case 512 + MACHO_X86_64_RELOC_GOT*2 + 1:
|
case 512 + MACHO_X86_64_RELOC_GOT*2 + 1:
|
||||||
if(targ->dynimpname == nil || targ->dynexport)
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
|
diag("unexpected GOT reloc for non-dynamic symbol %s", targ->name);
|
||||||
addgotsym(targ);
|
addgotsym(targ);
|
||||||
r->type = D_PCREL;
|
r->type = D_PCREL;
|
||||||
@ -229,7 +229,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle references to ELF symbols from our own object files.
|
// Handle references to ELF symbols from our own object files.
|
||||||
if(targ->dynimpname == nil || targ->dynexport)
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(r->type) {
|
switch(r->type) {
|
||||||
@ -470,7 +470,7 @@ adddynsym(Sym *s)
|
|||||||
adduint32(d, addstring(lookup(".dynstr", 0), name));
|
adduint32(d, addstring(lookup(".dynstr", 0), name));
|
||||||
/* type */
|
/* type */
|
||||||
t = STB_GLOBAL << 4;
|
t = STB_GLOBAL << 4;
|
||||||
if(s->dynexport && (s->type&SMASK) == STEXT)
|
if((s->cgoexport & CgoExportDynamic) && (s->type&SMASK) == STEXT)
|
||||||
t |= STT_FUNC;
|
t |= STT_FUNC;
|
||||||
else
|
else
|
||||||
t |= STT_OBJECT;
|
t |= STT_OBJECT;
|
||||||
@ -480,7 +480,7 @@ adddynsym(Sym *s)
|
|||||||
adduint8(d, 0);
|
adduint8(d, 0);
|
||||||
|
|
||||||
/* section where symbol is defined */
|
/* section where symbol is defined */
|
||||||
if(!s->dynexport && s->dynimpname != nil)
|
if(!(s->cgoexport & CgoExportDynamic) && s->dynimpname != nil)
|
||||||
adduint16(d, SHN_UNDEF);
|
adduint16(d, SHN_UNDEF);
|
||||||
else {
|
else {
|
||||||
switch(s->type) {
|
switch(s->type) {
|
||||||
@ -510,7 +510,7 @@ adddynsym(Sym *s)
|
|||||||
/* size of object */
|
/* size of object */
|
||||||
adduint64(d, s->size);
|
adduint64(d, s->size);
|
||||||
|
|
||||||
if(!s->dynexport && s->dynimplib && needlib(s->dynimplib)) {
|
if(!(s->cgoexport & CgoExportDynamic) && s->dynimplib && needlib(s->dynimplib)) {
|
||||||
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
|
elfwritedynent(lookup(".dynamic", 0), DT_NEEDED,
|
||||||
addstring(lookup(".dynstr", 0), s->dynimplib));
|
addstring(lookup(".dynstr", 0), s->dynimplib));
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ struct Sym
|
|||||||
short version;
|
short version;
|
||||||
uchar dupok;
|
uchar dupok;
|
||||||
uchar reachable;
|
uchar reachable;
|
||||||
uchar dynexport;
|
uchar cgoexport;
|
||||||
uchar special;
|
uchar special;
|
||||||
uchar stkcheck;
|
uchar stkcheck;
|
||||||
uchar hide;
|
uchar hide;
|
||||||
|
@ -83,6 +83,7 @@ main(int argc, char *argv[])
|
|||||||
INITRND = -1;
|
INITRND = -1;
|
||||||
INITENTRY = 0;
|
INITENTRY = 0;
|
||||||
LIBINITENTRY = 0;
|
LIBINITENTRY = 0;
|
||||||
|
linkmode = LinkInternal; // TODO: LinkAuto once everything works.
|
||||||
nuxiinit();
|
nuxiinit();
|
||||||
|
|
||||||
flagcount("1", "use alternate profiling code", &debug['1']);
|
flagcount("1", "use alternate profiling code", &debug['1']);
|
||||||
@ -123,6 +124,10 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
flagparse(&argc, &argv, usage);
|
flagparse(&argc, &argv, usage);
|
||||||
|
|
||||||
|
// TODO: link mode flag instead of isobj
|
||||||
|
if(isobj)
|
||||||
|
linkmode = LinkExternal;
|
||||||
|
|
||||||
if(argc != 1)
|
if(argc != 1)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
@ -282,6 +287,7 @@ main(int argc, char *argv[])
|
|||||||
reloc();
|
reloc();
|
||||||
asmb();
|
asmb();
|
||||||
undef();
|
undef();
|
||||||
|
hostlink();
|
||||||
if(debug['v']) {
|
if(debug['v']) {
|
||||||
Bprint(&bso, "%5.2f cpu time\n", cputime());
|
Bprint(&bso, "%5.2f cpu time\n", cputime());
|
||||||
Bprint(&bso, "%d symbols\n", nsymbol);
|
Bprint(&bso, "%d symbols\n", nsymbol);
|
||||||
|
@ -128,7 +128,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
|
|
||||||
// Handle relocations found in ELF object files.
|
// Handle relocations found in ELF object files.
|
||||||
case 256 + R_386_PC32:
|
case 256 + R_386_PC32:
|
||||||
if(targ->dynimpname != nil && !targ->dynexport)
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name);
|
diag("unexpected R_386_PC32 relocation for dynamic symbol %s", targ->name);
|
||||||
if(targ->type == 0 || targ->type == SXREF)
|
if(targ->type == 0 || targ->type == SXREF)
|
||||||
diag("unknown symbol %s in pcrel", targ->name);
|
diag("unknown symbol %s in pcrel", targ->name);
|
||||||
@ -139,7 +139,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
case 256 + R_386_PLT32:
|
case 256 + R_386_PLT32:
|
||||||
r->type = D_PCREL;
|
r->type = D_PCREL;
|
||||||
r->add += 4;
|
r->add += 4;
|
||||||
if(targ->dynimpname != nil && !targ->dynexport) {
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic)) {
|
||||||
addpltsym(targ);
|
addpltsym(targ);
|
||||||
r->sym = lookup(".plt", 0);
|
r->sym = lookup(".plt", 0);
|
||||||
r->add += targ->plt;
|
r->add += targ->plt;
|
||||||
@ -147,7 +147,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_386_GOT32:
|
case 256 + R_386_GOT32:
|
||||||
if(targ->dynimpname == nil || targ->dynexport) {
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic)) {
|
||||||
// have symbol
|
// have symbol
|
||||||
// turn MOVL of GOT entry into LEAL of symbol itself
|
// turn MOVL of GOT entry into LEAL of symbol itself
|
||||||
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
||||||
@ -175,19 +175,19 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 256 + R_386_32:
|
case 256 + R_386_32:
|
||||||
if(targ->dynimpname != nil && !targ->dynexport)
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name);
|
diag("unexpected R_386_32 relocation for dynamic symbol %s", targ->name);
|
||||||
r->type = D_ADDR;
|
r->type = D_ADDR;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0:
|
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 0:
|
||||||
r->type = D_ADDR;
|
r->type = D_ADDR;
|
||||||
if(targ->dynimpname != nil && !targ->dynexport)
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic))
|
||||||
diag("unexpected reloc for dynamic symbol %s", targ->name);
|
diag("unexpected reloc for dynamic symbol %s", targ->name);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1:
|
case 512 + MACHO_GENERIC_RELOC_VANILLA*2 + 1:
|
||||||
if(targ->dynimpname != nil && !targ->dynexport) {
|
if(targ->dynimpname != nil && !(targ->cgoexport & CgoExportDynamic)) {
|
||||||
addpltsym(targ);
|
addpltsym(targ);
|
||||||
r->sym = lookup(".plt", 0);
|
r->sym = lookup(".plt", 0);
|
||||||
r->add = targ->plt;
|
r->add = targ->plt;
|
||||||
@ -198,7 +198,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 512 + MACHO_FAKE_GOTPCREL:
|
case 512 + MACHO_FAKE_GOTPCREL:
|
||||||
if(targ->dynimpname == nil || targ->dynexport) {
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic)) {
|
||||||
// have symbol
|
// have symbol
|
||||||
// turn MOVL of GOT entry into LEAL of symbol itself
|
// turn MOVL of GOT entry into LEAL of symbol itself
|
||||||
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
if(r->off < 2 || s->p[r->off-2] != 0x8b) {
|
||||||
@ -217,7 +217,7 @@ adddynrel(Sym *s, Reloc *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle references to ELF symbols from our own object files.
|
// Handle references to ELF symbols from our own object files.
|
||||||
if(targ->dynimpname == nil || targ->dynexport)
|
if(targ->dynimpname == nil || (targ->cgoexport & CgoExportDynamic))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(r->type) {
|
switch(r->type) {
|
||||||
@ -461,7 +461,7 @@ adddynsym(Sym *s)
|
|||||||
|
|
||||||
/* type */
|
/* type */
|
||||||
t = STB_GLOBAL << 4;
|
t = STB_GLOBAL << 4;
|
||||||
if(s->dynexport && (s->type&SMASK) == STEXT)
|
if((s->cgoexport & CgoExportDynamic) && (s->type&SMASK) == STEXT)
|
||||||
t |= STT_FUNC;
|
t |= STT_FUNC;
|
||||||
else
|
else
|
||||||
t |= STT_OBJECT;
|
t |= STT_OBJECT;
|
||||||
@ -469,7 +469,7 @@ adddynsym(Sym *s)
|
|||||||
adduint8(d, 0);
|
adduint8(d, 0);
|
||||||
|
|
||||||
/* shndx */
|
/* shndx */
|
||||||
if(!s->dynexport && s->dynimpname != nil)
|
if(!(s->cgoexport & CgoExportDynamic) && s->dynimpname != nil)
|
||||||
adduint16(d, SHN_UNDEF);
|
adduint16(d, SHN_UNDEF);
|
||||||
else {
|
else {
|
||||||
switch(s->type) {
|
switch(s->type) {
|
||||||
|
@ -126,7 +126,7 @@ struct Sym
|
|||||||
short version;
|
short version;
|
||||||
uchar dupok;
|
uchar dupok;
|
||||||
uchar reachable;
|
uchar reachable;
|
||||||
uchar dynexport;
|
uchar cgoexport;
|
||||||
uchar special;
|
uchar special;
|
||||||
uchar stkcheck;
|
uchar stkcheck;
|
||||||
uchar hide;
|
uchar hide;
|
||||||
|
@ -90,6 +90,7 @@ main(int argc, char *argv[])
|
|||||||
INITRND = -1;
|
INITRND = -1;
|
||||||
INITENTRY = 0;
|
INITENTRY = 0;
|
||||||
LIBINITENTRY = 0;
|
LIBINITENTRY = 0;
|
||||||
|
linkmode = LinkInternal; // TODO: LinkAuto once everything works.
|
||||||
nuxiinit();
|
nuxiinit();
|
||||||
|
|
||||||
flagcount("1", "use alternate profiling code", &debug['1']);
|
flagcount("1", "use alternate profiling code", &debug['1']);
|
||||||
@ -125,6 +126,7 @@ main(int argc, char *argv[])
|
|||||||
flagcount("u", "reject unsafe packages", &debug['u']);
|
flagcount("u", "reject unsafe packages", &debug['u']);
|
||||||
flagcount("v", "print link trace", &debug['v']);
|
flagcount("v", "print link trace", &debug['v']);
|
||||||
flagcount("w", "disable DWARF generation", &debug['w']);
|
flagcount("w", "disable DWARF generation", &debug['w']);
|
||||||
|
// TODO: link mode flag
|
||||||
|
|
||||||
flagparse(&argc, &argv, usage);
|
flagparse(&argc, &argv, usage);
|
||||||
|
|
||||||
@ -308,6 +310,8 @@ main(int argc, char *argv[])
|
|||||||
reloc();
|
reloc();
|
||||||
asmb();
|
asmb();
|
||||||
undef();
|
undef();
|
||||||
|
hostlink();
|
||||||
|
|
||||||
if(debug['v']) {
|
if(debug['v']) {
|
||||||
Bprint(&bso, "%5.2f cpu time\n", cputime());
|
Bprint(&bso, "%5.2f cpu time\n", cputime());
|
||||||
Bprint(&bso, "%d symbols\n", nsymbol);
|
Bprint(&bso, "%d symbols\n", nsymbol);
|
||||||
|
@ -135,11 +135,7 @@ addrel(Sym *s)
|
|||||||
s->maxr = 4;
|
s->maxr = 4;
|
||||||
else
|
else
|
||||||
s->maxr <<= 1;
|
s->maxr <<= 1;
|
||||||
s->r = realloc(s->r, s->maxr*sizeof s->r[0]);
|
s->r = erealloc(s->r, s->maxr*sizeof s->r[0]);
|
||||||
if(s->r == 0) {
|
|
||||||
diag("out of memory");
|
|
||||||
errorexit();
|
|
||||||
}
|
|
||||||
memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
|
memset(s->r+s->nr, 0, (s->maxr-s->nr)*sizeof s->r[0]);
|
||||||
}
|
}
|
||||||
return &s->r[s->nr++];
|
return &s->r[s->nr++];
|
||||||
@ -300,7 +296,7 @@ dynrelocsym(Sym *s)
|
|||||||
for(r=s->r; r<s->r+s->nr; r++) {
|
for(r=s->r; r<s->r+s->nr; r++) {
|
||||||
if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
|
if(r->sym != S && r->sym->type == SDYNIMPORT || r->type >= 256)
|
||||||
adddynrel(s, r);
|
adddynrel(s, r);
|
||||||
if(flag_shared && r->sym != S && (r->sym->dynimpname == nil || r->sym->dynexport) && r->type == D_ADDR
|
if(flag_shared && r->sym != S && (r->sym->dynimpname == nil || (r->sym->cgoexport & CgoExportDynamic)) && r->type == D_ADDR
|
||||||
&& (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
|
&& (s == got || s->type == SDATA || s->type == SGOSTRING || s->type == STYPE || s->type == SRODATA)) {
|
||||||
// Create address based RELATIVE relocation
|
// Create address based RELATIVE relocation
|
||||||
adddynrela(rel, s, r);
|
adddynrela(rel, s, r);
|
||||||
@ -342,11 +338,7 @@ symgrow(Sym *s, int32 siz)
|
|||||||
s->maxp = 8;
|
s->maxp = 8;
|
||||||
while(s->maxp < siz)
|
while(s->maxp < siz)
|
||||||
s->maxp <<= 1;
|
s->maxp <<= 1;
|
||||||
s->p = realloc(s->p, s->maxp);
|
s->p = erealloc(s->p, s->maxp);
|
||||||
if(s->p == nil) {
|
|
||||||
diag("out of memory");
|
|
||||||
errorexit();
|
|
||||||
}
|
|
||||||
memset(s->p+s->np, 0, s->maxp-s->np);
|
memset(s->p+s->np, 0, s->maxp-s->np);
|
||||||
}
|
}
|
||||||
s->np = siz;
|
s->np = siz;
|
||||||
|
@ -1260,7 +1260,7 @@ dwarfaddfrag(int n, char *frag)
|
|||||||
if (n >= ftabsize) {
|
if (n >= ftabsize) {
|
||||||
s = ftabsize;
|
s = ftabsize;
|
||||||
ftabsize = 1 + n + (n >> 2);
|
ftabsize = 1 + n + (n >> 2);
|
||||||
ftab = realloc(ftab, ftabsize * sizeof(ftab[0]));
|
ftab = erealloc(ftab, ftabsize * sizeof(ftab[0]));
|
||||||
memset(ftab + s, 0, (ftabsize - s) * sizeof(ftab[0]));
|
memset(ftab + s, 0, (ftabsize - s) * sizeof(ftab[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1342,7 +1342,7 @@ addhistfile(char *zentry)
|
|||||||
|
|
||||||
if (histfilesize == histfilecap) {
|
if (histfilesize == histfilecap) {
|
||||||
histfilecap = 2 * histfilecap + 2;
|
histfilecap = 2 * histfilecap + 2;
|
||||||
histfile = realloc(histfile, histfilecap * sizeof(char*));
|
histfile = erealloc(histfile, histfilecap * sizeof(char*));
|
||||||
}
|
}
|
||||||
if (histfilesize == 0)
|
if (histfilesize == 0)
|
||||||
histfile[histfilesize++] = "<eof>";
|
histfile[histfilesize++] = "<eof>";
|
||||||
@ -1412,7 +1412,7 @@ checknesting(void)
|
|||||||
includestacksize += 1;
|
includestacksize += 1;
|
||||||
includestacksize <<= 2;
|
includestacksize <<= 2;
|
||||||
// print("checknesting: growing to %d\n", includestacksize);
|
// print("checknesting: growing to %d\n", includestacksize);
|
||||||
includestack = realloc(includestack, includestacksize * sizeof *includestack);
|
includestack = erealloc(includestack, includestacksize * sizeof *includestack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1651,7 +1651,7 @@ writelines(void)
|
|||||||
lang = guesslang(histfile[1]);
|
lang = guesslang(histfile[1]);
|
||||||
finddebugruntimepath();
|
finddebugruntimepath();
|
||||||
|
|
||||||
dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, strdup(histfile[1]));
|
dwinfo = newdie(&dwroot, DW_ABRV_COMPUNIT, estrdup(histfile[1]));
|
||||||
newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0);
|
newattr(dwinfo, DW_AT_language, DW_CLS_CONSTANT,lang, 0);
|
||||||
newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart - lineo, 0);
|
newattr(dwinfo, DW_AT_stmt_list, DW_CLS_PTR, unitstart - lineo, 0);
|
||||||
newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, 0);
|
newattr(dwinfo, DW_AT_low_pc, DW_CLS_ADDRESS, s->text->pc, 0);
|
||||||
|
@ -59,7 +59,7 @@ ilookup(char *name)
|
|||||||
if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
|
if(x->name[0] == name[0] && strcmp(x->name, name) == 0)
|
||||||
return x;
|
return x;
|
||||||
x = mal(sizeof *x);
|
x = mal(sizeof *x);
|
||||||
x->name = strdup(name);
|
x->name = estrdup(name);
|
||||||
x->hash = ihash[h];
|
x->hash = ihash[h];
|
||||||
ihash[h] = x;
|
ihash[h] = x;
|
||||||
nimport++;
|
nimport++;
|
||||||
@ -71,8 +71,6 @@ static void loadcgo(char*, char*, char*, int);
|
|||||||
static int parsemethod(char**, char*, char**);
|
static int parsemethod(char**, char*, char**);
|
||||||
static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**);
|
static int parsepkgdata(char*, char*, char**, char*, char**, char**, char**);
|
||||||
|
|
||||||
static Sym **dynexp;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
|
ldpkg(Biobuf *f, char *pkg, int64 len, char *filename, int whence)
|
||||||
{
|
{
|
||||||
@ -205,14 +203,14 @@ loadpkgdata(char *file, char *pkg, char *data, int len)
|
|||||||
char *p, *ep, *prefix, *name, *def;
|
char *p, *ep, *prefix, *name, *def;
|
||||||
Import *x;
|
Import *x;
|
||||||
|
|
||||||
file = strdup(file);
|
file = estrdup(file);
|
||||||
p = data;
|
p = data;
|
||||||
ep = data + len;
|
ep = data + len;
|
||||||
while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) {
|
while(parsepkgdata(file, pkg, &p, ep, &prefix, &name, &def) > 0) {
|
||||||
x = ilookup(name);
|
x = ilookup(name);
|
||||||
if(x->prefix == nil) {
|
if(x->prefix == nil) {
|
||||||
x->prefix = prefix;
|
x->prefix = prefix;
|
||||||
x->def = strdup(def);
|
x->def = estrdup(def);
|
||||||
x->file = file;
|
x->file = file;
|
||||||
} else if(strcmp(x->prefix, prefix) != 0) {
|
} else if(strcmp(x->prefix, prefix) != 0) {
|
||||||
fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
|
fprint(2, "%s: conflicting definitions for %s\n", argv0, name);
|
||||||
@ -244,7 +242,7 @@ expandpkg(char *t0, char *pkg)
|
|||||||
n++;
|
n++;
|
||||||
|
|
||||||
if(n == 0)
|
if(n == 0)
|
||||||
return strdup(t0);
|
return estrdup(t0);
|
||||||
|
|
||||||
// use malloc, not mal, so that caller can free
|
// use malloc, not mal, so that caller can free
|
||||||
w0 = malloc(strlen(t0) + strlen(pkg)*n);
|
w0 = malloc(strlen(t0) + strlen(pkg)*n);
|
||||||
@ -429,7 +427,7 @@ loadcgo(char *file, char *pkg, char *p, int n)
|
|||||||
*next++ = '\0';
|
*next++ = '\0';
|
||||||
|
|
||||||
free(p0);
|
free(p0);
|
||||||
p0 = strdup(p); // save for error message
|
p0 = estrdup(p); // save for error message
|
||||||
nf = tokenize(p, f, nelem(f));
|
nf = tokenize(p, f, nelem(f));
|
||||||
|
|
||||||
if(strcmp(f[0], "cgo_import_dynamic") == 0) {
|
if(strcmp(f[0], "cgo_import_dynamic") == 0) {
|
||||||
@ -487,9 +485,14 @@ loadcgo(char *file, char *pkg, char *p, int n)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: cgo_export_static
|
if(strcmp(f[0], "cgo_export_static") == 0 || strcmp(f[0], "cgo_export_dynamic") == 0) {
|
||||||
|
// TODO: Make Mach-O code happier. Right now it sees the dynimpname and
|
||||||
|
// includes CgoExportStatic symbols in the dynamic table, and then dyld
|
||||||
|
// cannot find them when we run the binary. Disabling Windows too
|
||||||
|
// because it probably has the same issue.
|
||||||
|
if(strcmp(f[0], "cgo_export_static") == 0 && (HEADTYPE == Hdarwin || HEADTYPE == Hwindows))
|
||||||
|
continue;
|
||||||
|
|
||||||
if(strcmp(f[0], "cgo_export_dynamic") == 0) {
|
|
||||||
if(nf < 2 || nf > 3)
|
if(nf < 2 || nf > 3)
|
||||||
goto err;
|
goto err;
|
||||||
local = f[1];
|
local = f[1];
|
||||||
@ -503,11 +506,15 @@ loadcgo(char *file, char *pkg, char *p, int n)
|
|||||||
fprint(2, "%s: symbol is both imported and exported: %s\n", argv0, local);
|
fprint(2, "%s: symbol is both imported and exported: %s\n", argv0, local);
|
||||||
nerrors++;
|
nerrors++;
|
||||||
}
|
}
|
||||||
s->dynexport = 1;
|
|
||||||
|
if(strcmp(f[0], "cgo_export_static") == 0)
|
||||||
|
s->cgoexport |= CgoExportStatic;
|
||||||
|
else
|
||||||
|
s->cgoexport |= CgoExportDynamic;
|
||||||
if(s->dynimpname == nil) {
|
if(s->dynimpname == nil) {
|
||||||
s->dynimpname = remote;
|
s->dynimpname = remote;
|
||||||
if(ndynexp%32 == 0)
|
if(ndynexp%32 == 0)
|
||||||
dynexp = realloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
|
dynexp = erealloc(dynexp, (ndynexp+32)*sizeof dynexp[0]);
|
||||||
dynexp[ndynexp++] = s;
|
dynexp[ndynexp++] = s;
|
||||||
} else if(strcmp(s->dynimpname, remote) != 0) {
|
} else if(strcmp(s->dynimpname, remote) != 0) {
|
||||||
fprint(2, "%s: conflicting cgo_export directives: %s as %s and %s\n", argv0, s->name, s->dynimpname, remote);
|
fprint(2, "%s: conflicting cgo_export directives: %s as %s and %s\n", argv0, s->name, s->dynimpname, remote);
|
||||||
@ -530,7 +537,7 @@ loadcgo(char *file, char *pkg, char *p, int n)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
free(interpreter);
|
free(interpreter);
|
||||||
interpreter = strdup(f[1]);
|
interpreter = estrdup(f[1]);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -539,8 +546,8 @@ loadcgo(char *file, char *pkg, char *p, int n)
|
|||||||
if(nf != 2)
|
if(nf != 2)
|
||||||
goto err;
|
goto err;
|
||||||
if(nldflag%32 == 0)
|
if(nldflag%32 == 0)
|
||||||
ldflag = realloc(ldflag, (nldflag+32)*sizeof ldflag[0]);
|
ldflag = erealloc(ldflag, (nldflag+32)*sizeof ldflag[0]);
|
||||||
ldflag[nldflag++] = strdup(f[1]);
|
ldflag[nldflag++] = estrdup(f[1]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -844,7 +851,7 @@ getpkg(char *path)
|
|||||||
if(strcmp(p->path, path) == 0)
|
if(strcmp(p->path, path) == 0)
|
||||||
return p;
|
return p;
|
||||||
p = mal(sizeof *p);
|
p = mal(sizeof *p);
|
||||||
p->path = strdup(path);
|
p->path = estrdup(path);
|
||||||
p->next = phash[h];
|
p->next = phash[h];
|
||||||
phash[h] = p;
|
phash[h] = p;
|
||||||
p->all = pkgall;
|
p->all = pkgall;
|
||||||
@ -868,7 +875,7 @@ imported(char *pkg, char *import)
|
|||||||
i->mimpby *= 2;
|
i->mimpby *= 2;
|
||||||
if(i->mimpby == 0)
|
if(i->mimpby == 0)
|
||||||
i->mimpby = 16;
|
i->mimpby = 16;
|
||||||
i->impby = realloc(i->impby, i->mimpby*sizeof i->impby[0]);
|
i->impby = erealloc(i->impby, i->mimpby*sizeof i->impby[0]);
|
||||||
}
|
}
|
||||||
i->impby[i->nimpby++] = p;
|
i->impby[i->nimpby++] = p;
|
||||||
free(pkg);
|
free(pkg);
|
||||||
|
@ -595,7 +595,7 @@ ldelf(Biobuf *f, char *pkg, int64 len, char *pn)
|
|||||||
s->sub = sect->sym->sub;
|
s->sub = sect->sym->sub;
|
||||||
sect->sym->sub = s;
|
sect->sym->sub = s;
|
||||||
s->type = sect->sym->type | (s->type&~SMASK) | SSUB;
|
s->type = sect->sym->type | (s->type&~SMASK) | SSUB;
|
||||||
if(!s->dynexport) {
|
if(!(s->cgoexport & CgoExportDynamic)) {
|
||||||
s->dynimplib = nil; // satisfy dynimport
|
s->dynimplib = nil; // satisfy dynimport
|
||||||
s->dynimpname = nil; // satisfy dynimport
|
s->dynimpname = nil; // satisfy dynimport
|
||||||
}
|
}
|
||||||
|
@ -639,7 +639,7 @@ ldmacho(Biobuf *f, char *pkg, int64 len, char *pn)
|
|||||||
s->size = (sym+1)->value - sym->value;
|
s->size = (sym+1)->value - sym->value;
|
||||||
else
|
else
|
||||||
s->size = sect->addr + sect->size - sym->value;
|
s->size = sect->addr + sect->size - sym->value;
|
||||||
if(!s->dynexport) {
|
if(!(s->cgoexport & CgoExportDynamic)) {
|
||||||
s->dynimplib = nil; // satisfy dynimport
|
s->dynimplib = nil; // satisfy dynimport
|
||||||
s->dynimpname = nil; // satisfy dynimport
|
s->dynimpname = nil; // satisfy dynimport
|
||||||
}
|
}
|
||||||
|
303
src/cmd/ld/lib.c
303
src/cmd/ld/lib.c
@ -44,6 +44,8 @@ int nlibdir = 0;
|
|||||||
static int maxlibdir = 0;
|
static int maxlibdir = 0;
|
||||||
static int cout = -1;
|
static int cout = -1;
|
||||||
|
|
||||||
|
static void hostlinksetup(void);
|
||||||
|
|
||||||
char* goroot;
|
char* goroot;
|
||||||
char* goarch;
|
char* goarch;
|
||||||
char* goos;
|
char* goos;
|
||||||
@ -59,11 +61,7 @@ Lflag(char *arg)
|
|||||||
maxlibdir = 8;
|
maxlibdir = 8;
|
||||||
else
|
else
|
||||||
maxlibdir *= 2;
|
maxlibdir *= 2;
|
||||||
p = realloc(libdir, maxlibdir * sizeof(*p));
|
p = erealloc(libdir, maxlibdir * sizeof(*p));
|
||||||
if (p == nil) {
|
|
||||||
print("too many -L's: %d\n", nlibdir);
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
libdir = p;
|
libdir = p;
|
||||||
}
|
}
|
||||||
libdir[nlibdir++] = arg;
|
libdir[nlibdir++] = arg;
|
||||||
@ -95,7 +93,7 @@ libinit(void)
|
|||||||
#endif
|
#endif
|
||||||
cout = create(outfile, 1, 0775);
|
cout = create(outfile, 1, 0775);
|
||||||
if(cout < 0) {
|
if(cout < 0) {
|
||||||
diag("cannot create %s", outfile);
|
diag("cannot create %s: %r", outfile);
|
||||||
errorexit();
|
errorexit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +240,7 @@ addlibpath(char *srcref, char *objref, char *file, char *pkg)
|
|||||||
|
|
||||||
if(libraryp == nlibrary){
|
if(libraryp == nlibrary){
|
||||||
nlibrary = 50 + 2*libraryp;
|
nlibrary = 50 + 2*libraryp;
|
||||||
library = realloc(library, sizeof library[0] * nlibrary);
|
library = erealloc(library, sizeof library[0] * nlibrary);
|
||||||
}
|
}
|
||||||
|
|
||||||
l = &library[libraryp++];
|
l = &library[libraryp++];
|
||||||
@ -288,7 +286,7 @@ loadinternal(char *name)
|
|||||||
void
|
void
|
||||||
loadlib(void)
|
loadlib(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i, w, x;
|
||||||
|
|
||||||
loadinternal("runtime");
|
loadinternal("runtime");
|
||||||
if(thechar == '5')
|
if(thechar == '5')
|
||||||
@ -303,6 +301,28 @@ loadlib(void)
|
|||||||
objfile(library[i].file, library[i].pkg);
|
objfile(library[i].file, library[i].pkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we got this far in automatic mode, there were no
|
||||||
|
// cgo uses that suggest we need external mode.
|
||||||
|
// Switch to internal.
|
||||||
|
if(linkmode == LinkAuto)
|
||||||
|
linkmode = LinkInternal;
|
||||||
|
|
||||||
|
// Now that we know the link mode, trim the dynexp list.
|
||||||
|
x = CgoExportDynamic;
|
||||||
|
if(linkmode == LinkExternal)
|
||||||
|
x = CgoExportStatic;
|
||||||
|
w = 0;
|
||||||
|
for(i=0; i<ndynexp; i++)
|
||||||
|
if(dynexp[i]->cgoexport & x)
|
||||||
|
dynexp[w++] = dynexp[i];
|
||||||
|
ndynexp = w;
|
||||||
|
|
||||||
|
// In internal link mode, read the host object files.
|
||||||
|
if(linkmode == LinkInternal)
|
||||||
|
hostobjs();
|
||||||
|
else
|
||||||
|
hostlinksetup();
|
||||||
|
|
||||||
// We've loaded all the code now.
|
// We've loaded all the code now.
|
||||||
// If there are no dynamic libraries needed, gcc disables dynamic linking.
|
// If there are no dynamic libraries needed, gcc disables dynamic linking.
|
||||||
// Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
|
// Because of this, glibc's dynamic ELF loader occasionally (like in version 2.13)
|
||||||
@ -375,7 +395,7 @@ objfile(char *file, char *pkg)
|
|||||||
/* load it as a regular file */
|
/* load it as a regular file */
|
||||||
l = Bseek(f, 0L, 2);
|
l = Bseek(f, 0L, 2);
|
||||||
Bseek(f, 0L, 0);
|
Bseek(f, 0L, 0);
|
||||||
ldobj(f, pkg, l, file, FileObj);
|
ldobj(f, pkg, l, file, file, FileObj);
|
||||||
Bterm(f);
|
Bterm(f);
|
||||||
free(pkg);
|
free(pkg);
|
||||||
return;
|
return;
|
||||||
@ -434,7 +454,7 @@ objfile(char *file, char *pkg)
|
|||||||
l--;
|
l--;
|
||||||
snprint(pname, sizeof pname, "%s(%.*s)", file, utfnlen(arhdr.name, l), arhdr.name);
|
snprint(pname, sizeof pname, "%s(%.*s)", file, utfnlen(arhdr.name, l), arhdr.name);
|
||||||
l = atolwhex(arhdr.size);
|
l = atolwhex(arhdr.size);
|
||||||
ldobj(f, pkg, l, pname, ArchiveObj);
|
ldobj(f, pkg, l, pname, file, ArchiveObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -442,8 +462,213 @@ out:
|
|||||||
free(pkg);
|
free(pkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dowrite(int fd, char *p, int n)
|
||||||
|
{
|
||||||
|
int m;
|
||||||
|
|
||||||
|
while(n > 0) {
|
||||||
|
m = write(fd, p, n);
|
||||||
|
if(m <= 0) {
|
||||||
|
cursym = S;
|
||||||
|
diag("write error: %r");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
n -= m;
|
||||||
|
p += m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct Hostobj Hostobj;
|
||||||
|
|
||||||
|
struct Hostobj
|
||||||
|
{
|
||||||
|
void (*ld)(Biobuf*, char*, int64, char*);
|
||||||
|
char *pkg;
|
||||||
|
char *pn;
|
||||||
|
char *file;
|
||||||
|
int64 off;
|
||||||
|
int64 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
Hostobj *hostobj;
|
||||||
|
int nhostobj;
|
||||||
|
int mhostobj;
|
||||||
|
|
||||||
|
// These packages can use internal linking mode.
|
||||||
|
// Others trigger external mode.
|
||||||
|
const char *internalpkg[] = {
|
||||||
|
"net",
|
||||||
|
"os/user",
|
||||||
|
"runtime/cgo"
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
|
ldhostobj(void (*ld)(Biobuf*, char*, int64, char*), Biobuf *f, char *pkg, int64 len, char *pn, char *file)
|
||||||
|
{
|
||||||
|
int i, isinternal;
|
||||||
|
Hostobj *h;
|
||||||
|
|
||||||
|
isinternal = 0;
|
||||||
|
for(i=0; i<nelem(internalpkg); i++) {
|
||||||
|
if(strcmp(pkg, internalpkg[i]) == 0) {
|
||||||
|
isinternal = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isinternal && linkmode == LinkAuto)
|
||||||
|
linkmode = LinkExternal;
|
||||||
|
|
||||||
|
if(nhostobj >= mhostobj) {
|
||||||
|
if(mhostobj == 0)
|
||||||
|
mhostobj = 16;
|
||||||
|
else
|
||||||
|
mhostobj *= 2;
|
||||||
|
hostobj = erealloc(hostobj, mhostobj*sizeof hostobj[0]);
|
||||||
|
}
|
||||||
|
h = &hostobj[nhostobj++];
|
||||||
|
h->ld = ld;
|
||||||
|
h->pkg = pkg;
|
||||||
|
h->pn = estrdup(pn);
|
||||||
|
h->file = estrdup(file);
|
||||||
|
h->off = Boffset(f);
|
||||||
|
h->len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hostobjs(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Biobuf *f;
|
||||||
|
Hostobj *h;
|
||||||
|
|
||||||
|
for(i=0; i<nhostobj; i++) {
|
||||||
|
h = &hostobj[i];
|
||||||
|
f = Bopen(h->file, OREAD);
|
||||||
|
if(f == nil) {
|
||||||
|
cursym = S;
|
||||||
|
diag("cannot reopen %s: %r", h->pn);
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
Bseek(f, h->off, 0);
|
||||||
|
h->ld(f, h->pkg, h->len, h->pn);
|
||||||
|
Bterm(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *tmpdir;
|
||||||
|
|
||||||
|
static void
|
||||||
|
rmtemp(void)
|
||||||
|
{
|
||||||
|
removeall(tmpdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hostlinksetup(void)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if(linkmode != LinkExternal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// create temporary directory and arrange cleanup
|
||||||
|
// TODO: Add flag to specify tempdir, which is then not cleaned up.
|
||||||
|
tmpdir = mktempdir();
|
||||||
|
atexit(rmtemp);
|
||||||
|
|
||||||
|
// change our output to temporary object file
|
||||||
|
close(cout);
|
||||||
|
p = smprint("%s/go.o", tmpdir);
|
||||||
|
cout = create(p, 1, 0775);
|
||||||
|
if(cout < 0) {
|
||||||
|
diag("cannot create %s: %r", p);
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hostlink(void)
|
||||||
|
{
|
||||||
|
char *p, **argv;
|
||||||
|
int i, w, n, argc, len;
|
||||||
|
Hostobj *h;
|
||||||
|
Biobuf *f;
|
||||||
|
static char buf[64<<10];
|
||||||
|
|
||||||
|
if(linkmode != LinkExternal)
|
||||||
|
return;
|
||||||
|
|
||||||
|
argv = malloc((10+nhostobj+nldflag)*sizeof argv[0]);
|
||||||
|
argc = 0;
|
||||||
|
// TODO: Add command-line flag to override gcc path and specify additional leading options.
|
||||||
|
// TODO: Add command-line flag to specify additional trailing options.
|
||||||
|
argv[argc++] = "gcc";
|
||||||
|
if(!debug['s'])
|
||||||
|
argv[argc++] = "-ggdb";
|
||||||
|
argv[argc++] = "-o";
|
||||||
|
argv[argc++] = outfile;
|
||||||
|
|
||||||
|
// Force global symbols to be exported for dlopen, etc.
|
||||||
|
// NOTE: May not work on OS X or Windows. We'll see.
|
||||||
|
argv[argc++] = "-rdynamic";
|
||||||
|
|
||||||
|
// already wrote main object file
|
||||||
|
// copy host objects to temporary directory
|
||||||
|
for(i=0; i<nhostobj; i++) {
|
||||||
|
h = &hostobj[i];
|
||||||
|
f = Bopen(h->file, OREAD);
|
||||||
|
if(f == nil) {
|
||||||
|
cursym = S;
|
||||||
|
diag("cannot reopen %s: %r", h->pn);
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
Bseek(f, h->off, 0);
|
||||||
|
p = smprint("%s/%06d.o", tmpdir, i);
|
||||||
|
argv[argc++] = p;
|
||||||
|
w = create(p, 1, 0775);
|
||||||
|
if(w < 0) {
|
||||||
|
diag("cannot create %s: %r", p);
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
len = h->len;
|
||||||
|
while(len > 0 && (n = Bread(f, buf, sizeof buf)) > 0){
|
||||||
|
if(n > len)
|
||||||
|
n = len;
|
||||||
|
dowrite(w, buf, n);
|
||||||
|
len -= n;
|
||||||
|
}
|
||||||
|
if(close(w) < 0) {
|
||||||
|
diag("cannot write %s: %r", p);
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
Bterm(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
argv[argc++] = smprint("%s/go.o", tmpdir);
|
||||||
|
for(i=0; i<nldflag; i++)
|
||||||
|
argv[argc++] = ldflag[i];
|
||||||
|
argv[argc] = nil;
|
||||||
|
|
||||||
|
quotefmtinstall();
|
||||||
|
if(debug['v']) {
|
||||||
|
Bprint(&bso, "host link:");
|
||||||
|
for(i=0; i<argc; i++)
|
||||||
|
Bprint(&bso, " %q", argv[i]);
|
||||||
|
Bprint(&bso, "\n");
|
||||||
|
Bflush(&bso);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(runcmd(argv) < 0) {
|
||||||
|
diag("%s: running %s failed: %r", argv0, argv[0]);
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ldobj(Biobuf *f, char *pkg, int64 len, char *pn, char *file, int whence)
|
||||||
{
|
{
|
||||||
char *line;
|
char *line;
|
||||||
int n, c1, c2, c3, c4;
|
int n, c1, c2, c3, c4;
|
||||||
@ -453,7 +678,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
|
|||||||
|
|
||||||
eof = Boffset(f) + len;
|
eof = Boffset(f) + len;
|
||||||
|
|
||||||
pn = strdup(pn);
|
pn = estrdup(pn);
|
||||||
|
|
||||||
c1 = Bgetc(f);
|
c1 = Bgetc(f);
|
||||||
c2 = Bgetc(f);
|
c2 = Bgetc(f);
|
||||||
@ -466,18 +691,15 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
|
|||||||
|
|
||||||
magic = c1<<24 | c2<<16 | c3<<8 | c4;
|
magic = c1<<24 | c2<<16 | c3<<8 | c4;
|
||||||
if(magic == 0x7f454c46) { // \x7F E L F
|
if(magic == 0x7f454c46) { // \x7F E L F
|
||||||
ldelf(f, pkg, len, pn);
|
ldhostobj(ldelf, f, pkg, len, pn, file);
|
||||||
free(pn);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
|
if((magic&~1) == 0xfeedface || (magic&~0x01000000) == 0xcefaedfe) {
|
||||||
ldmacho(f, pkg, len, pn);
|
ldhostobj(ldmacho, f, pkg, len, pn, file);
|
||||||
free(pn);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
|
if(c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86) {
|
||||||
ldpe(f, pkg, len, pn);
|
ldhostobj(ldpe, f, pkg, len, pn, file);
|
||||||
free(pn);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +746,7 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
|
|||||||
line[n] = '\0';
|
line[n] = '\0';
|
||||||
if(n-10 > strlen(t)) {
|
if(n-10 > strlen(t)) {
|
||||||
if(theline == nil)
|
if(theline == nil)
|
||||||
theline = strdup(line+10);
|
theline = estrdup(line+10);
|
||||||
else if(strcmp(theline, line+10) != 0) {
|
else if(strcmp(theline, line+10) != 0) {
|
||||||
line[n] = '\0';
|
line[n] = '\0';
|
||||||
diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
|
diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
|
||||||
@ -1460,23 +1682,6 @@ Yconv(Fmt *fp)
|
|||||||
|
|
||||||
vlong coutpos;
|
vlong coutpos;
|
||||||
|
|
||||||
static void
|
|
||||||
dowrite(int fd, char *p, int n)
|
|
||||||
{
|
|
||||||
int m;
|
|
||||||
|
|
||||||
while(n > 0) {
|
|
||||||
m = write(fd, p, n);
|
|
||||||
if(m <= 0) {
|
|
||||||
cursym = S;
|
|
||||||
diag("write error: %r");
|
|
||||||
errorexit();
|
|
||||||
}
|
|
||||||
n -= m;
|
|
||||||
p += m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
cflush(void)
|
cflush(void)
|
||||||
{
|
{
|
||||||
@ -1576,7 +1781,7 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
put(s, s->name, 'T', s->value, s->size, s->version, 0);
|
put(s, s->name, 'T', s->value, s->size, s->version, 0);
|
||||||
|
|
||||||
for(s=allsym; s!=S; s=s->allsym) {
|
for(s=allsym; s!=S; s=s->allsym) {
|
||||||
if(s->hide)
|
if(s->hide || (s->name[0] == '.' && s->version == 0))
|
||||||
continue;
|
continue;
|
||||||
switch(s->type&SMASK) {
|
switch(s->type&SMASK) {
|
||||||
case SCONST:
|
case SCONST:
|
||||||
@ -1664,3 +1869,27 @@ genasmsym(void (*put)(Sym*, char*, int, vlong, vlong, int, Sym*))
|
|||||||
Bprint(&bso, "symsize = %ud\n", symsize);
|
Bprint(&bso, "symsize = %ud\n", symsize);
|
||||||
Bflush(&bso);
|
Bflush(&bso);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
estrdup(char *p)
|
||||||
|
{
|
||||||
|
p = strdup(p);
|
||||||
|
if(p == nil) {
|
||||||
|
cursym = S;
|
||||||
|
diag("out of memory");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
erealloc(void *p, long n)
|
||||||
|
{
|
||||||
|
p = realloc(p, n);
|
||||||
|
if(p == nil) {
|
||||||
|
cursym = S;
|
||||||
|
diag("out of memory");
|
||||||
|
errorexit();
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
@ -138,6 +138,7 @@ EXTERN char* outfile;
|
|||||||
EXTERN int32 nsymbol;
|
EXTERN int32 nsymbol;
|
||||||
EXTERN char* thestring;
|
EXTERN char* thestring;
|
||||||
EXTERN int ndynexp;
|
EXTERN int ndynexp;
|
||||||
|
EXTERN Sym** dynexp;
|
||||||
EXTERN int nldflag;
|
EXTERN int nldflag;
|
||||||
EXTERN char** ldflag;
|
EXTERN char** ldflag;
|
||||||
EXTERN int havedynamic;
|
EXTERN int havedynamic;
|
||||||
@ -149,6 +150,21 @@ EXTERN int flag_shared;
|
|||||||
EXTERN char* tracksym;
|
EXTERN char* tracksym;
|
||||||
EXTERN char* interpreter;
|
EXTERN char* interpreter;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
LinkAuto = 0,
|
||||||
|
LinkInternal,
|
||||||
|
LinkExternal,
|
||||||
|
};
|
||||||
|
EXTERN int linkmode;
|
||||||
|
|
||||||
|
// for dynexport field of Sym
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CgoExportDynamic = 1<<0,
|
||||||
|
CgoExportStatic = 1<<1,
|
||||||
|
};
|
||||||
|
|
||||||
EXTERN Segment segtext;
|
EXTERN Segment segtext;
|
||||||
EXTERN Segment segdata;
|
EXTERN Segment segdata;
|
||||||
EXTERN Segment segsym;
|
EXTERN Segment segsym;
|
||||||
@ -187,7 +203,7 @@ void adddynrel(Sym*, Reloc*);
|
|||||||
void adddynrela(Sym*, Sym*, Reloc*);
|
void adddynrela(Sym*, Sym*, Reloc*);
|
||||||
Sym* lookuprel(void);
|
Sym* lookuprel(void);
|
||||||
void ldobj1(Biobuf *f, char*, int64 len, char *pn);
|
void ldobj1(Biobuf *f, char*, int64 len, char *pn);
|
||||||
void ldobj(Biobuf*, char*, int64, char*, int);
|
void ldobj(Biobuf*, char*, int64, char*, char*, int);
|
||||||
void ldelf(Biobuf*, char*, int64, char*);
|
void ldelf(Biobuf*, char*, int64, char*);
|
||||||
void ldmacho(Biobuf*, char*, int64, char*);
|
void ldmacho(Biobuf*, char*, int64, char*);
|
||||||
void ldpe(Biobuf*, char*, int64, char*);
|
void ldpe(Biobuf*, char*, int64, char*);
|
||||||
@ -242,6 +258,10 @@ void usage(void);
|
|||||||
void setinterp(char*);
|
void setinterp(char*);
|
||||||
Sym* listsort(Sym*, int(*cmp)(Sym*, Sym*), int);
|
Sym* listsort(Sym*, int(*cmp)(Sym*, Sym*), int);
|
||||||
int valuecmp(Sym*, Sym*);
|
int valuecmp(Sym*, Sym*);
|
||||||
|
void hostobjs(void);
|
||||||
|
void hostlink(void);
|
||||||
|
char* estrdup(char*);
|
||||||
|
void* erealloc(void*, long);
|
||||||
|
|
||||||
int pathchar(void);
|
int pathchar(void);
|
||||||
void* mal(uint32);
|
void* mal(uint32);
|
||||||
|
@ -56,11 +56,7 @@ newMachoLoad(uint32 type, uint32 ndata)
|
|||||||
mload = 1;
|
mload = 1;
|
||||||
else
|
else
|
||||||
mload *= 2;
|
mload *= 2;
|
||||||
load = realloc(load, mload*sizeof load[0]);
|
load = erealloc(load, mload*sizeof load[0]);
|
||||||
if(load == nil) {
|
|
||||||
diag("out of memory");
|
|
||||||
errorexit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(macho64 && (ndata & 1))
|
if(macho64 && (ndata & 1))
|
||||||
@ -286,13 +282,8 @@ machoadddynlib(char *lib)
|
|||||||
load_budget += 4096;
|
load_budget += 4096;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ndylib%32 == 0) {
|
if(ndylib%32 == 0)
|
||||||
dylib = realloc(dylib, (ndylib+32)*sizeof dylib[0]);
|
dylib = erealloc(dylib, (ndylib+32)*sizeof dylib[0]);
|
||||||
if(dylib == nil) {
|
|
||||||
diag("out of memory");
|
|
||||||
errorexit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dylib[ndylib++] = lib;
|
dylib[ndylib++] = lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ initdynimport(void)
|
|||||||
dr = nil;
|
dr = nil;
|
||||||
m = nil;
|
m = nil;
|
||||||
for(s = allsym; s != S; s = s->allsym) {
|
for(s = allsym; s != S; s = s->allsym) {
|
||||||
if(!s->reachable || !s->dynimpname || s->dynexport)
|
if(!s->reachable || !s->dynimpname || (s->cgoexport & CgoExportDynamic))
|
||||||
continue;
|
continue;
|
||||||
for(d = dr; d != nil; d = d->next) {
|
for(d = dr; d != nil; d = d->next) {
|
||||||
if(strcmp(d->name,s->dynimplib) == 0) {
|
if(strcmp(d->name,s->dynimplib) == 0) {
|
||||||
@ -335,7 +335,7 @@ initdynexport(void)
|
|||||||
|
|
||||||
nexport = 0;
|
nexport = 0;
|
||||||
for(s = allsym; s != S; s = s->allsym) {
|
for(s = allsym; s != S; s = s->allsym) {
|
||||||
if(!s->reachable || !s->dynimpname || !s->dynexport)
|
if(!s->reachable || !s->dynimpname || !(s->cgoexport & CgoExportDynamic))
|
||||||
continue;
|
continue;
|
||||||
if(nexport+1 > sizeof(dexport)/sizeof(dexport[0])) {
|
if(nexport+1 > sizeof(dexport)/sizeof(dexport[0])) {
|
||||||
diag("pe dynexport table is full");
|
diag("pe dynexport table is full");
|
||||||
|
@ -121,7 +121,17 @@ putelfsym(Sym *x, char *s, int t, vlong addr, vlong size, int ver, Sym *go)
|
|||||||
|
|
||||||
// One pass for each binding: STB_LOCAL, STB_GLOBAL,
|
// One pass for each binding: STB_LOCAL, STB_GLOBAL,
|
||||||
// maybe one day STB_WEAK.
|
// maybe one day STB_WEAK.
|
||||||
bind = (ver || (x->type & SHIDDEN)) ? STB_LOCAL : STB_GLOBAL;
|
bind = STB_GLOBAL;
|
||||||
|
if(ver || (x->type & SHIDDEN))
|
||||||
|
bind = STB_LOCAL;
|
||||||
|
|
||||||
|
// In external linking mode, we have to invoke gcc with -rdynamic
|
||||||
|
// to get the exported symbols put into the dynamic symbol table.
|
||||||
|
// To avoid filling the dynamic table with lots of unnecessary symbols,
|
||||||
|
// mark all Go symbols local (not global) in the final executable.
|
||||||
|
if(linkmode == LinkExternal && !(x->cgoexport&CgoExportStatic))
|
||||||
|
bind = STB_LOCAL;
|
||||||
|
|
||||||
if(bind != elfbind)
|
if(bind != elfbind)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -12,8 +12,10 @@
|
|||||||
// void crosscall2(void (*fn)(void *, int), void *, int);
|
// void crosscall2(void (*fn)(void *, int), void *, int);
|
||||||
//
|
//
|
||||||
// We need to export the symbol crosscall2 in order to support
|
// We need to export the symbol crosscall2 in order to support
|
||||||
// callbacks from shared libraries.
|
// callbacks from shared libraries. This applies regardless of
|
||||||
#pragma dynexport crosscall2 crosscall2
|
// linking mode.
|
||||||
|
#pragma cgo_export_static crosscall2
|
||||||
|
#pragma cgo_export_dynamic crosscall2
|
||||||
|
|
||||||
// Allocate memory. This allocates the requested number of bytes in
|
// Allocate memory. This allocates the requested number of bytes in
|
||||||
// memory controlled by the Go runtime. The allocated memory will be
|
// memory controlled by the Go runtime. The allocated memory will be
|
||||||
|
@ -280,3 +280,9 @@ runtime·cgounimpl(void) // called from (incomplete) assembly
|
|||||||
{
|
{
|
||||||
runtime·throw("runtime: cgo not implemented");
|
runtime·throw("runtime: cgo not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For cgo-using programs with external linking,
|
||||||
|
// export "main" (defined in assembly) so that libc can handle basic
|
||||||
|
// C runtime startup and call the Go program as if it were
|
||||||
|
// the C main function.
|
||||||
|
#pragma cgo_export_static main
|
||||||
|
Loading…
Reference in New Issue
Block a user