Home | History | Annotate | Download | only in ld
      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 	"cmd/internal/objabi"
      9 	"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 "android", "linux":
     42 		case "darwin":
     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 "darwin", "linux":
     55 		case "windows":
     56 			switch objabi.GOARCH {
     57 			case "amd64", "386":
     58 			default:
     59 				return badmode()
     60 			}
     61 		default:
     62 			return badmode()
     63 		}
     64 		*mode = BuildModeCArchive
     65 	case "c-shared":
     66 		switch objabi.GOARCH {
     67 		case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
     68 		default:
     69 			return badmode()
     70 		}
     71 		*mode = BuildModeCShared
     72 	case "shared":
     73 		switch objabi.GOOS {
     74 		case "linux":
     75 			switch objabi.GOARCH {
     76 			case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
     77 			default:
     78 				return badmode()
     79 			}
     80 		default:
     81 			return badmode()
     82 		}
     83 		*mode = BuildModeShared
     84 	case "plugin":
     85 		switch objabi.GOOS {
     86 		case "linux":
     87 			switch objabi.GOARCH {
     88 			case "386", "amd64", "arm", "arm64", "s390x", "ppc64le":
     89 			default:
     90 				return badmode()
     91 			}
     92 		case "darwin":
     93 			switch objabi.GOARCH {
     94 			case "amd64":
     95 			default:
     96 				return badmode()
     97 			}
     98 		default:
     99 			return badmode()
    100 		}
    101 		*mode = BuildModePlugin
    102 	}
    103 	return nil
    104 }
    105 
    106 func (mode *BuildMode) String() string {
    107 	switch *mode {
    108 	case BuildModeUnset:
    109 		return "" // avoid showing a default in usage message
    110 	case BuildModeExe:
    111 		return "exe"
    112 	case BuildModePIE:
    113 		return "pie"
    114 	case BuildModeCArchive:
    115 		return "c-archive"
    116 	case BuildModeCShared:
    117 		return "c-shared"
    118 	case BuildModeShared:
    119 		return "shared"
    120 	case BuildModePlugin:
    121 		return "plugin"
    122 	}
    123 	return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
    124 }
    125 
    126 // LinkMode indicates whether an external linker is used for the final link.
    127 type LinkMode uint8
    128 
    129 const (
    130 	LinkAuto LinkMode = iota
    131 	LinkInternal
    132 	LinkExternal
    133 )
    134 
    135 func (mode *LinkMode) Set(s string) error {
    136 	switch s {
    137 	default:
    138 		return fmt.Errorf("invalid linkmode: %q", s)
    139 	case "auto":
    140 		*mode = LinkAuto
    141 	case "internal":
    142 		*mode = LinkInternal
    143 	case "external":
    144 		*mode = LinkExternal
    145 	}
    146 	return nil
    147 }
    148 
    149 func (mode *LinkMode) String() string {
    150 	switch *mode {
    151 	case LinkAuto:
    152 		return "auto"
    153 	case LinkInternal:
    154 		return "internal"
    155 	case LinkExternal:
    156 		return "external"
    157 	}
    158 	return fmt.Sprintf("LinkMode(%d)", uint8(*mode))
    159 }
    160 
    161 // mustLinkExternal reports whether the program being linked requires
    162 // the external linker be used to complete the link.
    163 func mustLinkExternal(ctxt *Link) (res bool, reason string) {
    164 	if ctxt.Debugvlog > 1 {
    165 		defer func() {
    166 			if res {
    167 				log.Printf("external linking is forced by: %s\n", reason)
    168 			}
    169 		}()
    170 	}
    171 
    172 	switch objabi.GOOS {
    173 	case "android":
    174 		return true, "android"
    175 	case "darwin":
    176 		if ctxt.Arch.InFamily(sys.ARM, sys.ARM64) {
    177 			return true, "iOS"
    178 		}
    179 	}
    180 
    181 	if *flagMsan {
    182 		return true, "msan"
    183 	}
    184 
    185 	// Internally linking cgo is incomplete on some architectures.
    186 	// https://golang.org/issue/10373
    187 	// https://golang.org/issue/14449
    188 	// https://golang.org/issue/21961
    189 	if iscgo && ctxt.Arch.InFamily(sys.ARM64, sys.MIPS64, sys.MIPS, sys.PPC64) {
    190 		return true, objabi.GOARCH + " does not support internal cgo"
    191 	}
    192 
    193 	// Some build modes require work the internal linker cannot do (yet).
    194 	switch ctxt.BuildMode {
    195 	case BuildModeCArchive:
    196 		return true, "buildmode=c-archive"
    197 	case BuildModeCShared:
    198 		return true, "buildmode=c-shared"
    199 	case BuildModePIE:
    200 		switch objabi.GOOS + "/" + objabi.GOARCH {
    201 		case "linux/amd64":
    202 		default:
    203 			// Internal linking does not support TLS_IE.
    204 			return true, "buildmode=pie"
    205 		}
    206 	case BuildModePlugin:
    207 		return true, "buildmode=plugin"
    208 	case BuildModeShared:
    209 		return true, "buildmode=shared"
    210 	}
    211 	if ctxt.linkShared {
    212 		return true, "dynamically linking with a shared library"
    213 	}
    214 
    215 	return false, ""
    216 }
    217 
    218 // determineLinkMode sets ctxt.LinkMode.
    219 //
    220 // It is called after flags are processed and inputs are processed,
    221 // so the ctxt.LinkMode variable has an initial value from the -linkmode
    222 // flag and the iscgo externalobj variables are set.
    223 func determineLinkMode(ctxt *Link) {
    224 	switch ctxt.LinkMode {
    225 	case LinkAuto:
    226 		// The environment variable GO_EXTLINK_ENABLED controls the
    227 		// default value of -linkmode. If it is not set when the
    228 		// linker is called we take the value it was set to when
    229 		// cmd/link was compiled. (See make.bash.)
    230 		switch objabi.Getgoextlinkenabled() {
    231 		case "0":
    232 			if needed, reason := mustLinkExternal(ctxt); needed {
    233 				Exitf("internal linking requested via GO_EXTLINK_ENABLED, but external linking required: %s", reason)
    234 			}
    235 			ctxt.LinkMode = LinkInternal
    236 		case "1":
    237 			ctxt.LinkMode = LinkExternal
    238 		default:
    239 			if needed, _ := mustLinkExternal(ctxt); needed {
    240 				ctxt.LinkMode = LinkExternal
    241 			} else if iscgo && externalobj {
    242 				ctxt.LinkMode = LinkExternal
    243 			} else if ctxt.BuildMode == BuildModePIE {
    244 				ctxt.LinkMode = LinkExternal // https://golang.org/issue/18968
    245 			} else {
    246 				ctxt.LinkMode = LinkInternal
    247 			}
    248 		}
    249 	case LinkInternal:
    250 		if needed, reason := mustLinkExternal(ctxt); needed {
    251 			Exitf("internal linking requested but external linking required: %s", reason)
    252 		}
    253 	}
    254 }
    255