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