Source file src/cmd/internal/objabi/pkgspecial.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package objabi
     6  
     7  import "sync"
     8  
     9  // PkgSpecial indicates special build properties of a given runtime-related
    10  // package.
    11  type PkgSpecial struct {
    12  	// Runtime indicates that this package is "runtime" or imported by
    13  	// "runtime". This has several effects (which maybe should be split out):
    14  	//
    15  	// - Implicit allocation is disallowed.
    16  	//
    17  	// - Various runtime pragmas are enabled.
    18  	//
    19  	// - Optimizations are always enabled.
    20  	//
    21  	// - Checkptr is always disabled.
    22  	//
    23  	// This should be set for runtime and all packages it imports, and may be
    24  	// set for additional packages.
    25  	Runtime bool
    26  
    27  	// NoInstrument indicates this package should not receive sanitizer
    28  	// instrumentation. In many of these, instrumentation could cause infinite
    29  	// recursion. This is all runtime packages, plus those that support the
    30  	// sanitizers.
    31  	NoInstrument bool
    32  
    33  	// NoRaceFunc indicates functions in this package should not get
    34  	// racefuncenter/racefuncexit instrumentation Memory accesses in these
    35  	// packages are either uninteresting or will cause false positives.
    36  	NoRaceFunc bool
    37  
    38  	// AllowAsmABI indicates that assembly in this package is allowed to use ABI
    39  	// selectors in symbol names. Generally this is needed for packages that
    40  	// interact closely with the runtime package or have performance-critical
    41  	// assembly.
    42  	AllowAsmABI bool
    43  }
    44  
    45  var runtimePkgs = []string{
    46  	// TODO(panjf2000): consider syncing the list inside the
    47  	// 	isAsyncSafePoint in preempt.go based on this list?
    48  
    49  	"runtime",
    50  
    51  	"internal/runtime/atomic",
    52  	"internal/runtime/cgroup",
    53  	"internal/runtime/exithook",
    54  	"internal/runtime/gc",
    55  	"internal/runtime/gc/scan",
    56  	"internal/runtime/maps",
    57  	"internal/runtime/math",
    58  	"internal/runtime/strconv",
    59  	"internal/runtime/sys",
    60  	"internal/runtime/syscall/linux",
    61  	"internal/runtime/syscall/windows",
    62  
    63  	"internal/abi",
    64  	"internal/bytealg",
    65  	"internal/byteorder",
    66  	"internal/chacha8rand",
    67  	"internal/coverage/rtcov",
    68  	"internal/cpu",
    69  	"internal/goarch",
    70  	"internal/godebugs",
    71  	"internal/goexperiment",
    72  	"internal/goos",
    73  	"internal/profilerecord",
    74  	"internal/stringslite",
    75  }
    76  
    77  // extraNoInstrumentPkgs is the set of packages in addition to runtimePkgs that
    78  // should have NoInstrument set.
    79  var extraNoInstrumentPkgs = []string{
    80  	"runtime/race",
    81  	"runtime/msan",
    82  	"runtime/asan",
    83  	// We omit bytealg even though it's imported by runtime because it also
    84  	// backs a lot of package bytes. Currently we don't have a way to omit race
    85  	// instrumentation when used from the runtime while keeping race
    86  	// instrumentation when used from user code. Somehow this doesn't seem to
    87  	// cause problems, though we may be skating on thin ice. See #61204.
    88  	"-internal/bytealg",
    89  }
    90  
    91  var noRaceFuncPkgs = []string{"sync", "sync/atomic", "internal/sync", "internal/runtime/atomic"}
    92  
    93  var allowAsmABIPkgs = []string{
    94  	"runtime",
    95  	"reflect",
    96  	"syscall",
    97  	"internal/bytealg",
    98  	"internal/chacha8rand",
    99  	"internal/runtime/syscall/linux",
   100  	"internal/runtime/syscall/windows",
   101  	"internal/runtime/startlinetest",
   102  }
   103  
   104  // LookupPkgSpecial returns special build properties for the given package path.
   105  func LookupPkgSpecial(pkgPath string) PkgSpecial {
   106  	return pkgSpecialsOnce()[pkgPath]
   107  }
   108  
   109  var pkgSpecialsOnce = sync.OnceValue(func() map[string]PkgSpecial {
   110  	// Construct pkgSpecials from various package lists. This lets us use
   111  	// more flexible logic, while keeping the final map simple, and avoids
   112  	// the init-time cost of a map.
   113  	pkgSpecials := make(map[string]PkgSpecial)
   114  	set := func(elt string, f func(*PkgSpecial)) {
   115  		s := pkgSpecials[elt]
   116  		f(&s)
   117  		pkgSpecials[elt] = s
   118  	}
   119  	for _, pkg := range runtimePkgs {
   120  		set(pkg, func(ps *PkgSpecial) { ps.Runtime = true; ps.NoInstrument = true })
   121  	}
   122  	for _, pkg := range extraNoInstrumentPkgs {
   123  		if pkg[0] == '-' {
   124  			set(pkg[1:], func(ps *PkgSpecial) { ps.NoInstrument = false })
   125  		} else {
   126  			set(pkg, func(ps *PkgSpecial) { ps.NoInstrument = true })
   127  		}
   128  	}
   129  	for _, pkg := range noRaceFuncPkgs {
   130  		set(pkg, func(ps *PkgSpecial) { ps.NoRaceFunc = true })
   131  	}
   132  	for _, pkg := range allowAsmABIPkgs {
   133  		set(pkg, func(ps *PkgSpecial) { ps.AllowAsmABI = true })
   134  	}
   135  	return pkgSpecials
   136  })
   137  

View as plain text