mirror of
https://github.com/golang/go
synced 2024-11-26 21:01:31 -07:00
cmd/link: only include the version info and export data in ABI hash
Previously the "ABI hash" for a package (used to determine if a loaded shared library has the ABI expected by its loader) was the hash of the entire __.PKGDEF file. But that means it depends on the build ID generated by the go tool for the package, which means that if a file is added (even a .c or .h file!) to the package, the ABI changes, perhaps uncessarily. Fixes #19920 Change-Id: If919481e1a03afb350c8a9c7a0666bb90ee90270 Reviewed-on: https://go-review.googlesource.com/40401 Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
94b6011c78
commit
533ed967c6
@ -763,6 +763,13 @@ func appendFile(path, content string) {
|
||||
}
|
||||
}
|
||||
|
||||
func writeFile(path, content string) {
|
||||
err := ioutil.WriteFile(path, []byte(content), 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("ioutil.WriteFile failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestABIChecking(t *testing.T) {
|
||||
goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
|
||||
goCmd(t, "install", "-linkshared", "exe")
|
||||
@ -801,9 +808,10 @@ func TestABIChecking(t *testing.T) {
|
||||
run(t, "rebuilt exe", "./bin/exe")
|
||||
|
||||
// If we make a change which does not break ABI (such as adding an unexported
|
||||
// function) and rebuild libdepBase.so, exe still works.
|
||||
// function) and rebuild libdepBase.so, exe still works, even if new function
|
||||
// is in a file by itself.
|
||||
resetFileStamps()
|
||||
appendFile("src/depBase/dep.go", "func noABIBreak() {}\n")
|
||||
writeFile("src/depBase/dep2.go", "package depBase\nfunc noABIBreak() {}\n")
|
||||
goCmd(t, "install", "-buildmode=shared", "-linkshared", "depBase")
|
||||
run(t, "after non-ABI breaking change", "./bin/exe")
|
||||
}
|
||||
|
@ -720,10 +720,35 @@ func genhash(ctxt *Link, lib *Library) {
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
// To compute the hash of a package, we hash the first line of
|
||||
// __.PKGDEF (which contains the toolchain version and any
|
||||
// GOEXPERIMENT flags) and the export data (which is between
|
||||
// the first two occurences of "\n$$").
|
||||
|
||||
pkgDefBytes := make([]byte, atolwhex(arhdr.size))
|
||||
_, err = io.ReadFull(f, pkgDefBytes)
|
||||
if err != nil {
|
||||
Errorf(nil, "%s: error reading package data: %v", lib.File, err)
|
||||
return
|
||||
}
|
||||
firstEOL := bytes.Index(pkgDefBytes, []byte("\n"))
|
||||
if firstEOL < 0 {
|
||||
Errorf(nil, "cannot parse package data of %s for hash generation, no newline found", lib.File)
|
||||
return
|
||||
}
|
||||
firstDoubleDollar := bytes.Index(pkgDefBytes, []byte("\n$$"))
|
||||
if firstDoubleDollar < 0 {
|
||||
Errorf(nil, "cannot parse package data of %s for hash generation, no \\n$$ found", lib.File)
|
||||
return
|
||||
}
|
||||
secondDoubleDollar := bytes.Index(pkgDefBytes[firstDoubleDollar+1:], []byte("\n$$"))
|
||||
if secondDoubleDollar < 0 {
|
||||
Errorf(nil, "cannot parse package data of %s for hash generation, only one \\n$$ found", lib.File)
|
||||
return
|
||||
}
|
||||
h.Write(pkgDefBytes[0:firstEOL])
|
||||
h.Write(pkgDefBytes[firstDoubleDollar : firstDoubleDollar+secondDoubleDollar])
|
||||
lib.hash = hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user