Commit 3a43ff1a authored by Ian Lance Taylor's avatar Ian Lance Taylor

ld: Fix exported dynamic symbols on Mach-O.

* Avoid confusion between imported and exported symbols.
* Record number of imported and exported symbols correctly.
* Explictly relocate SMACHOSYM section, since it is not in datap.

R=rsc
CC=golang-dev
https://golang.org/cl/3920042
parent 3036604b
...@@ -184,7 +184,7 @@ adddynrel(Sym *s, Reloc *r) ...@@ -184,7 +184,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) if(targ->dynimpname != nil && !targ->dynexport)
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);
...@@ -195,7 +195,7 @@ adddynrel(Sym *s, Reloc *r) ...@@ -195,7 +195,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) { if(targ->dynimpname != nil && !targ->dynexport) {
addpltsym(targ); addpltsym(targ);
r->sym = lookup(".plt", 0); r->sym = lookup(".plt", 0);
r->add += targ->plt; r->add += targ->plt;
...@@ -203,7 +203,7 @@ adddynrel(Sym *s, Reloc *r) ...@@ -203,7 +203,7 @@ adddynrel(Sym *s, Reloc *r)
return; return;
case 256 + R_X86_64_GOTPCREL: case 256 + R_X86_64_GOTPCREL:
if(targ->dynimpname == nil) { if(targ->dynimpname == nil || targ->dynexport) {
// 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) {
...@@ -223,7 +223,7 @@ adddynrel(Sym *s, Reloc *r) ...@@ -223,7 +223,7 @@ adddynrel(Sym *s, Reloc *r)
return; return;
case 256 + R_X86_64_64: case 256 + R_X86_64_64:
if(targ->dynimpname) if(targ->dynimpname != nil && !targ->dynexport)
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;
...@@ -234,12 +234,12 @@ adddynrel(Sym *s, Reloc *r) ...@@ -234,12 +234,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) if(targ->dynimpname != nil && !targ->dynexport)
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) { if(targ->dynimpname != nil && !targ->dynexport) {
addpltsym(targ); addpltsym(targ);
r->sym = lookup(".plt", 0); r->sym = lookup(".plt", 0);
r->add = targ->plt; r->add = targ->plt;
...@@ -253,12 +253,12 @@ adddynrel(Sym *s, Reloc *r) ...@@ -253,12 +253,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) if(targ->dynimpname != nil && !targ->dynexport)
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) { if(targ->dynimpname == nil || targ->dynexport) {
// 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) {
...@@ -271,7 +271,7 @@ adddynrel(Sym *s, Reloc *r) ...@@ -271,7 +271,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) if(targ->dynimpname == nil || targ->dynexport)
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;
...@@ -281,7 +281,7 @@ adddynrel(Sym *s, Reloc *r) ...@@ -281,7 +281,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) if(targ->dynimpname == nil || targ->dynexport)
return; return;
switch(r->type) { switch(r->type) {
......
...@@ -71,7 +71,6 @@ static void loaddynexport(char*, char*, char*, int); ...@@ -71,7 +71,6 @@ static void loaddynexport(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 int ndynexp;
static Sym **dynexp; static Sym **dynexp;
void void
......
...@@ -92,6 +92,7 @@ EXTERN uchar inuxi8[8]; ...@@ -92,6 +92,7 @@ EXTERN uchar inuxi8[8];
EXTERN char* outfile; EXTERN char* outfile;
EXTERN int32 nsymbol; EXTERN int32 nsymbol;
EXTERN char* thestring; EXTERN char* thestring;
EXTERN int ndynexp;
EXTERN Segment segtext; EXTERN Segment segtext;
EXTERN Segment segdata; EXTERN Segment segdata;
...@@ -140,6 +141,7 @@ void codeblk(int32, int32); ...@@ -140,6 +141,7 @@ void codeblk(int32, int32);
void datblk(int32, int32); void datblk(int32, int32);
Sym* datsort(Sym*); Sym* datsort(Sym*);
void reloc(void); void reloc(void);
void relocsym(Sym*);
void savedata(Sym*, Prog*); void savedata(Sym*, Prog*);
void symgrow(Sym*, int32); void symgrow(Sym*, int32);
vlong addstring(Sym*, char*); vlong addstring(Sym*, char*);
......
...@@ -102,13 +102,6 @@ newMachoDebug(void) ...@@ -102,13 +102,6 @@ newMachoDebug(void)
// Generic linking code. // Generic linking code.
struct Expsym
{
int off;
Sym* s;
} *expsym;
static int nexpsym;
static char **dylib; static char **dylib;
static int ndylib; static int ndylib;
...@@ -415,9 +408,9 @@ asmbmacho(void) ...@@ -415,9 +408,9 @@ asmbmacho(void)
ml->data[0] = 0; /* ilocalsym */ ml->data[0] = 0; /* ilocalsym */
ml->data[1] = 0; /* nlocalsym */ ml->data[1] = 0; /* nlocalsym */
ml->data[2] = 0; /* iextdefsym */ ml->data[2] = 0; /* iextdefsym */
ml->data[3] = 0; /* nextdefsym */ // TODO nexpsym ml->data[3] = ndynexp; /* nextdefsym */
ml->data[4] = 0; /* iundefsym */ // TODO nexpsym ml->data[4] = ndynexp; /* iundefsym */
ml->data[5] = s1->size / (macho64 ? 16 : 12); /* nundefsym */ ml->data[5] = (s1->size / (macho64 ? 16 : 12)) - ndynexp; /* nundefsym */
ml->data[6] = 0; /* tocoffset */ ml->data[6] = 0; /* tocoffset */
ml->data[7] = 0; /* ntoc */ ml->data[7] = 0; /* ntoc */
ml->data[8] = 0; /* modtaboff */ ml->data[8] = 0; /* modtaboff */
...@@ -480,6 +473,7 @@ domacholink(void) ...@@ -480,6 +473,7 @@ domacholink(void)
// write data that will be linkedit section // write data that will be linkedit section
s1 = lookup(".dynsym", 0); s1 = lookup(".dynsym", 0);
relocsym(s1);
s2 = lookup(".dynstr", 0); s2 = lookup(".dynstr", 0);
s3 = lookup(".linkedit.plt", 0); s3 = lookup(".linkedit.plt", 0);
s4 = lookup(".linkedit.got", 0); s4 = lookup(".linkedit.got", 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment