From 5923df1af9f058a4f1bf095dfb1d2722cd4120a1 Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Thu, 25 Aug 2016 20:29:15 -0400 Subject: [PATCH] cmd/compile: generate table of main symbol types For each exported symbol in package main, add its name and type to go.plugin.tabs symbol. This is used by the runtime when loading a plugin to return a typed interface{} value. Change-Id: I23c39583e57180acb8f7a74d218dae4368614f46 Reviewed-on: https://go-review.googlesource.com/27818 Run-TryBot: David Crawshaw TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/compile/internal/gc/obj.go | 30 +++++++++++++++++++++++++ src/cmd/compile/internal/gc/reflect.go | 31 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index ed69c7a677..4748bcb8b6 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -130,6 +130,7 @@ func dumpobj1(outfile string, mode int) { externs := len(externdcl) dumpglobls() + dumpptabs() dumptypestructs() // Dump extra globals. @@ -163,6 +164,35 @@ func dumpobj1(outfile string, mode int) { bout.Close() } +func dumpptabs() { + if !Ctxt.Flag_dynlink || localpkg.Name != "main" { + return + } + for _, exportn := range exportlist { + s := exportn.Sym + n := s.Def + if n == nil { + continue + } + if n.Op != ONAME { + continue + } + if !exportname(s.Name) { + continue + } + if s.Pkg.Name != "main" { + continue + } + if n.Type.Etype == TFUNC && n.Class == PFUNC { + // function + ptabs = append(ptabs, ptabEntry{s: s, t: s.Def.Type}) + } else { + // variable + ptabs = append(ptabs, ptabEntry{s: s, t: typPtr(s.Def.Type)}) + } + } +} + func dumpglobls() { // add globals for _, n := range externdcl { diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go index 4a396d293a..31be43d8c3 100644 --- a/src/cmd/compile/internal/gc/reflect.go +++ b/src/cmd/compile/internal/gc/reflect.go @@ -18,9 +18,15 @@ type itabEntry struct { sym *Sym } +type ptabEntry struct { + s *Sym + t *Type +} + // runtime interface and reflection data structures var signatlist []*Node var itabs []itabEntry +var ptabs []ptabEntry type Sig struct { name string @@ -1405,6 +1411,31 @@ func dumptypestructs() { ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA)) } + // process ptabs + if localpkg.Name == "main" && len(ptabs) > 0 { + ot := 0 + s := obj.Linklookup(Ctxt, "go.plugin.tabs", 0) + for _, p := range ptabs { + // Dump ptab symbol into go.pluginsym package. + // + // type ptab struct { + // name nameOff + // typ typeOff // pointer to symbol + // } + nsym := dname(p.s.Name, "", nil, true) + ot = dsymptrOffLSym(s, ot, nsym, 0) + ot = dsymptrOffLSym(s, ot, Linksym(typesym(p.t)), 0) + } + ggloblLSym(s, int32(ot), int16(obj.RODATA)) + + ot = 0 + s = obj.Linklookup(Ctxt, "go.plugin.exports", 0) + for _, p := range ptabs { + ot = dsymptrLSym(s, ot, Linksym(p.s), 0) + } + ggloblLSym(s, int32(ot), int16(obj.RODATA)) + } + // generate import strings for imported packages if forceObjFileStability { // Sorting the packages is not necessary but to compare binaries created