Skip to content

Commit

Permalink
cmd/link, runtime: put hasmain bit in moduledata
Browse files Browse the repository at this point in the history
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 golang#22175

Change-Id: If313a118f17ab499d0a760bbc2519771ed654530
Reviewed-on: https://go-review.googlesource.com/69370
Run-TryBot: David Crawshaw <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
  • Loading branch information
crawshaw committed Oct 13, 2017
1 parent d06815b commit c58b98b
Showing 6 changed files with 74 additions and 2 deletions.
28 changes: 28 additions & 0 deletions misc/cgo/testplugin/src/issue22175/main.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
21 changes: 21 additions & 0 deletions misc/cgo/testplugin/src/issue22175/plugin1.go
Original file line number Diff line number Diff line change
@@ -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() {}
9 changes: 9 additions & 0 deletions misc/cgo/testplugin/src/issue22175/plugin2.go
Original file line number Diff line number Diff line change
@@ -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() {}
6 changes: 6 additions & 0 deletions misc/cgo/testplugin/test.bash
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions src/cmd/link/internal/ld/symtab.go
Original file line number Diff line number Diff line change
@@ -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
5 changes: 3 additions & 2 deletions src/runtime/symtab.go
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit c58b98b

Please sign in to comment.