2016-08-25 19:58:45 -06:00
|
|
|
// Copyright 2016 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package runtime
|
|
|
|
|
2016-08-26 06:50:50 -06:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
2016-09-19 12:08:21 -06:00
|
|
|
if fmd := &firstmoduledata; inRange(fmd.text, fmd.etext, md.text, md.etext) ||
|
|
|
|
inRange(fmd.bss, fmd.ebss, md.bss, md.ebss) ||
|
|
|
|
inRange(fmd.data, fmd.edata, md.data, md.edata) ||
|
|
|
|
inRange(fmd.types, fmd.etypes, md.types, md.etypes) {
|
|
|
|
println("plugin: new module data overlaps with firstmoduledata")
|
|
|
|
println("\tfirstmoduledata.text-etext=", hex(fmd.text), "-", hex(fmd.etext))
|
|
|
|
println("\tfirstmoduledata.bss-ebss=", hex(fmd.bss), "-", hex(fmd.ebss))
|
|
|
|
println("\tfirstmoduledata.data-edata=", hex(fmd.data), "-", hex(fmd.edata))
|
|
|
|
println("\tfirstmoduledata.types-etypes=", hex(fmd.types), "-", hex(fmd.etypes))
|
|
|
|
println("\tmd.text-etext=", hex(md.text), "-", hex(md.etext))
|
|
|
|
println("\tmd.bss-ebss=", hex(md.bss), "-", hex(md.ebss))
|
|
|
|
println("\tmd.data-edata=", hex(md.data), "-", hex(md.edata))
|
|
|
|
println("\tmd.types-etypes=", hex(md.types), "-", hex(md.etypes))
|
|
|
|
throw("plugin: new module data overlaps with firstmoduledata")
|
|
|
|
}
|
|
|
|
|
2016-08-26 06:50:50 -06:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2016-09-19 12:08:21 -06:00
|
|
|
// inRange reports whether v0 or v1 are in the range [r0, r1].
|
|
|
|
func inRange(r0, r1, v0, v1 uintptr) bool {
|
|
|
|
return (v0 >= r0 && v0 <= r1) || (v1 >= r0 && v1 <= r1)
|
|
|
|
}
|
|
|
|
|
2016-08-25 19:58:45 -06:00
|
|
|
// 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.
|
|
|
|
type ptabEntry struct {
|
|
|
|
name nameOff
|
|
|
|
typ typeOff
|
|
|
|
}
|