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