]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/ld, cmd/6l, cmd/8l: sort exported dynamic symbols for Darwin
authorShenghou Ma <minux.ma@gmail.com>
Tue, 9 Oct 2012 16:55:48 +0000 (00:55 +0800)
committerShenghou Ma <minux.ma@gmail.com>
Tue, 9 Oct 2012 16:55:48 +0000 (00:55 +0800)
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

misc/cgo/test/cgo_test.go
misc/cgo/test/issue4029.go [new file with mode: 0644]
src/cmd/6l/asm.c
src/cmd/8l/asm.c
src/cmd/ld/data.c
src/cmd/ld/go.c
src/cmd/ld/lib.c
src/cmd/ld/lib.h

index 3b866290fe29b3b9e3b829d21402b2609c6b3a61..682e292a7036a777a5acae1432d4009ae1bd0942 100644 (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) }
diff --git a/misc/cgo/test/issue4029.go b/misc/cgo/test/issue4029.go
new file mode 100644 (file)
index 0000000..b8a0a6d
--- /dev/null
@@ -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)
+       }
+}
index 05732d081d8ea3782e635e9a0e3bcdf18612d914..8af86066036b74138579fdf63df84c2926dfc5b6 100644 (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");
        }
index 4d7734f046c35e3c6abe4b9cf0a62850ea7abcfa..44cd77cbac4793431ebf61e3bf70e16dbaf1831e 100644 (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");
        }
index 4afe4b801cb08c142344cc456f5ceb708bdede3e..e551f72903049a8401b3548b72f13059298f5230 100644 (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)
 {
index 28cf06b8bd2c2bf158f94c10289dd69a80529df6..8def9b7301b0e023b4428f0111d854408245d3fa 100644 (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
+       }
+}
index 135426473fbb22379039e19663bace55ece018f3..8e3a8dd690fb9b6344168672dfc5aec3b634836e 100644 (file)
@@ -309,6 +309,7 @@ loadlib(void)
                debug['d'] = 1;
        
        importcycles();
+       sortdynexp();
 }
 
 /*
index d322df5c6b4775c7938df291782ed78ea7c4dbe5..162e16180f10e0d15d8f68060eb2258051b895a7 100644 (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);