Source file
src/runtime/plugin.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import "unsafe"
8
9
10 func plugin_lastmoduleinit() (path string, syms map[string]interface{}, errstr string) {
11 var md *moduledata
12 for pmd := firstmoduledata.next; pmd != nil; pmd = pmd.next {
13 if pmd.bad {
14 md = nil
15 continue
16 }
17 md = pmd
18 }
19 if md == nil {
20 throw("runtime: no plugin module data")
21 }
22 if md.pluginpath == "" {
23 throw("runtime: plugin has empty pluginpath")
24 }
25 if md.typemap != nil {
26 return "", nil, "plugin already loaded"
27 }
28
29 for _, pmd := range activeModules() {
30 if pmd.pluginpath == md.pluginpath {
31 md.bad = true
32 return "", nil, "plugin already loaded"
33 }
34
35 if inRange(pmd.text, pmd.etext, md.text, md.etext) ||
36 inRange(pmd.bss, pmd.ebss, md.bss, md.ebss) ||
37 inRange(pmd.data, pmd.edata, md.data, md.edata) ||
38 inRange(pmd.types, pmd.etypes, md.types, md.etypes) {
39 println("plugin: new module data overlaps with previous moduledata")
40 println("\tpmd.text-etext=", hex(pmd.text), "-", hex(pmd.etext))
41 println("\tpmd.bss-ebss=", hex(pmd.bss), "-", hex(pmd.ebss))
42 println("\tpmd.data-edata=", hex(pmd.data), "-", hex(pmd.edata))
43 println("\tpmd.types-etypes=", hex(pmd.types), "-", hex(pmd.etypes))
44 println("\tmd.text-etext=", hex(md.text), "-", hex(md.etext))
45 println("\tmd.bss-ebss=", hex(md.bss), "-", hex(md.ebss))
46 println("\tmd.data-edata=", hex(md.data), "-", hex(md.edata))
47 println("\tmd.types-etypes=", hex(md.types), "-", hex(md.etypes))
48 throw("plugin: new module data overlaps with previous moduledata")
49 }
50 }
51 for _, pkghash := range md.pkghashes {
52 if pkghash.linktimehash != *pkghash.runtimehash {
53 md.bad = true
54 return "", nil, "plugin was built with a different version of package " + pkghash.modulename
55 }
56 }
57
58
59 modulesinit()
60 typelinksinit()
61
62 pluginftabverify(md)
63 moduledataverify1(md)
64
65 lock(&itabLock)
66 for _, i := range md.itablinks {
67 itabAdd(i)
68 }
69 unlock(&itabLock)
70
71
72
73
74
75
76
77
78
79 syms = make(map[string]interface{}, len(md.ptab))
80 for _, ptab := range md.ptab {
81 symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name)
82 t := (*_type)(unsafe.Pointer(md.types)).typeOff(ptab.typ)
83 var val interface{}
84 valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val))
85 (*valp)[0] = unsafe.Pointer(t)
86
87 name := symName.name()
88 if t.kind&kindMask == kindFunc {
89 name = "." + name
90 }
91 syms[name] = val
92 }
93 return md.pluginpath, syms, ""
94 }
95
96 func pluginftabverify(md *moduledata) {
97 badtable := false
98 for i := 0; i < len(md.ftab); i++ {
99 entry := md.ftab[i].entry
100 if md.minpc <= entry && entry <= md.maxpc {
101 continue
102 }
103
104 f := funcInfo{(*_func)(unsafe.Pointer(&md.pclntable[md.ftab[i].funcoff])), md}
105 name := funcname(f)
106
107
108
109
110 name2 := "none"
111 entry2 := uintptr(0)
112 f2 := findfunc(entry)
113 if f2.valid() {
114 name2 = funcname(f2)
115 entry2 = f2.entry
116 }
117 badtable = true
118 println("ftab entry", hex(entry), "/", hex(entry2), ": ",
119 name, "/", name2, "outside pc range:[", hex(md.minpc), ",", hex(md.maxpc), "], modulename=", md.modulename, ", pluginpath=", md.pluginpath)
120 }
121 if badtable {
122 throw("runtime: plugin has bad symbol table")
123 }
124 }
125
126
127 func inRange(r0, r1, v0, v1 uintptr) bool {
128 return (v0 >= r0 && v0 <= r1) || (v1 >= r0 && v1 <= r1)
129 }
130
131
132
133
134 type ptabEntry struct {
135 name nameOff
136 typ typeOff
137 }
138
View as plain text