]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile,cmd/link: hooks for identifying coverage counters
authorThan McIntosh <thanm@google.com>
Tue, 19 Apr 2022 23:41:40 +0000 (19:41 -0400)
committerThan McIntosh <thanm@google.com>
Tue, 27 Sep 2022 10:29:51 +0000 (10:29 +0000)
Add a new "coverage counter" classification for variables to be used
for storing code coverage counter values (somewhat in the same way
that we identify fuzzer counters). Tagging such variables allows us to
aggregate them in the linker, and to treat updates specially.

Updates #51430.

Change-Id: Ib49fb05736ffece98bcc2f7a7c37e991b7f67bbb
Reviewed-on: https://go-review.googlesource.com/c/go/+/401235
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/compile/internal/gc/obj.go
src/cmd/compile/internal/inline/inl.go
src/cmd/compile/internal/ir/name.go
src/cmd/compile/internal/ssa/writebarrier.go
src/cmd/internal/objabi/symkind.go
src/cmd/internal/objabi/symkind_string.go
src/cmd/link/internal/ld/data.go
src/cmd/link/internal/ld/symtab.go
src/cmd/link/internal/sym/symkind.go
src/cmd/link/internal/sym/symkind_string.go
src/runtime/symtab.go

index 715b8ee2637e002ed58d6ef5caae0e62e939d827..504072bb173b7d0a78b5d06ebd8b49656116aec7 100644 (file)
@@ -195,6 +195,9 @@ func dumpGlobal(n *ir.Name) {
        }
        types.CalcSize(n.Type())
        ggloblnod(n)
+       if n.CoverageCounter() || n.CoverageAuxVar() {
+               return
+       }
        base.Ctxt.DwarfGlobal(base.Ctxt.Pkgpath, types.TypeSymName(n.Type()), n.Linksym())
 }
 
@@ -316,6 +319,9 @@ func ggloblnod(nam *ir.Name) {
        if nam.Libfuzzer8BitCounter() {
                s.Type = objabi.SLIBFUZZER_8BIT_COUNTER
        }
+       if nam.CoverageCounter() {
+               s.Type = objabi.SCOVERAGE_COUNTER
+       }
        if nam.Sym().Linkname != "" {
                // Make sure linkname'd symbol is non-package. When a symbol is
                // both imported and linkname'd, s.Pkg may not set to "_" in
index a7fd704b85450ea2756cd455ab37141394ea2bbf..14adbf5d43b90a79f3109df316f2c8954afc62aa 100644 (file)
@@ -37,6 +37,7 @@ import (
        "cmd/compile/internal/typecheck"
        "cmd/compile/internal/types"
        "cmd/internal/obj"
+       "cmd/internal/objabi"
        "cmd/internal/src"
 )
 
@@ -471,6 +472,28 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
                                }
                        }
                }
+
+       case ir.OAS:
+               // Special case for coverage counter updates and coverage
+               // function registrations. Although these correspond to real
+               // operations, we treat them as zero cost for the moment. This
+               // is primarily due to the existence of tests that are
+               // sensitive to inlining-- if the insertion of coverage
+               // instrumentation happens to tip a given function over the
+               // threshold and move it from "inlinable" to "not-inlinable",
+               // this can cause changes in allocation behavior, which can
+               // then result in test failures (a good example is the
+               // TestAllocations in crypto/ed25519).
+               n := n.(*ir.AssignStmt)
+               if n.X.Op() == ir.OINDEX {
+                       n := n.X.(*ir.IndexExpr)
+                       if n.X.Op() == ir.ONAME && n.X.Type().IsArray() {
+                               n := n.X.(*ir.Name)
+                               if n.Linksym().Type == objabi.SCOVERAGE_COUNTER {
+                                       return false
+                               }
+                       }
+               }
        }
 
        v.budget--
index 310481f6f0579e1810bfc9ae15f637aac75f38f6..f537ba49818f6d4dbd51918e0c5321b152c14d86 100644 (file)
@@ -236,6 +236,8 @@ const (
        nameInlLocal                 // PAUTO created by inliner, derived from callee local
        nameOpenDeferSlot            // if temporary var storing info for open-coded defers
        nameLibfuzzer8BitCounter     // if PEXTERN should be assigned to __sancov_cntrs section
+       nameCoverageCounter          // instrumentation counter var for cmd/cover
+       nameCoverageAuxVar           // instrumentation pkg ID variable cmd/cover
        nameAlias                    // is type name an alias
 )
 
@@ -251,6 +253,8 @@ func (n *Name) InlFormal() bool                { return n.flags&nameInlFormal !=
 func (n *Name) InlLocal() bool                 { return n.flags&nameInlLocal != 0 }
 func (n *Name) OpenDeferSlot() bool            { return n.flags&nameOpenDeferSlot != 0 }
 func (n *Name) Libfuzzer8BitCounter() bool     { return n.flags&nameLibfuzzer8BitCounter != 0 }
+func (n *Name) CoverageCounter() bool          { return n.flags&nameCoverageCounter != 0 }
+func (n *Name) CoverageAuxVar() bool           { return n.flags&nameCoverageAuxVar != 0 }
 
 func (n *Name) setReadonly(b bool)                 { n.flags.set(nameReadonly, b) }
 func (n *Name) SetNeedzero(b bool)                 { n.flags.set(nameNeedzero, b) }
@@ -264,6 +268,8 @@ func (n *Name) SetInlFormal(b bool)                { n.flags.set(nameInlFormal,
 func (n *Name) SetInlLocal(b bool)                 { n.flags.set(nameInlLocal, b) }
 func (n *Name) SetOpenDeferSlot(b bool)            { n.flags.set(nameOpenDeferSlot, b) }
 func (n *Name) SetLibfuzzer8BitCounter(b bool)     { n.flags.set(nameLibfuzzer8BitCounter, b) }
+func (n *Name) SetCoverageCounter(b bool)          { n.flags.set(nameCoverageCounter, b) }
+func (n *Name) SetCoverageAuxVar(b bool)           { n.flags.set(nameCoverageAuxVar, b) }
 
 // OnStack reports whether variable n may reside on the stack.
 func (n *Name) OnStack() bool {
index cb8c0a5e0eb7b4eef21f6c65a1426fd73be96a69..f5a7ed592814952e77ee8c615ae2b94ae23cb478 100644 (file)
@@ -652,7 +652,8 @@ func IsSanitizerSafeAddr(v *Value) bool {
                // read-only once initialized.
                return true
        case OpAddr:
-               return v.Aux.(*obj.LSym).Type == objabi.SRODATA || v.Aux.(*obj.LSym).Type == objabi.SLIBFUZZER_8BIT_COUNTER
+               vt := v.Aux.(*obj.LSym).Type
+               return vt == objabi.SRODATA || vt == objabi.SLIBFUZZER_8BIT_COUNTER || vt == objabi.SCOVERAGE_COUNTER || vt == objabi.SCOVERAGE_AUXVAR
        }
        return false
 }
index ba1e4d50d684cb3b409e71f77d9ca408986b9684..a58816e2927a822575a6b176fa18309df63967fc 100644 (file)
@@ -68,6 +68,9 @@ const (
        SDWARFLINES
        // Coverage instrumentation counter for libfuzzer.
        SLIBFUZZER_8BIT_COUNTER
-       // Update cmd/link/internal/sym/AbiSymKindToSymKind for new SymKind values.
+       // Coverage instrumentation counter, aux variable for cmd/cover
+       SCOVERAGE_COUNTER
+       SCOVERAGE_AUXVAR
 
+       // Update cmd/link/internal/sym/AbiSymKindToSymKind for new SymKind values.
 )
index d0606aa2daf2268cdce5a3341ff8616fa7f718c3..c0b84030f799a2233196cbc651e0a9bc644562c3 100644 (file)
@@ -26,11 +26,13 @@ func _() {
        _ = x[SDWARFLOC-15]
        _ = x[SDWARFLINES-16]
        _ = x[SLIBFUZZER_8BIT_COUNTER-17]
+       _ = x[SCOVERAGE_COUNTER-18]
+       _ = x[SCOVERAGE_AUXVAR-19]
 }
 
-const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSLIBFUZZER_8BIT_COUNTER"
+const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINESSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVAR"
 
-var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 63, 74, 83, 95, 105, 114, 125, 134, 145, 168}
+var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 63, 74, 83, 95, 105, 114, 125, 134, 145, 168, 185, 201}
 
 func (i SymKind) String() string {
        if i >= SymKind(len(_SymKind_index)-1) {
index c2668b29a44f882ba87b0db1a80f467ec738d818..c23eac08a4be2da98c944b6a685c6641652a63b6 100644 (file)
@@ -1074,6 +1074,8 @@ func dwarfblk(ctxt *Link, out *OutBuf, addr int64, size int64) {
        writeBlocks(ctxt, out, ctxt.outSem, ctxt.loader, syms, addr, size, zeros[:])
 }
 
+var covCounterDataStartOff, covCounterDataLen uint64
+
 var zeros [512]byte
 
 var (
@@ -1781,6 +1783,15 @@ func (state *dodataState) allocateDataSections(ctxt *Link) {
        ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.enoptrbss", 0), sect)
        ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.end", 0), sect)
 
+       // Code coverage counters are assigned to the .noptrbss section.
+       // We assign them in a separate pass so that they stay aggregated
+       // together in a single blob (coverage runtime depends on this).
+       covCounterDataStartOff = sect.Length
+       state.assignToSection(sect, sym.SCOVERAGE_COUNTER, sym.SNOPTRBSS)
+       covCounterDataLen = sect.Length - covCounterDataStartOff
+       ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.covctrs", 0), sect)
+       ldr.SetSymSect(ldr.LookupOrCreateSym("runtime.ecovctrs", 0), sect)
+
        // Coverage instrumentation counters for libfuzzer.
        if len(state.data[sym.SLIBFUZZER_8BIT_COUNTER]) > 0 {
                sect := state.allocateNamedSectionAndAssignSyms(&Segdata, "__sancov_cntrs", sym.SLIBFUZZER_8BIT_COUNTER, sym.Sxxx, 06)
@@ -2682,6 +2693,8 @@ func (ctxt *Link) address() []*sym.Segment {
        ctxt.xdefine("runtime.edata", sym.SDATA, int64(data.Vaddr+data.Length))
        ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr))
        ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, int64(noptrbss.Vaddr+noptrbss.Length))
+       ctxt.xdefine("runtime.covctrs", sym.SCOVERAGE_COUNTER, int64(noptrbss.Vaddr+covCounterDataStartOff))
+       ctxt.xdefine("runtime.ecovctrs", sym.SCOVERAGE_COUNTER, int64(noptrbss.Vaddr+covCounterDataStartOff+covCounterDataLen))
        ctxt.xdefine("runtime.end", sym.SBSS, int64(Segdata.Vaddr+Segdata.Length))
 
        if fuzzCounters != nil {
index 5074ffa8c9e743da544e9c1c01fcf266a8a55937..21a1466c491257e9e8caf137a89ae9011cea77cd 100644 (file)
@@ -453,6 +453,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
        ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
        ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
        ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
+       ctxt.xdefine("runtime.covctrs", sym.SNOPTRBSS, 0)
+       ctxt.xdefine("runtime.ecovctrs", sym.SNOPTRBSS, 0)
        ctxt.xdefine("runtime.end", sym.SBSS, 0)
        ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
        ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
@@ -529,7 +531,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
        nsym := loader.Sym(ldr.NSym())
        symGroupType := make([]sym.SymKind, nsym)
        for s := loader.Sym(1); s < nsym; s++ {
-               if !ctxt.IsExternal() && ldr.IsFileLocal(s) && !ldr.IsFromAssembly(s) && ldr.SymPkg(s) != "" {
+               if (!ctxt.IsExternal() && ldr.IsFileLocal(s) && !ldr.IsFromAssembly(s) && ldr.SymPkg(s) != "") || (ctxt.LinkMode == LinkInternal && ldr.SymType(s) == sym.SCOVERAGE_COUNTER) {
                        ldr.SetAttrNotInSymbolTable(s, true)
                }
                if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) {
@@ -672,6 +674,8 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind {
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ebss", 0))
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrbss", 0))
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrbss", 0))
+       moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.covctrs", 0))
+       moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ecovctrs", 0))
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.end", 0))
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcdata", 0))
        moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0))
index 0f8fbed8785cd20079a66b41d4a66dd360d2e5ce..2f8e8fe1336bb26557d7d46e3012a87ef78bd06d 100644 (file)
@@ -98,6 +98,8 @@ const (
        SBSS
        SNOPTRBSS
        SLIBFUZZER_8BIT_COUNTER
+       SCOVERAGE_COUNTER
+       SCOVERAGE_AUXVAR
        STLSBSS
        SXREF
        SMACHOSYMSTR
@@ -144,6 +146,8 @@ var AbiSymKindToSymKind = [...]SymKind{
        objabi.SDWARFLOC:               SDWARFLOC,
        objabi.SDWARFLINES:             SDWARFLINES,
        objabi.SLIBFUZZER_8BIT_COUNTER: SLIBFUZZER_8BIT_COUNTER,
+       objabi.SCOVERAGE_COUNTER:       SCOVERAGE_COUNTER,
+       objabi.SCOVERAGE_AUXVAR:        SCOVERAGE_AUXVAR,
 }
 
 // ReadOnly are the symbol kinds that form read-only sections. In some
index 14b57db41f0484521c87961d16276c864aad265f..1cd7ab17ef2569be13241a7039a05380d800307a 100644 (file)
@@ -45,31 +45,33 @@ func _() {
        _ = x[SBSS-34]
        _ = x[SNOPTRBSS-35]
        _ = x[SLIBFUZZER_8BIT_COUNTER-36]
-       _ = x[STLSBSS-37]
-       _ = x[SXREF-38]
-       _ = x[SMACHOSYMSTR-39]
-       _ = x[SMACHOSYMTAB-40]
-       _ = x[SMACHOINDIRECTPLT-41]
-       _ = x[SMACHOINDIRECTGOT-42]
-       _ = x[SFILEPATH-43]
-       _ = x[SDYNIMPORT-44]
-       _ = x[SHOSTOBJ-45]
-       _ = x[SUNDEFEXT-46]
-       _ = x[SDWARFSECT-47]
-       _ = x[SDWARFCUINFO-48]
-       _ = x[SDWARFCONST-49]
-       _ = x[SDWARFFCN-50]
-       _ = x[SDWARFABSFCN-51]
-       _ = x[SDWARFTYPE-52]
-       _ = x[SDWARFVAR-53]
-       _ = x[SDWARFRANGE-54]
-       _ = x[SDWARFLOC-55]
-       _ = x[SDWARFLINES-56]
+       _ = x[SCOVERAGE_COUNTER-37]
+       _ = x[SCOVERAGE_AUXVAR-38]
+       _ = x[STLSBSS-39]
+       _ = x[SXREF-40]
+       _ = x[SMACHOSYMSTR-41]
+       _ = x[SMACHOSYMTAB-42]
+       _ = x[SMACHOINDIRECTPLT-43]
+       _ = x[SMACHOINDIRECTGOT-44]
+       _ = x[SFILEPATH-45]
+       _ = x[SDYNIMPORT-46]
+       _ = x[SHOSTOBJ-47]
+       _ = x[SUNDEFEXT-48]
+       _ = x[SDWARFSECT-49]
+       _ = x[SDWARFCUINFO-50]
+       _ = x[SDWARFCONST-51]
+       _ = x[SDWARFFCN-52]
+       _ = x[SDWARFABSFCN-53]
+       _ = x[SDWARFTYPE-54]
+       _ = x[SDWARFVAR-55]
+       _ = x[SDWARFRANGE-56]
+       _ = x[SDWARFLOC-57]
+       _ = x[SDWARFLINES-58]
 }
 
-const _SymKind_name = "SxxxSTEXTSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_8BIT_COUNTERSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINES"
+const _SymKind_name = "SxxxSTEXTSELFRXSECTSMACHOPLTSTYPESSTRINGSGOSTRINGSGOFUNCSGCBITSSRODATASFUNCTABSELFROSECTSTYPERELROSSTRINGRELROSGOSTRINGRELROSGOFUNCRELROSGCBITSRELROSRODATARELROSFUNCTABRELROSTYPELINKSITABLINKSSYMTABSPCLNTABSFirstWritableSBUILDINFOSELFSECTSMACHOSMACHOGOTSWINDOWSSELFGOTSNOPTRDATASINITARRSDATASXCOFFTOCSBSSSNOPTRBSSSLIBFUZZER_8BIT_COUNTERSCOVERAGE_COUNTERSCOVERAGE_AUXVARSTLSBSSSXREFSMACHOSYMSTRSMACHOSYMTABSMACHOINDIRECTPLTSMACHOINDIRECTGOTSFILEPATHSDYNIMPORTSHOSTOBJSUNDEFEXTSDWARFSECTSDWARFCUINFOSDWARFCONSTSDWARFFCNSDWARFABSFCNSDWARFTYPESDWARFVARSDWARFRANGESDWARFLOCSDWARFLINES"
 
-var _SymKind_index = [...]uint16{0, 4, 9, 19, 28, 33, 40, 49, 56, 63, 70, 78, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 336, 343, 348, 360, 372, 389, 406, 415, 425, 433, 442, 452, 464, 475, 484, 496, 506, 515, 526, 535, 546}
+var _SymKind_index = [...]uint16{0, 4, 9, 19, 28, 33, 40, 49, 56, 63, 70, 78, 88, 98, 110, 124, 136, 148, 160, 173, 182, 191, 198, 206, 220, 230, 238, 244, 253, 261, 268, 278, 286, 291, 300, 304, 313, 336, 353, 369, 376, 381, 393, 405, 422, 439, 448, 458, 466, 475, 485, 497, 508, 517, 529, 539, 548, 559, 568, 579}
 
 func (i SymKind) String() string {
        if i >= SymKind(len(_SymKind_index)-1) {
index 79ca5cfc44093ba52c15b955cfb8e3836cd9128f..2da9a59b7e1a04c9d7a5fdc91772dc7de82b46af 100644 (file)
@@ -427,6 +427,7 @@ type moduledata struct {
        data, edata           uintptr
        bss, ebss             uintptr
        noptrbss, enoptrbss   uintptr
+       covctrs, ecovctrs     uintptr
        end, gcdata, gcbss    uintptr
        types, etypes         uintptr
        rodata                uintptr