1
0
mirror of https://github.com/golang/go synced 2024-11-22 03:34:40 -07:00

cmd/ld, cmd/6l, cmd/8l: sort exported dynamic symbols for Darwin

Also corrected cmd/8l's .dynsym handling (differentiate between exported symbols and imported symbols)

        Fixes #4029.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6620075
This commit is contained in:
Shenghou Ma 2012-10-10 00:55:48 +08:00
parent cffbfaeb18
commit fa563ae82e
8 changed files with 185 additions and 17 deletions

View File

@ -31,5 +31,6 @@ func TestHelpers(t *testing.T) { testHelpers(t) }
func TestLibgcc(t *testing.T) { testLibgcc(t) }
func Test1635(t *testing.T) { test1635(t) }
func TestPrintf(t *testing.T) { testPrintf(t) }
func Test4029(t *testing.T) { test4029(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }

View File

@ -0,0 +1,57 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cgotest
/*
#include <dlfcn.h>
*/
import "C"
import (
"fmt"
"testing"
)
//export IMPIsOpaque
func IMPIsOpaque() {
fmt.Println("isOpaque")
}
//export IMPInitWithFrame
func IMPInitWithFrame() {
fmt.Println("IInitWithFrame")
}
//export IMPDrawRect
func IMPDrawRect() {
fmt.Println("drawRect:")
}
//export IMPWindowResize
func IMPWindowResize() {
fmt.Println("windowDidResize:")
}
func test4029(t *testing.T) {
loadThySelf(t, "IMPWindowResize")
loadThySelf(t, "IMPDrawRect")
loadThySelf(t, "IMPInitWithFrame")
loadThySelf(t, "IMPIsOpaque")
}
func loadThySelf(t *testing.T, symbol string) {
this_process := C.dlopen(nil, C.RTLD_NOW)
if this_process == nil {
t.Fatal("dlopen:", C.GoString(C.dlerror()))
}
defer C.dlclose(this_process)
symbol_address := C.dlsym(this_process, C.CString(symbol))
if symbol_address == nil {
t.Fatal("dlsym:", C.GoString(C.dlerror()))
} else {
t.Log(symbol, symbol_address)
}
}

View File

@ -435,6 +435,7 @@ adddynsym(Sym *s)
Sym *d, *str;
int t;
char *name;
vlong off;
if(s->dynid >= 0)
return;
@ -503,35 +504,51 @@ adddynsym(Sym *s)
name = s->dynimpname;
if(name == nil)
name = s->name;
s->dynid = d->size/16;
if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
symgrow(d, ndynexp*16);
}
if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
s->dynid = -s->dynid-100;
off = s->dynid*16;
} else {
off = d->size;
s->dynid = off/16;
}
// darwin still puts _ prefixes on all C symbols
str = lookup(".dynstr", 0);
adduint32(d, str->size);
setuint32(d, off, str->size);
off += 4;
adduint8(str, '_');
addstring(str, name);
if(s->type == SDYNIMPORT) {
adduint8(d, 0x01); // type - N_EXT - external symbol
adduint8(d, 0); // section
setuint8(d, off, 0x01); // type - N_EXT - external symbol
off++;
setuint8(d, off, 0); // section
off++;
} else {
adduint8(d, 0x0f);
setuint8(d, off, 0x0f);
off++;
switch(s->type) {
default:
case STEXT:
adduint8(d, 1);
setuint8(d, off, 1);
break;
case SDATA:
adduint8(d, 2);
setuint8(d, off, 2);
break;
case SBSS:
adduint8(d, 4);
setuint8(d, off, 4);
break;
}
off++;
}
adduint16(d, 0); // desc
setuint16(d, off, 0); // desc
off += 2;
if(s->type == SDYNIMPORT)
adduint64(d, 0); // value
setuint64(d, off, 0); // value
else
addaddr(d, s);
setaddr(d, off, s);
off += 8;
} else if(HEADTYPE != Hwindows) {
diag("adddynsym: unsupported binary format");
}

View File

@ -416,6 +416,7 @@ adddynsym(Sym *s)
Sym *d, *str;
int t;
char *name;
vlong off;
if(s->dynid >= 0)
return;
@ -479,16 +480,51 @@ adddynsym(Sym *s)
name = s->dynimpname;
if(name == nil)
name = s->name;
s->dynid = d->size/12;
if(d->size == 0 && ndynexp > 0) { // pre-allocate for dynexps
symgrow(d, ndynexp*12);
}
if(s->dynid <= -100) { // pre-allocated, see cmd/ld/go.c:^sortdynexp()
s->dynid = -s->dynid-100;
off = s->dynid*12;
} else {
off = d->size;
s->dynid = off/12;
}
// darwin still puts _ prefixes on all C symbols
str = lookup(".dynstr", 0);
adduint32(d, str->size);
setuint32(d, off, str->size);
off += 4;
adduint8(str, '_');
addstring(str, name);
adduint8(d, 0x01); // type - N_EXT - external symbol
adduint8(d, 0); // section
adduint16(d, 0); // desc
adduint32(d, 0); // value
if(s->type == SDYNIMPORT) {
setuint8(d, off, 0x01); // type - N_EXT - external symbol
off++;
setuint8(d, off, 0); // section
off++;
} else {
setuint8(d, off, 0x0f);
off++;
switch(s->type) {
default:
case STEXT:
setuint8(d, off, 1);
break;
case SDATA:
setuint8(d, off, 2);
break;
case SBSS:
setuint8(d, off, 4);
break;
}
off++;
}
setuint16(d, off, 0); // desc
off += 2;
if(s->type == SDYNIMPORT)
setuint32(d, off, 0); // value
else
setaddr(d, off, s);
off += 4;
} else if(HEADTYPE != Hwindows) {
diag("adddynsym: unsupported binary format");
}

View File

@ -793,6 +793,33 @@ addaddr(Sym *s, Sym *t)
return addaddrplus(s, t, 0);
}
vlong
setaddrplus(Sym *s, vlong off, Sym *t, int32 add)
{
Reloc *r;
if(s->type == 0)
s->type = SDATA;
s->reachable = 1;
if(off+PtrSize > s->size) {
s->size = off + PtrSize;
symgrow(s, s->size);
}
r = addrel(s);
r->sym = t;
r->off = off;
r->siz = PtrSize;
r->type = D_ADDR;
r->add = add;
return off;
}
vlong
setaddr(Sym *s, vlong off, Sym *t)
{
return setaddrplus(s, off, t, 0);
}
vlong
addsize(Sym *s, Sym *t)
{

View File

@ -932,3 +932,28 @@ importcycles(void)
for(p=pkgall; p; p=p->all)
cycle(p);
}
static int
scmp(const void *p1, const void *p2)
{
Sym *s1, *s2;
s1 = *(Sym**)p1;
s2 = *(Sym**)p2;
return strcmp(s1->dynimpname, s2->dynimpname);
}
void
sortdynexp(void)
{
int i;
// On Mac OS X Mountain Lion, we must sort exported symbols
// So we sort them here and pre-allocate dynid for them
// See http://golang.org/issue/4029
if(HEADTYPE != Hdarwin)
return;
qsort(dynexp, ndynexp, sizeof dynexp[0], scmp);
for(i=0; i<ndynexp; i++) {
dynexp[i]->dynid = -i-100; // also known to [68]l/asm.c:^adddynsym
}
}

View File

@ -309,6 +309,7 @@ loadlib(void)
debug['d'] = 1;
importcycles();
sortdynexp();
}
/*

View File

@ -196,6 +196,8 @@ vlong addaddr(Sym*, Sym*);
vlong addaddrplus(Sym*, Sym*, int32);
vlong addpcrelplus(Sym*, Sym*, int32);
vlong addsize(Sym*, Sym*);
vlong setaddrplus(Sym*, vlong, Sym*, int32);
vlong setaddr(Sym*, vlong, Sym*);
void setuint8(Sym*, vlong, uint8);
void setuint16(Sym*, vlong, uint16);
void setuint32(Sym*, vlong, uint32);
@ -341,3 +343,5 @@ char* decodetype_structfieldname(Sym*, int);
Sym* decodetype_structfieldtype(Sym*, int);
vlong decodetype_structfieldoffs(Sym*, int);
vlong decodetype_ifacemethodcount(Sym*);
void sortdynexp(void);