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