dclcontext = PEXTERN
}
-func funcsym(s *Sym) *Sym {
- if s.Fsym != nil {
- return s.Fsym
- }
+func (s *Sym) funcsymname() string {
+ return s.Name + "·f"
+}
- s1 := Pkglookup(s.Name+"·f", s.Pkg)
- if !Ctxt.Flag_dynlink && s1.Def == nil {
- s1.Def = newfuncname(s1)
- s1.Def.Func.Shortname = s
- funcsyms = append(funcsyms, s1.Def)
- }
- s.Fsym = s1
- return s1
+// funcsym returns s·f.
+func funcsym(s *Sym) *Sym {
+ sf, existed := s.Pkg.LookupOK(s.funcsymname())
+ // Don't export s·f when compiling for dynamic linking.
+ // When dynamically linking, the necessary function
+ // symbols will be created explicitly with makefuncsym.
+ // See the makefuncsym comment for details.
+ if !Ctxt.Flag_dynlink && !existed {
+ funcsyms = append(funcsyms, s)
+ }
+ return sf
}
+// makefuncsym ensures that s·f is exported.
+// It is only used with -dynlink.
+// When not compiling for dynamic linking,
+// the funcsyms are created as needed by
+// the packages that use them.
+// Normally we emit the s·f stubs as DUPOK syms,
+// but DUPOK doesn't work across shared library boundaries.
+// So instead, when dynamic linking, we only create
+// the s·f stubs in s's package.
func makefuncsym(s *Sym) {
+ if !Ctxt.Flag_dynlink {
+ Fatalf("makefuncsym dynlink")
+ }
if isblanksym(s) {
return
}
// not get a funcsym.
return
}
- s1 := funcsym(s)
- if s1.Def != nil {
- return
+ if _, existed := s.Pkg.LookupOK(s.funcsymname()); !existed {
+ funcsyms = append(funcsyms, s)
}
- s1.Def = newfuncname(s1)
- s1.Def.Func.Shortname = s
- funcsyms = append(funcsyms, s1.Def)
}
type nowritebarrierrecChecker struct {
ggloblnod(n)
}
- for _, n := range funcsyms {
- dsymptr(n.Sym, 0, n.Sym.Def.Func.Shortname, 0)
- ggloblsym(n.Sym, int32(Widthptr), obj.DUPOK|obj.RODATA)
+ for _, s := range funcsyms {
+ sf := s.Pkg.Lookup(s.funcsymname())
+ dsymptr(sf, 0, s, 0)
+ ggloblsym(sf, int32(Widthptr), obj.DUPOK|obj.RODATA)
}
// Do not reprocess funcsyms on next dumpglobls call.
}
func (pkg *Pkg) Lookup(name string) *Sym {
+ s, _ := pkg.LookupOK(name)
+ return s
+}
+
+// LookupOK looks up name in pkg and reports whether it previously existed.
+func (pkg *Pkg) LookupOK(name string) (s *Sym, existed bool) {
if pkg == nil {
pkg = nopkg
}
if s := pkg.Syms[name]; s != nil {
- return s
+ return s, true
}
- s := &Sym{
+ s = &Sym{
Name: name,
Pkg: pkg,
}
initSyms = append(initSyms, s)
}
pkg.Syms[name] = s
- return s
+ return s, false
}
func (pkg *Pkg) LookupBytes(name []byte) *Sym {