mirror of
https://github.com/golang/go
synced 2024-11-05 15:36:09 -07:00
liblink, cmd/ld, cmd/5l: darwin/arm support
liblink: - set dummy value for ctxt->tlsoffset. cmd/ld: - always do external linking when using cgo on darwin/arm, as our linker might not generate codesign-compatible binary. cmd/5l: - support generate ARM Mach-O binaries - add machoreloc1() that translate our internal relocation to macho relocations used by external linking. Change-Id: Ic5454aeb87009aaf8f1453ec7fe33e6da55d5f06 Reviewed-on: https://go-review.googlesource.com/3273 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
db0d3892e0
commit
1083715b7f
@ -33,9 +33,9 @@
|
|||||||
#include "l.h"
|
#include "l.h"
|
||||||
#include "../ld/lib.h"
|
#include "../ld/lib.h"
|
||||||
#include "../ld/elf.h"
|
#include "../ld/elf.h"
|
||||||
|
#include "../ld/macho.h"
|
||||||
#include "../ld/dwarf.h"
|
#include "../ld/dwarf.h"
|
||||||
|
|
||||||
|
|
||||||
char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
|
char linuxdynld[] = "/lib/ld-linux.so.3"; // 2 for OABI, 3 for EABI
|
||||||
char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
|
char freebsddynld[] = "/usr/libexec/ld-elf.so.1";
|
||||||
char openbsddynld[] = "XXX";
|
char openbsddynld[] = "XXX";
|
||||||
@ -301,10 +301,58 @@ elfsetupplt(void)
|
|||||||
int
|
int
|
||||||
machoreloc1(Reloc *r, vlong sectoff)
|
machoreloc1(Reloc *r, vlong sectoff)
|
||||||
{
|
{
|
||||||
USED(r);
|
uint32 v;
|
||||||
USED(sectoff);
|
LSym *rs;
|
||||||
|
|
||||||
return -1;
|
rs = r->xsym;
|
||||||
|
|
||||||
|
if(rs->type == SHOSTOBJ || r->type == R_CALLARM) {
|
||||||
|
if(rs->dynid < 0) {
|
||||||
|
diag("reloc %d to non-macho symbol %s type=%d", r->type, rs->name, rs->type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
v = rs->dynid;
|
||||||
|
v |= 1<<27; // external relocation
|
||||||
|
} else {
|
||||||
|
v = rs->sect->extnum;
|
||||||
|
if(v == 0) {
|
||||||
|
diag("reloc %d to symbol %s in non-macho section %s type=%d", r->type, rs->name, rs->sect->name, rs->type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(r->type) {
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
case R_ADDR:
|
||||||
|
v |= MACHO_GENERIC_RELOC_VANILLA<<28;
|
||||||
|
break;
|
||||||
|
case R_CALLARM:
|
||||||
|
v |= 1<<24; // pc-relative bit
|
||||||
|
v |= MACHO_ARM_RELOC_BR24<<28;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(r->siz) {
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
case 1:
|
||||||
|
v |= 0<<25;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
v |= 1<<25;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
v |= 2<<25;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
v |= 3<<25;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPUT(sectoff);
|
||||||
|
LPUT(v);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -333,6 +381,14 @@ archreloc(Reloc *r, LSym *s, vlong *val)
|
|||||||
diag("missing section for %s", rs->name);
|
diag("missing section for %s", rs->name);
|
||||||
r->xsym = rs;
|
r->xsym = rs;
|
||||||
|
|
||||||
|
// ld64 for arm seems to want the symbol table to contain offset
|
||||||
|
// into the section rather than pseudo virtual address that contains
|
||||||
|
// the section load address.
|
||||||
|
// we need to compensate that by removing the instruction's address
|
||||||
|
// from addend.
|
||||||
|
if(HEADTYPE == Hdarwin)
|
||||||
|
r->xadd -= symaddr(s) + r->off;
|
||||||
|
|
||||||
*val = braddoff((0xff000000U & (uint32)r->add),
|
*val = braddoff((0xff000000U & (uint32)r->add),
|
||||||
(0xffffff & (uint32)(r->xadd / 4)));
|
(0xffffff & (uint32)(r->xadd / 4)));
|
||||||
return 0;
|
return 0;
|
||||||
@ -539,6 +595,8 @@ adddynlib(char *lib)
|
|||||||
if(s->size == 0)
|
if(s->size == 0)
|
||||||
addstring(s, "");
|
addstring(s, "");
|
||||||
elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib));
|
elfwritedynent(linklookup(ctxt, ".dynamic", 0), DT_NEEDED, addstring(s, lib));
|
||||||
|
} else if(HEADTYPE == Hdarwin) {
|
||||||
|
machoadddynlib(lib);
|
||||||
} else {
|
} else {
|
||||||
diag("adddynlib: unsupported binary format");
|
diag("adddynlib: unsupported binary format");
|
||||||
}
|
}
|
||||||
@ -547,7 +605,7 @@ adddynlib(char *lib)
|
|||||||
void
|
void
|
||||||
asmb(void)
|
asmb(void)
|
||||||
{
|
{
|
||||||
uint32 symo;
|
uint32 symo, dwarfoff, machlink;
|
||||||
Section *sect;
|
Section *sect;
|
||||||
LSym *sym;
|
LSym *sym;
|
||||||
int i;
|
int i;
|
||||||
@ -583,6 +641,22 @@ asmb(void)
|
|||||||
cseek(segdata.fileoff);
|
cseek(segdata.fileoff);
|
||||||
datblk(segdata.vaddr, segdata.filelen);
|
datblk(segdata.vaddr, segdata.filelen);
|
||||||
|
|
||||||
|
machlink = 0;
|
||||||
|
if(HEADTYPE == Hdarwin) {
|
||||||
|
if(debug['v'])
|
||||||
|
Bprint(&bso, "%5.2f dwarf\n", cputime());
|
||||||
|
|
||||||
|
if(!debug['w']) { // TODO(minux): enable DWARF Support
|
||||||
|
dwarfoff = rnd(HEADR+segtext.len, INITRND) + rnd(segdata.filelen, INITRND);
|
||||||
|
cseek(dwarfoff);
|
||||||
|
|
||||||
|
segdwarf.fileoff = cpos();
|
||||||
|
dwarfemitdebugsections();
|
||||||
|
segdwarf.filelen = cpos() - segdwarf.fileoff;
|
||||||
|
}
|
||||||
|
machlink = domacholink();
|
||||||
|
}
|
||||||
|
|
||||||
/* output symbol table */
|
/* output symbol table */
|
||||||
symsize = 0;
|
symsize = 0;
|
||||||
lcsize = 0;
|
lcsize = 0;
|
||||||
@ -599,6 +673,9 @@ asmb(void)
|
|||||||
case Hplan9:
|
case Hplan9:
|
||||||
symo = segdata.fileoff+segdata.filelen;
|
symo = segdata.fileoff+segdata.filelen;
|
||||||
break;
|
break;
|
||||||
|
case Hdarwin:
|
||||||
|
symo = rnd(HEADR+segtext.filelen, INITRND)+rnd(segdata.filelen, INITRND)+machlink;
|
||||||
|
break;
|
||||||
ElfSym:
|
ElfSym:
|
||||||
symo = segdata.fileoff+segdata.filelen;
|
symo = segdata.fileoff+segdata.filelen;
|
||||||
symo = rnd(symo, INITRND);
|
symo = rnd(symo, INITRND);
|
||||||
@ -635,6 +712,10 @@ asmb(void)
|
|||||||
cflush();
|
cflush();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Hdarwin:
|
||||||
|
if(linkmode == LinkExternal)
|
||||||
|
machoemitreloc();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,6 +743,9 @@ asmb(void)
|
|||||||
case Hnacl:
|
case Hnacl:
|
||||||
asmbelf(symo);
|
asmbelf(symo);
|
||||||
break;
|
break;
|
||||||
|
case Hdarwin:
|
||||||
|
asmbmacho();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
cflush();
|
cflush();
|
||||||
if(debug['c']){
|
if(debug['c']){
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "l.h"
|
#include "l.h"
|
||||||
#include "../ld/lib.h"
|
#include "../ld/lib.h"
|
||||||
#include "../ld/elf.h"
|
#include "../ld/elf.h"
|
||||||
|
#include "../ld/macho.h"
|
||||||
#include "../ld/dwarf.h"
|
#include "../ld/dwarf.h"
|
||||||
#include <ar.h>
|
#include <ar.h>
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ archinit(void)
|
|||||||
case Hlinux:
|
case Hlinux:
|
||||||
case Hfreebsd:
|
case Hfreebsd:
|
||||||
case Hnacl:
|
case Hnacl:
|
||||||
|
case Hdarwin:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +106,17 @@ archinit(void)
|
|||||||
if(INITRND == -1)
|
if(INITRND == -1)
|
||||||
INITRND = 0x10000;
|
INITRND = 0x10000;
|
||||||
break;
|
break;
|
||||||
|
case Hdarwin: /* apple MACH */
|
||||||
|
debug['w'] = 1; // disable DWARF generataion
|
||||||
|
machoinit();
|
||||||
|
HEADR = INITIAL_MACHO_HEADR;
|
||||||
|
if(INITTEXT == -1)
|
||||||
|
INITTEXT = 4096+HEADR;
|
||||||
|
if(INITDAT == -1)
|
||||||
|
INITDAT = 0;
|
||||||
|
if(INITRND == -1)
|
||||||
|
INITRND = 4096;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(INITDAT != 0 && INITRND != 0)
|
if(INITDAT != 0 && INITRND != 0)
|
||||||
print("warning: -D0x%ux is ignored because of -R0x%ux\n",
|
print("warning: -D0x%ux is ignored because of -R0x%ux\n",
|
||||||
|
@ -212,6 +212,14 @@ loadlib(void)
|
|||||||
// Force external linking for android.
|
// Force external linking for android.
|
||||||
if(strcmp(goos, "android") == 0)
|
if(strcmp(goos, "android") == 0)
|
||||||
linkmode = LinkExternal;
|
linkmode = LinkExternal;
|
||||||
|
|
||||||
|
// cgo on Darwin must use external linking
|
||||||
|
// we can always use external linking, but then there will be circular
|
||||||
|
// dependency problems when compiling natively (external linking requires
|
||||||
|
// runtime/cgo, runtime/cgo requires cmd/cgo, but cmd/cgo needs to be
|
||||||
|
// compiled using external linking.)
|
||||||
|
if(thechar == '5' && HEADTYPE == Hdarwin && iscgo)
|
||||||
|
linkmode = LinkExternal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(linkmode == LinkExternal && !iscgo) {
|
if(linkmode == LinkExternal && !iscgo) {
|
||||||
|
@ -357,6 +357,10 @@ asmbmacho(void)
|
|||||||
default:
|
default:
|
||||||
diag("unknown mach architecture");
|
diag("unknown mach architecture");
|
||||||
errorexit();
|
errorexit();
|
||||||
|
case '5':
|
||||||
|
mh->cpu = MACHO_CPU_ARM;
|
||||||
|
mh->subcpu = MACHO_SUBCPU_ARMV7;
|
||||||
|
break;
|
||||||
case '6':
|
case '6':
|
||||||
mh->cpu = MACHO_CPU_AMD64;
|
mh->cpu = MACHO_CPU_AMD64;
|
||||||
mh->subcpu = MACHO_SUBCPU_X86;
|
mh->subcpu = MACHO_SUBCPU_X86;
|
||||||
@ -416,6 +420,12 @@ asmbmacho(void)
|
|||||||
default:
|
default:
|
||||||
diag("unknown macho architecture");
|
diag("unknown macho architecture");
|
||||||
errorexit();
|
errorexit();
|
||||||
|
case '5':
|
||||||
|
ml = newMachoLoad(5, 17+2); /* unix thread */
|
||||||
|
ml->data[0] = 1; /* thread type */
|
||||||
|
ml->data[1] = 17; /* word count */
|
||||||
|
ml->data[2+15] = entryvalue(); /* start pc */
|
||||||
|
break;
|
||||||
case '6':
|
case '6':
|
||||||
ml = newMachoLoad(5, 42+2); /* unix thread */
|
ml = newMachoLoad(5, 42+2); /* unix thread */
|
||||||
ml->data[0] = 4; /* thread type */
|
ml->data[0] = 4; /* thread type */
|
||||||
|
@ -66,6 +66,9 @@ enum {
|
|||||||
MACHO_CPU_AMD64 = (1<<24)|7,
|
MACHO_CPU_AMD64 = (1<<24)|7,
|
||||||
MACHO_CPU_386 = 7,
|
MACHO_CPU_386 = 7,
|
||||||
MACHO_SUBCPU_X86 = 3,
|
MACHO_SUBCPU_X86 = 3,
|
||||||
|
MACHO_CPU_ARM = 12,
|
||||||
|
MACHO_SUBCPU_ARM = 0,
|
||||||
|
MACHO_SUBCPU_ARMV7 = 9,
|
||||||
|
|
||||||
MACHO32SYMSIZE = 12,
|
MACHO32SYMSIZE = 12,
|
||||||
MACHO64SYMSIZE = 16,
|
MACHO64SYMSIZE = 16,
|
||||||
@ -80,6 +83,9 @@ enum {
|
|||||||
MACHO_X86_64_RELOC_SIGNED_2 = 7,
|
MACHO_X86_64_RELOC_SIGNED_2 = 7,
|
||||||
MACHO_X86_64_RELOC_SIGNED_4 = 8,
|
MACHO_X86_64_RELOC_SIGNED_4 = 8,
|
||||||
|
|
||||||
|
MACHO_ARM_RELOC_VANILLA = 0,
|
||||||
|
MACHO_ARM_RELOC_BR24 = 5,
|
||||||
|
|
||||||
MACHO_GENERIC_RELOC_VANILLA = 0,
|
MACHO_GENERIC_RELOC_VANILLA = 0,
|
||||||
|
|
||||||
MACHO_FAKE_GOTPCREL = 100,
|
MACHO_FAKE_GOTPCREL = 100,
|
||||||
|
@ -148,15 +148,15 @@ linknew(LinkArch *arch)
|
|||||||
switch(ctxt->arch->thechar) {
|
switch(ctxt->arch->thechar) {
|
||||||
default:
|
default:
|
||||||
sysfatal("unknown thread-local storage offset for nacl/%s", ctxt->arch->name);
|
sysfatal("unknown thread-local storage offset for nacl/%s", ctxt->arch->name);
|
||||||
|
case '5':
|
||||||
|
ctxt->tlsoffset = 0;
|
||||||
|
break;
|
||||||
case '6':
|
case '6':
|
||||||
ctxt->tlsoffset = 0;
|
ctxt->tlsoffset = 0;
|
||||||
break;
|
break;
|
||||||
case '8':
|
case '8':
|
||||||
ctxt->tlsoffset = -8;
|
ctxt->tlsoffset = -8;
|
||||||
break;
|
break;
|
||||||
case '5':
|
|
||||||
ctxt->tlsoffset = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -174,6 +174,9 @@ linknew(LinkArch *arch)
|
|||||||
case '8':
|
case '8':
|
||||||
ctxt->tlsoffset = 0x468;
|
ctxt->tlsoffset = 0x468;
|
||||||
break;
|
break;
|
||||||
|
case '5':
|
||||||
|
ctxt->tlsoffset = 0; // dummy value, not needed
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user