]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/link,runtime: remove relocations from stkobjs
authorJosh Bleecher Snyder <josharian@gmail.com>
Mon, 27 Sep 2021 21:27:20 +0000 (14:27 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 5 Oct 2021 19:16:08 +0000 (19:16 +0000)
Use an offset from go.func.* instead.
This removes the last relocation from funcdata symbols,
which lets us simplify that code.

size      before    after     Δ       %
addr2line 3683218   3680706   -2512   -0.068%
api       4951074   4944850   -6224   -0.126%
asm       4744258   4757586   +13328  +0.281%
buildid   2419986   2418546   -1440   -0.060%
cgo       4218306   4197346   -20960  -0.497%
compile   22132066  22076882  -55184  -0.249%
cover     4432834   4411362   -21472  -0.484%
dist      3111202   3091346   -19856  -0.638%
doc       3583602   3563234   -20368  -0.568%
fix       3023922   3020658   -3264   -0.108%
link      6188034   6164642   -23392  -0.378%
nm        3665826   3646818   -19008  -0.519%
objdump   4015234   4012450   -2784   -0.069%
pack      2155010   2153554   -1456   -0.068%
pprof     13044178  13011522  -32656  -0.250%
test2json 2402146   2383906   -18240  -0.759%
trace     9765410   9736514   -28896  -0.296%
vet       6681250   6655058   -26192  -0.392%
total     104217556 103926980 -290576 -0.279%

relocs    before  after   Δ       %
addr2line 25563   25066   -497    -1.944%
api       18409   17176   -1233   -6.698%
asm       18903   18271   -632    -3.343%
buildid   9513    9233    -280    -2.943%
cgo       17103   16222   -881    -5.151%
compile   64825   60421   -4404   -6.794%
cover     19464   18479   -985    -5.061%
dist      10798   10135   -663    -6.140%
doc       13503   12735   -768    -5.688%
fix       11465   10820   -645    -5.626%
link      23214   21849   -1365   -5.880%
nm        25480   24987   -493    -1.935%
objdump   26610   26057   -553    -2.078%
pack      7951    7665    -286    -3.597%
pprof     63964   60761   -3203   -5.008%
test2json 8735    8389    -346    -3.961%
trace     39639   37180   -2459   -6.203%
vet       25970   24044   -1926   -7.416%
total     431108  409489  -21619  -5.015%

Change-Id: I43c26196a008da6d1cb3a782eea2f428778bd569
Reviewed-on: https://go-review.googlesource.com/c/go/+/353138
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/compile/internal/liveness/plive.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/pcln.go
src/cmd/link/internal/ld/symtab.go
src/runtime/mgcmark.go
src/runtime/proc.go
src/runtime/stack.go
src/runtime/symtab.go

index dc778a6fb91cb6d961a555e85877d67ccec36f1f..e358155a341740f74de266e6dc96a8d7d40222ae 100644 (file)
@@ -1443,7 +1443,7 @@ func (lv *liveness) emitStackObjects() *obj.LSym {
                }
                off = objw.Uint32(x, off, uint32(sz))
                off = objw.Uint32(x, off, uint32(ptrdata))
-               off = objw.SymPtr(x, off, lsym, 0)
+               off = objw.SymPtrOff(x, off, lsym)
        }
 
        if base.Flag.Live != 0 {
index 8de0e0df1a711172a5369d788b60aff33a160b08..4f0ce23ce7ae650481830476693c5b4627956b8e 100644 (file)
@@ -1367,6 +1367,11 @@ func (state *dodataState) makeRelroForSharedLib(target *Link) {
                                        // the relro data.
                                        isRelro = true
                                }
+                       case sym.SGOFUNC:
+                               // The only SGOFUNC symbols that contain relocations are .stkobj,
+                               // and their relocations are of type objabi.R_ADDROFF,
+                               // which always get resolved during linking.
+                               isRelro = false
                        }
                        if isRelro {
                                state.setSymType(s, symnrelro)
index b041174cfe5fd437602aa4518bedd7e66b5b224c..b5a66b8517800f7a4c07ce45bc06e07d1e1b919c 100644 (file)
@@ -711,7 +711,7 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym
        ldr := ctxt.loader
        deferReturnSym := ldr.Lookup("runtime.deferreturn", abiInternalVer)
        gofunc := ldr.Lookup("go.func.*", 0)
-       gofuncrel := ldr.Lookup("go.funcrel.*", 0)
+       gofuncBase := ldr.SymValue(gofunc)
        textStart := ldr.SymValue(ldr.Lookup("runtime.text", 0))
        funcdata := []loader.Sym{}
        var pcsp, pcfile, pcline, pcinline loader.Sym
@@ -813,24 +813,10 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym
                                continue
                        }
 
-                       outer := ldr.OuterSym(fdsym)
-                       if outer == 0 {
-                               panic(fmt.Sprintf("no carrier sym for symbol %s (funcdata %s#%d)", ldr.SymName(fdsym), ldr.SymName(s), j))
+                       if outer := ldr.OuterSym(fdsym); outer != gofunc {
+                               panic(fmt.Sprintf("bad carrier sym for symbol %s (funcdata %s#%d), want go.func.* got %s", ldr.SymName(fdsym), ldr.SymName(s), j, ldr.SymName(outer)))
                        }
-                       rel := uint32(ldr.SymValue(fdsym) - ldr.SymValue(outer))
-                       // Record gofunc vs gofuncrel in bottom bit. See runtime/symtab.go:funcdata.
-                       // TODO: The only symbols that in gofuncrel are .stkobj symbols.
-                       // Remove those relocations, and simplify this.
-                       rel <<= 1
-                       switch outer {
-                       case gofunc:
-                       case gofuncrel:
-                               rel |= 1
-                       default:
-                               panic(fmt.Sprintf("expected symbol %s (funcdata %s#%d) to be placed in go.func.* or go.funcrel.*, got %s (%d)",
-                                       ldr.SymName(fdsym), ldr.SymName(s), j, ldr.SymName(outer), outer))
-                       }
-                       sb.SetUint32(ctxt.Arch, int64(dataoff), rel)
+                       sb.SetUint32(ctxt.Arch, int64(dataoff), uint32(ldr.SymValue(fdsym)-gofuncBase))
                }
        }
 }
index c582e4908db6c527cb7d78c9e94b1f2deb1c42be..878d30b5f17c56fd2b495ce04efb634f5a9acd3e 100644 (file)
@@ -569,13 +569,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
                        strings.HasSuffix(name, ".args_stackmap"),
                        strings.HasSuffix(name, ".stkobj"):
                        ldr.SetAttrNotInSymbolTable(s, true)
-                       if ctxt.UseRelro() && strings.HasSuffix(name, ".stkobj") {
-                               symGroupType[s] = sym.SGOFUNCRELRO
-                               ldr.SetCarrierSym(s, symgofuncrel)
-                       } else {
-                               symGroupType[s] = sym.SGOFUNC
-                               ldr.SetCarrierSym(s, symgofunc)
-                       }
+                       symGroupType[s] = sym.SGOFUNC
+                       ldr.SetCarrierSym(s, symgofunc)
                        if ctxt.Debugvlog != 0 {
                                align := ldr.SymAlign(s)
                                liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)
@@ -676,12 +671,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0))
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0))
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0))
+       moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0))
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go.func.*", 0))
-       if gofuncrel := ldr.Lookup("go.funcrel.*", 0); gofuncrel != 0 {
-               moduledata.AddAddr(ctxt.Arch, gofuncrel)
-       } else {
-               moduledata.AddUint(ctxt.Arch, 0)
-       }
 
        if ctxt.IsAIX() && ctxt.IsExternal() {
                // Add R_XCOFFREF relocation to prevent ld's garbage collection of
index eb5221443e7990c80fe601fc53655e052a1ddbb4..246907e53851571e0035e5a4b57f44730e009b13 100644 (file)
@@ -803,7 +803,7 @@ func scanstack(gp *g, gcw *gcWork) {
                        println()
                        printunlock()
                }
-               gcdata := r.gcdata
+               gcdata := r.gcdata()
                var s *mspan
                if r.useGCProg() {
                        // This path is pretty unlikely, an object large enough
@@ -923,7 +923,8 @@ func scanframeworker(frame *stkframe, state *stackScanState, gcw *gcWork) {
                // varp is 0 for defers, where there are no locals.
                // In that case, there can't be a pointer to its args, either.
                // (And all args would be scanned above anyway.)
-               for i, obj := range objs {
+               for i := range objs {
+                       obj := &objs[i]
                        off := obj.off
                        base := frame.varp // locals base pointer
                        if off >= 0 {
@@ -937,7 +938,7 @@ func scanframeworker(frame *stkframe, state *stackScanState, gcw *gcWork) {
                        if stackTraceDebug {
                                println("stkobj at", hex(ptr), "of size", obj.size)
                        }
-                       state.addObject(ptr, &objs[i])
+                       state.addObject(ptr, obj)
                }
        }
 }
index 2f619f93d3d402eeeb32e744bab349edbe331946..aa2ba96c8f78d8a56e9ea926afdf7f76dcc2e2fe 100644 (file)
@@ -687,6 +687,7 @@ func schedinit() {
        modulesinit()   // provides activeModules
        typelinksinit() // uses maps, activeModules
        itabsinit()     // uses activeModules
+       stkobjinit()    // must run before GC starts
 
        sigsave(&_g_.m.sigmask)
        initSigmask = _g_.m.sigmask
index 0946e6975a88649d84b654288ecc32d9970c911e..efaa799022f3f4c6b1109469f3d084a429ed11bb 100644 (file)
@@ -691,7 +691,8 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
        // Adjust pointers in all stack objects (whether they are live or not).
        // See comments in mgcmark.go:scanframeworker.
        if frame.varp != 0 {
-               for _, obj := range objs {
+               for i := range objs {
+                       obj := &objs[i]
                        off := obj.off
                        base := frame.varp // locals base pointer
                        if off >= 0 {
@@ -705,7 +706,7 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
                                continue
                        }
                        ptrdata := obj.ptrdata()
-                       gcdata := obj.gcdata
+                       gcdata := obj.gcdata()
                        var s *mspan
                        if obj.useGCProg() {
                                // See comments in mgcmark.go:scanstack
@@ -1321,7 +1322,7 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args
                // We don't actually use argmap in this case, but we need to fake the stack object
                // record for these frames which contain an internal/abi.RegArgs at a hard-coded offset.
                // This offset matches the assembly code on amd64 and arm64.
-               objs = methodValueCallFrameObjs
+               objs = methodValueCallFrameObjs[:]
        } else {
                p := funcdata(f, _FUNCDATA_StackObjects)
                if p != nil {
@@ -1340,23 +1341,33 @@ func getStackMap(frame *stkframe, cache *pcvalueCache, debug bool) (locals, args
        return
 }
 
-var (
-       abiRegArgsEface          interface{} = abi.RegArgs{}
-       abiRegArgsType           *_type      = efaceOf(&abiRegArgsEface)._type
-       methodValueCallFrameObjs             = []stackObjectRecord{
-               {
-                       off:      -int32(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local.
-                       size:     int32(abiRegArgsType.size),
-                       _ptrdata: int32(abiRegArgsType.ptrdata),
-                       gcdata:   abiRegArgsType.gcdata,
-               },
-       }
-)
+var methodValueCallFrameObjs [1]stackObjectRecord // initialized in stackobjectinit
 
-func init() {
+func stkobjinit() {
+       var abiRegArgsEface interface{} = abi.RegArgs{}
+       abiRegArgsType := efaceOf(&abiRegArgsEface)._type
        if abiRegArgsType.kind&kindGCProg != 0 {
                throw("abiRegArgsType needs GC Prog, update methodValueCallFrameObjs")
        }
+       // Set methodValueCallFrameObjs[0].gcdataoff so that
+       // stackObjectRecord.gcdata() will work correctly with it.
+       ptr := uintptr(unsafe.Pointer(&methodValueCallFrameObjs[0]))
+       var mod *moduledata
+       for datap := &firstmoduledata; datap != nil; datap = datap.next {
+               if datap.gofunc <= ptr && ptr < datap.end {
+                       mod = datap
+                       break
+               }
+       }
+       if mod == nil {
+               throw("methodValueCallFrameObjs is not in a module")
+       }
+       methodValueCallFrameObjs[0] = stackObjectRecord{
+               off:       -int32(alignUp(abiRegArgsType.size, 8)), // It's always the highest address local.
+               size:      int32(abiRegArgsType.size),
+               _ptrdata:  int32(abiRegArgsType.ptrdata),
+               gcdataoff: uint32(uintptr(unsafe.Pointer(abiRegArgsType.gcdata)) - mod.rodata),
+       }
 }
 
 // A stackObjectRecord is generated by the compiler for each stack object in a stack frame.
@@ -1365,10 +1376,10 @@ type stackObjectRecord struct {
        // offset in frame
        // if negative, offset from varp
        // if non-negative, offset from argp
-       off      int32
-       size     int32
-       _ptrdata int32 // ptrdata, or -ptrdata is GC prog is used
-       gcdata   *byte // pointer map or GC prog of the type
+       off       int32
+       size      int32
+       _ptrdata  int32  // ptrdata, or -ptrdata is GC prog is used
+       gcdataoff uint32 // offset to gcdata from moduledata.rodata
 }
 
 func (r *stackObjectRecord) useGCProg() bool {
@@ -1383,6 +1394,23 @@ func (r *stackObjectRecord) ptrdata() uintptr {
        return uintptr(x)
 }
 
+// gcdata returns pointer map or GC prog of the type.
+func (r *stackObjectRecord) gcdata() *byte {
+       ptr := uintptr(unsafe.Pointer(r))
+       var mod *moduledata
+       for datap := &firstmoduledata; datap != nil; datap = datap.next {
+               if datap.gofunc <= ptr && ptr < datap.end {
+                       mod = datap
+                       break
+               }
+       }
+       // If you get a panic here due to a nil mod,
+       // you may have made a copy of a stackObjectRecord.
+       // You must use the original pointer.
+       res := mod.rodata + uintptr(r.gcdataoff)
+       return (*byte)(unsafe.Pointer(res))
+}
+
 // This is exported as ABI0 via linkname so obj can call it.
 //
 //go:nosplit
index 8f7b439dc53cb5303adbe52d64b318e6f1c6887a..cbfe604f1bb279f6b925ff4fd44993f7f698662d 100644 (file)
@@ -427,7 +427,8 @@ type moduledata struct {
        noptrbss, enoptrbss   uintptr
        end, gcdata, gcbss    uintptr
        types, etypes         uintptr
-       gofunc, gofuncrel     uintptr // go.func.*, go.funcrel.*
+       rodata                uintptr
+       gofunc                uintptr // go.func.*
 
        textsectmap []textsect
        typelinks   []int32 // offsets from types
@@ -1092,11 +1093,7 @@ func funcdata(f funcInfo, i uint8) unsafe.Pointer {
        if off == ^uint32(0) {
                return nil
        }
-       base := f.datap.gofunc
-       if off&1 != 0 {
-               base = f.datap.gofuncrel
-       }
-       return unsafe.Pointer(base + uintptr(off>>1))
+       return unsafe.Pointer(f.datap.gofunc + uintptr(off))
 }
 
 // step advances to the next pc, value pair in the encoded table.