// }
// }
//
+// Fingerprint [8]byte
+//
// uvarint means a uint64 written out using uvarint encoding.
//
// []T means a uvarint followed by that many T objects. In other
io.Copy(out, &hdr)
io.Copy(out, &p.strings)
io.Copy(out, &p.data0)
+
+ // Add fingerprint (used by linker object file).
+ // Attach this to the end, so tools (e.g. gcimporter) don't care.
+ out.Write(Ctxt.Fingerprint[:])
}
// writeIndex writes out an object index. mainIndex indicates whether
import (
"cmd/compile/internal/types"
"cmd/internal/bio"
+ "cmd/internal/goobj2"
"cmd/internal/obj"
"cmd/internal/src"
"encoding/binary"
return i
}
-func iimport(pkg *types.Pkg, in *bio.Reader) {
+func iimport(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj2.FingerprintType) {
ir := &intReader{in, pkg}
version := ir.uint64()
inlineImporter[s] = iimporterAndOffset{p, off}
}
}
+
+ // Fingerprint
+ n, err := in.Read(fingerprint[:])
+ if err != nil || n != len(fingerprint) {
+ yyerror("import %s: error reading fingerprint", pkg.Path)
+ errorexit()
+ }
+ return fingerprint
}
type iimporter struct {
"cmd/compile/internal/types"
"cmd/internal/bio"
"cmd/internal/dwarf"
+ "cmd/internal/goobj2"
"cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/src"
}
}
- // assume files move (get installed) so don't record the full path
- if packageFile != nil {
- // If using a packageFile map, assume path_ can be recorded directly.
- Ctxt.AddImport(path_)
- } else {
- // For file "/Users/foo/go/pkg/darwin_amd64/math.a" record "math.a".
- Ctxt.AddImport(file[len(file)-len(path_)-len(".a"):])
- }
-
// In the importfile, if we find:
// $$\n (textual format): not supported anymore
// $$B\n (binary format) : import directly, then feed the lexer a dummy statement
c, _ = imp.ReadByte()
}
+ var fingerprint goobj2.FingerprintType
switch c {
case '\n':
yyerror("cannot import %s: old export format no longer supported (recompile library)", path_)
yyerror("import %s: unexpected package format byte: %v", file, c)
errorexit()
}
- iimport(importpkg, imp)
+ fingerprint = iimport(importpkg, imp)
default:
yyerror("no import in %q", path_)
errorexit()
}
+ // assume files move (get installed) so don't record the full path
+ if packageFile != nil {
+ // If using a packageFile map, assume path_ can be recorded directly.
+ Ctxt.AddImport(path_, fingerprint)
+ } else {
+ // For file "/Users/foo/go/pkg/darwin_amd64/math.a" record "math.a".
+ Ctxt.AddImport(file[len(file)-len(path_)-len(".a"):], fingerprint)
+ }
+
if importpkg.Height >= myheight {
myheight = importpkg.Height + 1
}
}
// Imports
- r.p.Imports = rr.Autolib()
+ autolib := rr.Autolib()
+ for _, p := range autolib {
+ r.p.Imports = append(r.p.Imports, p.Pkg)
+ // Ignore fingerprint (for tools like objdump which only reads one object).
+ }
pkglist := rr.Pkglist()
// New object file format.
//
// Header struct {
-// Magic [...]byte // "\x00go115ld"
-// Flags uint32
-// // TODO: Fingerprint
-// Offsets [...]uint32 // byte offset of each block below
+// Magic [...]byte // "\x00go115ld"
+// Fingerprint [8]byte
+// Flags uint32
+// Offsets [...]uint32 // byte offset of each block below
// }
//
// Strings [...]struct {
// Data [...]byte
// }
//
-// Autolib [...]string // imported packages (for file loading) // TODO: add fingerprints
+// Autolib [...]struct { // imported packages (for file loading)
+// Pkg string
+// Fingerprint [8]byte
+// }
+//
// PkgIndex [...]string // referenced packages by index
//
// DwarfFiles [...]string
const stringRefSize = 8 // two uint32s
+type FingerprintType [8]byte
+
// Package Index.
const (
PkgIdxNone = (1<<31 - 1) - iota // Non-package symbols
// File header.
// TODO: probably no need to export this.
type Header struct {
- Magic string
- Flags uint32
- Offsets [NBlk]uint32
+ Magic string
+ Fingerprint FingerprintType
+ Flags uint32
+ Offsets [NBlk]uint32
}
const Magic = "\x00go115ld"
func (h *Header) Write(w *Writer) {
w.RawString(h.Magic)
+ w.Bytes(h.Fingerprint[:])
w.Uint32(h.Flags)
for _, x := range h.Offsets {
w.Uint32(x)
return errors.New("wrong magic, not a Go object file")
}
off := uint32(len(h.Magic))
+ copy(h.Fingerprint[:], r.BytesAt(off, len(h.Fingerprint)))
+ off += 8
h.Flags = r.uint32At(off)
off += 4
for i := range h.Offsets {
return len(h.Magic) + 4 + 4*len(h.Offsets)
}
+// Autolib
+type ImportedPkg struct {
+ Pkg string
+ Fingerprint FingerprintType
+}
+
+const importedPkgSize = stringRefSize + 8
+
+func (p *ImportedPkg) Write(w *Writer) {
+ w.StringRef(p.Pkg)
+ w.Bytes(p.Fingerprint[:])
+}
+
// Symbol definition.
//
// Serialized format:
return r.StringAt(r.uint32At(off+4), l)
}
-func (r *Reader) Autolib() []string {
- n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / stringRefSize
- s := make([]string, n)
+func (r *Reader) Fingerprint() FingerprintType {
+ return r.h.Fingerprint
+}
+
+func (r *Reader) Autolib() []ImportedPkg {
+ n := (r.h.Offsets[BlkAutolib+1] - r.h.Offsets[BlkAutolib]) / importedPkgSize
+ s := make([]ImportedPkg, n)
+ off := r.h.Offsets[BlkAutolib]
for i := range s {
- off := r.h.Offsets[BlkAutolib] + uint32(i)*stringRefSize
- s[i] = r.StringRef(off)
+ s[i].Pkg = r.StringRef(off)
+ copy(s[i].Fingerprint[:], r.BytesAt(off+stringRefSize, len(s[i].Fingerprint)))
+ off += importedPkgSize
}
return s
}
func (r *Reader) Pkglist() []string {
n := (r.h.Offsets[BlkPkgIdx+1] - r.h.Offsets[BlkPkgIdx]) / stringRefSize
s := make([]string, n)
+ off := r.h.Offsets[BlkPkgIdx]
for i := range s {
- off := r.h.Offsets[BlkPkgIdx] + uint32(i)*stringRefSize
s[i] = r.StringRef(off)
+ off += stringRefSize
}
return s
}
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) {
import (
"bufio"
"cmd/internal/dwarf"
+ "cmd/internal/goobj2"
"cmd/internal/objabi"
"cmd/internal/src"
"cmd/internal/sys"
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
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{}) {
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("")
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
// 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
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)
import (
"cmd/internal/goobj2"
"cmd/internal/objabi"
+ "crypto/md5"
"fmt"
"log"
"math"
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
or := &oReader{r, unit, localSymVersion, r.Flags(), pkgprefix, make([]Sym, ndef+nnonpkgdef+r.NNonpkgref()), ndef, uint32(len(l.objs))}
// Autolib
- lib.ImportStrings = append(lib.ImportStrings, r.Autolib()...)
+ autolib := r.Autolib()
+ for _, p := range autolib {
+ lib.ImportStrings = append(lib.ImportStrings, p.Pkg)
+ // TODO: fingerprint is ignored for now
+ }
// DWARF file table
nfile := r.NDwarfFile()