github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/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  	"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  }