]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: always resolve functions locally when linking dynamically
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Wed, 28 Oct 2015 23:17:43 +0000 (12:17 +1300)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Thu, 29 Oct 2015 19:19:07 +0000 (19:19 +0000)
When dynamically linking, we want references to functions defined
in this module to always be to the function object, not to the
PLT. We force this by writing an additional local symbol for
every global function symbol and making all relocations against
the global symbol refer to this local symbol instead. This is
approximately equivalent to the ELF linker -Bsymbolic-functions
option, but that is buggy on several platforms.

Change-Id: Ie6983eb4d1947f8543736fd349f9a90df3cce91a
Reviewed-on: https://go-review.googlesource.com/16436
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/link/internal/amd64/asm.go
src/cmd/link/internal/arm/asm.go
src/cmd/link/internal/arm64/asm.go
src/cmd/link/internal/ld/elf.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/link.go
src/cmd/link/internal/ld/symtab.go
src/cmd/link/internal/x86/asm.go

index 51765a1847faae27c507fc67e0440f7097336298..1e50802bb3fc6076643270f0f6643ae8b746f3b2 100644 (file)
@@ -323,7 +323,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
        ld.Thearch.Vput(uint64(sectoff))
 
-       elfsym := r.Xsym.Elfsym
+       elfsym := r.Xsym.ElfsymForReloc()
        switch r.Type {
        default:
                return -1
index 01b2aaa3b4d21c2b1b9430325e4eb7020209e363..5507312a1b1e836f12073c19c62ef8674b6157aa 100644 (file)
@@ -193,7 +193,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
        ld.Thearch.Lput(uint32(sectoff))
 
-       elfsym := r.Xsym.Elfsym
+       elfsym := r.Xsym.ElfsymForReloc()
        switch r.Type {
        default:
                return -1
index 58d5236398a53b178f393fdfe04abf8afcba2fff..7308d2fce13094c2d6f37fe075b6520ebb7c5559 100644 (file)
@@ -51,7 +51,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
        ld.Thearch.Vput(uint64(sectoff))
 
-       elfsym := r.Xsym.Elfsym
+       elfsym := r.Xsym.ElfsymForReloc()
        switch r.Type {
        default:
                return -1
index 16c669e806455f6976bd14804e78e04160d5ee27..2cce02287d4ea705ce3f9870eaa1060573ea09d0 100644 (file)
@@ -1615,7 +1615,7 @@ func elfrelocsect(sect *Section, first *LSym) {
                                continue
                        }
 
-                       if r.Xsym.Elfsym == 0 {
+                       if r.Xsym.ElfsymForReloc() == 0 {
                                Diag("reloc %d to non-elf symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
                        }
                        if Thearch.Elfreloc1(r, int64(uint64(sym.Value+int64(r.Off))-sect.Vaddr)) < 0 {
index ff9cabc21435ba447f0fe38e2353f7803c943d42..a311c780ed88730e5e0103a2b9bab8adf970410c 100644 (file)
@@ -1031,14 +1031,6 @@ func hostlink() {
                        argv = append(argv, "-shared", "-Wl,-z,nodelete")
                }
        case BuildmodeShared:
-               // TODO(mwhudson): unless you do this, dynamic relocations fill
-               // out the findfunctab table and for some reason shared libraries
-               // and the executable both define a main function and putting the
-               // address of executable's main into the shared libraries
-               // findfunctab violates the assumptions of the runtime.  TBH, I
-               // think we may well end up wanting to use -Bsymbolic here
-               // anyway.
-               argv = append(argv, "-Wl,-Bsymbolic-functions")
                if UseRelro() {
                        argv = append(argv, "-Wl,-z,relro")
                }
index 7102edfb4d45299d1926aa2a90a5cfd526bff1e1..495d11ac7e3ce81de56e1fd5e8ce4b51aa243d88 100644 (file)
@@ -63,6 +63,7 @@ type LSym struct {
        Got         int32
        Align       int32
        Elfsym      int32
+       LocalElfsym int32
        Args        int32
        Locals      int32
        Value       int64
@@ -92,6 +93,16 @@ func (s *LSym) String() string {
        return fmt.Sprintf("%s<%d>", s.Name, s.Version)
 }
 
+func (s *LSym) ElfsymForReloc() int32 {
+       // If putelfsym created a local version of this symbol, use that in all
+       // relocations.
+       if s.LocalElfsym != 0 {
+               return s.LocalElfsym
+       } else {
+               return s.Elfsym
+       }
+}
+
 type Reloc struct {
        Off     int32
        Siz     uint8
index f71158663c7abcd22df3e322de1a1350cbefc017..c53037168ab43d274f89258c4d765995569b98eb 100644 (file)
@@ -155,11 +155,6 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
                bind = STB_LOCAL
        }
 
-       if bind != elfbind {
-               return
-       }
-
-       off := putelfstr(s)
        if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
                addr -= int64(xo.Sect.Vaddr)
        }
@@ -167,7 +162,24 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
        if x.Type&obj.SHIDDEN != 0 {
                other = STV_HIDDEN
        }
-       putelfsyment(off, addr, size, bind<<4|type_&0xf, elfshnum, other)
+
+       if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT {
+               // When dynamically linking, we want references to functions defined
+               // in this module to always be to the function object, not to the
+               // PLT. We force this by writing an additional local symbol for every
+               // global function symbol and making all relocations against the
+               // global symbol refer to this local symbol instead (see
+               // (*LSym).ElfsymForReloc). This is approximately equivalent to the
+               // ELF linker -Bsymbolic-functions option, but that is buggy on
+               // several platforms.
+               putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other)
+               x.LocalElfsym = int32(numelfsym)
+               numelfsym++
+       } else if bind != elfbind {
+               return
+       }
+
+       putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other)
        x.Elfsym = int32(numelfsym)
        numelfsym++
 }
index d30bd48b4e61d60f3016a58a6b2269802a6000a5..8f9507168c1f1f3c9825cffd10592963b02772c2 100644 (file)
@@ -231,7 +231,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
        ld.Thearch.Lput(uint32(sectoff))
 
-       elfsym := r.Xsym.Elfsym
+       elfsym := r.Xsym.ElfsymForReloc()
        switch r.Type {
        default:
                return -1