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 {