]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/ld: put the list of packages built into a shared library into an ELF...
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Wed, 29 Apr 2015 10:58:52 +0000 (22:58 +1200)
committerIan Lance Taylor <iant@golang.org>
Thu, 30 Apr 2015 18:04:43 +0000 (18:04 +0000)
Change-Id: I611f7dec2109dc7e2f090ced0a1dca3d4b577134
Reviewed-on: https://go-review.googlesource.com/9520
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>

src/cmd/internal/ld/elf.go
src/cmd/internal/ld/lib.go
src/cmd/internal/ld/pobj.go

index cb4a73a3380ad5f6e4a733c8f0b35a0974b6f016..01be55e16d5fe10c0f4355729a9b44bb56240984 100644 (file)
@@ -1039,11 +1039,13 @@ func elfwriteinterp() int {
        return int(sh.size)
 }
 
-func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sz int) int {
+func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sz int, alloc bool) int {
        n := 3*4 + uint64(sz) + resoff%4
 
        sh.type_ = SHT_NOTE
-       sh.flags = SHF_ALLOC
+       if alloc {
+               sh.flags = SHF_ALLOC
+       }
        sh.addralign = 4
        sh.addr = startva + resoff - n
        sh.off = resoff - n
@@ -1077,7 +1079,7 @@ var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00")
 
 func elfnetbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
        n := int(Rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + Rnd(ELF_NOTE_NETBSD_DESCSZ, 4))
-       return elfnote(sh, startva, resoff, n)
+       return elfnote(sh, startva, resoff, n, true)
 }
 
 func elfwritenetbsdsig() int {
@@ -1109,7 +1111,7 @@ var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00")
 
 func elfopenbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int {
        n := ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ
-       return elfnote(sh, startva, resoff, n)
+       return elfnote(sh, startva, resoff, n, true)
 }
 
 func elfwriteopenbsdsig() int {
@@ -1180,7 +1182,7 @@ var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00")
 
 func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int {
        n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4))
-       return elfnote(sh, startva, resoff, n)
+       return elfnote(sh, startva, resoff, n, true)
 }
 
 func elfwritebuildinfo() int {
@@ -1197,6 +1199,32 @@ func elfwritebuildinfo() int {
        return int(sh.size)
 }
 
+// Go package list note
+const (
+       ELF_NOTE_GOPKGLIST_TAG = 1
+)
+
+var ELF_NOTE_GO_NAME = []byte("GO\x00\x00")
+
+func elfgopkgnote(sh *ElfShdr, startva uint64, resoff uint64) int {
+       n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(pkglistfornote)), 4))
+       return elfnote(sh, startva, resoff, n, false)
+}
+
+func elfwritegopkgnote() int {
+       sh := elfwritenotehdr(".note.go.pkg-list", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(pkglistfornote)), ELF_NOTE_GOPKGLIST_TAG)
+       if sh == nil {
+               return 0
+       }
+
+       Cwrite(ELF_NOTE_GO_NAME)
+       Cwrite(pkglistfornote)
+       var zero = make([]byte, 4)
+       Cwrite(zero[:int(Rnd(int64(len(pkglistfornote)), 4)-int64(len(pkglistfornote)))])
+
+       return int(sh.size)
+}
+
 var elfverneed int
 
 type Elfaux struct {
@@ -1604,6 +1632,9 @@ func doelf() {
        if len(buildinfo) > 0 {
                Addstring(shstrtab, ".note.gnu.build-id")
        }
+       if Buildmode == BuildmodeShared {
+               Addstring(shstrtab, ".note.go.pkg-list")
+       }
        Addstring(shstrtab, ".elfdata")
        Addstring(shstrtab, ".rodata")
        Addstring(shstrtab, ".typelink")
@@ -1888,6 +1919,11 @@ func Asmbelf(symo int64) {
                eh.phoff = 0
 
                eh.phentsize = 0
+
+               if Buildmode == BuildmodeShared {
+                       sh := elfshname(".note.go.pkg-list")
+                       resoff -= int64(elfgopkgnote(sh, uint64(startva), uint64(resoff)))
+               }
                goto elfobj
        }
 
@@ -2296,6 +2332,9 @@ elfobj:
                        a += int64(elfwritebuildinfo())
                }
        }
+       if Buildmode == BuildmodeShared {
+               a += int64(elfwritegopkgnote())
+       }
 
        if a > ELFRESERVE {
                Diag("ELFRESERVE too small: %d > %d", a, ELFRESERVE)
index 44389c9fa81260d80c5f4429df85f968e41d4f85..75a88541b05e476703a9f38ad50a9d9298dd9d2b 100644 (file)
@@ -516,6 +516,15 @@ func loadlib() {
                        if Ctxt.Library[i].Shlib != "" {
                                ldshlibsyms(Ctxt.Library[i].Shlib)
                        } else {
+                               // Because the linker always looks for runtime/cgo when
+                               // -buildmode=shared is passed, the go tool never passes
+                               // runtime/cgo on the command line. But runtime/cgo needs
+                               // to end up in the package list if it is being built into
+                               // the shared libarary.
+                               if Buildmode == BuildmodeShared {
+                                       pkglistfornote = append(pkglistfornote, "runtime/cgo"...)
+                                       pkglistfornote = append(pkglistfornote, '\n')
+                               }
                                objfile(Ctxt.Library[i].File, Ctxt.Library[i].Pkg)
                        }
                }
index dbfe8a044afe2b44351076bd325831f2957e8f7b..9b3e1151831e81a14df928183d7f372116615f55 100644 (file)
@@ -38,6 +38,8 @@ import (
        "strings"
 )
 
+var pkglistfornote []byte
+
 // Reading object files.
 
 func Ldmain() {
@@ -196,6 +198,8 @@ func Ldmain() {
                        } else {
                                pkgpath, file = parts[0], parts[1]
                        }
+                       pkglistfornote = append(pkglistfornote, pkgpath...)
+                       pkglistfornote = append(pkglistfornote, '\n')
                        addlibpath(Ctxt, "command line", "command line", file, pkgpath, "")
                }
        } else {