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 for _, i := range md.itablinks {
70 itabAdd(i)
71 }
72 unlock(&itabLock)
73
74
75
76
77
78
79
80
81
82 syms = make(map[string]any, len(md.ptab))
83 for _, ptab := range md.ptab {
84 symName := resolveNameOff(unsafe.Pointer(md.types), ptab.name)
85 t := toRType((*_type)(unsafe.Pointer(md.types))).typeOff(ptab.typ)
86 var val any
87 valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&val))
88 (*valp)[0] = unsafe.Pointer(t)
89
90 name := symName.Name()
91 if t.Kind_&abi.KindMask == abi.Func {
92 name = "." + name
93 }
94 syms[name] = val
95 }
96 return md.pluginpath, syms, md.inittasks, ""
97 }
98
99 func pluginftabverify(md *moduledata) {
100 badtable := false
101 for i := 0; i < len(md.ftab); i++ {
102 entry := md.textAddr(md.ftab[i].entryoff)
103 if md.minpc <= entry && entry <= md.maxpc {
104 continue
105 }
106
107 f := funcInfo{(*_func)(unsafe.Pointer(&md.pclntable[md.ftab[i].funcoff])), md}
108 name := funcname(f)
109
110
111
112
113 name2 := "none"
114 entry2 := uintptr(0)
115 f2 := findfunc(entry)
116 if f2.valid() {
117 name2 = funcname(f2)
118 entry2 = f2.entry()
119 }
120 badtable = true
121 println("ftab entry", hex(entry), "/", hex(entry2), ": ",
122 name, "/", name2, "outside pc range:[", hex(md.minpc), ",", hex(md.maxpc), "], modulename=", md.modulename, ", pluginpath=", md.pluginpath)
123 }
124 if badtable {
125 throw("runtime: plugin has bad symbol table")
126 }
127 }
128
129
130 func inRange(r0, r1, v0, v1 uintptr) bool {
131 return (v0 >= r0 && v0 <= r1) || (v1 >= r0 && v1 <= r1)
132 }
133
134
135
136
137 type ptabEntry struct {
138 name nameOff
139 typ typeOff
140 }
141
View as plain text