]> Cypherpunks repositories - gostls13.git/commitdiff
internal/godebugs: add decoratemappings as an opaque godebug setting
authorMichael Pratt <mpratt@google.com>
Fri, 7 Mar 2025 18:53:34 +0000 (13:53 -0500)
committerGopher Robot <gobot@golang.org>
Mon, 10 Mar 2025 15:29:59 +0000 (08:29 -0700)
This adds a new godebug to control whether the runtime applies the
anonymous memory mapping annotations added in https://go.dev/cl/646095.
It is enabled by default.

This has several effects:

* The feature is only enabled by default when the main go.mod has go >=
  1.25.
* This feature can be disabled with GODEBUG=decoratemappings=0, or the
  equivalents in go.mod or package main. See https://go.dev/doc/godebug.
* As an opaque setting, this option will not appear in runtime/metrics.
* This setting is non-atomic, so it cannot be changed after startup.

I am not 100% sure about my decision for the last two points.

I've made this an opaque setting because it affects every memory mapping
the runtime performs. Thus every mapping would report "non-default
behavior", which doesn't seem useful.

This setting could trivially be atomic and allow changes at run time,
but those changes would only affect future mappings. That seems
confusing and not helpful. On the other hand, going back to annotate or
unannotate every previous mapping when the setting changes is
unwarranted complexity.

For #71546.

Change-Id: I6a6a636c5ad551d76691cba2a6f668d5cff0e352
Reviewed-on: https://go-review.googlesource.com/c/go/+/655895
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Pratt <mpratt@google.com>

doc/godebug.md
doc/next/4-runtime.md
src/cmd/go/testdata/script/godebug_decoratemappings.txt [new file with mode: 0644]
src/internal/godebugs/table.go
src/runtime/extern.go
src/runtime/runtime1.go
src/runtime/set_vma_name_linux.go
test/decoratemappingszero.go [new file with mode: 0644]

index 4325b958204f19da690735f351a4b87bad7a09e7..650a8e20bf7a809a424b492a4f417c10c0b1ccd1 100644 (file)
@@ -153,6 +153,17 @@ for example,
 see the [runtime documentation](/pkg/runtime#hdr-Environment_Variables)
 and the [go command documentation](/cmd/go#hdr-Build_and_test_caching).
 
+### Go 1.25
+
+Go 1.25 added a new `decoratemappings` setting that controls whether the Go
+runtime annotates OS anonymous memory mappings with context about their
+purpose. These annotations appear in /proc/self/maps and /proc/self/smaps as
+"[anon: Go: ...]". This setting is only used on Linux. For Go 1.25, it defaults
+to `decoratemappings=1`, enabling annotations. Using `decoratemappings=0`
+reverts to the pre-Go 1.25 behavior. This setting is fixed at program startup
+time, and can't be modified by changing the `GODEBUG` environment variable
+after the program starts.
+
 ### Go 1.24
 
 Go 1.24 added a new `fips140` setting that controls whether the Go
index 28483eb519d3423489383716ea4573437d625fb0..b6b50f1c0a755f96669b439c1d56fd275764eec9 100644 (file)
@@ -16,3 +16,11 @@ value would print:
 This program will now print:
 
     panic: PANIC [recovered, reraised]
+
+<!-- go.dev/issue/71546 -->
+
+On Linux systems with kernel support for anonymous VMA names
+(`CONFIG_ANON_VMA_NAME`), the Go runtime will annotate anonymous memory
+mappings with context about their purpose. e.g., `[anon: Go: heap]` for heap
+memory. This can be disabled with the [GODEBUG setting](/doc/godebug)
+`decoratemappings=0`.
diff --git a/src/cmd/go/testdata/script/godebug_decoratemappings.txt b/src/cmd/go/testdata/script/godebug_decoratemappings.txt
new file mode 100644 (file)
index 0000000..19b466c
--- /dev/null
@@ -0,0 +1,37 @@
+env GO111MODULE=on
+
+# Go 1.24 module should disable decoratemappings.
+go list -f '{{.Module.GoVersion}} {{.DefaultGODEBUG}}'
+stdout decoratemappings=0
+
+[!GOOS:linux] skip
+[short] skip
+
+# Programs in Go 1.24 module should never see annotations. This ensures that
+# the runtime has not overridden the default.
+go run .
+
+-- go.mod --
+go 1.24
+module m
+
+-- main.go --
+package main
+
+import (
+       "log"
+       "os"
+       "strings"
+)
+
+func main() {
+       b, err := os.ReadFile("/proc/self/maps")
+       if err != nil {
+               log.Fatalf("Error reading: %v", err)
+       }
+
+       if strings.Contains(string(b), "[anon: Go:") {
+               log.Printf("/proc/self/maps:\n%s", string(b))
+               log.Fatalf("/proc/self/maps contains Go annotation")
+       }
+}
index e0fde01f09d9bb40f06e3d724c61b793278a7fc9..214de6bdbe54c7e9b1bc8171d9344a019e4dbd80 100644 (file)
@@ -27,6 +27,7 @@ type Info struct {
 var All = []Info{
        {Name: "asynctimerchan", Package: "time", Changed: 23, Old: "1"},
        {Name: "dataindependenttiming", Package: "crypto/subtle", Opaque: true},
+       {Name: "decoratemappings", Package: "runtime", Opaque: true, Changed: 25, Old: "0"},
        {Name: "execerrdot", Package: "os/exec"},
        {Name: "fips140", Package: "crypto/fips140", Opaque: true},
        {Name: "gocachehash", Package: "cmd/go"},
index fad19b9449a5eb0f46a149113fa558c506e16f11..8ee89ab94fd1cb974d0c5e5f93336e0720aa240f 100644 (file)
@@ -52,6 +52,13 @@ It is a comma-separated list of name=val pairs setting these named variables:
        cgocheck mode can be enabled using GOEXPERIMENT (which
        requires a rebuild), see https://pkg.go.dev/internal/goexperiment for details.
 
+       decoratemappings: controls whether the Go runtime annotates OS
+       anonymous memory mappings with context about their purpose. These
+       annotations appear in /proc/self/maps and /proc/self/smaps as
+       "[anon: Go: ...]". This setting is only used on Linux. For Go 1.25, it
+       defaults to `decoratemappings=1`, enabling annotations. Using
+       `decoratemappings=0` reverts to the pre-Go 1.25 behavior.
+
        disablethp: setting disablethp=1 on Linux disables transparent huge pages for the heap.
        It has no effect on other platforms. disablethp is meant for compatibility with versions
        of Go before 1.21, which stopped working around a Linux kernel default that can result
index fb16f6daefda40d3f1159bd41fa6bc9f5de50f3b..ec4f7d043393f42f853a89fef3b8b67794165d86 100644 (file)
@@ -309,6 +309,7 @@ type dbgVar struct {
 var debug struct {
        cgocheck                 int32
        clobberfree              int32
+       decoratemappings         int32
        disablethp               int32
        dontfreezetheworld       int32
        efence                   int32
@@ -369,6 +370,7 @@ var dbgvars = []*dbgVar{
        {name: "cgocheck", value: &debug.cgocheck},
        {name: "clobberfree", value: &debug.clobberfree},
        {name: "dataindependenttiming", value: &debug.dataindependenttiming},
+       {name: "decoratemappings", value: &debug.decoratemappings, def: 1},
        {name: "disablethp", value: &debug.disablethp},
        {name: "dontfreezetheworld", value: &debug.dontfreezetheworld},
        {name: "efence", value: &debug.efence},
index b413b1ce9bc6e62c24e7768bc84f77ca6dd51aa4..100c2bfecac60c90c089c91eb2adabcc723927fc 100644 (file)
@@ -16,7 +16,7 @@ var prSetVMAUnsupported atomic.Bool
 
 // setVMAName calls prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, start, len, name)
 func setVMAName(start unsafe.Pointer, length uintptr, name string) {
-       if unsupported := prSetVMAUnsupported.Load(); unsupported {
+       if debug.decoratemappings == 0 || prSetVMAUnsupported.Load() {
                return
        }
 
diff --git a/test/decoratemappingszero.go b/test/decoratemappingszero.go
new file mode 100644 (file)
index 0000000..162e553
--- /dev/null
@@ -0,0 +1,30 @@
+// run
+
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Disable mapping annotations, which only exists for Linux.
+
+//go:debug decoratemappings=0
+//go:build linux
+
+package main
+
+import (
+       "log"
+       "os"
+       "strings"
+)
+
+func main() {
+       b, err := os.ReadFile("/proc/self/maps")
+       if err != nil {
+               log.Fatalf("Error reading: %v", err)
+       }
+
+       if strings.Contains(string(b), "[anon: Go:") {
+               log.Printf("/proc/self/maps:\n%s", string(b))
+               log.Fatalf("/proc/self/maps contains Go annotation")
+       }
+}