cmd/internal/ld: support for -buildmode=shared

Change-Id: Id4997d611ced29397133f14def6abc88aa9e811e
Reviewed-on: https://go-review.googlesource.com/8252
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Michael Hudson-Doyle 2015-03-30 02:59:10 +00:00 committed by Ian Lance Taylor
parent 6f6512bd60
commit 00bc19e996
11 changed files with 153 additions and 61 deletions

View file

@ -150,6 +150,14 @@ type Section struct {
Rellen uint64
}
// DynlinkingGo returns whether we are producing Go code that can live
// in separate shared libraries linked together at runtime.
func DynlinkingGo() bool {
// TODO(mwhudson): This is a bit silly for now, but it will need to have
// "|| Linkshared" appended when a subsequent change adds that flag.
return Buildmode == BuildmodeShared
}
var (
Thestring string
Thelinkarch *LinkArch
@ -241,11 +249,15 @@ func Lflag(arg string) {
// "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 (
BuildmodeExe BuildMode = iota
BuildmodeCShared
BuildmodeShared
)
func (mode *BuildMode) Set(s string) error {
@ -260,6 +272,13 @@ func (mode *BuildMode) Set(s string) error {
return fmt.Errorf("not supported on %s", goarch)
}
*mode = BuildmodeCShared
case "shared":
goos := obj.Getgoos()
goarch := obj.Getgoarch()
if goos != "linux" || goarch != "amd64" {
return fmt.Errorf("not supported on %s/%s", goos, goarch)
}
*mode = BuildmodeShared
}
return nil
}
@ -270,6 +289,8 @@ func (mode *BuildMode) String() string {
return "exe"
case BuildmodeCShared:
return "c-shared"
case BuildmodeShared:
return "shared"
}
return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
}
@ -321,12 +342,16 @@ func libinit() {
INITENTRY = fmt.Sprintf("_rt0_%s_%s_lib", goarch, goos)
case BuildmodeExe:
INITENTRY = fmt.Sprintf("_rt0_%s_%s", goarch, goos)
case BuildmodeShared:
// No INITENTRY for -buildmode=shared
default:
Diag("unknown INITENTRY for buildmode %v", Buildmode)
}
}
Linklookup(Ctxt, INITENTRY, 0).Type = SXREF
if !DynlinkingGo() {
Linklookup(Ctxt, INITENTRY, 0).Type = SXREF
}
}
func Errorexit() {
@ -790,6 +815,16 @@ func hostlink() {
if Buildmode == BuildmodeCShared {
argv = append(argv, "-Wl,-Bsymbolic")
argv = append(argv, "-shared")
} else if Buildmode == BuildmodeShared {
// TODO(mwhudson): unless you do this, dynamic relocations fill
// out the findfunctab table and for some reason shared libraries
// and the executable both define a main function and putting the
// address of executable's main into the shared libraries
// findfunctab violates the assumptions of the runtime. TBH, I
// think we may well end up wanting to use -Bsymbolic here
// anyway.
argv = append(argv, "-Wl,-Bsymbolic-functions")
argv = append(argv, "-shared")
}
argv = append(argv, "-o")
@ -1162,7 +1197,8 @@ func stkcheck(up *Chain, depth int) int {
// external function.
// should never be called directly.
// only diagnose the direct caller.
if depth == 1 && s.Type != SXREF {
// TODO(mwhudson): actually think about this.
if depth == 1 && s.Type != SXREF && !DynlinkingGo() {
Diag("call to external function %s", s.Name)
}
return -1
@ -1477,6 +1513,7 @@ func xdefine(p string, t int, v int64) {
s.Value = v
s.Reachable = true
s.Special = 1
s.Local = true
}
func datoff(addr int64) int64 {