Skip to content

Commit

Permalink
cmd/link, plugin: always encode path
Browse files Browse the repository at this point in the history
Both the linker and the plugin package were inconsistent
about when they applied the path encoding defined in
objabi.PathToPrefix. As a result, only some symbols from
a package path that required encoding were being found.

So always encoding the path.

Fixes #22295

Change-Id: Ife86c79ca20b2e9307008ed83885e193d32b7dc4
Reviewed-on: https://go-review.googlesource.com/72390
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
crawshaw committed Oct 26, 2017
1 parent 78ea9a7 commit 6355d6c
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 35 deletions.
28 changes: 28 additions & 0 deletions misc/cgo/testplugin/src/issue22295.pkg/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.

// +build ignore

package main

import (
"log"
"plugin"
)

func main() {
p, err := plugin.Open("issue.22295.so")
if err != nil {
log.Fatal(err)
}
f, err := p.Lookup("F")
if err != nil {
log.Fatal(err)
}
const want = 2503
got := f.(func() int)()
if got != want {
log.Fatalf("got %d, want %d", got, want)
}
}
16 changes: 16 additions & 0 deletions misc/cgo/testplugin/src/issue22295.pkg/plugin.go
@@ -0,0 +1,16 @@
// 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

var f *int

func init() {
f = new(int)
*f = 2503
}

func F() int { return *f }

func main() {}
5 changes: 5 additions & 0 deletions misc/cgo/testplugin/test.bash
Expand Up @@ -80,3 +80,8 @@ GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue22175_pl
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

# Test for issue 22295
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -buildmode=plugin -o issue.22295.so issue22295.pkg
GOPATH=$(pwd) go build -gcflags "$GO_GCFLAGS" -o issue22295 src/issue22295.pkg/main.go
./issue22295
3 changes: 2 additions & 1 deletion src/cmd/link/internal/ld/data.go
Expand Up @@ -782,10 +782,11 @@ func addstrdata1(ctxt *Link, arg string) {
if eq < 0 || dot < 0 {
Exitf("-X flag requires argument of the form importpath.name=value")
}
pkg := objabi.PathToPrefix(arg[:dot])
pkg := arg[:dot]
if ctxt.BuildMode == BuildModePlugin && pkg == "main" {
pkg = *flagPluginPath
}
pkg = objabi.PathToPrefix(pkg)
addstrdata(ctxt, pkg+arg[dot:eq], arg[eq+1:])
}

Expand Down
2 changes: 1 addition & 1 deletion src/cmd/link/internal/ld/deadcode.go
Expand Up @@ -230,7 +230,7 @@ func (d *deadcodepass) init() {
}
names = append(names, *flagEntrySymbol)
if d.ctxt.BuildMode == BuildModePlugin {
names = append(names, *flagPluginPath+".init", *flagPluginPath+".main", "go.plugin.tabs")
names = append(names, objabi.PathToPrefix(*flagPluginPath)+".init", objabi.PathToPrefix(*flagPluginPath)+".main", "go.plugin.tabs")

// We don't keep the go.plugin.exports symbol,
// but we do keep the symbols it refers to.
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/link/internal/ld/symtab.go
Expand Up @@ -586,7 +586,7 @@ func (ctxt *Link) symtab() {
moduledata.AddUint(ctxt.Arch, 0)
}
if ctxt.BuildMode == BuildModePlugin {
addgostring(ctxt, moduledata, "go.link.thispluginpath", *flagPluginPath)
addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))

pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0)
pkghashes.Attr |= sym.AttrReachable
Expand Down
33 changes: 1 addition & 32 deletions src/plugin/plugin_dlopen.go
Expand Up @@ -49,37 +49,6 @@ func lastIndexByte(s string, c byte) int {
return -1
}

// pathToPrefix converts raw string to the prefix that will be used in the symbol
// table. If modifying, modify the version in internal/obj/sym.go as well.
func pathToPrefix(s string) string {
slash := lastIndexByte(s, '/')
// check for chars that need escaping
n := 0
for r := 0; r < len(s); r++ {
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
n++
}
}

// quick exit
if n == 0 {
return s
}

// escape
const hex = "0123456789abcdef"
p := make([]byte, 0, len(s)+2*n)
for r := 0; r < len(s); r++ {
if c := s[r]; c <= ' ' || (c == '.' && r > slash) || c == '%' || c == '"' || c >= 0x7F {
p = append(p, '%', hex[c>>4], hex[c&0xF])
} else {
p = append(p, c)
}
}

return string(p)
}

func open(name string) (*Plugin, error) {
cPath := make([]byte, C.PATH_MAX+1)
cRelName := make([]byte, len(name)+1)
Expand Down Expand Up @@ -153,7 +122,7 @@ func open(name string) (*Plugin, error) {
symName = symName[1:]
}

fullName := pathToPrefix(pluginpath) + "." + symName
fullName := pluginpath + "." + symName
cname := make([]byte, len(fullName)+1)
copy(cname, fullName)

Expand Down

0 comments on commit 6355d6c

Please sign in to comment.