// 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 

//go:linkname plugin_lastmoduleinit plugin.lastmoduleinit
func plugin_lastmoduleinit() ( string,  map[string]any,  []*initTask,  string) {
	var  *moduledata
	for  := firstmoduledata.next;  != nil;  = .next {
		if .bad {
			 = nil // we only want the last module
			continue
		}
		 = 
	}
	if  == nil {
		throw("runtime: no plugin module data")
	}
	if .pluginpath == "" {
		throw("runtime: plugin has empty pluginpath")
	}
	if .typemap != nil {
		return "", nil, nil, "plugin already loaded"
	}

	for ,  := range activeModules() {
		if .pluginpath == .pluginpath {
			.bad = true
			return "", nil, nil, "plugin already loaded"
		}

		if inRange(.text, .etext, .text, .etext) ||
			inRange(.bss, .ebss, .bss, .ebss) ||
			inRange(.data, .edata, .data, .edata) ||
			inRange(.types, .etypes, .types, .etypes) {
			println("plugin: new module data overlaps with previous moduledata")
			println("\tpmd.text-etext=", hex(.text), "-", hex(.etext))
			println("\tpmd.bss-ebss=", hex(.bss), "-", hex(.ebss))
			println("\tpmd.data-edata=", hex(.data), "-", hex(.edata))
			println("\tpmd.types-etypes=", hex(.types), "-", hex(.etypes))
			println("\tmd.text-etext=", hex(.text), "-", hex(.etext))
			println("\tmd.bss-ebss=", hex(.bss), "-", hex(.ebss))
			println("\tmd.data-edata=", hex(.data), "-", hex(.edata))
			println("\tmd.types-etypes=", hex(.types), "-", hex(.etypes))
			throw("plugin: new module data overlaps with previous moduledata")
		}
	}
	for ,  := range .pkghashes {
		if .linktimehash != *.runtimehash {
			.bad = true
			return "", nil, nil, "plugin was built with a different version of package " + .modulename
		}
	}

	// Initialize the freshly loaded module.
	modulesinit()
	typelinksinit()

	pluginftabverify()
	moduledataverify1()

	lock(&itabLock)
	for ,  := range .itablinks {
		itabAdd()
	}
	unlock(&itabLock)

	// 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.
	 = make(map[string]any, len(.ptab))
	for ,  := range .ptab {
		 := resolveNameOff(unsafe.Pointer(.types), .name)
		 := toRType((*_type)(unsafe.Pointer(.types))).typeOff(.typ) // TODO can this stack of conversions be simpler?
		var  any
		 := (*[2]unsafe.Pointer)(unsafe.Pointer(&))
		(*)[0] = unsafe.Pointer()

		 := .Name()
		if .Kind_&kindMask == kindFunc {
			 = "." + 
		}
		[] = 
	}
	return .pluginpath, , .inittasks, ""
}

func pluginftabverify( *moduledata) {
	 := false
	for  := 0;  < len(.ftab); ++ {
		 := .textAddr(.ftab[].entryoff)
		if .minpc <=  &&  <= .maxpc {
			continue
		}

		 := funcInfo{(*_func)(unsafe.Pointer(&.pclntable[.ftab[].funcoff])), }
		 := funcname()

		// A common bug is f.entry has a relocation to a duplicate
		// function symbol, meaning if we search for its PC we get
		// a valid entry with a name that is useful for debugging.
		 := "none"
		 := uintptr(0)
		 := findfunc()
		if .valid() {
			 = funcname()
			 = .entry()
		}
		 = true
		println("ftab entry", hex(), "/", hex(), ": ",
			, "/", , "outside pc range:[", hex(.minpc), ",", hex(.maxpc), "], modulename=", .modulename, ", pluginpath=", .pluginpath)
	}
	if  {
		throw("runtime: plugin has bad symbol table")
	}
}

// inRange reports whether v0 or v1 are in the range [r0, r1].
func inRange(, , ,  uintptr) bool {
	return ( >=  &&  <= ) || ( >=  &&  <= )
}

// 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
}