Source file src/runtime/runtime1.go

     1  // Copyright 2009 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 runtime
     6  
     7  import (
     8  	"internal/bytealg"
     9  	"internal/goarch"
    10  	"internal/runtime/atomic"
    11  	"internal/strconv"
    12  	"unsafe"
    13  )
    14  
    15  // Keep a cached value to make gotraceback fast,
    16  // since we call it on every call to gentraceback.
    17  // The cached value is a uint32 in which the low bits
    18  // are the "crash" and "all" settings and the remaining
    19  // bits are the traceback value (0 off, 1 on, 2 include system).
    20  const (
    21  	tracebackCrash = 1 << iota
    22  	tracebackAll
    23  	tracebackShift = iota
    24  )
    25  
    26  var traceback_cache uint32 = 2 << tracebackShift
    27  var traceback_env uint32
    28  
    29  // gotraceback returns the current traceback settings.
    30  //
    31  // If level is 0, suppress all tracebacks.
    32  // If level is 1, show tracebacks, but exclude runtime frames.
    33  // If level is 2, show tracebacks including runtime frames.
    34  // If all is set, print all goroutine stacks. Otherwise, print just the current goroutine.
    35  // If crash is set, crash (core dump, etc) after tracebacking.
    36  //
    37  //go:nosplit
    38  func gotraceback() (level int32, all, crash bool) {
    39  	gp := getg()
    40  	t := atomic.Load(&traceback_cache)
    41  	crash = t&tracebackCrash != 0
    42  	all = gp.m.throwing >= throwTypeUser || t&tracebackAll != 0
    43  	if gp.m.traceback != 0 {
    44  		level = int32(gp.m.traceback)
    45  	} else if gp.m.throwing >= throwTypeRuntime {
    46  		// Always include runtime frames in runtime throws unless
    47  		// otherwise overridden by m.traceback.
    48  		level = 2
    49  	} else {
    50  		level = int32(t >> tracebackShift)
    51  	}
    52  	return
    53  }
    54  
    55  var (
    56  	argc int32
    57  	argv **byte
    58  )
    59  
    60  // nosplit for use in linux startup sysargs.
    61  //
    62  //go:nosplit
    63  func argv_index(argv **byte, i int32) *byte {
    64  	return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*goarch.PtrSize))
    65  }
    66  
    67  func args(c int32, v **byte) {
    68  	argc = c
    69  	argv = v
    70  	sysargs(c, v)
    71  }
    72  
    73  func goargs() {
    74  	if GOOS == "windows" {
    75  		return
    76  	}
    77  	argslice = make([]string, argc)
    78  	for i := int32(0); i < argc; i++ {
    79  		argslice[i] = gostringnocopy(argv_index(argv, i))
    80  	}
    81  }
    82  
    83  func goenvs_unix() {
    84  	// TODO(austin): ppc64 in dynamic linking mode doesn't
    85  	// guarantee env[] will immediately follow argv. Might cause
    86  	// problems.
    87  	n := int32(0)
    88  	for argv_index(argv, argc+1+n) != nil {
    89  		n++
    90  	}
    91  
    92  	envs = make([]string, n)
    93  	for i := int32(0); i < n; i++ {
    94  		envs[i] = gostring(argv_index(argv, argc+1+i))
    95  	}
    96  }
    97  
    98  func environ() []string {
    99  	return envs
   100  }
   101  
   102  // TODO: These should be locals in testAtomic64, but we don't 8-byte
   103  // align stack variables on 386.
   104  var test_z64, test_x64 uint64
   105  
   106  func testAtomic64() {
   107  	test_z64 = 42
   108  	test_x64 = 0
   109  	if atomic.Cas64(&test_z64, test_x64, 1) {
   110  		throw("cas64 failed")
   111  	}
   112  	if test_x64 != 0 {
   113  		throw("cas64 failed")
   114  	}
   115  	test_x64 = 42
   116  	if !atomic.Cas64(&test_z64, test_x64, 1) {
   117  		throw("cas64 failed")
   118  	}
   119  	if test_x64 != 42 || test_z64 != 1 {
   120  		throw("cas64 failed")
   121  	}
   122  	if atomic.Load64(&test_z64) != 1 {
   123  		throw("load64 failed")
   124  	}
   125  	atomic.Store64(&test_z64, (1<<40)+1)
   126  	if atomic.Load64(&test_z64) != (1<<40)+1 {
   127  		throw("store64 failed")
   128  	}
   129  	if atomic.Xadd64(&test_z64, (1<<40)+1) != (2<<40)+2 {
   130  		throw("xadd64 failed")
   131  	}
   132  	if atomic.Load64(&test_z64) != (2<<40)+2 {
   133  		throw("xadd64 failed")
   134  	}
   135  	if atomic.Xchg64(&test_z64, (3<<40)+3) != (2<<40)+2 {
   136  		throw("xchg64 failed")
   137  	}
   138  	if atomic.Load64(&test_z64) != (3<<40)+3 {
   139  		throw("xchg64 failed")
   140  	}
   141  }
   142  
   143  func check() {
   144  	var (
   145  		a     int8
   146  		b     uint8
   147  		c     int16
   148  		d     uint16
   149  		e     int32
   150  		f     uint32
   151  		g     int64
   152  		h     uint64
   153  		i, i1 float32
   154  		j, j1 float64
   155  		k     unsafe.Pointer
   156  		l     *uint16
   157  		m     [4]byte
   158  	)
   159  	type x1t struct {
   160  		x uint8
   161  	}
   162  	type y1t struct {
   163  		x1 x1t
   164  		y  uint8
   165  	}
   166  	var x1 x1t
   167  	var y1 y1t
   168  
   169  	if unsafe.Sizeof(a) != 1 {
   170  		throw("bad a")
   171  	}
   172  	if unsafe.Sizeof(b) != 1 {
   173  		throw("bad b")
   174  	}
   175  	if unsafe.Sizeof(c) != 2 {
   176  		throw("bad c")
   177  	}
   178  	if unsafe.Sizeof(d) != 2 {
   179  		throw("bad d")
   180  	}
   181  	if unsafe.Sizeof(e) != 4 {
   182  		throw("bad e")
   183  	}
   184  	if unsafe.Sizeof(f) != 4 {
   185  		throw("bad f")
   186  	}
   187  	if unsafe.Sizeof(g) != 8 {
   188  		throw("bad g")
   189  	}
   190  	if unsafe.Sizeof(h) != 8 {
   191  		throw("bad h")
   192  	}
   193  	if unsafe.Sizeof(i) != 4 {
   194  		throw("bad i")
   195  	}
   196  	if unsafe.Sizeof(j) != 8 {
   197  		throw("bad j")
   198  	}
   199  	if unsafe.Sizeof(k) != goarch.PtrSize {
   200  		throw("bad k")
   201  	}
   202  	if unsafe.Sizeof(l) != goarch.PtrSize {
   203  		throw("bad l")
   204  	}
   205  	if unsafe.Sizeof(x1) != 1 {
   206  		throw("bad unsafe.Sizeof x1")
   207  	}
   208  	if unsafe.Offsetof(y1.y) != 1 {
   209  		throw("bad offsetof y1.y")
   210  	}
   211  	if unsafe.Sizeof(y1) != 2 {
   212  		throw("bad unsafe.Sizeof y1")
   213  	}
   214  
   215  	var z uint32
   216  	z = 1
   217  	if !atomic.Cas(&z, 1, 2) {
   218  		throw("cas1")
   219  	}
   220  	if z != 2 {
   221  		throw("cas2")
   222  	}
   223  
   224  	z = 4
   225  	if atomic.Cas(&z, 5, 6) {
   226  		throw("cas3")
   227  	}
   228  	if z != 4 {
   229  		throw("cas4")
   230  	}
   231  
   232  	z = 0xffffffff
   233  	if !atomic.Cas(&z, 0xffffffff, 0xfffffffe) {
   234  		throw("cas5")
   235  	}
   236  	if z != 0xfffffffe {
   237  		throw("cas6")
   238  	}
   239  
   240  	m = [4]byte{1, 1, 1, 1}
   241  	atomic.Or8(&m[1], 0xf0)
   242  	if m[0] != 1 || m[1] != 0xf1 || m[2] != 1 || m[3] != 1 {
   243  		throw("atomicor8")
   244  	}
   245  
   246  	m = [4]byte{0xff, 0xff, 0xff, 0xff}
   247  	atomic.And8(&m[1], 0x1)
   248  	if m[0] != 0xff || m[1] != 0x1 || m[2] != 0xff || m[3] != 0xff {
   249  		throw("atomicand8")
   250  	}
   251  
   252  	*(*uint64)(unsafe.Pointer(&j)) = ^uint64(0)
   253  	if j == j {
   254  		throw("float64nan")
   255  	}
   256  	if !(j != j) {
   257  		throw("float64nan1")
   258  	}
   259  
   260  	*(*uint64)(unsafe.Pointer(&j1)) = ^uint64(1)
   261  	if j == j1 {
   262  		throw("float64nan2")
   263  	}
   264  	if !(j != j1) {
   265  		throw("float64nan3")
   266  	}
   267  
   268  	*(*uint32)(unsafe.Pointer(&i)) = ^uint32(0)
   269  	if i == i {
   270  		throw("float32nan")
   271  	}
   272  	if i == i {
   273  		throw("float32nan1")
   274  	}
   275  
   276  	*(*uint32)(unsafe.Pointer(&i1)) = ^uint32(1)
   277  	if i == i1 {
   278  		throw("float32nan2")
   279  	}
   280  	if i == i1 {
   281  		throw("float32nan3")
   282  	}
   283  
   284  	testAtomic64()
   285  
   286  	if fixedStack != round2(fixedStack) {
   287  		throw("FixedStack is not power-of-2")
   288  	}
   289  
   290  	if !checkASM() {
   291  		throw("assembly checks failed")
   292  	}
   293  }
   294  
   295  type dbgVar struct {
   296  	name   string
   297  	value  *int32        // for variables that can only be set at startup
   298  	atomic *atomic.Int32 // for variables that can be changed during execution
   299  	def    int32         // default value (ideally zero)
   300  }
   301  
   302  // Holds variables parsed from GODEBUG env var,
   303  // except for "memprofilerate" since there is an
   304  // existing int var for that value, which may
   305  // already have an initial value.
   306  var debug struct {
   307  	cgocheck                 int32
   308  	clobberfree              int32
   309  	containermaxprocs        int32
   310  	decoratemappings         int32
   311  	disablethp               int32
   312  	dontfreezetheworld       int32
   313  	efence                   int32
   314  	gccheckmark              int32
   315  	gcpacertrace             int32
   316  	gcshrinkstackoff         int32
   317  	gcstoptheworld           int32
   318  	gctrace                  int32
   319  	invalidptr               int32
   320  	madvdontneed             int32 // for Linux; issue 28466
   321  	scavtrace                int32
   322  	scheddetail              int32
   323  	schedtrace               int32
   324  	tracebackancestors       int32
   325  	updatemaxprocs           int32
   326  	asyncpreemptoff          int32
   327  	harddecommit             int32
   328  	adaptivestackstart       int32
   329  	tracefpunwindoff         int32
   330  	traceadvanceperiod       int32
   331  	traceCheckStackOwnership int32
   332  	profstackdepth           int32
   333  	dataindependenttiming    int32
   334  
   335  	// debug.malloc is used as a combined debug check
   336  	// in the malloc function and should be set
   337  	// if any of the below debug options is != 0.
   338  	malloc          bool
   339  	inittrace       int32
   340  	sbrk            int32
   341  	checkfinalizers int32
   342  	// traceallocfree controls whether execution traces contain
   343  	// detailed trace data about memory allocation. This value
   344  	// affects debug.malloc only if it is != 0 and the execution
   345  	// tracer is enabled, in which case debug.malloc will be
   346  	// set to "true" if it isn't already while tracing is enabled.
   347  	// It will be set while the world is stopped, so it's safe.
   348  	// The value of traceallocfree can be changed any time in response
   349  	// to os.Setenv("GODEBUG").
   350  	traceallocfree atomic.Int32
   351  
   352  	panicnil atomic.Int32
   353  
   354  	// asynctimerchan controls whether timer channels
   355  	// behave asynchronously (as in Go 1.22 and earlier)
   356  	// instead of their Go 1.23+ synchronous behavior.
   357  	// The value can change at any time (in response to os.Setenv("GODEBUG"))
   358  	// and affects all extant timer channels immediately.
   359  	// Programs wouldn't normally change over an execution,
   360  	// but allowing it is convenient for testing and for programs
   361  	// that do an os.Setenv in main.init or main.main.
   362  	asynctimerchan atomic.Int32
   363  }
   364  
   365  var dbgvars = []*dbgVar{
   366  	{name: "adaptivestackstart", value: &debug.adaptivestackstart},
   367  	{name: "asyncpreemptoff", value: &debug.asyncpreemptoff},
   368  	{name: "asynctimerchan", atomic: &debug.asynctimerchan},
   369  	{name: "cgocheck", value: &debug.cgocheck},
   370  	{name: "clobberfree", value: &debug.clobberfree},
   371  	{name: "containermaxprocs", value: &debug.containermaxprocs, def: 1},
   372  	{name: "dataindependenttiming", value: &debug.dataindependenttiming},
   373  	{name: "decoratemappings", value: &debug.decoratemappings, def: 1},
   374  	{name: "disablethp", value: &debug.disablethp},
   375  	{name: "dontfreezetheworld", value: &debug.dontfreezetheworld},
   376  	{name: "checkfinalizers", value: &debug.checkfinalizers},
   377  	{name: "efence", value: &debug.efence},
   378  	{name: "gccheckmark", value: &debug.gccheckmark},
   379  	{name: "gcpacertrace", value: &debug.gcpacertrace},
   380  	{name: "gcshrinkstackoff", value: &debug.gcshrinkstackoff},
   381  	{name: "gcstoptheworld", value: &debug.gcstoptheworld},
   382  	{name: "gctrace", value: &debug.gctrace},
   383  	{name: "harddecommit", value: &debug.harddecommit},
   384  	{name: "inittrace", value: &debug.inittrace},
   385  	{name: "invalidptr", value: &debug.invalidptr},
   386  	{name: "madvdontneed", value: &debug.madvdontneed},
   387  	{name: "panicnil", atomic: &debug.panicnil},
   388  	{name: "profstackdepth", value: &debug.profstackdepth, def: 128},
   389  	{name: "sbrk", value: &debug.sbrk},
   390  	{name: "scavtrace", value: &debug.scavtrace},
   391  	{name: "scheddetail", value: &debug.scheddetail},
   392  	{name: "schedtrace", value: &debug.schedtrace},
   393  	{name: "traceadvanceperiod", value: &debug.traceadvanceperiod},
   394  	{name: "traceallocfree", atomic: &debug.traceallocfree},
   395  	{name: "tracecheckstackownership", value: &debug.traceCheckStackOwnership},
   396  	{name: "tracebackancestors", value: &debug.tracebackancestors},
   397  	{name: "tracefpunwindoff", value: &debug.tracefpunwindoff},
   398  	{name: "updatemaxprocs", value: &debug.updatemaxprocs, def: 1},
   399  }
   400  
   401  func parseRuntimeDebugVars(godebug string) {
   402  	// defaults
   403  	debug.cgocheck = 1
   404  	debug.invalidptr = 1
   405  	debug.adaptivestackstart = 1 // set this to 0 to turn larger initial goroutine stacks off
   406  	if GOOS == "linux" {
   407  		// On Linux, MADV_FREE is faster than MADV_DONTNEED,
   408  		// but doesn't affect many of the statistics that
   409  		// MADV_DONTNEED does until the memory is actually
   410  		// reclaimed. This generally leads to poor user
   411  		// experience, like confusing stats in top and other
   412  		// monitoring tools; and bad integration with
   413  		// management systems that respond to memory usage.
   414  		// Hence, default to MADV_DONTNEED.
   415  		debug.madvdontneed = 1
   416  	}
   417  	debug.traceadvanceperiod = defaultTraceAdvancePeriod
   418  
   419  	// apply runtime defaults, if any
   420  	for _, v := range dbgvars {
   421  		if v.def != 0 {
   422  			// Every var should have either v.value or v.atomic set.
   423  			if v.value != nil {
   424  				*v.value = v.def
   425  			} else if v.atomic != nil {
   426  				v.atomic.Store(v.def)
   427  			}
   428  		}
   429  	}
   430  	// apply compile-time GODEBUG settings
   431  	parsegodebug(godebugDefault, nil)
   432  
   433  	// apply environment settings
   434  	parsegodebug(godebug, nil)
   435  
   436  	debug.malloc = (debug.inittrace | debug.sbrk | debug.checkfinalizers) != 0
   437  	debug.profstackdepth = min(debug.profstackdepth, maxProfStackDepth)
   438  
   439  	// Disable async preemption in checkmark mode. The following situation is
   440  	// problematic with checkmark mode:
   441  	//
   442  	// - The GC doesn't mark object A because it is truly dead.
   443  	// - The GC stops the world, asynchronously preempting G1 which has a reference
   444  	//   to A in its top stack frame
   445  	// - During the stop the world, we run the second checkmark GC. It marks the roots
   446  	//   and discovers A through G1.
   447  	// - Checkmark mode reports a failure since there's a discrepancy in mark metadata.
   448  	//
   449  	// We could disable just conservative scanning during the checkmark scan, which is
   450  	// safe but makes checkmark slightly less powerful, but that's a lot more invasive
   451  	// than just disabling async preemption altogether.
   452  	if debug.gccheckmark > 0 {
   453  		debug.asyncpreemptoff = 1
   454  	}
   455  }
   456  
   457  func finishDebugVarsSetup() {
   458  	p := new(string)
   459  	*p = gogetenv("GODEBUG")
   460  	godebugEnv.Store(p)
   461  
   462  	setTraceback(gogetenv("GOTRACEBACK"))
   463  	traceback_env = traceback_cache
   464  }
   465  
   466  // reparsedebugvars reparses the runtime's debug variables
   467  // because the environment variable has been changed to env.
   468  func reparsedebugvars(env string) {
   469  	seen := make(map[string]bool)
   470  	// apply environment settings
   471  	parsegodebug(env, seen)
   472  	// apply compile-time GODEBUG settings for as-yet-unseen variables
   473  	parsegodebug(godebugDefault, seen)
   474  	// apply defaults for as-yet-unseen variables
   475  	for _, v := range dbgvars {
   476  		if v.atomic != nil && !seen[v.name] {
   477  			v.atomic.Store(0)
   478  		}
   479  	}
   480  }
   481  
   482  // parsegodebug parses the godebug string, updating variables listed in dbgvars.
   483  // If seen == nil, this is startup time and we process the string left to right
   484  // overwriting older settings with newer ones.
   485  // If seen != nil, $GODEBUG has changed and we are doing an
   486  // incremental update. To avoid flapping in the case where a value is
   487  // set multiple times (perhaps in the default and the environment,
   488  // or perhaps twice in the environment), we process the string right-to-left
   489  // and only change values not already seen. After doing this for both
   490  // the environment and the default settings, the caller must also call
   491  // cleargodebug(seen) to reset any now-unset values back to their defaults.
   492  func parsegodebug(godebug string, seen map[string]bool) {
   493  	for p := godebug; p != ""; {
   494  		var field string
   495  		if seen == nil {
   496  			// startup: process left to right, overwriting older settings with newer
   497  			i := bytealg.IndexByteString(p, ',')
   498  			if i < 0 {
   499  				field, p = p, ""
   500  			} else {
   501  				field, p = p[:i], p[i+1:]
   502  			}
   503  		} else {
   504  			// incremental update: process right to left, updating and skipping seen
   505  			i := len(p) - 1
   506  			for i >= 0 && p[i] != ',' {
   507  				i--
   508  			}
   509  			if i < 0 {
   510  				p, field = "", p
   511  			} else {
   512  				p, field = p[:i], p[i+1:]
   513  			}
   514  		}
   515  		i := bytealg.IndexByteString(field, '=')
   516  		if i < 0 {
   517  			continue
   518  		}
   519  		key, value := field[:i], field[i+1:]
   520  		if seen[key] {
   521  			continue
   522  		}
   523  		if seen != nil {
   524  			seen[key] = true
   525  		}
   526  
   527  		// Update MemProfileRate directly here since it
   528  		// is int, not int32, and should only be updated
   529  		// if specified in GODEBUG.
   530  		if seen == nil && key == "memprofilerate" {
   531  			if n, err := strconv.Atoi(value); err == nil {
   532  				MemProfileRate = n
   533  			}
   534  		} else {
   535  			for _, v := range dbgvars {
   536  				if v.name == key {
   537  					if n, err := strconv.ParseInt(value, 10, 32); err == nil {
   538  						if seen == nil && v.value != nil {
   539  							*v.value = int32(n)
   540  						} else if v.atomic != nil {
   541  							v.atomic.Store(int32(n))
   542  						}
   543  					}
   544  				}
   545  			}
   546  		}
   547  	}
   548  
   549  	if debug.cgocheck > 1 {
   550  		throw("cgocheck > 1 mode is no longer supported at runtime. Use GOEXPERIMENT=cgocheck2 at build time instead.")
   551  	}
   552  }
   553  
   554  //go:linkname setTraceback runtime/debug.SetTraceback
   555  func setTraceback(level string) {
   556  	var t uint32
   557  	switch level {
   558  	case "none":
   559  		t = 0
   560  	case "single", "":
   561  		t = 1 << tracebackShift
   562  	case "all":
   563  		t = 1<<tracebackShift | tracebackAll
   564  	case "system":
   565  		t = 2<<tracebackShift | tracebackAll
   566  	case "crash":
   567  		t = 2<<tracebackShift | tracebackAll | tracebackCrash
   568  	case "wer":
   569  		if GOOS == "windows" {
   570  			t = 2<<tracebackShift | tracebackAll | tracebackCrash
   571  			enableWER()
   572  			break
   573  		}
   574  		fallthrough
   575  	default:
   576  		t = tracebackAll
   577  		if n, err := strconv.Atoi(level); err == nil && n == int(uint32(n)) {
   578  			t |= uint32(n) << tracebackShift
   579  		}
   580  	}
   581  	// when C owns the process, simply exit'ing the process on fatal errors
   582  	// and panics is surprising. Be louder and abort instead.
   583  	if islibrary || isarchive {
   584  		t |= tracebackCrash
   585  	}
   586  
   587  	t |= traceback_env
   588  
   589  	atomic.Store(&traceback_cache, t)
   590  }
   591  
   592  // Helpers for Go. Must be NOSPLIT, must only call NOSPLIT functions, and must not block.
   593  
   594  //go:nosplit
   595  func acquirem() *m {
   596  	gp := getg()
   597  	gp.m.locks++
   598  	return gp.m
   599  }
   600  
   601  //go:nosplit
   602  func releasem(mp *m) {
   603  	gp := getg()
   604  	mp.locks--
   605  	if mp.locks == 0 && gp.preempt {
   606  		// restore the preemption request in case we've cleared it in newstack
   607  		gp.stackguard0 = stackPreempt
   608  	}
   609  }
   610  
   611  // reflect_typelinks is meant for package reflect,
   612  // but widely used packages access it using linkname.
   613  // Notable members of the hall of shame include:
   614  //   - gitee.com/quant1x/gox
   615  //   - github.com/goccy/json
   616  //   - github.com/modern-go/reflect2
   617  //   - github.com/vmware/govmomi
   618  //   - github.com/pinpoint-apm/pinpoint-go-agent
   619  //   - github.com/timandy/routine
   620  //   - github.com/v2pro/plz
   621  //
   622  // Do not remove or change the type signature.
   623  // See go.dev/issue/67401.
   624  //
   625  //go:linkname reflect_typelinks reflect.typelinks
   626  func reflect_typelinks() ([]unsafe.Pointer, [][]int32) {
   627  	modules := activeModules()
   628  	sections := []unsafe.Pointer{unsafe.Pointer(modules[0].types)}
   629  	ret := [][]int32{modules[0].typelinks}
   630  	for _, md := range modules[1:] {
   631  		sections = append(sections, unsafe.Pointer(md.types))
   632  		ret = append(ret, md.typelinks)
   633  	}
   634  	return sections, ret
   635  }
   636  
   637  // reflect_resolveNameOff resolves a name offset from a base pointer.
   638  //
   639  // reflect_resolveNameOff is for package reflect,
   640  // but widely used packages access it using linkname.
   641  // Notable members of the hall of shame include:
   642  //   - github.com/agiledragon/gomonkey/v2
   643  //
   644  // Do not remove or change the type signature.
   645  // See go.dev/issue/67401.
   646  //
   647  //go:linkname reflect_resolveNameOff reflect.resolveNameOff
   648  func reflect_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
   649  	return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
   650  }
   651  
   652  // reflect_resolveTypeOff resolves an *rtype offset from a base type.
   653  //
   654  // reflect_resolveTypeOff is meant for package reflect,
   655  // but widely used packages access it using linkname.
   656  // Notable members of the hall of shame include:
   657  //   - gitee.com/quant1x/gox
   658  //   - github.com/modern-go/reflect2
   659  //   - github.com/v2pro/plz
   660  //   - github.com/timandy/routine
   661  //
   662  // Do not remove or change the type signature.
   663  // See go.dev/issue/67401.
   664  //
   665  //go:linkname reflect_resolveTypeOff reflect.resolveTypeOff
   666  func reflect_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
   667  	return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
   668  }
   669  
   670  // reflect_resolveTextOff resolves a function pointer offset from a base type.
   671  //
   672  // reflect_resolveTextOff is for package reflect,
   673  // but widely used packages access it using linkname.
   674  // Notable members of the hall of shame include:
   675  //   - github.com/agiledragon/gomonkey/v2
   676  //
   677  // Do not remove or change the type signature.
   678  // See go.dev/issue/67401.
   679  //
   680  //go:linkname reflect_resolveTextOff reflect.resolveTextOff
   681  func reflect_resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
   682  	return toRType((*_type)(rtype)).textOff(textOff(off))
   683  }
   684  
   685  // reflectlite_resolveNameOff resolves a name offset from a base pointer.
   686  //
   687  //go:linkname reflectlite_resolveNameOff internal/reflectlite.resolveNameOff
   688  func reflectlite_resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer {
   689  	return unsafe.Pointer(resolveNameOff(ptrInModule, nameOff(off)).Bytes)
   690  }
   691  
   692  // reflectlite_resolveTypeOff resolves an *rtype offset from a base type.
   693  //
   694  //go:linkname reflectlite_resolveTypeOff internal/reflectlite.resolveTypeOff
   695  func reflectlite_resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer {
   696  	return unsafe.Pointer(toRType((*_type)(rtype)).typeOff(typeOff(off)))
   697  }
   698  
   699  // reflect_addReflectOff adds a pointer to the reflection offset lookup map.
   700  //
   701  //go:linkname reflect_addReflectOff reflect.addReflectOff
   702  func reflect_addReflectOff(ptr unsafe.Pointer) int32 {
   703  	reflectOffsLock()
   704  	if reflectOffs.m == nil {
   705  		reflectOffs.m = make(map[int32]unsafe.Pointer)
   706  		reflectOffs.minv = make(map[unsafe.Pointer]int32)
   707  		reflectOffs.next = -1
   708  	}
   709  	id, found := reflectOffs.minv[ptr]
   710  	if !found {
   711  		id = reflectOffs.next
   712  		reflectOffs.next-- // use negative offsets as IDs to aid debugging
   713  		reflectOffs.m[id] = ptr
   714  		reflectOffs.minv[ptr] = id
   715  	}
   716  	reflectOffsUnlock()
   717  	return id
   718  }
   719  
   720  //go:linkname fips_getIndicator crypto/internal/fips140.getIndicator
   721  func fips_getIndicator() uint8 {
   722  	return getg().fipsIndicator
   723  }
   724  
   725  //go:linkname fips_setIndicator crypto/internal/fips140.setIndicator
   726  func fips_setIndicator(indicator uint8) {
   727  	getg().fipsIndicator = indicator
   728  }
   729  

View as plain text