mirror of
https://github.com/golang/go
synced 2024-11-12 05:30:21 -07: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:
parent
47746f10fe
commit
2a5f88d850
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
@ -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':
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user