// first word dumped is the total number of bitmaps. The second word is the
 // length of the bitmaps. All bitmaps are assumed to be of equal length. The
 // remaining bytes are the raw bitmaps.
-func (lv *Liveness) emit(argssym, livesym, regssym *obj.LSym) {
+func (lv *Liveness) emit() (argsSym, liveSym, regsSym *obj.LSym) {
        // Size args bitmaps to be just large enough to hold the largest pointer.
        // First, find the largest Xoffset node we care about.
        // (Nodes without pointers aren't in lv.vars; see livenessShouldTrack.)
        // This would require shifting all bitmaps.
        maxLocals := lv.stkptrsize
 
+       // Temporary symbols for encoding bitmaps.
+       var argsSymTmp, liveSymTmp, regsSymTmp obj.LSym
+
        args := bvalloc(int32(maxArgs / int64(Widthptr)))
-       aoff := duint32(argssym, 0, uint32(len(lv.stackMaps))) // number of bitmaps
-       aoff = duint32(argssym, aoff, uint32(args.n))          // number of bits in each bitmap
+       aoff := duint32(&argsSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
+       aoff = duint32(&argsSymTmp, aoff, uint32(args.n))          // number of bits in each bitmap
 
        locals := bvalloc(int32(maxLocals / int64(Widthptr)))
-       loff := duint32(livesym, 0, uint32(len(lv.stackMaps))) // number of bitmaps
-       loff = duint32(livesym, loff, uint32(locals.n))        // number of bits in each bitmap
+       loff := duint32(&liveSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
+       loff = duint32(&liveSymTmp, loff, uint32(locals.n))        // number of bits in each bitmap
 
        for _, live := range lv.stackMaps {
                args.Clear()
 
                lv.pointerMap(live, lv.vars, args, locals)
 
-               aoff = dbvec(argssym, aoff, args)
-               loff = dbvec(livesym, loff, locals)
+               aoff = dbvec(&argsSymTmp, aoff, args)
+               loff = dbvec(&liveSymTmp, loff, locals)
        }
 
        regs := bvalloc(lv.usedRegs())
-       roff := duint32(regssym, 0, uint32(len(lv.regMaps))) // number of bitmaps
-       roff = duint32(regssym, roff, uint32(regs.n))        // number of bits in each bitmap
+       roff := duint32(®sSymTmp, 0, uint32(len(lv.regMaps))) // number of bitmaps
+       roff = duint32(®sSymTmp, roff, uint32(regs.n))        // number of bits in each bitmap
        if regs.n > 32 {
                // Our uint32 conversion below won't work.
                Fatalf("GP registers overflow uint32")
                for _, live := range lv.regMaps {
                        regs.Clear()
                        regs.b[0] = uint32(live)
-                       roff = dbvec(regssym, roff, regs)
+                       roff = dbvec(®sSymTmp, roff, regs)
                }
        }
 
        // Give these LSyms content-addressable names,
        // so that they can be de-duplicated.
        // This provides significant binary size savings.
-       // It is safe to rename these LSyms because
-       // they are tracked separately from ctxt.hash.
-       argssym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(argssym.P))
-       livesym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(livesym.P))
-       regssym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(regssym.P))
+       //
+       // These symbols will be added to Ctxt.Data by addGCLocals
+       // after parallel compilation is done.
+       makeSym := func(tmpSym *obj.LSym) *obj.LSym {
+               return Ctxt.LookupInit(fmt.Sprintf("gclocals·%x", md5.Sum(tmpSym.P)), func(lsym *obj.LSym) {
+                       lsym.P = tmpSym.P
+               })
+       }
+       return makeSym(&argsSymTmp), makeSym(&liveSymTmp), makeSym(®sSymTmp)
 }
 
 // Entry pointer for liveness analysis. Solves for the liveness of
 // pointer variables in the function and emits a runtime data
 // structure read by the garbage collector.
 // Returns a map from GC safe points to their corresponding stack map index.
-func liveness(e *ssafn, f *ssa.Func) LivenessMap {
+func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap {
        // Construct the global liveness state.
        vars, idx := getvariables(e.curfn)
        lv := newliveness(e.curfn, f, vars, idx, e.stkptrsize)
 
        // Emit the live pointer map data structures
        if ls := e.curfn.Func.lsym; ls != nil {
-               lv.emit(&ls.Func.GCArgs, &ls.Func.GCLocals, &ls.Func.GCRegs)
+               ls.Func.GCArgs, ls.Func.GCLocals, ls.Func.GCRegs = lv.emit()
+
+               p := pp.Prog(obj.AFUNCDATA)
+               Addrconst(&p.From, objabi.FUNCDATA_ArgsPointerMaps)
+               p.To.Type = obj.TYPE_MEM
+               p.To.Name = obj.NAME_EXTERN
+               p.To.Sym = ls.Func.GCArgs
+
+               p = pp.Prog(obj.AFUNCDATA)
+               Addrconst(&p.From, objabi.FUNCDATA_LocalsPointerMaps)
+               p.To.Type = obj.TYPE_MEM
+               p.To.Name = obj.NAME_EXTERN
+               p.To.Sym = ls.Func.GCLocals
+
+               p = pp.Prog(obj.AFUNCDATA)
+               Addrconst(&p.From, objabi.FUNCDATA_RegPointerMaps)
+               p.To.Type = obj.TYPE_MEM
+               p.To.Name = obj.NAME_EXTERN
+               p.To.Sym = ls.Func.GCRegs
        }
        return lv.livenessMap
 }