cmd/link: hash packages after loading all symbols

Conditioning on the plugin.Open symbol existing before loading all
symbols means sometimes some packages don't have a hash value.

Fixes #17928

Change-Id: I2722449aa58eca08a25117d3ce976f11f805b5ac
Reviewed-on: https://go-review.googlesource.com/33925
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
David Crawshaw 2016-12-05 23:20:20 -05:00
parent 10f43a1f4f
commit 348a7c5397
3 changed files with 37 additions and 13 deletions

View file

@ -39,6 +39,7 @@ import (
"crypto/sha1"
"debug/elf"
"encoding/binary"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
@ -603,6 +604,16 @@ func (ctxt *Link) loadlib() {
}
}
// If package versioning is required, generate a hash of the
// the packages used in the link.
if Buildmode == BuildmodeShared || Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
for i = 0; i < len(ctxt.Library); i++ {
if ctxt.Library[i].Shlib == "" {
genhash(ctxt, ctxt.Library[i])
}
}
}
if SysArch == sys.Arch386 {
if (Buildmode == BuildmodeCArchive && Iself) || Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE || ctxt.DynlinkingGo() {
got := ctxt.Syms.Lookup("_GLOBAL_OFFSET_TABLE_", 0)
@ -678,6 +689,29 @@ func nextar(bp *bio.Reader, off int64, a *ArHdr) int64 {
return arsize + SAR_HDR
}
func genhash(ctxt *Link, lib *Library) {
f, err := bio.Open(lib.File)
if err != nil {
Errorf(nil, "cannot open file %s for hash generation: %v", lib.File, err)
return
}
defer f.Close()
var arhdr ArHdr
l := nextar(f, int64(len(ARMAG)), &arhdr)
if l <= 0 {
Errorf(nil, "%s: short read on archive file symbol header", lib.File)
return
}
h := sha1.New()
if _, err := io.CopyN(h, f, atolwhex(arhdr.size)); err != nil {
Errorf(nil, "bad read of %s for hash generation: %v", lib.File, err)
return
}
lib.hash = hex.EncodeToString(h.Sum(nil))
}
func objfile(ctxt *Link, lib *Library) {
pkg := pathtoprefix(lib.Pkg)
@ -720,17 +754,6 @@ func objfile(ctxt *Link, lib *Library) {
goto out
}
if Buildmode == BuildmodeShared || Buildmode == BuildmodePlugin || ctxt.Syms.ROLookup("plugin.Open", 0) != nil {
before := f.Offset()
pkgdefBytes := make([]byte, atolwhex(arhdr.size))
if _, err := io.ReadFull(f, pkgdefBytes); err != nil {
Errorf(nil, "%s: short read on archive file symbol header: %v", lib.File, err)
}
hash := sha1.Sum(pkgdefBytes)
lib.hash = hash[:]
f.Seek(before, 0)
}
off += l
ldpkg(ctxt, f, pkg, atolwhex(arhdr.size), lib.File, Pkgdef)