/usr/share/go-1.8/src/runtime/plugin.go is in golang-1.8-src 1.8.3-2ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | // 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
import "unsafe"
//go:linkname plugin_lastmoduleinit plugin.lastmoduleinit
func plugin_lastmoduleinit() (path string, syms map[string]interface{}, mismatchpkg string) {
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")
}
for _, pmd := range activeModules() {
if pmd.pluginpath == md.pluginpath {
println("plugin: plugin", md.pluginpath, "already loaded")
throw("plugin: plugin already loaded")
}
if inRange(pmd.text, pmd.etext, md.text, md.etext) ||
inRange(pmd.bss, pmd.ebss, md.bss, md.ebss) ||
inRange(pmd.data, pmd.edata, md.data, md.edata) ||
inRange(pmd.types, pmd.etypes, md.types, md.etypes) {
println("plugin: new module data overlaps with previous moduledata")
println("\tpmd.text-etext=", hex(pmd.text), "-", hex(pmd.etext))
println("\tpmd.bss-ebss=", hex(pmd.bss), "-", hex(pmd.ebss))
println("\tpmd.data-edata=", hex(pmd.data), "-", hex(pmd.edata))
println("\tpmd.types-etypes=", hex(pmd.types), "-", hex(pmd.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 previous moduledata")
}
}
for _, pkghash := range md.pkghashes {
if pkghash.linktimehash != *pkghash.runtimehash {
return "", nil, pkghash.modulename
}
}
// Initialize the freshly loaded module.
modulesinit()
typelinksinit()
pluginftabverify(md)
moduledataverify1(md)
lock(&ifaceLock)
for _, i := range md.itablinks {
if i.inhash == 0 {
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 md.pluginpath, syms, ""
}
func pluginftabverify(md *moduledata) {
badtable := false
for i := 0; i < len(md.ftab); i++ {
entry := md.ftab[i].entry
if md.minpc <= entry && entry <= md.maxpc {
continue
}
f := (*_func)(unsafe.Pointer(&md.pclntable[md.ftab[i].funcoff]))
name := funcname(f)
// A common bug is f.entry has a relocation to a duplicate
// function symbol, meaning if we search for its PC we get
// a valid entry with a name that is useful for debugging.
name2 := "none"
entry2 := uintptr(0)
f2 := findfunc(entry)
if f2 != nil {
name2 = funcname(f2)
entry2 = f2.entry
}
badtable = true
println("ftab entry outside pc range: ", hex(entry), "/", hex(entry2), ": ", name, "/", name2)
}
if badtable {
throw("runtime: plugin has bad symbol table")
}
}
// 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)
}
// 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
}
|