]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: pass-through undefined call targets in external link mode
authorJohn Papandriopoulos <jpap.code@gmail.com>
Sun, 29 Sep 2019 23:59:56 +0000 (16:59 -0700)
committerIan Lance Taylor <iant@golang.org>
Mon, 28 Oct 2019 22:10:06 +0000 (22:10 +0000)
Allows Go asm calls referencing a function in a .syso file to be
passed through to the external linker, that would have otherwise
raised a "relocation target X not defined" error in cmd/link.

Fixes #33139

Change-Id: I2a8eb6063ebcd05fac96f141acf7652cf9189766
Reviewed-on: https://go-review.googlesource.com/c/go/+/198798
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
12 files changed:
src/cmd/go/testdata/script/link_syso_issue33139.txt [new file with mode: 0644]
src/cmd/link/internal/arm/asm.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/go.go
src/cmd/link/internal/ld/lib.go
src/cmd/link/internal/ld/macho.go
src/cmd/link/internal/ld/pe.go
src/cmd/link/internal/ld/symtab.go
src/cmd/link/internal/ld/xcoff.go
src/cmd/link/internal/ppc64/asm.go
src/cmd/link/internal/sym/symkind.go
src/cmd/link/internal/sym/symkind_string.go

diff --git a/src/cmd/go/testdata/script/link_syso_issue33139.txt b/src/cmd/go/testdata/script/link_syso_issue33139.txt
new file mode 100644 (file)
index 0000000..c2ca27a
--- /dev/null
@@ -0,0 +1,43 @@
+# Test that we can use the external linker with a host syso file that is
+# embedded in a package, that is referenced by a Go assembly function.
+# See issue 33139.
+[!gc] skip
+[!exec:cc] skip
+
+# External linking is not supported on linux/ppc64.
+# See: https://github.com/golang/go/issues/8912
+[linux] [ppc64] skip
+
+# External linking is not supported on darwin/386 (10.14+).
+# See: https://github.com/golang/go/issues/31751
+[darwin] [386] skip
+
+cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c
+go build -ldflags='-linkmode=external' ./cmd/main.go
+
+-- syso/objTest.s --
+#include "textflag.h"
+
+TEXT ·ObjTest(SB), NOSPLIT, $0
+       // We do not actually execute this function in the test above, thus
+       // there is no stack frame setup here.
+       // We only care about Go build and/or link errors when referencing
+       // the objTestImpl symbol in the syso file.
+       JMP objTestImpl(SB)
+
+-- syso/pkg.go --
+package syso
+
+func ObjTest()
+
+-- syso/src/objTestImpl.c --
+void objTestImpl() { /* Empty */ }
+
+-- cmd/main.go --
+package main
+
+import "syso"
+
+func main() {
+       syso.ObjTest()
+}
index 995a703dd4692467751b07da1451c422400c8376..f2fb6543d0d939e17264f95a42d6c7c6c33b0764 100644 (file)
@@ -613,7 +613,7 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
                                rs = rs.Outer
                        }
 
-                       if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
+                       if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
                                ld.Errorf(s, "missing section for %s", rs.Name)
                        }
                        r.Xsym = rs
index 4da5ce3f704acbc3e5b6f47a82a45ffec43f3faa..89485b8be43932991d985a53caaeae575c92509e 100644 (file)
@@ -96,7 +96,7 @@ func trampoline(ctxt *Link, s *sym.Symbol) {
                if !r.Type.IsDirectJump() {
                        continue
                }
-               if Symaddr(r.Sym) == 0 && r.Sym.Type != sym.SDYNIMPORT {
+               if Symaddr(r.Sym) == 0 && (r.Sym.Type != sym.SDYNIMPORT && r.Sym.Type != sym.SUNDEFEXT) {
                        if r.Sym.File != s.File {
                                if !isRuntimeDepPkg(s.File) || !isRuntimeDepPkg(r.Sym.File) {
                                        ctxt.ErrorUnresolved(s, r)
@@ -298,7 +298,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
                                        rs = rs.Outer
                                }
 
-                               if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
+                               if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
                                        Errorf(s, "missing section for relocation target %s", rs.Name)
                                }
                                r.Xsym = rs
@@ -418,6 +418,17 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
                        }
                        fallthrough
                case objabi.R_CALL, objabi.R_PCREL:
+                       if ctxt.LinkMode == LinkExternal && r.Sym != nil && r.Sym.Type == sym.SUNDEFEXT {
+                               // pass through to the external linker.
+                               r.Done = false
+                               r.Xadd = 0
+                               if ctxt.IsELF {
+                                       r.Xadd -= int64(r.Siz)
+                               }
+                               r.Xsym = r.Sym
+                               o = 0
+                               break
+                       }
                        if ctxt.LinkMode == LinkExternal && r.Sym != nil && r.Sym.Type != sym.SCONST && (r.Sym.Sect != s.Sect || r.Type == objabi.R_GOTPCREL) {
                                r.Done = false
 
index 80d7ac32f524b9cc090ae84d9c00fc34f9aa1c83..37adeb770115c1b5f1334ab31c8b7322a68d249c 100644 (file)
@@ -334,6 +334,24 @@ func fieldtrack(ctxt *Link) {
 }
 
 func (ctxt *Link) addexport() {
+       // Track undefined external symbols during external link.
+       if ctxt.LinkMode == LinkExternal {
+               for _, s := range ctxt.Syms.Allsym {
+                       if !s.Attr.Reachable() || s.Attr.Special() || s.Attr.SubSymbol() {
+                               continue
+                       }
+                       if s.Type != sym.STEXT {
+                               continue
+                       }
+                       for i := range s.R {
+                               r := &s.R[i]
+                               if r.Sym != nil && r.Sym.Type == sym.Sxxx {
+                                       r.Sym.Type = sym.SUNDEFEXT
+                               }
+                       }
+               }
+       }
+
        // TODO(aix)
        if ctxt.HeadType == objabi.Hdarwin || ctxt.HeadType == objabi.Haix {
                return
index a6fa14cc747854579bfb5c5ab6a86fa0dbd1d2e5..308d506fc3d8a363d3cdcedce4825196fa0027dc 100644 (file)
@@ -2369,6 +2369,11 @@ func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int6
                        }
                        put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype)
 
+               case sym.SUNDEFEXT:
+                       if ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Haix || ctxt.IsELF {
+                               put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
+                       }
+
                case sym.SHOSTOBJ:
                        if ctxt.HeadType == objabi.Hwindows || ctxt.IsELF {
                                put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
index 7453f37c62fec81c459eaa43cd24bed5e96a9b1f..e9e48768c14d3312b93f1ab4a7f5d80ad6fcda83 100644 (file)
@@ -809,7 +809,7 @@ func machogenasmsym(ctxt *Link) {
                        }
                }
 
-               if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ {
+               if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
                        if s.Attr.Reachable() {
                                addsym(ctxt, s, "", DataSym, 0, nil)
                        }
@@ -886,7 +886,7 @@ func machosymtab(ctxt *Link) {
                // replace "·" as ".", because DTrace cannot handle it.
                Addstring(symstr, strings.Replace(s.Extname(), "·", ".", -1))
 
-               if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ {
+               if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
                        symtab.AddUint8(0x01)                             // type N_EXT, external symbol
                        symtab.AddUint8(0)                                // no section
                        symtab.AddUint16(ctxt.Arch, 0)                    // desc
index b5851a94a0fb1d3f9d266dd115ae2b62105393e1..4ab346e733a97fe05fa1ecd3fea9fc55d43ce7ad 100644 (file)
@@ -685,7 +685,7 @@ func (f *peFile) writeSymbols(ctxt *Link) {
                // Only windows/386 requires underscore prefix on external symbols.
                if ctxt.Arch.Family == sys.I386 &&
                        ctxt.LinkMode == LinkExternal &&
-                       (s.Type == sym.SHOSTOBJ || s.Attr.CgoExport()) {
+                       (s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT || s.Attr.CgoExport()) {
                        s.Name = "_" + s.Name
                }
 
index b4236a52399da96aada23fed2a0954292dc7fc91..9ed5db05575f61ac0e4506ee295c4718a492181b 100644 (file)
@@ -110,7 +110,7 @@ func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64, go
        }
 
        var elfshnum int
-       if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ {
+       if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ || xo.Type == sym.SUNDEFEXT {
                elfshnum = SHN_UNDEF
        } else {
                if xo.Sect == nil {
index c64066acec7b7b575f3a04a746876461f64f2594..fe35578225a79e84c6574722a4e2113e4f6a2198 100644 (file)
@@ -955,7 +955,7 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64,
                syms = append(syms, a4)
 
        case UndefinedSym:
-               if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ {
+               if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ && x.Type != sym.SUNDEFEXT {
                        return
                }
                s := &XcoffSymEnt64{
index fadff89a46914e90ae41495fb3683ea28db568a2..45731c0638e14382ab0d75858ada4203c9f3dccd 100644 (file)
@@ -801,7 +801,7 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
                                rs = rs.Outer
                        }
 
-                       if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
+                       if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
                                ld.Errorf(s, "missing section for %s", rs.Name)
                        }
                        r.Xsym = rs
index 4e44d3fce106a19b5bb91ad4f492d36b2f5e711e..5309e07ecff21940f9cc37b55eef4abc67863ec6 100644 (file)
@@ -104,6 +104,7 @@ const (
        SCONST
        SDYNIMPORT
        SHOSTOBJ
+       SUNDEFEXT // Undefined symbol for resolution by external linker
 
        // Sections for debugging information
        SDWARFSECT
index 2732ec7654fb4f72a021809f67c642db213c7bdb..e48d90c511b26756dff82891690c4d42ccd350c5 100644 (file)
@@ -1,4 +1,4 @@
-// Code generated by "stringer -type=SymKind"; DO NOT EDIT.
+// Code generated by "stringer -type=SymKind symkind.go"; DO NOT EDIT.
 
 package sym
 
@@ -54,17 +54,18 @@ func _() {
        _ = x[SCONST-43]
        _ = x[SDYNIMPORT-44]
        _ = x[SHOSTOBJ-45]
-       _ = x[SDWARFSECT-46]
-       _ = x[SDWARFINFO-47]
-       _ = x[SDWARFRANGE-48]
-       _ = x[SDWARFLOC-49]
-       _ = x[SDWARFLINES-50]
-       _ = x[SABIALIAS-51]
+       _ = x[SUNDEFEXT-46]
+       _ = x[SDWARFSECT-47]
+       _ = x[SDWARFINFO-48]
+       _ = x[SDWARFRANGE-49]
+       _ = x[SDWARFLOC-50]
+       _ = x[SDWARFLINES-51]
+       _ = x[SABIALIAS-52]
 }
 
-const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSCONSTSDYNIMPORTSHOSTOBJSDWARFSECTSDWARFINFOSDWARFRANGESDWARFLOCSDWARFLINESSABIALIAS"
+const _SymKind_name = "SxxxSTEXTSELFRXSECTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSMACHOPLTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSCONSTSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFINFOSDWARFRANGESDWARFLOCSDWARFLINESSABIALIAS"
 
-var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 320, 325, 337, 349, 366, 383, 392, 398, 408, 416, 426, 436, 447, 456, 467, 476}
+var _SymKind_index = [...]uint16{0, 4, 9, 19, 24, 31, 40, 47, 54, 61, 69, 79, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 320, 325, 337, 349, 366, 383, 392, 398, 408, 416, 425, 435, 445, 456, 465, 476, 485}
 
 func (i SymKind) String() string {
        if i >= SymKind(len(_SymKind_index)-1) {