Commit c58b98b2 authored by David Crawshaw's avatar David Crawshaw

cmd/link, runtime: put hasmain bit in moduledata

Currently we look to see if the main.main symbol address is in the
module data text range. This requires access to the main.main
symbol, which usually the runtime has, but does not when building
a plugin.

To avoid a dynamic relocation to main.main (which I haven't worked
out how to have the linker generate on darwin), stop using the
symbol. Instead record a boolean in the moduledata if the module
has the main function.

Fixes #22175

Change-Id: If313a118f17ab499d0a760bbc2519771ed654530
Reviewed-on: https://go-review.googlesource.com/69370
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent d06815ba
// 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)
}
}
// 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() {}
// 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() {}
...@@ -74,3 +74,9 @@ GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue19418 src/issue19418/main. ...@@ -74,3 +74,9 @@ GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue19418 src/issue19418/main.
# Test for issue 19529 # Test for issue 19529
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o plugin.so src/issue19529/plugin.go 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
...@@ -641,6 +641,13 @@ func (ctxt *Link) symtab() { ...@@ -641,6 +641,13 @@ func (ctxt *Link) symtab() {
moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) 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. // The rest of moduledata is zero initialized.
// When linking an object that does not contain the runtime we are // When linking an object that does not contain the runtime we are
// creating the moduledata from scratch and it does not have a // creating the moduledata from scratch and it does not have a
......
...@@ -375,6 +375,8 @@ type moduledata struct { ...@@ -375,6 +375,8 @@ type moduledata struct {
modulename string modulename string
modulehashes []modulehash modulehashes []modulehash
hasmain uint8 // 1 if module contains the main function, 0 otherwise
gcdatamask, gcbssmask bitvector gcdatamask, gcbssmask bitvector
typemap map[typeOff]*_type // offset to *_rtype in previous module typemap map[typeOff]*_type // offset to *_rtype in previous module
...@@ -472,9 +474,8 @@ func modulesinit() { ...@@ -472,9 +474,8 @@ func modulesinit() {
// contains the main function. // contains the main function.
// //
// See Issue #18729. // See Issue #18729.
mainText := funcPC(main_main)
for i, md := range *modules { for i, md := range *modules {
if md.text <= mainText && mainText <= md.etext { if md.hasmain != 0 {
(*modules)[0] = md (*modules)[0] = md
(*modules)[i] = &firstmoduledata (*modules)[i] = &firstmoduledata
break break
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment