]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/ld: add -buildmode=c-shared as an alternative to -shared
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Fri, 27 Mar 2015 02:48:27 +0000 (02:48 +0000)
committerIan Lance Taylor <iant@golang.org>
Wed, 8 Apr 2015 21:51:14 +0000 (21:51 +0000)
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>
src/cmd/5l/asm.go
src/cmd/6l/asm.go
src/cmd/6l/obj.go
src/cmd/internal/ld/data.go
src/cmd/internal/ld/elf.go
src/cmd/internal/ld/go.go
src/cmd/internal/ld/lib.go
src/cmd/internal/ld/pobj.go

index 525764edf4aac9c7bfa5773c484c2f872ae7c902..abe91fd4849a2e48d73eb491f93231caa57d0e82 100644 (file)
@@ -245,7 +245,7 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
 
        case ld.R_TLS:
                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)
                        } else {
                                ld.Thearch.Lput(ld.R_ARM_TLS_LE32 | uint32(elfsym)<<8)
index 1df166f100ad35e480386d036cd2eee940a2e905..c55dae462df4577de8fe9dc7c1725cb73d2ee802 100644 (file)
@@ -330,7 +330,7 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
 
        case ld.R_TLS:
                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)
                        } else {
                                ld.Thearch.Vput(ld.R_X86_64_TPOFF32 | uint64(elfsym)<<32)
index f7165ab05e0d4341b391c3df2e7429aed98642b2..ad1cf92bd542e0c0ee73b98e651652170b25ccc7 100644 (file)
@@ -91,7 +91,7 @@ func archinit() {
                ld.Linkmode = ld.LinkInternal
        }
 
-       if ld.Flag_shared != 0 {
+       if ld.Buildmode == ld.BuildmodeCShared {
                ld.Linkmode = ld.LinkExternal
        }
 
index e67451419f7d2076f382f52949fff292fb3d47a9..76446b1187d0c48275926f0256826a05a71b077b 100644 (file)
@@ -960,7 +960,7 @@ func dosymtype() {
                }
                // Create a new entry in the .init_array section that points to the
                // library initializer function.
-               if Flag_shared != 0 && s.Name == INITENTRY {
+               if Buildmode == BuildmodeCShared && s.Name == INITENTRY {
                        addinitarrdata(s)
                }
        }
@@ -1322,7 +1322,7 @@ func dodata() {
        sect.Length = uint64(datsize) - sect.Vaddr
 
        /* shared library initializer */
-       if Flag_shared != 0 {
+       if Buildmode == BuildmodeCShared {
                sect := addsection(&Segdata, ".init_array", 06)
                sect.Align = maxalign(s, SINITARR)
                datsize = Rnd(datsize, int64(sect.Align))
index c588d93933e57899369ec739f48e09933f76fa10..3448fe6ce4fdd37ed38be1419bf8e6d1d3116564 100644 (file)
@@ -1658,7 +1658,7 @@ func doelf() {
                Addstring(shstrtab, ".note.GNU-stack")
        }
 
-       if Flag_shared != 0 {
+       if Buildmode == BuildmodeCShared {
                Addstring(shstrtab, ".init_array")
                switch Thearch.Thechar {
                case '6', '7', '9':
index 1aab4f96802b402ab8d6bb09b61f69a2fc754bee..fac72f7d0523004377e678fea13720defdba8675 100644 (file)
@@ -474,7 +474,7 @@ func loadcgo(file string, pkg string, p string) {
                        local = expandpkg(local, pkg)
                        s = Linklookup(Ctxt, local, 0)
 
-                       if Flag_shared != 0 && s == Linklookup(Ctxt, "main", 0) {
+                       if Buildmode == BuildmodeCShared && s == Linklookup(Ctxt, "main", 0) {
                                continue
                        }
 
index 94c0562b0f809070d8cd4129643f87799c0b85ba..339e872d021780b09def0ee61fa788f09e87ce42 100644 (file)
@@ -33,6 +33,7 @@ package ld
 import (
        "bytes"
        "cmd/internal/obj"
+       "errors"
        "fmt"
        "io/ioutil"
        "log"
@@ -160,7 +161,7 @@ var (
        elfglobalsymndx    int
        flag_installsuffix string
        flag_race          int
-       Flag_shared        int
+       Buildmode          BuildMode
        tracksym           string
        interpreter        string
        tmpdir             string
@@ -234,6 +235,44 @@ func Lflag(arg string) {
        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,
  * recently run) binary, so remove the output file before writing it.
@@ -276,10 +315,13 @@ func libinit() {
        coutbuf = *Binitw(f)
 
        if INITENTRY == "" {
-               if Flag_shared == 0 {
-                       INITENTRY = fmt.Sprintf("_rt0_%s_%s", goarch, goos)
-               } else {
+               switch Buildmode {
+               case BuildmodeCShared:
                        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() {
-       if Flag_shared != 0 {
+       if Buildmode == BuildmodeCShared {
                s := Linklookup(Ctxt, "runtime.islibrary", 0)
                s.Dupok = 1
                Adduint8(Ctxt, s, 1)
@@ -454,7 +496,7 @@ func loadlib() {
        // binaries, so leave it enabled on OS X (Mach-O) binaries.
        // Also leave it enabled on Solaris which doesn't support
        // 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
        }
 
@@ -746,7 +788,7 @@ func hostlink() {
                argv = append(argv, "-Wl,--rosegment")
        }
 
-       if Flag_shared != 0 {
+       if Buildmode == BuildmodeCShared {
                argv = append(argv, "-Wl,-Bsymbolic")
                argv = append(argv, "-shared")
        }
index 221f2b06a9b4b59dec488ccd1cfd820307c06ac7..32a89084402c92d4761d1bee91723e164f7602ee 100644 (file)
@@ -102,6 +102,7 @@ func Ldmain() {
        obj.Flagfn1("X", "name value: define string data", addstrdata1)
        obj.Flagcount("Z", "clear stack frame on entry", &Debug['Z'])
        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("d", "disable dynamic executable", &Debug['d'])
        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.Flagcount("race", "enable race detector", &flag_race)
        obj.Flagcount("s", "disable symbol table", &Debug['s'])
+       var flagShared int
        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.Flagcount("u", "reject unsafe packages", &Debug['u'])
@@ -141,6 +143,14 @@ func Ldmain() {
        startProfile()
        Ctxt.Bso = &Bso
        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 {
                usage()