mirror of
https://github.com/golang/go
synced 2024-11-05 16:06:10 -07:00
cmd/link: attempt to rationalize linkmode init
This CL gives Linkmode a type, switches it to the standard flag handling mechanism, and deduplicates some logic. There is a semantic change in this CL. Previously if a link was invoked explicitly with -linkmode=internal, any condition that forced external linking would silently override this and use external linking. Instead it now fails with a reason why. I believe this is an improvement, but will change it back if there's disagreement. Fixes #12848 Change-Id: Ic80e341fff65ecfdd2b6fdd6079674cc7210fc5f Reviewed-on: https://go-review.googlesource.com/28971 Run-TryBot: David Crawshaw <crawshaw@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
1df438f79c
commit
6007c8c76b
@ -35,7 +35,6 @@ import (
|
|||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"cmd/link/internal/ld"
|
"cmd/link/internal/ld"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reading object files.
|
// Reading object files.
|
||||||
@ -84,34 +83,6 @@ func linkarchinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archinit(ctxt *ld.Link) {
|
func archinit(ctxt *ld.Link) {
|
||||||
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
|
|
||||||
// Go was built; see ../../make.bash.
|
|
||||||
if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
|
||||||
default:
|
|
||||||
if ld.Linkmode == ld.LinkAuto {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
|
|
||||||
log.Fatalf("cannot use -linkmode=external with -H %v", ld.Headtype)
|
|
||||||
}
|
|
||||||
|
|
||||||
case obj.Hdarwin,
|
|
||||||
obj.Hdragonfly,
|
|
||||||
obj.Hfreebsd,
|
|
||||||
obj.Hlinux,
|
|
||||||
obj.Hnacl,
|
|
||||||
obj.Hnetbsd,
|
|
||||||
obj.Hopenbsd,
|
|
||||||
obj.Hsolaris,
|
|
||||||
obj.Hwindows,
|
|
||||||
obj.Hwindowsgui:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
switch ld.Headtype {
|
||||||
default:
|
default:
|
||||||
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
||||||
|
@ -35,7 +35,6 @@ import (
|
|||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"cmd/link/internal/ld"
|
"cmd/link/internal/ld"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reading object files.
|
// Reading object files.
|
||||||
@ -79,28 +78,6 @@ func linkarchinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archinit(ctxt *ld.Link) {
|
func archinit(ctxt *ld.Link) {
|
||||||
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
|
|
||||||
// Go was built; see ../../make.bash.
|
|
||||||
if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
|
||||||
default:
|
|
||||||
if ld.Linkmode == ld.LinkAuto {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
|
|
||||||
log.Fatalf("cannot use -linkmode=external with -H %v", ld.Headtype)
|
|
||||||
}
|
|
||||||
|
|
||||||
case obj.Hlinux,
|
|
||||||
obj.Hfreebsd,
|
|
||||||
obj.Hnacl,
|
|
||||||
obj.Hdarwin:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
switch ld.Headtype {
|
||||||
default:
|
default:
|
||||||
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
||||||
|
@ -35,7 +35,6 @@ import (
|
|||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"cmd/link/internal/ld"
|
"cmd/link/internal/ld"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reading object files.
|
// Reading object files.
|
||||||
@ -80,29 +79,6 @@ func linkarchinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archinit(ctxt *ld.Link) {
|
func archinit(ctxt *ld.Link) {
|
||||||
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
|
|
||||||
// Go was built; see ../../make.bash.
|
|
||||||
if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
// Darwin/arm64 only supports external linking
|
|
||||||
if ld.Headtype == obj.Hdarwin {
|
|
||||||
ld.Linkmode = ld.LinkExternal
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
|
||||||
default:
|
|
||||||
if ld.Linkmode == ld.LinkAuto {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
|
|
||||||
log.Fatalf("cannot use -linkmode=external with -H %v", ld.Headtype)
|
|
||||||
}
|
|
||||||
case obj.Hlinux, obj.Hdarwin:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
switch ld.Headtype {
|
||||||
default:
|
default:
|
||||||
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
||||||
|
242
src/cmd/link/internal/ld/config.go
Normal file
242
src/cmd/link/internal/ld/config.go
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
// Copyright 2016 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package ld
|
||||||
|
|
||||||
|
import (
|
||||||
|
"cmd/internal/obj"
|
||||||
|
"cmd/internal/sys"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
Linkmode LinkMode
|
||||||
|
Buildmode BuildMode
|
||||||
|
)
|
||||||
|
|
||||||
|
// A BuildMode indicates the sort of object we are building.
|
||||||
|
//
|
||||||
|
// Possible build modes are the same as those for the -buildmode flag
|
||||||
|
// in cmd/go, and are documented in 'go help buildmode'.
|
||||||
|
type BuildMode uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
BuildmodeUnset BuildMode = iota
|
||||||
|
BuildmodeExe
|
||||||
|
BuildmodePIE
|
||||||
|
BuildmodeCArchive
|
||||||
|
BuildmodeCShared
|
||||||
|
BuildmodeShared
|
||||||
|
BuildmodePlugin
|
||||||
|
)
|
||||||
|
|
||||||
|
func (mode *BuildMode) Set(s string) error {
|
||||||
|
badmode := func() error {
|
||||||
|
return fmt.Errorf("buildmode %s not supported on %s/%s", s, obj.GOOS, obj.GOARCH)
|
||||||
|
}
|
||||||
|
switch s {
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid buildmode: %q", s)
|
||||||
|
case "exe":
|
||||||
|
*mode = BuildmodeExe
|
||||||
|
case "pie":
|
||||||
|
switch obj.GOOS {
|
||||||
|
case "android", "linux":
|
||||||
|
default:
|
||||||
|
return badmode()
|
||||||
|
}
|
||||||
|
*mode = BuildmodePIE
|
||||||
|
case "c-archive":
|
||||||
|
switch obj.GOOS {
|
||||||
|
case "darwin", "linux":
|
||||||
|
case "windows":
|
||||||
|
switch obj.GOARCH {
|
||||||
|
case "amd64", "386":
|
||||||
|
default:
|
||||||
|
return badmode()
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return badmode()
|
||||||
|
}
|
||||||
|
*mode = BuildmodeCArchive
|
||||||
|
case "c-shared":
|
||||||
|
switch obj.GOARCH {
|
||||||
|
case "386", "amd64", "arm", "arm64":
|
||||||
|
default:
|
||||||
|
return badmode()
|
||||||
|
}
|
||||||
|
*mode = BuildmodeCShared
|
||||||
|
case "shared":
|
||||||
|
switch obj.GOOS {
|
||||||
|
case "linux":
|
||||||
|
switch obj.GOARCH {
|
||||||
|
case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
|
||||||
|
default:
|
||||||
|
return badmode()
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return badmode()
|
||||||
|
}
|
||||||
|
*mode = BuildmodeShared
|
||||||
|
case "plugin":
|
||||||
|
switch obj.GOOS {
|
||||||
|
case "linux":
|
||||||
|
switch obj.GOARCH {
|
||||||
|
case "386", "amd64", "arm", "arm64":
|
||||||
|
default:
|
||||||
|
return badmode()
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return badmode()
|
||||||
|
}
|
||||||
|
*mode = BuildmodePlugin
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mode *BuildMode) String() string {
|
||||||
|
switch *mode {
|
||||||
|
case BuildmodeUnset:
|
||||||
|
return "" // avoid showing a default in usage message
|
||||||
|
case BuildmodeExe:
|
||||||
|
return "exe"
|
||||||
|
case BuildmodePIE:
|
||||||
|
return "pie"
|
||||||
|
case BuildmodeCArchive:
|
||||||
|
return "c-archive"
|
||||||
|
case BuildmodeCShared:
|
||||||
|
return "c-shared"
|
||||||
|
case BuildmodeShared:
|
||||||
|
return "shared"
|
||||||
|
case BuildmodePlugin:
|
||||||
|
return "plugin"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinkMode indicates whether an external linker is used for the final link.
|
||||||
|
type LinkMode uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
LinkAuto LinkMode = iota
|
||||||
|
LinkInternal
|
||||||
|
LinkExternal
|
||||||
|
)
|
||||||
|
|
||||||
|
func (mode *LinkMode) Set(s string) error {
|
||||||
|
switch s {
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid linkmode: %q", s)
|
||||||
|
case "auto":
|
||||||
|
*mode = LinkAuto
|
||||||
|
case "internal":
|
||||||
|
*mode = LinkInternal
|
||||||
|
case "external":
|
||||||
|
*mode = LinkExternal
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mode *LinkMode) String() string {
|
||||||
|
switch *mode {
|
||||||
|
case LinkAuto:
|
||||||
|
return "auto"
|
||||||
|
case LinkInternal:
|
||||||
|
return "internal"
|
||||||
|
case LinkExternal:
|
||||||
|
return "external"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("LinkMode(%d)", uint8(*mode))
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustLinkExternal reports whether the program being linked requires
|
||||||
|
// the external linker be used to complete the link.
|
||||||
|
func mustLinkExternal(ctxt *Link) (res bool, reason string) {
|
||||||
|
if ctxt.Debugvlog > 1 {
|
||||||
|
defer func() {
|
||||||
|
if res {
|
||||||
|
log.Printf("external linking is forced by: %s\n", reason)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch obj.GOOS {
|
||||||
|
case "android":
|
||||||
|
return true, "android"
|
||||||
|
case "darwin":
|
||||||
|
if SysArch.InFamily(sys.ARM, sys.ARM64) {
|
||||||
|
return true, "iOS"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if *flagMsan {
|
||||||
|
return true, "msan"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internally linking cgo is incomplete on some architectures.
|
||||||
|
// https://golang.org/issue/10373
|
||||||
|
// https://golang.org/issue/14449
|
||||||
|
if iscgo && SysArch.InFamily(sys.ARM64, sys.MIPS64) {
|
||||||
|
return true, obj.GOARCH + " does not support internal cgo"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some build modes require work the internal linker cannot do (yet).
|
||||||
|
switch Buildmode {
|
||||||
|
case BuildmodeCArchive:
|
||||||
|
return true, "buildmode=c-archive"
|
||||||
|
case BuildmodeCShared:
|
||||||
|
return true, "buildmode=c-shared"
|
||||||
|
case BuildmodePIE:
|
||||||
|
switch obj.GOOS + "/" + obj.GOARCH {
|
||||||
|
case "linux/amd64":
|
||||||
|
default:
|
||||||
|
// Internal linking does not support TLS_IE.
|
||||||
|
return true, "buildmode=pie"
|
||||||
|
}
|
||||||
|
case BuildmodeShared:
|
||||||
|
return true, "buildmode=shared"
|
||||||
|
}
|
||||||
|
if *FlagLinkshared {
|
||||||
|
return true, "dynamically linking with a shared library"
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// determineLinkMode sets Linkmode.
|
||||||
|
//
|
||||||
|
// It is called after flags are processed and inputs are processed,
|
||||||
|
// so the Linkmode variable has an initial value from the -linkmode
|
||||||
|
// flag and the iscgo externalobj variables are set.
|
||||||
|
func determineLinkMode(ctxt *Link) {
|
||||||
|
switch Linkmode {
|
||||||
|
case LinkAuto:
|
||||||
|
// The environment variable GO_EXTLINK_ENABLED controls the
|
||||||
|
// default value of -linkmode. If it is not set when the
|
||||||
|
// linker is called we take the value it was set to when
|
||||||
|
// cmd/link was compiled. (See make.bash.)
|
||||||
|
switch obj.Getgoextlinkenabled() {
|
||||||
|
case "0":
|
||||||
|
if needed, reason := mustLinkExternal(ctxt); needed {
|
||||||
|
Exitf("internal linking requested via GO_EXTLINK_ENABLED, but external linking required: %s", reason)
|
||||||
|
}
|
||||||
|
Linkmode = LinkInternal
|
||||||
|
case "1":
|
||||||
|
Linkmode = LinkExternal
|
||||||
|
default:
|
||||||
|
if needed, _ := mustLinkExternal(ctxt); needed {
|
||||||
|
Linkmode = LinkExternal
|
||||||
|
} else if iscgo && externalobj {
|
||||||
|
Linkmode = LinkExternal
|
||||||
|
} else {
|
||||||
|
Linkmode = LinkInternal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case LinkInternal:
|
||||||
|
if needed, reason := mustLinkExternal(ctxt); needed {
|
||||||
|
Exitf("internal linking requested but external linking required: %s", reason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -419,15 +419,3 @@ func importcycles() {
|
|||||||
p.cycle()
|
p.cycle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setlinkmode(arg string) {
|
|
||||||
if arg == "internal" {
|
|
||||||
Linkmode = LinkInternal
|
|
||||||
} else if arg == "external" {
|
|
||||||
Linkmode = LinkExternal
|
|
||||||
} else if arg == "auto" {
|
|
||||||
Linkmode = LinkAuto
|
|
||||||
} else {
|
|
||||||
Exitf("unknown link mode -linkmode %s", arg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -198,7 +198,6 @@ var (
|
|||||||
Headtype obj.HeadType
|
Headtype obj.HeadType
|
||||||
|
|
||||||
nerrors int
|
nerrors int
|
||||||
Linkmode int
|
|
||||||
liveness int64
|
liveness int64
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -441,49 +440,12 @@ func (ctxt *Link) loadlib() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Linkmode == LinkAuto {
|
// We now have enough information to determine the link mode.
|
||||||
if iscgo && externalobj {
|
determineLinkMode(ctxt)
|
||||||
Linkmode = LinkExternal
|
|
||||||
} else {
|
|
||||||
Linkmode = LinkInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force external linking for android.
|
if Linkmode == LinkExternal && SysArch.Family == sys.PPC64 {
|
||||||
if obj.GOOS == "android" {
|
toc := Linklookup(ctxt, ".TOC.", 0)
|
||||||
Linkmode = LinkExternal
|
toc.Type = obj.SDYNIMPORT
|
||||||
}
|
|
||||||
|
|
||||||
// These build modes depend on the external linker
|
|
||||||
// to handle some relocations (such as TLS IE) not
|
|
||||||
// yet supported by the internal linker.
|
|
||||||
switch Buildmode {
|
|
||||||
case BuildmodeCArchive, BuildmodeCShared, BuildmodePIE, BuildmodePlugin, BuildmodeShared:
|
|
||||||
Linkmode = LinkExternal
|
|
||||||
}
|
|
||||||
if *FlagLinkshared {
|
|
||||||
Linkmode = LinkExternal
|
|
||||||
}
|
|
||||||
|
|
||||||
// cgo on Darwin must use external linking
|
|
||||||
// we can always use external linking, but then there will be circular
|
|
||||||
// dependency problems when compiling natively (external linking requires
|
|
||||||
// runtime/cgo, runtime/cgo requires cmd/cgo, but cmd/cgo needs to be
|
|
||||||
// compiled using external linking.)
|
|
||||||
if SysArch.InFamily(sys.ARM, sys.ARM64) && Headtype == obj.Hdarwin && iscgo {
|
|
||||||
Linkmode = LinkExternal
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force external linking for msan.
|
|
||||||
if *flagMsan {
|
|
||||||
Linkmode = LinkExternal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cmd/7l doesn't support cgo internal linking
|
|
||||||
// This is https://golang.org/issue/10373.
|
|
||||||
// mips64x doesn't support cgo internal linking either (golang.org/issue/14449)
|
|
||||||
if iscgo && (obj.GOARCH == "arm64" || obj.GOARCH == "mips64" || obj.GOARCH == "mips64le") {
|
|
||||||
Linkmode = LinkExternal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if Linkmode == LinkExternal && !iscgo {
|
if Linkmode == LinkExternal && !iscgo {
|
||||||
|
@ -159,6 +159,8 @@ type Shlib struct {
|
|||||||
gcdataAddresses map[*Symbol]uint64
|
gcdataAddresses map[*Symbol]uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Link holds the context for writing object code from a compiler
|
||||||
|
// or for reading that input into the linker.
|
||||||
type Link struct {
|
type Link struct {
|
||||||
Arch *sys.Arch
|
Arch *sys.Arch
|
||||||
Debugvlog int
|
Debugvlog int
|
||||||
@ -265,17 +267,3 @@ const (
|
|||||||
RV_CHECK_OVERFLOW = 1 << 8
|
RV_CHECK_OVERFLOW = 1 << 8
|
||||||
RV_TYPE_MASK = RV_CHECK_OVERFLOW - 1
|
RV_TYPE_MASK = RV_CHECK_OVERFLOW - 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pcdata iterator.
|
|
||||||
// for(pciterinit(ctxt, &it, &pcd); !it.done; pciternext(&it)) { it.value holds in [it.pc, it.nextpc) }
|
|
||||||
|
|
||||||
// Link holds the context for writing object code from a compiler
|
|
||||||
// to be linker input or for reading that input into the linker.
|
|
||||||
|
|
||||||
// LinkArch is the definition of a single architecture.
|
|
||||||
|
|
||||||
const (
|
|
||||||
LinkAuto = 0 + iota
|
|
||||||
LinkInternal
|
|
||||||
LinkExternal
|
|
||||||
)
|
|
||||||
|
@ -48,6 +48,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
flag.Var(&Linkmode, "linkmode", "set link `mode`")
|
||||||
flag.Var(&Buildmode, "buildmode", "set build `mode`")
|
flag.Var(&Buildmode, "buildmode", "set build `mode`")
|
||||||
flag.Var(&Headtype, "H", "set header `type`")
|
flag.Var(&Headtype, "H", "set header `type`")
|
||||||
flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
|
flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
|
||||||
@ -59,7 +60,6 @@ var (
|
|||||||
|
|
||||||
flagOutfile = flag.String("o", "", "write output to `file`")
|
flagOutfile = flag.String("o", "", "write output to `file`")
|
||||||
FlagLinkshared = flag.Bool("linkshared", false, "link against installed Go shared libraries")
|
FlagLinkshared = flag.Bool("linkshared", false, "link against installed Go shared libraries")
|
||||||
Buildmode BuildMode
|
|
||||||
|
|
||||||
flagInstallSuffix = flag.String("installsuffix", "", "set package directory `suffix`")
|
flagInstallSuffix = flag.String("installsuffix", "", "set package directory `suffix`")
|
||||||
flagDumpDep = flag.Bool("dumpdep", false, "dump symbol dependency graph")
|
flagDumpDep = flag.Bool("dumpdep", false, "dump symbol dependency graph")
|
||||||
@ -120,7 +120,6 @@ func Main() {
|
|||||||
obj.Flagfn0("V", "print version and exit", doversion)
|
obj.Flagfn0("V", "print version and exit", doversion)
|
||||||
obj.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
|
obj.Flagfn1("X", "add string value `definition` of the form importpath.name=value", func(s string) { addstrdata1(ctxt, s) })
|
||||||
obj.Flagcount("v", "print link trace", &ctxt.Debugvlog)
|
obj.Flagcount("v", "print link trace", &ctxt.Debugvlog)
|
||||||
obj.Flagfn1("linkmode", "set link `mode` (internal, external, auto)", setlinkmode)
|
|
||||||
|
|
||||||
obj.Flagparse(usage)
|
obj.Flagparse(usage)
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@ package ld
|
|||||||
import (
|
import (
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -166,107 +165,3 @@ func Linklookup(ctxt *Link, name string, v int) *Symbol {
|
|||||||
func Linkrlookup(ctxt *Link, name string, v int) *Symbol {
|
func Linkrlookup(ctxt *Link, name string, v int) *Symbol {
|
||||||
return ctxt.Hash[v][name]
|
return ctxt.Hash[v][name]
|
||||||
}
|
}
|
||||||
|
|
||||||
// A BuildMode indicates the sort of object we are building:
|
|
||||||
// "exe": build a main package and everything it imports into an executable.
|
|
||||||
// "c-shared": build a main package, plus all packages that it imports, into a
|
|
||||||
// single C shared library. The only callable symbols will be those functions
|
|
||||||
// marked as exported.
|
|
||||||
// "shared": combine all packages passed on the command line, and their
|
|
||||||
// dependencies, into a single shared library that will be used when
|
|
||||||
// building with the -linkshared option.
|
|
||||||
type BuildMode uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
BuildmodeUnset BuildMode = iota
|
|
||||||
BuildmodeExe
|
|
||||||
BuildmodePIE
|
|
||||||
BuildmodeCArchive
|
|
||||||
BuildmodeCShared
|
|
||||||
BuildmodeShared
|
|
||||||
BuildmodePlugin
|
|
||||||
)
|
|
||||||
|
|
||||||
func (mode *BuildMode) Set(s string) error {
|
|
||||||
badmode := func() error {
|
|
||||||
return fmt.Errorf("buildmode %s not supported on %s/%s", s, obj.GOOS, obj.GOARCH)
|
|
||||||
}
|
|
||||||
switch s {
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("invalid buildmode: %q", s)
|
|
||||||
case "exe":
|
|
||||||
*mode = BuildmodeExe
|
|
||||||
case "pie":
|
|
||||||
switch obj.GOOS {
|
|
||||||
case "android", "linux":
|
|
||||||
default:
|
|
||||||
return badmode()
|
|
||||||
}
|
|
||||||
*mode = BuildmodePIE
|
|
||||||
case "c-archive":
|
|
||||||
switch obj.GOOS {
|
|
||||||
case "darwin", "linux":
|
|
||||||
case "windows":
|
|
||||||
switch obj.GOARCH {
|
|
||||||
case "amd64", "386":
|
|
||||||
default:
|
|
||||||
return badmode()
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return badmode()
|
|
||||||
}
|
|
||||||
*mode = BuildmodeCArchive
|
|
||||||
case "c-shared":
|
|
||||||
switch obj.GOARCH {
|
|
||||||
case "386", "amd64", "arm", "arm64":
|
|
||||||
default:
|
|
||||||
return badmode()
|
|
||||||
}
|
|
||||||
*mode = BuildmodeCShared
|
|
||||||
case "shared":
|
|
||||||
switch obj.GOOS {
|
|
||||||
case "linux":
|
|
||||||
switch obj.GOARCH {
|
|
||||||
case "386", "amd64", "arm", "arm64", "ppc64le", "s390x":
|
|
||||||
default:
|
|
||||||
return badmode()
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return badmode()
|
|
||||||
}
|
|
||||||
*mode = BuildmodeShared
|
|
||||||
case "plugin":
|
|
||||||
switch obj.GOOS {
|
|
||||||
case "linux":
|
|
||||||
switch obj.GOARCH {
|
|
||||||
case "386", "amd64", "arm", "arm64":
|
|
||||||
default:
|
|
||||||
return badmode()
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return badmode()
|
|
||||||
}
|
|
||||||
*mode = BuildmodePlugin
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mode *BuildMode) String() string {
|
|
||||||
switch *mode {
|
|
||||||
case BuildmodeUnset:
|
|
||||||
return "" // avoid showing a default in usage message
|
|
||||||
case BuildmodeExe:
|
|
||||||
return "exe"
|
|
||||||
case BuildmodePIE:
|
|
||||||
return "pie"
|
|
||||||
case BuildmodeCArchive:
|
|
||||||
return "c-archive"
|
|
||||||
case BuildmodeCShared:
|
|
||||||
return "c-shared"
|
|
||||||
case BuildmodeShared:
|
|
||||||
return "shared"
|
|
||||||
case BuildmodePlugin:
|
|
||||||
return "plugin"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
|
|
||||||
}
|
|
||||||
|
@ -35,7 +35,6 @@ import (
|
|||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"cmd/link/internal/ld"
|
"cmd/link/internal/ld"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reading object files.
|
// Reading object files.
|
||||||
@ -93,25 +92,6 @@ func linkarchinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archinit(ctxt *ld.Link) {
|
func archinit(ctxt *ld.Link) {
|
||||||
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
|
|
||||||
// Go was built; see ../../make.bash.
|
|
||||||
if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
|
||||||
default:
|
|
||||||
if ld.Linkmode == ld.LinkAuto {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
|
|
||||||
log.Fatalf("cannot use -linkmode=external with -H %v", ld.Headtype)
|
|
||||||
}
|
|
||||||
|
|
||||||
case obj.Hlinux:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
switch ld.Headtype {
|
||||||
default:
|
default:
|
||||||
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
||||||
|
@ -35,7 +35,6 @@ import (
|
|||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"cmd/link/internal/ld"
|
"cmd/link/internal/ld"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reading object files.
|
// Reading object files.
|
||||||
@ -94,39 +93,6 @@ func linkarchinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archinit(ctxt *ld.Link) {
|
func archinit(ctxt *ld.Link) {
|
||||||
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
|
|
||||||
// Go was built; see ../../make.bash.
|
|
||||||
if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Buildmode {
|
|
||||||
case ld.BuildmodePIE, ld.BuildmodeShared:
|
|
||||||
ld.Linkmode = ld.LinkExternal
|
|
||||||
}
|
|
||||||
|
|
||||||
if *ld.FlagLinkshared {
|
|
||||||
ld.Linkmode = ld.LinkExternal
|
|
||||||
}
|
|
||||||
|
|
||||||
if ld.Linkmode == ld.LinkExternal {
|
|
||||||
toc := ld.Linklookup(ctxt, ".TOC.", 0)
|
|
||||||
toc.Type = obj.SDYNIMPORT
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
|
||||||
default:
|
|
||||||
if ld.Linkmode == ld.LinkAuto {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
|
|
||||||
log.Fatalf("cannot use -linkmode=external with -H %v", ld.Headtype)
|
|
||||||
}
|
|
||||||
|
|
||||||
case obj.Hlinux:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
switch ld.Headtype {
|
||||||
default:
|
default:
|
||||||
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
||||||
|
@ -80,12 +80,6 @@ func linkarchinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archinit(ctxt *ld.Link) {
|
func archinit(ctxt *ld.Link) {
|
||||||
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
|
|
||||||
// Go was built; see ../../make.bash.
|
|
||||||
if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
switch ld.Headtype {
|
||||||
default:
|
default:
|
||||||
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
||||||
|
@ -35,7 +35,6 @@ import (
|
|||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
"cmd/link/internal/ld"
|
"cmd/link/internal/ld"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reading object files.
|
// Reading object files.
|
||||||
@ -79,31 +78,6 @@ func linkarchinit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func archinit(ctxt *ld.Link) {
|
func archinit(ctxt *ld.Link) {
|
||||||
// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
|
|
||||||
// Go was built; see ../../make.bash.
|
|
||||||
if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
|
||||||
default:
|
|
||||||
if ld.Linkmode == ld.LinkAuto {
|
|
||||||
ld.Linkmode = ld.LinkInternal
|
|
||||||
}
|
|
||||||
if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
|
|
||||||
log.Fatalf("cannot use -linkmode=external with -H %v", ld.Headtype)
|
|
||||||
}
|
|
||||||
|
|
||||||
case obj.Hdarwin,
|
|
||||||
obj.Hfreebsd,
|
|
||||||
obj.Hlinux,
|
|
||||||
obj.Hnetbsd,
|
|
||||||
obj.Hopenbsd,
|
|
||||||
obj.Hwindows,
|
|
||||||
obj.Hwindowsgui:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ld.Headtype {
|
switch ld.Headtype {
|
||||||
default:
|
default:
|
||||||
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
ld.Exitf("unknown -H option: %v", ld.Headtype)
|
||||||
|
Loading…
Reference in New Issue
Block a user