summaryrefslogtreecommitdiff
path: root/libgo/go/plugin/plugin_dlopen.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/plugin/plugin_dlopen.go')
-rw-r--r--libgo/go/plugin/plugin_dlopen.go52
1 files changed, 48 insertions, 4 deletions
diff --git a/libgo/go/plugin/plugin_dlopen.go b/libgo/go/plugin/plugin_dlopen.go
index c5b0a4721c5..3237598f06b 100644
--- a/libgo/go/plugin/plugin_dlopen.go
+++ b/libgo/go/plugin/plugin_dlopen.go
@@ -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))
@@ -82,7 +123,6 @@ func open(name string) (*Plugin, error) {
p := &Plugin{
pluginpath: pluginpath,
loaded: make(chan struct{}),
- syms: syms,
}
plugins[filepath] = p
pluginsMu.Unlock()
@@ -97,14 +137,14 @@ func open(name string) (*Plugin, error) {
}
// Fill out the value of each plugin symbol.
+ updatedSyms := map[string]interface{}{}
for symName, sym := range syms {
isFunc := symName[0] == '.'
if isFunc {
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 {
@@ -116,8 +156,12 @@ func open(name string) (*Plugin, error) {
} else {
(*valp)[1] = p
}
- syms[symName] = sym
+ // we can't add to syms during iteration as we'll end up processing
+ // some symbols twice with the inability to tell if the symbol is a function
+ updatedSyms[symName] = sym
}
+ p.syms = updatedSyms
+
close(p.loaded)
return p, nil
}