package runtime
import (
"internal/abi"
"unsafe"
)
func plugin_lastmoduleinit() (path string , syms map [string ]any , initTasks []*initTask , errstr string ) {
var md *moduledata
for pmd := firstmoduledata .next ; pmd != nil ; pmd = pmd .next {
if pmd .bad {
md = nil
continue
}
md = pmd
}
if md == nil {
throw ("runtime: no plugin module data" )
}
if md .pluginpath == "" {
throw ("runtime: plugin has empty pluginpath" )
}
if md .typemap != nil {
return "" , nil , nil , "plugin already loaded"
}
for _ , pmd := range activeModules () {
if pmd .pluginpath == md .pluginpath {
md .bad = true
return "" , nil , nil , "plugin already loaded"
}
if inRange (pmd .text , pmd .etext , md .text , md .etext ) ||
inRange (pmd .bss , pmd .ebss , md .bss , md .ebss ) ||
inRange (pmd .data , pmd .edata , md .data , md .edata ) ||
inRange (pmd .types , pmd .etypes , md .types , md .etypes ) {
println ("plugin: new module data overlaps with previous moduledata" )
println ("\tpmd.text-etext=" , hex (pmd .text ), "-" , hex (pmd .etext ))
println ("\tpmd.bss-ebss=" , hex (pmd .bss ), "-" , hex (pmd .ebss ))
println ("\tpmd.data-edata=" , hex (pmd .data ), "-" , hex (pmd .edata ))
println ("\tpmd.types-etypes=" , hex (pmd .types ), "-" , hex (pmd .etypes ))
println ("\tmd.text-etext=" , hex (md .text ), "-" , hex (md .etext ))
println ("\tmd.bss-ebss=" , hex (md .bss ), "-" , hex (md .ebss ))
println ("\tmd.data-edata=" , hex (md .data ), "-" , hex (md .edata ))
println ("\tmd.types-etypes=" , hex (md .types ), "-" , hex (md .etypes ))
throw ("plugin: new module data overlaps with previous moduledata" )
}
}
for _ , pkghash := range md .pkghashes {
if pkghash .linktimehash != *pkghash .runtimehash {
md .bad = true
return "" , nil , nil , "plugin was built with a different version of package " + pkghash .modulename
}
}
modulesinit ()
typelinksinit ()
pluginftabverify (md )
moduledataverify1 (md )
lock (&itabLock )
for _ , i := range md .itablinks {
itabAdd (i )
}
unlock (&itabLock )
syms = make (map [string ]any , len (md .ptab ))
for _ , ptab := range md .ptab {
symName := resolveNameOff (unsafe .Pointer (md .types ), ptab .name )
t := toRType ((*_type )(unsafe .Pointer (md .types ))).typeOff (ptab .typ )
var val any
valp := (*[2 ]unsafe .Pointer )(unsafe .Pointer (&val ))
(*valp )[0 ] = unsafe .Pointer (t )
name := symName .Name ()
if t .Kind_ &abi .KindMask == abi .Func {
name = "." + name
}
syms [name ] = val
}
return md .pluginpath , syms , md .inittasks , ""
}
func pluginftabverify(md *moduledata ) {
badtable := false
for i := 0 ; i < len (md .ftab ); i ++ {
entry := md .textAddr (md .ftab [i ].entryoff )
if md .minpc <= entry && entry <= md .maxpc {
continue
}
f := funcInfo {(*_func )(unsafe .Pointer (&md .pclntable [md .ftab [i ].funcoff ])), md }
name := funcname (f )
name2 := "none"
entry2 := uintptr (0 )
f2 := findfunc (entry )
if f2 .valid () {
name2 = funcname (f2 )
entry2 = f2 .entry ()
}
badtable = true
println ("ftab entry" , hex (entry ), "/" , hex (entry2 ), ": " ,
name , "/" , name2 , "outside pc range:[" , hex (md .minpc ), "," , hex (md .maxpc ), "], modulename=" , md .modulename , ", pluginpath=" , md .pluginpath )
}
if badtable {
throw ("runtime: plugin has bad symbol table" )
}
}
func inRange(r0 , r1 , v0 , v1 uintptr ) bool {
return (v0 >= r0 && v0 <= r1 ) || (v1 >= r0 && v1 <= r1 )
}
type ptabEntry struct {
name nameOff
typ typeOff
}
The pages are generated with Golds v0.7.0-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .