Skip to content

Commit 59a6847

Browse files
jpapianlancetaylor
authored andcommitted
cmd/link: pass-through undefined call targets in external link mode
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 81d6ec2 commit 59a6847

File tree

12 files changed

+97
-18
lines changed

12 files changed

+97
-18
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Test that we can use the external linker with a host syso file that is
2+
# embedded in a package, that is referenced by a Go assembly function.
3+
# See issue 33139.
4+
[!gc] skip
5+
[!exec:cc] skip
6+
7+
# External linking is not supported on linux/ppc64.
8+
# See: https://github.com/golang/go/issues/8912
9+
[linux] [ppc64] skip
10+
11+
# External linking is not supported on darwin/386 (10.14+).
12+
# See: https://github.com/golang/go/issues/31751
13+
[darwin] [386] skip
14+
15+
cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c
16+
go build -ldflags='-linkmode=external' ./cmd/main.go
17+
18+
-- syso/objTest.s --
19+
#include "textflag.h"
20+
21+
TEXT ·ObjTest(SB), NOSPLIT, $0
22+
// We do not actually execute this function in the test above, thus
23+
// there is no stack frame setup here.
24+
// We only care about Go build and/or link errors when referencing
25+
// the objTestImpl symbol in the syso file.
26+
JMP objTestImpl(SB)
27+
28+
-- syso/pkg.go --
29+
package syso
30+
31+
func ObjTest()
32+
33+
-- syso/src/objTestImpl.c --
34+
void objTestImpl() { /* Empty */ }
35+
36+
-- cmd/main.go --
37+
package main
38+
39+
import "syso"
40+
41+
func main() {
42+
syso.ObjTest()
43+
}

src/cmd/link/internal/arm/asm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
613613
rs = rs.Outer
614614
}
615615

616-
if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
616+
if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
617617
ld.Errorf(s, "missing section for %s", rs.Name)
618618
}
619619
r.Xsym = rs

src/cmd/link/internal/ld/data.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func trampoline(ctxt *Link, s *sym.Symbol) {
9696
if !r.Type.IsDirectJump() {
9797
continue
9898
}
99-
if Symaddr(r.Sym) == 0 && r.Sym.Type != sym.SDYNIMPORT {
99+
if Symaddr(r.Sym) == 0 && (r.Sym.Type != sym.SDYNIMPORT && r.Sym.Type != sym.SUNDEFEXT) {
100100
if r.Sym.File != s.File {
101101
if !isRuntimeDepPkg(s.File) || !isRuntimeDepPkg(r.Sym.File) {
102102
ctxt.ErrorUnresolved(s, r)
@@ -298,7 +298,7 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
298298
rs = rs.Outer
299299
}
300300

301-
if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
301+
if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
302302
Errorf(s, "missing section for relocation target %s", rs.Name)
303303
}
304304
r.Xsym = rs
@@ -418,6 +418,17 @@ func relocsym(ctxt *Link, s *sym.Symbol) {
418418
}
419419
fallthrough
420420
case objabi.R_CALL, objabi.R_PCREL:
421+
if ctxt.LinkMode == LinkExternal && r.Sym != nil && r.Sym.Type == sym.SUNDEFEXT {
422+
// pass through to the external linker.
423+
r.Done = false
424+
r.Xadd = 0
425+
if ctxt.IsELF {
426+
r.Xadd -= int64(r.Siz)
427+
}
428+
r.Xsym = r.Sym
429+
o = 0
430+
break
431+
}
421432
if ctxt.LinkMode == LinkExternal && r.Sym != nil && r.Sym.Type != sym.SCONST && (r.Sym.Sect != s.Sect || r.Type == objabi.R_GOTPCREL) {
422433
r.Done = false
423434

src/cmd/link/internal/ld/go.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,24 @@ func fieldtrack(ctxt *Link) {
334334
}
335335

336336
func (ctxt *Link) addexport() {
337+
// Track undefined external symbols during external link.
338+
if ctxt.LinkMode == LinkExternal {
339+
for _, s := range ctxt.Syms.Allsym {
340+
if !s.Attr.Reachable() || s.Attr.Special() || s.Attr.SubSymbol() {
341+
continue
342+
}
343+
if s.Type != sym.STEXT {
344+
continue
345+
}
346+
for i := range s.R {
347+
r := &s.R[i]
348+
if r.Sym != nil && r.Sym.Type == sym.Sxxx {
349+
r.Sym.Type = sym.SUNDEFEXT
350+
}
351+
}
352+
}
353+
}
354+
337355
// TODO(aix)
338356
if ctxt.HeadType == objabi.Hdarwin || ctxt.HeadType == objabi.Haix {
339357
return

src/cmd/link/internal/ld/lib.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,6 +2369,11 @@ func genasmsym(ctxt *Link, put func(*Link, *sym.Symbol, string, SymbolType, int6
23692369
}
23702370
put(ctxt, s, s.Name, BSSSym, Symaddr(s), s.Gotype)
23712371

2372+
case sym.SUNDEFEXT:
2373+
if ctxt.HeadType == objabi.Hwindows || ctxt.HeadType == objabi.Haix || ctxt.IsELF {
2374+
put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)
2375+
}
2376+
23722377
case sym.SHOSTOBJ:
23732378
if ctxt.HeadType == objabi.Hwindows || ctxt.IsELF {
23742379
put(ctxt, s, s.Name, UndefinedSym, s.Value, nil)

src/cmd/link/internal/ld/macho.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ func machogenasmsym(ctxt *Link) {
809809
}
810810
}
811811

812-
if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ {
812+
if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
813813
if s.Attr.Reachable() {
814814
addsym(ctxt, s, "", DataSym, 0, nil)
815815
}
@@ -886,7 +886,7 @@ func machosymtab(ctxt *Link) {
886886
// replace "·" as ".", because DTrace cannot handle it.
887887
Addstring(symstr, strings.Replace(s.Extname(), "·", ".", -1))
888888

889-
if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ {
889+
if s.Type == sym.SDYNIMPORT || s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT {
890890
symtab.AddUint8(0x01) // type N_EXT, external symbol
891891
symtab.AddUint8(0) // no section
892892
symtab.AddUint16(ctxt.Arch, 0) // desc

src/cmd/link/internal/ld/pe.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ func (f *peFile) writeSymbols(ctxt *Link) {
685685
// Only windows/386 requires underscore prefix on external symbols.
686686
if ctxt.Arch.Family == sys.I386 &&
687687
ctxt.LinkMode == LinkExternal &&
688-
(s.Type == sym.SHOSTOBJ || s.Attr.CgoExport()) {
688+
(s.Type == sym.SHOSTOBJ || s.Type == sym.SUNDEFEXT || s.Attr.CgoExport()) {
689689
s.Name = "_" + s.Name
690690
}
691691

src/cmd/link/internal/ld/symtab.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ func putelfsym(ctxt *Link, x *sym.Symbol, s string, t SymbolType, addr int64, go
110110
}
111111

112112
var elfshnum int
113-
if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ {
113+
if xo.Type == sym.SDYNIMPORT || xo.Type == sym.SHOSTOBJ || xo.Type == sym.SUNDEFEXT {
114114
elfshnum = SHN_UNDEF
115115
} else {
116116
if xo.Sect == nil {

src/cmd/link/internal/ld/xcoff.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64,
955955
syms = append(syms, a4)
956956

957957
case UndefinedSym:
958-
if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ {
958+
if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ && x.Type != sym.SUNDEFEXT {
959959
return
960960
}
961961
s := &XcoffSymEnt64{

src/cmd/link/internal/ppc64/asm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bo
801801
rs = rs.Outer
802802
}
803803

804-
if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Sect == nil {
804+
if rs.Type != sym.SHOSTOBJ && rs.Type != sym.SDYNIMPORT && rs.Type != sym.SUNDEFEXT && rs.Sect == nil {
805805
ld.Errorf(s, "missing section for %s", rs.Name)
806806
}
807807
r.Xsym = rs

src/cmd/link/internal/sym/symkind.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ const (
104104
SCONST
105105
SDYNIMPORT
106106
SHOSTOBJ
107+
SUNDEFEXT // Undefined symbol for resolution by external linker
107108

108109
// Sections for debugging information
109110
SDWARFSECT

src/cmd/link/internal/sym/symkind_string.go

Lines changed: 10 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)