1
2
3
4
5 package load
6
7 import (
8 "errors"
9 "fmt"
10 "go/build"
11 "internal/godebugs"
12 "maps"
13 "sort"
14 "strconv"
15 "strings"
16
17 "cmd/go/internal/fips140"
18 "cmd/go/internal/gover"
19 "cmd/go/internal/modload"
20 )
21
22 var ErrNotGoDebug = errors.New("not //go:debug line")
23
24 func ParseGoDebug(text string) (key, value string, err error) {
25 if !strings.HasPrefix(text, "//go:debug") {
26 return "", "", ErrNotGoDebug
27 }
28 i := strings.IndexAny(text, " \t")
29 if i < 0 {
30 if strings.TrimSpace(text) == "//go:debug" {
31 return "", "", fmt.Errorf("missing key=value")
32 }
33 return "", "", ErrNotGoDebug
34 }
35 k, v, ok := strings.Cut(strings.TrimSpace(text[i:]), "=")
36 if !ok {
37 return "", "", fmt.Errorf("missing key=value")
38 }
39 if err := modload.CheckGodebug("//go:debug setting", k, v); err != nil {
40 return "", "", err
41 }
42 return k, v, nil
43 }
44
45
46
47
48 func defaultGODEBUG(p *Package, directives, testDirectives, xtestDirectives []build.Directive) string {
49 if p.Name != "main" {
50 return ""
51 }
52 goVersion := modload.MainModules.GoVersion()
53 if modload.RootMode == modload.NoRoot && p.Module != nil {
54
55
56
57
58 goVersion = p.Module.GoVersion
59 if goVersion == "" {
60 goVersion = "1.20"
61 }
62 }
63
64 var m map[string]string
65
66
67
68 if fips140.Enabled() {
69 if m == nil {
70 m = make(map[string]string)
71 }
72 m["fips140"] = "on"
73 }
74
75
76 for _, g := range modload.MainModules.Godebugs() {
77 if m == nil {
78 m = make(map[string]string)
79 }
80 m[g.Key] = g.Value
81 }
82
83
84 for _, list := range [][]build.Directive{p.Internal.Build.Directives, directives, testDirectives, xtestDirectives} {
85 for _, d := range list {
86 k, v, err := ParseGoDebug(d.Text)
87 if err != nil {
88 continue
89 }
90 if m == nil {
91 m = make(map[string]string)
92 }
93 m[k] = v
94 }
95 }
96 if v, ok := m["default"]; ok {
97 delete(m, "default")
98 v = strings.TrimPrefix(v, "go")
99 if gover.IsValid(v) {
100 goVersion = v
101 }
102 }
103
104 defaults := godebugForGoVersion(goVersion)
105 if defaults != nil {
106
107 maps.Copy(defaults, m)
108 m = defaults
109 }
110
111 keys := make([]string, 0, len(m))
112 for k := range m {
113 keys = append(keys, k)
114 }
115 sort.Strings(keys)
116 var b strings.Builder
117 for _, k := range keys {
118 if b.Len() > 0 {
119 b.WriteString(",")
120 }
121 b.WriteString(k)
122 b.WriteString("=")
123 b.WriteString(m[k])
124 }
125 return b.String()
126 }
127
128 func godebugForGoVersion(v string) map[string]string {
129 if strings.Count(v, ".") >= 2 {
130 i := strings.Index(v, ".")
131 j := i + 1 + strings.Index(v[i+1:], ".")
132 v = v[:j]
133 }
134
135 if !strings.HasPrefix(v, "1.") {
136 return nil
137 }
138 n, err := strconv.Atoi(v[len("1."):])
139 if err != nil {
140 return nil
141 }
142
143 def := make(map[string]string)
144 for _, info := range godebugs.All {
145 if n < info.Changed {
146 def[info.Name] = info.Old
147 }
148 }
149 return def
150 }
151
View as plain text