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) }
--- /dev/null
+// 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)
+ }
+}
Sym *d, *str;
int t;
char *name;
+ vlong off;
if(s->dynid >= 0)
return;
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");
}
Sym *d, *str;
int t;
char *name;
+ vlong off;
if(s->dynid >= 0)
return;
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");
}
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)
{
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
+ }
+}
debug['d'] = 1;
importcycles();
+ sortdynexp();
}
/*
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);
Sym* decodetype_structfieldtype(Sym*, int);
vlong decodetype_structfieldoffs(Sym*, int);
vlong decodetype_ifacemethodcount(Sym*);
+
+void sortdynexp(void);