Skip to content

Commit

Permalink
cmd/link: load symbols from .syso in external link mode
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jpap committed Jul 17, 2019
1 parent a6a7b14 commit dceb816
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 14 deletions.
36 changes: 36 additions & 0 deletions src/cmd/go/testdata/script/link_syso_issue33139.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Test that we can link a syso file that is embedded in a package, that is
# referenced by an assembly stub. See issue 33139.
[!gc] stop
[darwin] cc -c -o syso/test.syso syso/asm/test_darwin.s
[!darwin] cc -c -o syso/test.syso syso/asm/test.s
go build -ldflags='-linkmode=external' ./cmd/main.go

-- syso/test.s --
#include "textflag.h"

TEXT ·Test(SB), NOSPLIT, $0
JMP asmTest(SB)

-- syso/test.go --
package syso

func Test()

-- syso/asm/test.s --
.globl asmTest
asmTest:
ret

-- syso/asm/test_darwin.s --
.globl _asmTest
_asmTest:
ret

-- cmd/main.go --
package main

import "syso"

func main() {
syso.Test()
}
1 change: 1 addition & 0 deletions src/cmd/link/internal/ld/go.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ func ldpkg(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, filename s
}
p1 += p0

lib.Cgo = true
loadcgo(ctxt, filename, objabi.PathToPrefix(lib.Pkg), data[p0:p1])
}
}
Expand Down
37 changes: 23 additions & 14 deletions src/cmd/link/internal/ld/lib.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,10 +542,10 @@ func (ctxt *Link) loadlib() {
}
dynexp = dynexp[:w]

// In internal link mode, read the host object files.
if ctxt.LinkMode == LinkInternal {
hostobjs(ctxt)
// Read the host object files.
hostobjs(ctxt)

if ctxt.LinkMode == LinkInternal {
// If we have any undefined symbols in external
// objects, try to read them from the libgcc file.
any := false
Expand Down Expand Up @@ -918,12 +918,13 @@ func loadobjfile(ctxt *Link, lib *sym.Library) {
}

type Hostobj struct {
ld func(*Link, *bio.Reader, string, int64, string)
pkg string
pn string
file string
off int64
length int64
ld func(*Link, *bio.Reader, string, int64, string)
pkg string
pn string
file string
off int64
length int64
isCgoPkg bool // part of a Cgo package
}

var hostobj []Hostobj
Expand All @@ -939,7 +940,7 @@ var internalpkg = []string{
"runtime/msan",
}

func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType objabi.HeadType, f *bio.Reader, pkg string, length int64, pn string, file string) *Hostobj {
func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType objabi.HeadType, f *bio.Reader, lib *sym.Library, pkg string, length int64, pn string, file string) *Hostobj {
isinternal := false
for _, intpkg := range internalpkg {
if pkg == intpkg {
Expand Down Expand Up @@ -972,6 +973,7 @@ func ldhostobj(ld func(*Link, *bio.Reader, string, int64, string), headType obja
h.file = file
h.off = f.Offset()
h.length = length
h.isCgoPkg = lib.Cgo
return h
}

Expand All @@ -980,6 +982,13 @@ func hostobjs(ctxt *Link) {

for i := 0; i < len(hostobj); i++ {
h = &hostobj[i]
if h.isCgoPkg && ctxt.LinkMode == LinkExternal {
// The Hostobj is part of a cgo package during an external link.
// Any host objects within this package are accessed from symbols
// already loaded from a Go object file, so we do not need to load
// any of the host object symbols in this file.
continue
}
f, err := bio.Open(h.file)
if err != nil {
Exitf("cannot reopen %s: %v", h.pn, err)
Expand Down Expand Up @@ -1620,7 +1629,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
ehdr.flags = flags
ctxt.Textp = append(ctxt.Textp, textp...)
}
return ldhostobj(ldelf, ctxt.HeadType, f, pkg, length, pn, file)
return ldhostobj(ldelf, ctxt.HeadType, f, lib, pkg, length, pn, file)
}

if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
Expand All @@ -1632,7 +1641,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
}
ctxt.Textp = append(ctxt.Textp, textp...)
}
return ldhostobj(ldmacho, ctxt.HeadType, f, pkg, length, pn, file)
return ldhostobj(ldmacho, ctxt.HeadType, f, lib, pkg, length, pn, file)
}

if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 {
Expand All @@ -1647,7 +1656,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
}
ctxt.Textp = append(ctxt.Textp, textp...)
}
return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
return ldhostobj(ldpe, ctxt.HeadType, f, lib, pkg, length, pn, file)
}

if c1 == 0x01 && (c2 == 0xD7 || c2 == 0xF7) {
Expand All @@ -1659,7 +1668,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
}
ctxt.Textp = append(ctxt.Textp, textp...)
}
return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file)
return ldhostobj(ldxcoff, ctxt.HeadType, f, lib, pkg, length, pn, file)
}

/* check the header */
Expand Down
1 change: 1 addition & 0 deletions src/cmd/link/internal/sym/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Library struct {
DupTextSyms []*Symbol // dupok text symbols defined in this library
Main bool
Safe bool
Cgo bool
}

func (l Library) String() string {
Expand Down

0 comments on commit dceb816

Please sign in to comment.