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

Plugins can't use different C libraries by CGO with the same symbol names #42854

Closed
dsxack opened this issue Nov 27, 2020 · 4 comments
Closed

Comments

@dsxack
Copy link

dsxack commented Nov 27, 2020

What version of Go are you using (go version)?

$ go version
go version go1.15.5 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
go version go1.15.5 linux/amd64
root@2ce5210666df:/go# go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build189801058=/tmp/go-build -gno-record-gcc-switches"

What did you do?

hello1.c:

I have a hello1/lib/hello1.c library and built it into hello1/lib/libhello1.a

#include <stdio.h>

void hello() {
    printf("Hello from C hello1.c\n");
}

hello2.c:

I have a hello2/lib/hello2.c library with the same function name hello that in hello1.c and built it into hello2/lib/libhello2.a

#include <stdio.h>

void hello() {
    printf("Hello from C hello2.c\n");
}

hello1.go:

I have a hello1/hello1.go and built it into hello1/hello1.so with go build -buildmode=plugin

package main

/*
#cgo LDFLAGS: -L${SRCDIR}/lib -lhello1

void hello();
*/
import "C"
import "fmt"

func Hello() {
	fmt.Println("Hello from Go plugin hello1.go")
	fmt.Println("Call C hello1.c")
	C.hello()
}

hello2.go:

I have a hello2/hello2.go and built it into hello2/hello2.so with go build -buildmode=plugin

package main

/*
#cgo LDFLAGS: -L${SRCDIR}/lib -lhello2

void hello();
*/
import "C"
import "fmt"

func Hello() {
	fmt.Println("Hello from Go plugin hello2.go")
	fmt.Println("Call C hello2.c")
	C.hello()
}

main.go:

I have a main.go in the root project dir and built it into main with go build.

package main

import (
	"fmt"
	"plugin"
)

func main() {
	p1, err := plugin.Open("hello1/hello1.so")
	if err != nil {
		panic(err)
	}
	fmt.Println("Load Go plugin hello1.so")

	p2, err := plugin.Open("hello2/hello2.so")
	if err != nil {
		panic(err)
	}
	fmt.Println("Load Go plugin hello2.so")

	h1, err := p1.Lookup("Hello")
	if err != nil {
		panic(err)
	}

	h2, err := p2.Lookup("Hello")
	if err != nil {
		panic(err)
	}

	fmt.Println("Call Go plugin hello1.go")
	h1.(func())()
	fmt.Println("\nCall Go plugin hello2.go")
	h2.(func())()
}

What did you expect to see?

Load Go plugin hello1.so
Load Go plugin hello2.so

Call Go plugin hello1.go
Hello from Go plugin hello1.go
Call C hello1.c
Hello from C hello1.c

Call Go plugin hello2.go
Hello from Go plugin hello2.go
Call C hello2.c
Hello from C hello2.c

What did you see instead?

I see Hello from C hello1.c at the last line but I expected Hello from C hello2.c

Load Go plugin hello1.so
Load Go plugin hello2.so

Call Go plugin hello1.go
Hello from Go plugin hello1.go
Call C hello1.c
Hello from C hello1.c

Call Go plugin hello2.go
Hello from Go plugin hello2.go
Call C hello2.c
Hello from C hello1.c
@dsxack dsxack changed the title Plugins can't use different CGO libraries with the same symbol names Plugins can't use different C libraries by CGO with the same symbol names Nov 27, 2020
@AlexRouSg
Copy link
Contributor

AlexRouSg commented Nov 27, 2020

If you only load hello2.so does it print what you expect?
Have you tried using __attribute__ ((visibility ("hidden"))) on the C functions with the same name?

@dsxack
Copy link
Author

dsxack commented Nov 27, 2020

@AlexRouSg yes, if I load hello2.so only it prints what I expect:

Load Go plugin hello2.so

Call Go plugin hello2.go
Hello from Go plugin hello2.go
Call C hello2.c
Hello from C hello2.c

Also I can't impact to C libraries code because it is vendor libraries.

@AlexRouSg
Copy link
Contributor

What happens when you use the -fvisibility=hidden gcc flag?

@dsxack
Copy link
Author

dsxack commented Nov 27, 2020

@AlexRouSg yes, it works! Thank you!

Add -fvisibility=hidden gcc flag when to C libraries compile resolves my issue.

Load Go plugin hello1.so
Load Go plugin hello2.so

Call Go plugin hello1.go
Hello from Go plugin hello1.go
Call C hello1.c
Hello from C hello1.c

Call Go plugin hello2.go
Hello from Go plugin hello2.go
Call С hello2.c
Hello from C hello2.c

@dsxack dsxack closed this as completed Nov 27, 2020
@golang golang locked and limited conversation to collaborators Nov 27, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants