From: David Crawshaw Date: Tue, 6 Dec 2016 04:20:20 +0000 (-0500) Subject: cmd/link: hash packages after loading all symbols X-Git-Tag: go1.8beta2~83 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=348a7c5397f996a333f88cf9f0c912b282368f32;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go index b4d5aae27a..7304b5b0d3 100644 --- a/src/cmd/link/internal/ld/elf.go +++ b/src/cmd/link/internal/ld/elf.go @@ -10,6 +10,7 @@ import ( "crypto/sha1" "encoding/binary" "encoding/hex" + "io" "path/filepath" "sort" "strings" @@ -2130,7 +2131,7 @@ func (ctxt *Link) doelf() { sort.Sort(byPkg(ctxt.Library)) h := sha1.New() for _, l := range ctxt.Library { - h.Write(l.hash) + io.WriteString(h, l.hash) } addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{})) addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index fb321905e1..a2700d9698 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -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) diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go index ab7e49b51f..ffe0873fc8 100644 --- a/src/cmd/link/internal/ld/link.go +++ b/src/cmd/link/internal/ld/link.go @@ -223,7 +223,7 @@ type Library struct { File string Pkg string Shlib string - hash []byte + hash string imports []*Library textp []*Symbol // text symbols defined in this library dupTextSyms []*Symbol // dupok text symbols defined in this library