1
0
mirror of https://github.com/golang/go synced 2024-11-22 19:34:59 -07:00

plugin: resolve plugin import path issue

Resolve import paths to get plugin symbol prefixes.

Fixes #19534

Change-Id: Ic25d83e72465ba8f6be0337218a1627b5dc702dc
Reviewed-on: https://go-review.googlesource.com/40994
Run-TryBot: Todd Neal <todd@tneal.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Todd Neal 2017-04-25 19:32:48 -04:00
parent 819d1cce6e
commit 7a92395ddd
4 changed files with 81 additions and 2 deletions

View File

@ -0,0 +1,23 @@
// 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 main() {
p, err := plugin.Open("plugin.so")
if err != nil {
panic(err)
}
sym, err := p.Lookup("Foo")
if err != nil {
panic(err)
}
f := sym.(func() int)
if f() != 42 {
panic("expected f() == 42")
}
}

View File

@ -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 Foo() int {
return 42
}

View File

@ -16,7 +16,7 @@ goarch=$(go env GOARCH)
function cleanup() {
rm -f plugin*.so unnamed*.so iface*.so
rm -rf host pkg sub iface issue18676
rm -rf host pkg sub iface issue18676 issue19534
}
trap cleanup EXIT
@ -44,3 +44,9 @@ LD_LIBRARY_PATH=$(pwd) ./iface
GOPATH=$(pwd) go build -buildmode=plugin -o plugin.so src/issue18676/plugin.go
GOPATH=$(pwd) go build -o issue18676 src/issue18676/main.go
timeout 10s ./issue18676
# Test for issue 19534 - that we can load a plugin built in a path with non-alpha
# characters
GOPATH=$(pwd) go build -buildmode=plugin -ldflags='-pluginpath=issue.19534' -o plugin.so src/issue19534/plugin.go
GOPATH=$(pwd) go build -o issue19534 src/issue19534/main.go
./issue19534

View File

@ -39,6 +39,47 @@ import (
"unsafe"
)
// avoid a dependency on strings
func lastIndexByte(s string, c byte) int {
for i := len(s) - 1; i >= 0; i-- {
if s[i] == c {
return i
}
}
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 := (*C.char)(C.malloc(C.PATH_MAX + 1))
defer C.free(unsafe.Pointer(cPath))
@ -103,7 +144,7 @@ func open(name string) (*Plugin, error) {
delete(syms, symName)
symName = symName[1:]
}
cname := C.CString(pluginpath + "." + symName)
cname := C.CString(pathToPrefix(pluginpath) + "." + symName)
p := C.pluginLookup(h, cname, &cErr)
C.free(unsafe.Pointer(cname))
if p == nil {