1
2
3
4
5 package ld
6
7 import (
8 "cmd/internal/sys"
9 "fmt"
10 "internal/buildcfg"
11 )
12
13
14
15
16
17 type BuildMode uint8
18
19 const (
20 BuildModeUnset BuildMode = iota
21 BuildModeExe
22 BuildModePIE
23 BuildModeCArchive
24 BuildModeCShared
25 BuildModeShared
26 BuildModePlugin
27 )
28
29 func (mode *BuildMode) Set(s string) error {
30 badmode := func() error {
31 return fmt.Errorf("buildmode %s not supported on %s/%s", s, buildcfg.GOOS, buildcfg.GOARCH)
32 }
33 switch s {
34 default:
35 return fmt.Errorf("invalid buildmode: %q", s)
36 case "exe":
37 switch buildcfg.GOOS + "/" + buildcfg.GOARCH {
38 case "darwin/arm64", "windows/arm", "windows/arm64":
39 *mode = BuildModePIE
40 default:
41 *mode = BuildModeExe
42 }
43 case "pie":
44 switch buildcfg.GOOS {
45 case "aix", "android", "linux", "windows", "darwin", "ios":
46 case "freebsd":
47 switch buildcfg.GOARCH {
48 case "amd64":
49 default:
50 return badmode()
51 }
52 default:
53 return badmode()
54 }
55 *mode = BuildModePIE
56 case "c-archive":
57 switch buildcfg.GOOS {
58 case "aix", "darwin", "ios", "linux":
59 case "freebsd":
60 switch buildcfg.GOARCH {
61 case "amd64":
62 default:
63 return badmode()
64 }
65 case "windows":
66 switch buildcfg.GOARCH {
67 case "amd64", "386", "arm", "arm64":
68 default:
69 return badmode()
70 }
71 default:
72 return badmode()
73 }
74 *mode = BuildModeCArchive
75 case "c-shared":
76 switch buildcfg.GOARCH {
77 case "386", "amd64", "arm", "arm64", "ppc64le", "riscv64", "s390x":
78 default:
79 return badmode()
80 }
81 *mode = BuildModeCShared
82 case "shared":
83 switch buildcfg.GOOS {
84 case "linux":
85 switch buildcfg.GOARCH {
86 case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
87 default:
88 return badmode()
89 }
90 default:
91 return badmode()
92 }
93 *mode = BuildModeShared
94 case "plugin":
95 switch buildcfg.GOOS {
96 case "linux":
97 switch buildcfg.GOARCH {
98 case "386", "amd64", "arm", "arm64", "s390x", "ppc64le":
99 default:
100 return badmode()
101 }
102 case "darwin":
103 switch buildcfg.GOARCH {
104 case "amd64", "arm64":
105 default:
106 return badmode()
107 }
108 case "freebsd":
109 switch buildcfg.GOARCH {
110 case "amd64":
111 default:
112 return badmode()
113 }
114 default:
115 return badmode()
116 }
117 *mode = BuildModePlugin
118 }
119 return nil
120 }
121
122 func (mode *BuildMode) String() string {
123 switch *mode {
124 case BuildModeUnset:
125 return ""
126 case BuildModeExe:
127 return "exe"
128 case BuildModePIE:
129 return "pie"
130 case BuildModeCArchive:
131 return "c-archive"
132 case BuildModeCShared:
133 return "c-shared"
134 case BuildModeShared:
135 return "shared"
136 case BuildModePlugin:
137 return "plugin"
138 }
139 return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
140 }
141
142
143 type LinkMode uint8
144
145 const (
146 LinkAuto LinkMode = iota
147 LinkInternal
148 LinkExternal
149 )
150
151 func (mode *LinkMode) Set(s string) error {
152 switch s {
153 default:
154 return fmt.Errorf("invalid linkmode: %q", s)
155 case "auto":
156 *mode = LinkAuto
157 case "internal":
158 *mode = LinkInternal
159 case "external":
160 *mode = LinkExternal
161 }
162 return nil
163 }
164
165 func (mode *LinkMode) String() string {
166 switch *mode {
167 case LinkAuto:
168 return "auto"
169 case LinkInternal:
170 return "internal"
171 case LinkExternal:
172 return "external"
173 }
174 return fmt.Sprintf("LinkMode(%d)", uint8(*mode))
175 }
176
177
178
179 func mustLinkExternal(ctxt *Link) (res bool, reason string) {
180 if ctxt.Debugvlog > 1 {
181 defer func() {
182 if res {
183 ctxt.Logf("external linking is forced by: %s\n", reason)
184 }
185 }()
186 }
187
188 if sys.MustLinkExternal(buildcfg.GOOS, buildcfg.GOARCH) {
189 return true, fmt.Sprintf("%s/%s requires external linking", buildcfg.GOOS, buildcfg.GOARCH)
190 }
191
192 if *flagMsan {
193 return true, "msan"
194 }
195
196 if *flagAsan {
197 return true, "asan"
198 }
199
200
201
202 if iscgo && ctxt.Arch.InFamily(sys.MIPS64, sys.MIPS, sys.RISCV64) {
203 return true, buildcfg.GOARCH + " does not support internal cgo"
204 }
205 if iscgo && (buildcfg.GOOS == "android" || buildcfg.GOOS == "dragonfly") {
206
207
208
209 return true, buildcfg.GOOS + " does not support internal cgo"
210 }
211 if iscgo && buildcfg.GOOS == "windows" && buildcfg.GOARCH == "arm64" {
212
213 return true, buildcfg.GOOS + "/" + buildcfg.GOARCH + " does not support internal cgo"
214 }
215 if iscgo && ctxt.Arch == sys.ArchPPC64 {
216
217 return true, buildcfg.GOOS + " does not support internal cgo"
218 }
219
220
221 switch ctxt.BuildMode {
222 case BuildModeCArchive:
223 return true, "buildmode=c-archive"
224 case BuildModeCShared:
225 return true, "buildmode=c-shared"
226 case BuildModePIE:
227 switch buildcfg.GOOS + "/" + buildcfg.GOARCH {
228 case "android/arm64":
229 case "linux/amd64", "linux/arm64", "linux/ppc64le":
230 case "windows/386", "windows/amd64", "windows/arm", "windows/arm64":
231 case "darwin/amd64", "darwin/arm64":
232 default:
233
234 return true, "buildmode=pie"
235 }
236 case BuildModePlugin:
237 return true, "buildmode=plugin"
238 case BuildModeShared:
239 return true, "buildmode=shared"
240 }
241 if ctxt.linkShared {
242 return true, "dynamically linking with a shared library"
243 }
244
245 if unknownObjFormat {
246 return true, "some input objects have an unrecognized file format"
247 }
248
249 return false, ""
250 }
251
252
253
254
255
256
257 func determineLinkMode(ctxt *Link) {
258 extNeeded, extReason := mustLinkExternal(ctxt)
259 via := ""
260
261 if ctxt.LinkMode == LinkAuto {
262
263
264
265
266 switch buildcfg.Getgoextlinkenabled() {
267 case "0":
268 ctxt.LinkMode = LinkInternal
269 via = "via GO_EXTLINK_ENABLED "
270 case "1":
271 ctxt.LinkMode = LinkExternal
272 via = "via GO_EXTLINK_ENABLED "
273 default:
274 if extNeeded || (iscgo && externalobj) {
275 ctxt.LinkMode = LinkExternal
276 } else {
277 ctxt.LinkMode = LinkInternal
278 }
279 }
280 }
281
282 switch ctxt.LinkMode {
283 case LinkInternal:
284 if extNeeded {
285 Exitf("internal linking requested %sbut external linking required: %s", via, extReason)
286 }
287 case LinkExternal:
288 switch {
289 case buildcfg.GOARCH == "ppc64" && buildcfg.GOOS != "aix":
290 Exitf("external linking not supported for %s/ppc64", buildcfg.GOOS)
291 }
292 }
293 }
294
View as plain text