Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin: can not lookup exported function #17141

Closed
nussjustin opened this issue Sep 17, 2016 · 8 comments
Closed

plugin: can not lookup exported function #17141

nussjustin opened this issue Sep 17, 2016 · 8 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@nussjustin
Copy link
Contributor

Please answer these questions before submitting your issue. Thanks!

What did you do?

Build a plugin and tried to lookup a function.

plugin.go:

package main

// // Nothing to do
import "C"

func Init() {
}

func main() {

}

main.go:

package main

import (
    "log"
    "plugin"
)

func main() {
    p, err := plugin.Open("plugin.so")

    if err != nil {
        log.Fatal(err)
    }

    _, err = p.Lookup("Init")

    if err != nil {
        log.Fatal(err)
    }
}

Commands:

  • go build -buildmode=plugin plugin.go
  • go run main.go

What did you expect to see?

No errors.

What did you see instead?

2016/09/17 12:07:57 plugin.Open: could not find symbol Init: /home/justinn/Workspace/go/src/github.com/nuss-justin/plugintest/plugin/plugin2.so: undefined symbol: plugin2.Init

Trying the example code from the plugin.Symbol documentation I get a similiar error:

panic: plugin.Open: could not find symbol F: /home/justinn/Workspace/go/src/github.com/nuss-justin/plugintest/plugin_name.so: undefined symbol: plugin_name.F

System details

go version devel +2e2db7a Sat Sep 17 02:54:11 2016 +0000 linux/amd64
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/justinn/Workspace/go"
GORACE=""
GOROOT="/opt/go"
GOTOOLDIR="/opt/go/pkg/tool/linux_amd64"
TERM="dumb"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build787786251=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
uname -sr: Linux 4.7.2-1-ARCH
/usr/lib/libc.so.6: GNU C Library (GNU libc) stable release version 2.24, by Roland McGrath et al.
gdb --version: GNU gdb (GDB) 7.11.1
@reusee
Copy link

reusee commented Sep 17, 2016

same here

What did you do?

plugin.go

package main

import "C"

import "fmt"

func H() {
    fmt.Printf("hello, world!")
}

main.go

package main

import (
    "plugin"
)

func main() {
    p, err := plugin.Open("plugin.so")
    if err != nil {
        panic(err)
    }

    hello, err := p.Lookup("H")
    if err != nil {
        panic(err)
    }

    hello.(func())()
}

What did you expect to see?

prints 'hello, world'

What did you see instead?

go build -buildmode=plugin plugin.go 

go run main.go
panic: plugin.Open: could not find symbol H: /home/reus/plugin/plugin.so: undefined symbol: plugin.H

goroutine 1 [running]:
panic(0x499ac0, 0xc42000c110)
    /home/reus/go/src/runtime/panic.go:496 +0x1a0
main.main()
    /home/reus/plugin/main.go:10 +0x207
exit status 2

Does this issue reproduce with the latest release (go1.7.1)?

tip

System details

go version devel +2e2db7a Sat Sep 17 02:54:11 2016 +0000 linux/amd64
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/reus"
GORACE=""
GOROOT="/home/reus/go"
GOTOOLDIR="/home/reus/go/pkg/tool/linux_amd64"
TERM="dumb"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build888965219=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
uname -sr: Linux 4.6.4-1-ARCH
/usr/lib/libc.so.6: GNU C Library (GNU libc) stable release version 2.24, by Roland McGrath et al.
gdb --version: GNU gdb (GDB) 7.11.1

@crawshaw crawshaw self-assigned this Sep 17, 2016
@crawshaw
Copy link
Member

(I was not expecting bug reports this quickly. I'll take a look on Monday.)

@crawshaw crawshaw added this to the Go1.8 milestone Sep 17, 2016
@minux
Copy link
Member

minux commented Sep 18, 2016 via email

@Merovius
Copy link
Contributor

There is also an issue (for me), if I use a path when opening the plugin: http://sprunge.us/STRM
It works fine if I Load("a.so"), instead of Load("./a.so"). The same happens, when I use an absolute path, instead of ./.

@Merovius
Copy link
Contributor

(btw: It's pretty awesome that this actually happened :) )

@patricksuo
Copy link

Awesome feature!

Quick workaround:

diff --git a/src/plugin/plugin_dlopen.go b/src/plugin/plugin_dlopen.go
index 45c0eeb..db667f9 100644
--- a/src/plugin/plugin_dlopen.go
+++ b/src/plugin/plugin_dlopen.go
@@ -33,6 +33,7 @@ import "C"

 import (
        "errors"
+       libpath "path"
        "sync"
        "unsafe"
 )
@@ -58,6 +59,7 @@ func open(name string) (*Plugin, error) {
        // TODO(crawshaw): look for plugin note, confirm it is a Go plugin
        // and it was built with the correct toolchain.
        // TODO(crawshaw): get full plugin name from note.
+       name = libpath.Base(name)
        if len(name) > 3 && name[len(name)-3:] == ".so" {
                name = name[:len(name)-3]
        }

@quentinmit quentinmit added the NeedsFix The path to resolution is known, but the work has not been done. label Oct 10, 2016
@rogpeppe
Copy link
Contributor

I didn't find that the workaround above worked for me.
What did work for me was putting the dynamically loaded
code into a package inside $GOPATH rather than explicitly
passing a Go source file to go build.

For me, the unexpected thing here is that the file name of the dynamically loaded module is important.
For example, if I put my dynamic module into package "foo", then build it, creating
"foo.so", and load it with plugin.Load("foo.so"), it works. However if I rename
"foo.so" to "bar.so", the load no longer works.

The plugin documentation seems to indicate that the path name is not important,
but it is. In fact, it doesn't seem to be possible to load two dynamically loaded
modules that have the same package name. When I tried it with two
packages (with different package paths) but the same name, I got this panic:

runtime: impossible type kind 0
fatal error: runtime: impossible type kind

goroutine 1 [running]:
runtime.throw(0x54ab9e, 0x1d)
    /home/rog/go/src/runtime/panic.go:587 +0x95 fp=0xc420051710 sp=0xc4200516f0
runtime.typesEqual(0x7f2fd74ac1c0, 0x7f2fd77af1e0, 0x7f2fd77af1e0)
    /home/rog/go/src/runtime/type.go:651 +0x91d fp=0xc420051828 sp=0xc420051710
runtime.typesEqual(0x7f2fd74ae280, 0x7f2fd77b1280, 0xc40e105ecb)
    /home/rog/go/src/runtime/type.go:606 +0x734 fp=0xc420051940 sp=0xc420051828
runtime.typelinksinit()
    /home/rog/go/src/runtime/type.go:504 +0x3bd fp=0xc420051b30 sp=0xc420051940
plugin.lastmoduleinit(0x54c8fb)
    /home/rog/go/src/runtime/plugin.go:39 +0x16a fp=0xc420051bf0 sp=0xc420051b30
plugin.open(0x54c91e, 0x3, 0x0, 0x0, 0x0)
    /home/rog/go/src/plugin/plugin_dlopen.go:76 +0x3b8 fp=0xc420051e28 sp=0xc420051bf0
plugin.Open(0x54c8fb, 0x29, 0xc420051ee8, 0x1, 0x1)
    /home/rog/go/src/plugin/plugin.go:28 +0x35 fp=0xc420051e60 sp=0xc420051e28
main.test(0x54c8fb, 0x29)
    /home/rog/src/tstplugin.go:13 +0x4d fp=0xc420051f28 sp=0xc420051e60
main.main()
    /home/rog/src/tstplugin.go:9 +0x4f fp=0xc420051f48 sp=0xc420051f28
runtime.main()
    /home/rog/go/src/runtime/proc.go:185 +0x20a fp=0xc420051fa0 sp=0xc420051f48
runtime.goexit()
    /home/rog/go/src/runtime/asm_amd64.s:2158 +0x1 fp=0xc420051fa8 sp=0xc420051fa0

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
    /home/rog/go/src/runtime/asm_amd64.s:2158 +0x1

@crawshaw
Copy link
Member

crawshaw commented Nov 3, 2016

I believe this was fixed by 9da7058.

@crawshaw crawshaw closed this as completed Nov 3, 2016
@golang golang locked and limited conversation to collaborators Nov 3, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

9 participants