github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/ld/config.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ld 6 7 import ( 8 "fmt" 9 "github.com/bir3/gocompiler/src/internal/buildcfg" 10 "github.com/bir3/gocompiler/src/internal/platform" 11 ) 12 13 // A BuildMode indicates the sort of object we are building. 14 // 15 // Possible build modes are the same as those for the -buildmode flag 16 // in cmd/go, and are documented in 'go help buildmode'. 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 // Set implements flag.Value to set the build mode based on the argument 30 // to the -buildmode flag. 31 func (mode *BuildMode) Set(s string) error { 32 switch s { 33 default: 34 return fmt.Errorf("invalid buildmode: %q", s) 35 case "exe": 36 switch buildcfg.GOOS + "/" + buildcfg.GOARCH { 37 case "darwin/arm64", "windows/arm", "windows/arm64": // On these platforms, everything is PIE 38 *mode = BuildModePIE 39 default: 40 *mode = BuildModeExe 41 } 42 case "pie": 43 *mode = BuildModePIE 44 case "c-archive": 45 *mode = BuildModeCArchive 46 case "c-shared": 47 *mode = BuildModeCShared 48 case "shared": 49 *mode = BuildModeShared 50 case "plugin": 51 *mode = BuildModePlugin 52 } 53 54 if !platform.BuildModeSupported("gc", s, buildcfg.GOOS, buildcfg.GOARCH) { 55 return fmt.Errorf("buildmode %s not supported on %s/%s", s, buildcfg.GOOS, buildcfg.GOARCH) 56 } 57 58 return nil 59 } 60 61 func (mode BuildMode) String() string { 62 switch mode { 63 case BuildModeUnset: 64 return "" // avoid showing a default in usage message 65 case BuildModeExe: 66 return "exe" 67 case BuildModePIE: 68 return "pie" 69 case BuildModeCArchive: 70 return "c-archive" 71 case BuildModeCShared: 72 return "c-shared" 73 case BuildModeShared: 74 return "shared" 75 case BuildModePlugin: 76 return "plugin" 77 } 78 return fmt.Sprintf("BuildMode(%d)", uint8(mode)) 79 } 80 81 // LinkMode indicates whether an external linker is used for the final link. 82 type LinkMode uint8 83 84 const ( 85 LinkAuto LinkMode = iota 86 LinkInternal 87 LinkExternal 88 ) 89 90 func (mode *LinkMode) Set(s string) error { 91 switch s { 92 default: 93 return fmt.Errorf("invalid linkmode: %q", s) 94 case "auto": 95 *mode = LinkAuto 96 case "internal": 97 *mode = LinkInternal 98 case "external": 99 *mode = LinkExternal 100 } 101 return nil 102 } 103 104 func (mode *LinkMode) String() string { 105 switch *mode { 106 case LinkAuto: 107 return "auto" 108 case LinkInternal: 109 return "internal" 110 case LinkExternal: 111 return "external" 112 } 113 return fmt.Sprintf("LinkMode(%d)", uint8(*mode)) 114 } 115 116 // mustLinkExternal reports whether the program being linked requires 117 // the external linker be used to complete the link. 118 func mustLinkExternal(ctxt *Link) (res bool, reason string) { 119 if ctxt.Debugvlog > 1 { 120 defer func() { 121 if res { 122 ctxt.Logf("external linking is forced by: %s\n", reason) 123 } 124 }() 125 } 126 127 if platform.MustLinkExternal(buildcfg.GOOS, buildcfg.GOARCH, false) { 128 return true, fmt.Sprintf("%s/%s requires external linking", buildcfg.GOOS, buildcfg.GOARCH) 129 } 130 131 if *flagMsan { 132 return true, "msan" 133 } 134 135 if *flagAsan { 136 return true, "asan" 137 } 138 139 if iscgo && platform.MustLinkExternal(buildcfg.GOOS, buildcfg.GOARCH, true) { 140 return true, buildcfg.GOARCH + " does not support internal cgo" 141 } 142 143 // Some build modes require work the internal linker cannot do (yet). 144 switch ctxt.BuildMode { 145 case BuildModeCArchive: 146 return true, "buildmode=c-archive" 147 case BuildModeCShared: 148 return true, "buildmode=c-shared" 149 case BuildModePIE: 150 if !platform.InternalLinkPIESupported(buildcfg.GOOS, buildcfg.GOARCH) { 151 // Internal linking does not support TLS_IE. 152 return true, "buildmode=pie" 153 } 154 case BuildModePlugin: 155 return true, "buildmode=plugin" 156 case BuildModeShared: 157 return true, "buildmode=shared" 158 } 159 if ctxt.linkShared { 160 return true, "dynamically linking with a shared library" 161 } 162 163 if unknownObjFormat { 164 return true, "some input objects have an unrecognized file format" 165 } 166 167 if len(dynimportfail) > 0 { 168 // This error means that we were unable to generate 169 // the _cgo_import.go file for some packages. 170 // This typically means that there are some dependencies 171 // that the cgo tool could not figure out. 172 // See issue #52863. 173 return true, fmt.Sprintf("some packages could not be built to support internal linking (%v)", dynimportfail) 174 } 175 176 return false, "" 177 } 178 179 // determineLinkMode sets ctxt.LinkMode. 180 // 181 // It is called after flags are processed and inputs are processed, 182 // so the ctxt.LinkMode variable has an initial value from the -linkmode 183 // flag and the iscgo, externalobj, and unknownObjFormat variables are set. 184 func determineLinkMode(ctxt *Link) { 185 extNeeded, extReason := mustLinkExternal(ctxt) 186 via := "" 187 188 if ctxt.LinkMode == LinkAuto { 189 // The environment variable GO_EXTLINK_ENABLED controls the 190 // default value of -linkmode. If it is not set when the 191 // linker is called we take the value it was set to when 192 // cmd/link was compiled. (See make.bash.) 193 switch buildcfg.Getgoextlinkenabled() { 194 case "0": 195 ctxt.LinkMode = LinkInternal 196 via = "via GO_EXTLINK_ENABLED " 197 case "1": 198 ctxt.LinkMode = LinkExternal 199 via = "via GO_EXTLINK_ENABLED " 200 default: 201 preferExternal := len(preferlinkext) != 0 202 if preferExternal && ctxt.Debugvlog > 0 { 203 ctxt.Logf("external linking prefer list is %v\n", preferlinkext) 204 } 205 if extNeeded || (iscgo && (externalobj || preferExternal)) { 206 ctxt.LinkMode = LinkExternal 207 } else { 208 ctxt.LinkMode = LinkInternal 209 } 210 } 211 } 212 213 switch ctxt.LinkMode { 214 case LinkInternal: 215 if extNeeded { 216 Exitf("internal linking requested %sbut external linking required: %s", via, extReason) 217 } 218 case LinkExternal: 219 switch { 220 case buildcfg.GOARCH == "ppc64" && buildcfg.GOOS == "linux": 221 Exitf("external linking not supported for %s/ppc64", buildcfg.GOOS) 222 } 223 } 224 }