1
0
mirror of https://github.com/golang/go synced 2024-09-24 21:10:12 -06:00

cmd/internal/ld: add -buildmode=c-shared as an alternative to -shared

The linker currently (on some platforms) takes a -shared flag, which means
approximately what -buildmode=c-shared means in the in the proposed "Go
Execution Modes" document. As part of implementing other modes, the term
"shared" becomes horribly overloaded, so this replaces -shared with a
-buildmode argument instead (which currently only handles -buildmode=c-shared
and the default -buildmode=exe -- no new behaviour here).

As the linker support for -shared was in 1.4 this retains it as an alias.

Change-Id: Id2ebb8e05ee07f46208a554bc2622d0e67b47082
Reviewed-on: https://go-review.googlesource.com/8304
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Michael Hudson-Doyle 2015-03-27 02:48:27 +00:00 committed by Ian Lance Taylor
parent 47746f10fe
commit 2a5f88d850
8 changed files with 67 additions and 15 deletions

View File

@ -245,7 +245,7 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
case ld.R_TLS: case ld.R_TLS:
if r.Siz == 4 { if r.Siz == 4 {
if ld.Flag_shared != 0 { if ld.Buildmode == ld.BuildmodeCShared {
ld.Thearch.Lput(ld.R_ARM_TLS_IE32 | uint32(elfsym)<<8) ld.Thearch.Lput(ld.R_ARM_TLS_IE32 | uint32(elfsym)<<8)
} else { } else {
ld.Thearch.Lput(ld.R_ARM_TLS_LE32 | uint32(elfsym)<<8) ld.Thearch.Lput(ld.R_ARM_TLS_LE32 | uint32(elfsym)<<8)

View File

@ -330,7 +330,7 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
case ld.R_TLS: case ld.R_TLS:
if r.Siz == 4 { if r.Siz == 4 {
if ld.Flag_shared != 0 { if ld.Buildmode == ld.BuildmodeCShared {
ld.Thearch.Vput(ld.R_X86_64_GOTTPOFF | uint64(elfsym)<<32) ld.Thearch.Vput(ld.R_X86_64_GOTTPOFF | uint64(elfsym)<<32)
} else { } else {
ld.Thearch.Vput(ld.R_X86_64_TPOFF32 | uint64(elfsym)<<32) ld.Thearch.Vput(ld.R_X86_64_TPOFF32 | uint64(elfsym)<<32)

View File

@ -91,7 +91,7 @@ func archinit() {
ld.Linkmode = ld.LinkInternal ld.Linkmode = ld.LinkInternal
} }
if ld.Flag_shared != 0 { if ld.Buildmode == ld.BuildmodeCShared {
ld.Linkmode = ld.LinkExternal ld.Linkmode = ld.LinkExternal
} }

View File

@ -960,7 +960,7 @@ func dosymtype() {
} }
// Create a new entry in the .init_array section that points to the // Create a new entry in the .init_array section that points to the
// library initializer function. // library initializer function.
if Flag_shared != 0 && s.Name == INITENTRY { if Buildmode == BuildmodeCShared && s.Name == INITENTRY {
addinitarrdata(s) addinitarrdata(s)
} }
} }
@ -1322,7 +1322,7 @@ func dodata() {
sect.Length = uint64(datsize) - sect.Vaddr sect.Length = uint64(datsize) - sect.Vaddr
/* shared library initializer */ /* shared library initializer */
if Flag_shared != 0 { if Buildmode == BuildmodeCShared {
sect := addsection(&Segdata, ".init_array", 06) sect := addsection(&Segdata, ".init_array", 06)
sect.Align = maxalign(s, SINITARR) sect.Align = maxalign(s, SINITARR)
datsize = Rnd(datsize, int64(sect.Align)) datsize = Rnd(datsize, int64(sect.Align))

View File

@ -1658,7 +1658,7 @@ func doelf() {
Addstring(shstrtab, ".note.GNU-stack") Addstring(shstrtab, ".note.GNU-stack")
} }
if Flag_shared != 0 { if Buildmode == BuildmodeCShared {
Addstring(shstrtab, ".init_array") Addstring(shstrtab, ".init_array")
switch Thearch.Thechar { switch Thearch.Thechar {
case '6', '7', '9': case '6', '7', '9':

View File

@ -474,7 +474,7 @@ func loadcgo(file string, pkg string, p string) {
local = expandpkg(local, pkg) local = expandpkg(local, pkg)
s = Linklookup(Ctxt, local, 0) s = Linklookup(Ctxt, local, 0)
if Flag_shared != 0 && s == Linklookup(Ctxt, "main", 0) { if Buildmode == BuildmodeCShared && s == Linklookup(Ctxt, "main", 0) {
continue continue
} }

View File

@ -33,6 +33,7 @@ package ld
import ( import (
"bytes" "bytes"
"cmd/internal/obj" "cmd/internal/obj"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
@ -160,7 +161,7 @@ var (
elfglobalsymndx int elfglobalsymndx int
flag_installsuffix string flag_installsuffix string
flag_race int flag_race int
Flag_shared int Buildmode BuildMode
tracksym string tracksym string
interpreter string interpreter string
tmpdir string tmpdir string
@ -234,6 +235,44 @@ func Lflag(arg string) {
Ctxt.Libdir = append(Ctxt.Libdir, arg) Ctxt.Libdir = append(Ctxt.Libdir, arg)
} }
// 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.
type BuildMode uint8
const (
BuildmodeExe BuildMode = iota
BuildmodeCShared
)
func (mode *BuildMode) Set(s string) error {
switch s {
default:
return errors.New("invalid mode")
case "exe":
*mode = BuildmodeExe
case "c-shared":
goarch := obj.Getgoarch()
if goarch != "amd64" && goarch != "arm" {
return fmt.Errorf("not supported on %s", goarch)
}
*mode = BuildmodeCShared
}
return nil
}
func (mode *BuildMode) String() string {
switch *mode {
case BuildmodeExe:
return "exe"
case BuildmodeCShared:
return "c-shared"
}
return fmt.Sprintf("BuildMode(%d)", uint8(*mode))
}
/* /*
* Unix doesn't like it when we write to a running (or, sometimes, * Unix doesn't like it when we write to a running (or, sometimes,
* recently run) binary, so remove the output file before writing it. * recently run) binary, so remove the output file before writing it.
@ -276,10 +315,13 @@ func libinit() {
coutbuf = *Binitw(f) coutbuf = *Binitw(f)
if INITENTRY == "" { if INITENTRY == "" {
if Flag_shared == 0 { switch Buildmode {
INITENTRY = fmt.Sprintf("_rt0_%s_%s", goarch, goos) case BuildmodeCShared:
} else {
INITENTRY = fmt.Sprintf("_rt0_%s_%s_lib", goarch, goos) INITENTRY = fmt.Sprintf("_rt0_%s_%s_lib", goarch, goos)
case BuildmodeExe:
INITENTRY = fmt.Sprintf("_rt0_%s_%s", goarch, goos)
default:
Diag("unknown INITENTRY for buildmode %v", Buildmode)
} }
} }
@ -324,7 +366,7 @@ func loadinternal(name string) {
} }
func loadlib() { func loadlib() {
if Flag_shared != 0 { if Buildmode == BuildmodeCShared {
s := Linklookup(Ctxt, "runtime.islibrary", 0) s := Linklookup(Ctxt, "runtime.islibrary", 0)
s.Dupok = 1 s.Dupok = 1
Adduint8(Ctxt, s, 1) Adduint8(Ctxt, s, 1)
@ -454,7 +496,7 @@ func loadlib() {
// binaries, so leave it enabled on OS X (Mach-O) binaries. // binaries, so leave it enabled on OS X (Mach-O) binaries.
// Also leave it enabled on Solaris which doesn't support // Also leave it enabled on Solaris which doesn't support
// statically linked binaries. // statically linked binaries.
if Flag_shared == 0 && havedynamic == 0 && HEADTYPE != Hdarwin && HEADTYPE != Hsolaris { if Buildmode == BuildmodeExe && havedynamic == 0 && HEADTYPE != Hdarwin && HEADTYPE != Hsolaris {
Debug['d'] = 1 Debug['d'] = 1
} }
@ -746,7 +788,7 @@ func hostlink() {
argv = append(argv, "-Wl,--rosegment") argv = append(argv, "-Wl,--rosegment")
} }
if Flag_shared != 0 { if Buildmode == BuildmodeCShared {
argv = append(argv, "-Wl,-Bsymbolic") argv = append(argv, "-Wl,-Bsymbolic")
argv = append(argv, "-shared") argv = append(argv, "-shared")
} }

View File

@ -102,6 +102,7 @@ func Ldmain() {
obj.Flagfn1("X", "name value: define string data", addstrdata1) obj.Flagfn1("X", "name value: define string data", addstrdata1)
obj.Flagcount("Z", "clear stack frame on entry", &Debug['Z']) obj.Flagcount("Z", "clear stack frame on entry", &Debug['Z'])
obj.Flagcount("a", "disassemble output", &Debug['a']) obj.Flagcount("a", "disassemble output", &Debug['a'])
flag.Var(&Buildmode, "buildmode", "build mode to use")
obj.Flagcount("c", "dump call graph", &Debug['c']) obj.Flagcount("c", "dump call graph", &Debug['c'])
obj.Flagcount("d", "disable dynamic executable", &Debug['d']) obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
obj.Flagstr("extld", "ld: linker to run in external mode", &extld) obj.Flagstr("extld", "ld: linker to run in external mode", &extld)
@ -116,8 +117,9 @@ func Ldmain() {
obj.Flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath) obj.Flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath)
obj.Flagcount("race", "enable race detector", &flag_race) obj.Flagcount("race", "enable race detector", &flag_race)
obj.Flagcount("s", "disable symbol table", &Debug['s']) obj.Flagcount("s", "disable symbol table", &Debug['s'])
var flagShared int
if Thearch.Thechar == '5' || Thearch.Thechar == '6' { if Thearch.Thechar == '5' || Thearch.Thechar == '6' {
obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &Flag_shared) obj.Flagcount("shared", "generate shared object (implies -linkmode external)", &flagShared)
} }
obj.Flagstr("tmpdir", "dir: leave temporary files in this directory", &tmpdir) obj.Flagstr("tmpdir", "dir: leave temporary files in this directory", &tmpdir)
obj.Flagcount("u", "reject unsafe packages", &Debug['u']) obj.Flagcount("u", "reject unsafe packages", &Debug['u'])
@ -141,6 +143,14 @@ func Ldmain() {
startProfile() startProfile()
Ctxt.Bso = &Bso Ctxt.Bso = &Bso
Ctxt.Debugvlog = int32(Debug['v']) Ctxt.Debugvlog = int32(Debug['v'])
if flagShared != 0 {
if Buildmode == BuildmodeExe {
Buildmode = BuildmodeCShared
} else if Buildmode != BuildmodeCShared {
Diag("-shared and -buildmode=%s are incompatible\n", Buildmode.String())
Errorexit()
}
}
if flag.NArg() != 1 { if flag.NArg() != 1 {
usage() usage()