From 5e514b76e2e55efbca917c686c93b2299d57386c Mon Sep 17 00:00:00 2001 From: John Papandriopoulos Date: Sun, 29 Sep 2019 16:59:56 -0700 Subject: [PATCH] cmd/link: load symbols from .syso in external link mode Fix linking with a package having a .syso file in external link mode, that would otherwise cause an error before executing the external linker because it can't find symbols that are exported in the said .syso file. Fixes #33139 Change-Id: Id3ee737fba1c6f1e37910593dfedf9c84486d398 Reviewed-on: https://go-review.googlesource.com/c/go/+/186417 Reviewed-by: Ian Lance Taylor --- .../testdata/script/link_syso_issue33139.txt | 29 +++++++++++++++++++ src/cmd/link/internal/arm/asm.go | 2 +- src/cmd/link/internal/ld/data.go | 13 ++++++++- src/cmd/link/internal/ld/go.go | 18 ++++++++++++ src/cmd/link/internal/ld/lib.go | 2 +- src/cmd/link/internal/ld/macho.go | 4 +-- src/cmd/link/internal/ld/pe.go | 2 +- src/cmd/link/internal/ld/symtab.go | 2 +- src/cmd/link/internal/sym/symkind.go | 1 + src/cmd/link/internal/sym/symkind_string.go | 19 ++++++------ 10 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 src/cmd/go/testdata/script/link_syso_issue33139.txt 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 index 0000000000..53587e6823 --- /dev/null +++ b/src/cmd/go/testdata/script/link_syso_issue33139.txt @@ -0,0 +1,29 @@ +# 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 stub. +# See issue 33139. +[!gc] stop +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 + 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() +} diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go index 43d387c862..41efd935ee 100644 --- a/src/cmd/link/internal/arm/asm.go +++ b/src/cmd/link/internal/arm/asm.go @@ -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 diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 2266d301dd..ea674832a9 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -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) @@ -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 diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go index 80d7ac32f5..37adeb7701 100644 --- a/src/cmd/link/internal/ld/go.go +++ b/src/cmd/link/internal/ld/go.go @@ -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 diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 182e5b0769..98c5e6ca6d 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2348,7 +2348,7 @@ func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int6 } put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype) - case sym.SHOSTOBJ: + case sym.SHOSTOBJ, sym.SUNDEFEXT: if ctxt.HeadType == objabi.Hwindows || ctxt.IsELF { put(ctxt, s, s.Name, UndefinedSym, s.Value, nil) } diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index 7453f37c62..e9e48768c1 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -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 diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 12363626ae..6d4674dbfd 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -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 } diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index d686a8a476..4925eda0e6 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -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 { diff --git a/src/cmd/link/internal/sym/symkind.go b/src/cmd/link/internal/sym/symkind.go index 4e44d3fce1..5309e07ecf 100644 --- a/src/cmd/link/internal/sym/symkind.go +++ b/src/cmd/link/internal/sym/symkind.go @@ -104,6 +104,7 @@ const ( SCONST SDYNIMPORT SHOSTOBJ + SUNDEFEXT // Undefined symbol for resolution by external linker // Sections for debugging information SDWARFSECT diff --git a/src/cmd/link/internal/sym/symkind_string.go b/src/cmd/link/internal/sym/symkind_string.go index 2732ec7654..e48d90c511 100644 --- a/src/cmd/link/internal/sym/symkind_string.go +++ b/src/cmd/link/internal/sym/symkind_string.go @@ -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) {