-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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: convert iface to type failed with "types from different scopes" #48532
Comments
Change https://golang.org/cl/351850 mentions this issue: |
Here's an even trickier case:
This panics in the plugin. The Note that if you move the This issue is about itabs, but the same underlying problem occurs - dynamically created types (created explicitly with reflect) or itabs (often created implicitly in type conversions) won't match with statically declared types or itabs in a plugin. I think plugins are going to have to indirect all of their types and itabs, and resolve all of them at plugin load time, deduplicating with their dynamically created doppelgangers. |
This case can reproduce,too. pluginassert/main.go:
The itab created by assertI2I , assertE2I in main process has the same problem. |
genssa # /plugin.go 00000 (3) TEXT "".F(SB), ABIInternal 00001 (3) FUNCDATA $0, gclocals·09cf9819fc716118c209c2d2155a3632(SB) 00002 (3) FUNCDATA $1, gclocals·69c1753bd5f81501d95132d08af04464(SB) 00003 (3) FUNCDATA $5, "".F.arginfo1(SB) 00004 (+4) LEAQ type.[37]int(SB), BX 00005 (4) CMPQ AX, BX 00006 (4) JNE 8 00007 (5) RET 00008 (4) LEAQ type.interface {}(SB), CX 00009 (4) PCDATA $1, $1 00010 (4) CALL runtime.panicdottypeE(SB) 00011 (4) XCHGL AX, AX 00012 (?) END In this case, it compare the type field of eface and address of type.[37]int. This behavior is same with itab. |
Yes, I think for plugins we'll need to have an array of |
I'm working on it. I will try to implement it. |
I sent a CL for itabs, can you review the CL when you're free? |
a.go: package min
type InterA interface {
Method1()
}
type ImplB struct{}
func (b *ImplB) Method1() {
println("Method1 in B")
}
func TestFunc(a InterA) {
b := a.(*ImplB)
b.Method1()
} Before my CL(go 1.17): $ go tool compile -S a.go ……………… "".TestFunc STEXT size=134 args=0x10 locals=0x20 funcid=0x0 ……………… 0x001e 00030 (a.go:14) LEAQ go.itab.*"".ImplB,"".InterA(SB), DX 0x0025 00037 (a.go:14) CMPQ AX, DX ……………… After my CL: $ go tool compile -S a.go ……………… "".TestFunc STEXT size=134 args=0x10 locals=0x20 funcid=0x0 ……………… 0x0020 00032 (a.go:14) CMPQ go.itabaddr.*"".ImplB,"".InterA(SB), AX ……………… go.itabaddr.*"".ImplB,"".InterA SNOPTRDATA dupok size=8 0x0000 00 00 00 00 00 00 00 00 ........ rel 0+8 t=1 go.itab.*"".ImplB,"".InterA+0 And in linker, runtime.itablilnk will be container symbol for all the symbols prefix with "go.itabaddr". |
If we had our own dynamic linker... |
Plugins already load the address of a type descriptor from the GOT entry. Can we modify the GOT entry? (I know this sounds crazy...) |
Change https://golang.org/cl/362635 mentions this issue: |
Change https://golang.org/cl/362935 mentions this issue: |
Change https://golang.org/cl/362936 mentions this issue: |
Change https://golang.org/cl/362937 mentions this issue: |
@cherrymui @randall77 |
I'm not sure that is the best way to resolve this. I'm still thinking if there is a better way (like, modifying the GOT?). And it is probably too late for 1.18. |
Emm.. Maybe modifying the GOT is not a normal way. |
I'm not sure modifying GOT is the best way, either. Maybe there is a simpler approach. We can still think about it. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
pluginassert/go.mod:
pluginassert/inter/iface.go:
pluginassert/main.go:
pluginassert/plugin.go:
~/pluginassert $ go build -buildmode=plugin
~/pluginassert $ go build
~/pluginassert $ ./pluginassert
What did you expect to see?
What did you see instead?
There is no symbol
go.itab.*pluginassert/inter.B,pluginassert/inter.A
in main binary. So it will invoke persistentalloc in function getitab in first switch-case to allocate an itab.But unfortunately, after plugin is loaded, the itab
go.itab.*pluginassert/inter.B,pluginassert/inter.A
was added to itabTable. When the TestFunc was invoked in second switch-case, x is a iface with itab which was allocated in first switch-case.In plugin, the implement of
a.(*inter.B)
is to compare the address of a.tab andgo.itab.*pluginassert/inter.B,pluginassert/inter.A
. Certainly they are different. So we get this panic.The text was updated successfully, but these errors were encountered: