github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/runtime/plugin.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime
     6  
     7  import "unsafe"
     8  
     9  //go:linkname plugin_lastmoduleinit plugin.lastmoduleinit
    10  func plugin_lastmoduleinit() (path string, syms map[string]interface{}) {
    11  	md := firstmoduledata.next
    12  	if md == nil {
    13  		throw("runtime: no plugin module data")
    14  	}
    15  	for md.next != nil {
    16  		md = md.next
    17  	}
    18  	if md.typemap != nil {
    19  		throw("runtime: plugin already initialized")
    20  	}
    21  
    22  	for _, pmd := range activeModules() {
    23  		if pmd.pluginpath == md.pluginpath {
    24  			println("plugin: plugin", md.pluginpath, "already loaded")
    25  			throw("plugin: plugin already loaded")
    26  		}
    27  
    28  		if inRange(pmd.text, pmd.etext, md.text, md.etext) ||
    29  			inRange(pmd.bss, pmd.ebss, md.bss, md.ebss) ||
    30  			inRange(pmd.data, pmd.edata, md.data, md.edata) ||
    31  			inRange(pmd.types, pmd.etypes, md.types, md.etypes) {
    32  			println("plugin: new module data overlaps with previous moduledata")
    33  			println("\tpmd.text-etext=", hex(pmd.text), "-", hex(pmd.etext))
    34  			println("\tpmd.bss-ebss=", hex(pmd.bss), "-", hex(pmd.ebss))
    35  			println("\tpmd.data-edata=", hex(pmd.data), "-", hex(pmd.edata))
    36  			println("\tpmd.types-etypes=", hex(pmd.types), "-", hex(pmd.etypes))
    37  			println("\tmd.text-etext=", hex(md.text), "-", hex(md.etext))
    38  			println("\tmd.bss-ebss=", hex(md.bss), "-", hex(md.ebss))
    39  			println("\tmd.data-edata=", hex(md.data), "-", hex(md.edata))
    40  			println("\tmd.types-etypes=", hex(md.types), "-", hex(md.etypes))
    41  			throw("plugin: new module data overlaps with previous moduledata")
    42  		}
    43  	}
    44  
    45  	// Initialize the freshly loaded module.
    46  	modulesinit()
    47  	typelinksinit()
    48  
    49  	lock(&ifaceLock)
    50  	for _, i := range md.itablinks {
    51  		additab(i, true, false)
    52  	}
    53  	unlock(&ifaceLock)
    54  
    55  	// Build a map of symbol names to symbols. Here in the runtime
    56  	// we fill out the first word of the interface, the type. We
    57  	// pass these zero value interfaces to the plugin package,
    58  	// where the symbol value is filled in (usually via cgo).
    59  	//
    60  	// Because functions are handled specially in the plugin package,
    61  	// function symbol names are prefixed here with '.' to avoid
    62  	// a dependency on the reflect package.
    63  	syms = make(map[string]interface{}, len(md.ptab))
    64  	for _, ptab := range md.ptab {
    65  		symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name)
    66  		t := (*_type)(unsafe.Pointer(md.types)).typeOff(ptab.typ)
    67  		var val interface{}
    68  		valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val))
    69  		(*valp)[0] = unsafe.Pointer(t)
    70  
    71  		name := symName.name()
    72  		if t.kind&kindMask == kindFunc {
    73  			name = "." + name
    74  		}
    75  		syms[name] = val
    76  	}
    77  	return md.pluginpath, syms
    78  }
    79  
    80  // inRange reports whether v0 or v1 are in the range [r0, r1].
    81  func inRange(r0, r1, v0, v1 uintptr) bool {
    82  	return (v0 >= r0 && v0 <= r1) || (v1 >= r0 && v1 <= r1)
    83  }
    84  
    85  // A ptabEntry is generated by the compiler for each exported function
    86  // and global variable in the main package of a plugin. It is used to
    87  // initialize the plugin module's symbol map.
    88  type ptabEntry struct {
    89  	name nameOff
    90  	typ  typeOff
    91  }