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", "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
197
198
199 if iscgo && ctxt.Arch.InFamily(sys.MIPS64, sys.MIPS, sys.PPC64, sys.RISCV64) {
200 return true, buildcfg.GOARCH + " does not support internal cgo"
201 }
202 if iscgo && (buildcfg.GOOS == "android" || buildcfg.GOOS == "dragonfly") {
203
204
205
206 return true, buildcfg.GOOS + " does not support internal cgo"
207 }
208 if iscgo && buildcfg.GOOS == "windows" && buildcfg.GOARCH == "arm64" {
209
210 return true, buildcfg.GOOS + "/" + buildcfg.GOARCH + " does not support internal cgo"
211 }
212
213
214
215
216 if *flagRace && ctxt.Arch.InFamily(sys.PPC64) {
217 return true, "race on " + buildcfg.GOARCH
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 "linux/amd64", "linux/arm64", "android/arm64":
229 case "windows/386", "windows/amd64", "windows/arm", "windows/arm64":
230 case "darwin/amd64", "darwin/arm64":
231 default:
232
233 return true, "buildmode=pie"
234 }
235 case BuildModePlugin:
236 return true, "buildmode=plugin"
237 case BuildModeShared:
238 return true, "buildmode=shared"
239 }
240 if ctxt.linkShared {
241 return true, "dynamically linking with a shared library"
242 }
243
244 if unknownObjFormat {
245 return true, "some input objects have an unrecognized file format"
246 }
247
248 return false, ""
249 }
250
251
252
253
254
255
256 func determineLinkMode(ctxt *Link) {
257 extNeeded, extReason := mustLinkExternal(ctxt)
258 via := ""
259
260 if ctxt.LinkMode == LinkAuto {
261
262
263
264
265 switch buildcfg.Getgoextlinkenabled() {
266 case "0":
267 ctxt.LinkMode = LinkInternal
268 via = "via GO_EXTLINK_ENABLED "
269 case "1":
270 ctxt.LinkMode = LinkExternal
271 via = "via GO_EXTLINK_ENABLED "
272 default:
273 if extNeeded || (iscgo && externalobj) {
274 ctxt.LinkMode = LinkExternal
275 } else {
276 ctxt.LinkMode = LinkInternal
277 }
278 }
279 }
280
281 switch ctxt.LinkMode {
282 case LinkInternal:
283 if extNeeded {
284 Exitf("internal linking requested %sbut external linking required: %s", via, extReason)
285 }
286 case LinkExternal:
287 switch {
288 case buildcfg.GOARCH == "ppc64" && buildcfg.GOOS != "aix":
289 Exitf("external linking not supported for %s/ppc64", buildcfg.GOOS)
290 }
291 }
292 }
293
View as plain text