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

View as plain text