aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/plugin.go
diff options
context:
space:
mode:
authorDavid Crawshaw <crawshaw@golang.org>2016-08-26 08:50:50 -0400
committerDavid Crawshaw <crawshaw@golang.org>2016-09-16 17:54:40 +0000
commit0cbb12f0bbaeb3893b3d011fdb1a270291747ab0 (patch)
tree27aad9e8d195e1bc06a2f93b14cdec6839474d62 /src/runtime/plugin.go
parentc87528d7761e3f133fe238937019a18bf7cf0d3c (diff)
downloadgo-0cbb12f0bbaeb3893b3d011fdb1a270291747ab0.tar.xz
plugin: new package for loading plugins
Includes a linux implementation. Change-Id: Iacc2ed7da760ae9deebc928adf2b334b043b07ec Reviewed-on: https://go-review.googlesource.com/27823 Run-TryBot: David Crawshaw <crawshaw@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime/plugin.go')
-rw-r--r--src/runtime/plugin.go51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/runtime/plugin.go b/src/runtime/plugin.go
index f5f3aa2e5b..2e01650824 100644
--- a/src/runtime/plugin.go
+++ b/src/runtime/plugin.go
@@ -4,6 +4,57 @@
package runtime
+import "unsafe"
+
+//go:linkname plugin_lastmoduleinit plugin.lastmoduleinit
+func plugin_lastmoduleinit() map[string]interface{} {
+ md := firstmoduledata.next
+ if md == nil {
+ throw("runtime: no plugin module data")
+ }
+ for md.next != nil {
+ md = md.next
+ }
+ if md.typemap != nil {
+ throw("runtime: plugin already initialized")
+ }
+
+ // Initialize the freshly loaded module.
+ typelinksinit()
+ md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), md.edata-md.data)
+ md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), md.ebss-md.bss)
+
+ lock(&ifaceLock)
+ for _, i := range md.itablinks {
+ additab(i, true, false)
+ }
+ unlock(&ifaceLock)
+
+ // Build a map of symbol names to symbols. Here in the runtime
+ // we fill out the first word of the interface, the type. We
+ // pass these zero value interfaces to the plugin package,
+ // where the symbol value is filled in (usually via cgo).
+ //
+ // Because functions are handled specially in the plugin package,
+ // function symbol names are prefixed here with '.' to avoid
+ // a dependency on the reflect package.
+ syms := make(map[string]interface{}, len(md.ptab))
+ for _, ptab := range md.ptab {
+ symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name)
+ t := (*_type)(unsafe.Pointer(md.types)).typeOff(ptab.typ)
+ var val interface{}
+ valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val))
+ (*valp)[0] = unsafe.Pointer(t)
+
+ name := symName.name()
+ if t.kind&kindMask == kindFunc {
+ name = "." + name
+ }
+ syms[name] = val
+ }
+ return syms
+}
+
// A ptabEntry is generated by the compiler for each exported function
// and global variable in the main package of a plugin. It is used to
// initialize the plugin module's symbol map.