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:
parent
cffbfaeb18
commit
fa563ae82e
@ -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) }
|
||||
|
57
misc/cgo/test/issue4029.go
Normal file
57
misc/cgo/test/issue4029.go
Normal 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)
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -309,6 +309,7 @@ loadlib(void)
|
||||
debug['d'] = 1;
|
||||
|
||||
importcycles();
|
||||
sortdynexp();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user