diff options
| author | Cherry Zhang <cherryyz@google.com> | 2020-04-22 19:21:30 -0400 |
|---|---|---|
| committer | Cherry Zhang <cherryyz@google.com> | 2020-04-24 17:47:14 +0000 |
| commit | e08f10b8b5fbb82ff1e2c263ad57e19d2de1e323 (patch) | |
| tree | 1a7332196907af1966807e1664e2734ba6bb41f7 /src/cmd/internal/obj | |
| parent | 880ef2da7b81fe2e4e9fb75f4677377eeba70d1e (diff) | |
| download | go-e08f10b8b5fbb82ff1e2c263ad57e19d2de1e323.tar.xz | |
[dev.link] cmd/internal/goobj2: add index fingerprint to object file
The new object files use indices for symbol references, instead
of names. Fundamental to the design, it requires that the
importing and imported packages have consistent view of symbol
indices. The Go command should already ensure this, when using
"go build". But in case it goes wrong, it could lead to obscure
errors like run-time crashes. It would be better to check the
index consistency at build time.
To do that, we add a fingerprint to each object file, which is
a hash of symbol indices. In the object file it records the
fingerprints of all imported packages, as well as its own
fingerprint. At link time, the linker checks that a package's
fingerprint matches the fingerprint recorded in the importing
packages, and issue an error if they don't match.
This CL does the first part: introducing the fingerprint in the
object file, and propagating fingerprints through
importing/exporting by the compiler. It is not yet used by the
linker. Next CL will do.
Change-Id: I0aa372da652e4afb11f2867cb71689a3e3f9966e
Reviewed-on: https://go-review.googlesource.com/c/go/+/229617
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Diffstat (limited to 'src/cmd/internal/obj')
| -rw-r--r-- | src/cmd/internal/obj/line.go | 5 | ||||
| -rw-r--r-- | src/cmd/internal/obj/link.go | 5 | ||||
| -rw-r--r-- | src/cmd/internal/obj/objfile.go | 5 | ||||
| -rw-r--r-- | src/cmd/internal/obj/objfile2.go | 14 | ||||
| -rw-r--r-- | src/cmd/internal/obj/sym.go | 10 |
5 files changed, 29 insertions, 10 deletions
diff --git a/src/cmd/internal/obj/line.go b/src/cmd/internal/obj/line.go index fecf90c491..79ecb0068f 100644 --- a/src/cmd/internal/obj/line.go +++ b/src/cmd/internal/obj/line.go @@ -5,12 +5,13 @@ package obj import ( + "cmd/internal/goobj2" "cmd/internal/src" ) // AddImport adds a package to the list of imported packages. -func (ctxt *Link) AddImport(pkg string) { - ctxt.Imports = append(ctxt.Imports, pkg) +func (ctxt *Link) AddImport(pkg string, fingerprint goobj2.FingerprintType) { + ctxt.Imports = append(ctxt.Imports, goobj2.ImportedPkg{Pkg: pkg, Fingerprint: fingerprint}) } func linkgetlineFromPos(ctxt *Link, xpos src.XPos) (f string, l int32) { diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 046ad53ac7..e6f917dedb 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -33,6 +33,7 @@ package obj import ( "bufio" "cmd/internal/dwarf" + "cmd/internal/goobj2" "cmd/internal/objabi" "cmd/internal/src" "cmd/internal/sys" @@ -666,7 +667,7 @@ type Link struct { PosTable src.PosTable InlTree InlTree // global inlining tree used by gc/inl.go DwFixups *DwarfFixupTable - Imports []string + Imports []goobj2.ImportedPkg DiagFunc func(string, ...interface{}) DiagFlush func() DebugInfo func(fn *LSym, info *LSym, curfn interface{}) ([]dwarf.Scope, dwarf.InlCalls) // if non-nil, curfn is a *gc.Node @@ -698,6 +699,8 @@ type Link struct { defs []*LSym // list of defined symbols in the current package nonpkgdefs []*LSym // list of defined non-package symbols nonpkgrefs []*LSym // list of referenced non-package symbols + + Fingerprint goobj2.FingerprintType // fingerprint of symbol indices, to catch index mismatch } func (ctxt *Link) Diag(format string, args ...interface{}) { diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 2b0c45d6b2..6d7f42ed0b 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -98,8 +98,9 @@ func WriteObjFile(ctxt *Link, bout *bio.Writer, pkgpath string) { w.wr.WriteByte(1) // Autolib - for _, pkg := range ctxt.Imports { - w.writeString(pkg) + for _, p := range ctxt.Imports { + w.writeString(p.Pkg) + // This object format ignores p.Fingerprint. } w.writeString("") diff --git a/src/cmd/internal/obj/objfile2.go b/src/cmd/internal/obj/objfile2.go index 9792ef0846..061e43c434 100644 --- a/src/cmd/internal/obj/objfile2.go +++ b/src/cmd/internal/obj/objfile2.go @@ -38,7 +38,11 @@ func WriteObjFile2(ctxt *Link, b *bio.Writer, pkgpath string) { if ctxt.Flag_shared { flags |= goobj2.ObjFlagShared } - h := goobj2.Header{Magic: goobj2.Magic, Flags: flags} + h := goobj2.Header{ + Magic: goobj2.Magic, + Fingerprint: ctxt.Fingerprint, + Flags: flags, + } h.Write(w.Writer) // String table @@ -46,8 +50,8 @@ func WriteObjFile2(ctxt *Link, b *bio.Writer, pkgpath string) { // Autolib h.Offsets[goobj2.BlkAutolib] = w.Offset() - for _, pkg := range ctxt.Imports { - w.StringRef(pkg) + for i := range ctxt.Imports { + ctxt.Imports[i].Write(w.Writer) } // Package references @@ -180,8 +184,8 @@ func (w *writer) init() { func (w *writer) StringTable() { w.AddString("") - for _, pkg := range w.ctxt.Imports { - w.AddString(pkg) + for _, p := range w.ctxt.Imports { + w.AddString(p.Pkg) } for _, pkg := range w.pkglist { w.AddString(pkg) diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go index 03ce8ddc5a..4a8b0ebb6f 100644 --- a/src/cmd/internal/obj/sym.go +++ b/src/cmd/internal/obj/sym.go @@ -34,6 +34,7 @@ package obj import ( "cmd/internal/goobj2" "cmd/internal/objabi" + "crypto/md5" "fmt" "log" "math" @@ -241,6 +242,15 @@ func (ctxt *Link) NumberSyms(asm bool) { ctxt.pkgIdx[pkg] = ipkg ipkg++ }) + + // Compute a fingerprint of the indices, for exporting. + if !asm { + h := md5.New() + for _, s := range ctxt.defs { + h.Write([]byte(s.Name)) + } + copy(ctxt.Fingerprint[:], h.Sum(nil)[:]) + } } // Returns whether s is a non-package symbol, which needs to be referenced |
