diff --git a/misc/cgo/testplugin/src/issue22175/main.go b/misc/cgo/testplugin/src/issue22175/main.go new file mode 100644 index 0000000000..9be9bab9dc --- /dev/null +++ b/misc/cgo/testplugin/src/issue22175/main.go @@ -0,0 +1,28 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "os" + "plugin" +) + +func main() { + p2, err := plugin.Open("issue22175_plugin1.so") + if err != nil { + panic(err) + } + f, err := p2.Lookup("F") + if err != nil { + panic(err) + } + got := f.(func() int)() + const want = 971 + if got != want { + fmt.Fprintf(os.Stderr, "issue22175: F()=%d, want %d", got, want) + os.Exit(1) + } +} diff --git a/misc/cgo/testplugin/src/issue22175/plugin1.go b/misc/cgo/testplugin/src/issue22175/plugin1.go new file mode 100644 index 0000000000..5ae6cb631e --- /dev/null +++ b/misc/cgo/testplugin/src/issue22175/plugin1.go @@ -0,0 +1,21 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "plugin" + +func F() int { + p2, err := plugin.Open("issue22175_plugin2.so") + if err != nil { + panic(err) + } + g, err := p2.Lookup("G") + if err != nil { + panic(err) + } + return g.(func() int)() +} + +func main() {} diff --git a/misc/cgo/testplugin/src/issue22175/plugin2.go b/misc/cgo/testplugin/src/issue22175/plugin2.go new file mode 100644 index 0000000000..f387a192e6 --- /dev/null +++ b/misc/cgo/testplugin/src/issue22175/plugin2.go @@ -0,0 +1,9 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func G() int { return 971 } + +func main() {} diff --git a/misc/cgo/testplugin/test.bash b/misc/cgo/testplugin/test.bash index 6c13aa5fd7..dbc28b19aa 100755 --- a/misc/cgo/testplugin/test.bash +++ b/misc/cgo/testplugin/test.bash @@ -74,3 +74,9 @@ GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue19418 src/issue19418/main. # Test for issue 19529 GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o plugin.so src/issue19529/plugin.go + +# Test for issue 22175 +GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue22175_plugin1.so src/issue22175/plugin1.go +GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue22175_plugin2.so src/issue22175/plugin2.go +GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue22175 src/issue22175/main.go +./issue22175 diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 0a819fcd23..c77298e870 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -641,6 +641,13 @@ func (ctxt *Link) symtab() { moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) } + hasmain := ctxt.BuildMode == BuildModeExe || ctxt.BuildMode == BuildModePIE + if hasmain { + moduledata.AddUint8(1) + } else { + moduledata.AddUint8(0) + } + // The rest of moduledata is zero initialized. // When linking an object that does not contain the runtime we are // creating the moduledata from scratch and it does not have a diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 542c29ecd6..2f426c7bf1 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -375,6 +375,8 @@ type moduledata struct { modulename string modulehashes []modulehash + hasmain uint8 // 1 if module contains the main function, 0 otherwise + gcdatamask, gcbssmask bitvector typemap map[typeOff]*_type // offset to *_rtype in previous module @@ -472,9 +474,8 @@ func modulesinit() { // contains the main function. // // See Issue #18729. - mainText := funcPC(main_main) for i, md := range *modules { - if md.text <= mainText && mainText <= md.etext { + if md.hasmain != 0 { (*modules)[0] = md (*modules)[i] = &firstmoduledata break