aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/plugin.go
blob: 2e0165082420597a24f691a534089f0d0929bc00 (plain)
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
// 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() 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.
type ptabEntry struct {
	name nameOff
	typ  typeOff
}