github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/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 "github.com/gagliardetto/golang-go/cmd/internal/objabi" 9 "github.com/gagliardetto/golang-go/cmd/internal/sys" 10 "fmt" 11 "log" 12 ) 13 14 // A BuildMode indicates the sort of object we are building. 15 // 16 // Possible build modes are the same as those for the -buildmode flag 17 // in cmd/go, and are documented in 'go help buildmode'. 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", "freebsd": 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 "" // avoid showing a default in usage message 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 // LinkMode indicates whether an external linker is used for the final link. 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 // mustLinkExternal reports whether the program being linked requires 168 // the external linker be used to complete the link. 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 // Internally linking cgo is incomplete on some architectures. 187 // https://golang.org/issue/14449 188 // https://golang.org/issue/21961 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 // When the race flag is set, the LLVM tsan relocatable file is linked 194 // into the final binary, which means external linking is required because 195 // internal linking does not support it. 196 if *flagRace && ctxt.Arch.InFamily(sys.PPC64) { 197 return true, "race on " + objabi.GOARCH 198 } 199 200 // Some build modes require work the internal linker cannot do (yet). 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 // Internal linking does not support TLS_IE. 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 // determineLinkMode sets ctxt.LinkMode. 226 // 227 // It is called after flags are processed and inputs are processed, 228 // so the ctxt.LinkMode variable has an initial value from the -linkmode 229 // flag and the iscgo externalobj variables are set. 230 func determineLinkMode(ctxt *Link) { 231 extNeeded, extReason := mustLinkExternal(ctxt) 232 via := "" 233 234 if ctxt.LinkMode == LinkAuto { 235 // The environment variable GO_EXTLINK_ENABLED controls the 236 // default value of -linkmode. If it is not set when the 237 // linker is called we take the value it was set to when 238 // cmd/link was compiled. (See make.bash.) 239 switch objabi.Getgoextlinkenabled() { 240 case "0": 241 ctxt.LinkMode = LinkInternal 242 via = "via GO_EXTLINK_ENABLED " 243 case "1": 244 ctxt.LinkMode = LinkExternal 245 via = "via GO_EXTLINK_ENABLED " 246 default: 247 if extNeeded || (iscgo && externalobj) || ctxt.BuildMode == BuildModePIE { 248 ctxt.LinkMode = LinkExternal 249 } else { 250 ctxt.LinkMode = LinkInternal 251 } 252 } 253 } 254 255 switch ctxt.LinkMode { 256 case LinkInternal: 257 if extNeeded { 258 Exitf("internal linking requested %sbut external linking required: %s", via, extReason) 259 } 260 case LinkExternal: 261 switch { 262 case objabi.GOARCH == "riscv64": 263 Exitf("external linking not supported for %s/riscv64", objabi.GOOS) 264 case objabi.GOARCH == "ppc64" && objabi.GOOS != "aix": 265 Exitf("external linking not supported for %s/ppc64", objabi.GOOS) 266 } 267 } 268 }