]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.link] cmd/compile, cmd/link: make itab symbols content-addressable
authorCherry Zhang <cherryyz@google.com>
Wed, 29 Jul 2020 22:10:15 +0000 (18:10 -0400)
committerCherry Zhang <cherryyz@google.com>
Mon, 3 Aug 2020 21:12:28 +0000 (21:12 +0000)
Extend the content-addressable symbol mechanism to itab symbols.
Itab symbols require global uniqueness (as at run time we compare
pointers), so it needs to be reliably deduplicated. Currently the
content hash depends on symbol name expansion, so we can only do
this when all Go packages are built with know package paths. Fall
back to checking names if any Go package is built with unknown
package path.

Change-Id: Icf5e8873755050c20e5fc6549f6de1c883254c89
Reviewed-on: https://go-review.googlesource.com/c/go/+/245719
Reviewed-by: Jeremy Faller <jeremy@golang.org>
src/cmd/compile/internal/gc/reflect.go
src/cmd/internal/obj/objfile2.go
src/cmd/link/internal/loader/loader.go

index 7758097db8cdabbf5715d5b21dce1aaaa31912ea..ce4838ce801b153ad5d99ff3e12e8ff146df5769 100644 (file)
@@ -1559,6 +1559,7 @@ func dumptabs() {
                }
                // Nothing writes static itabs, so they are read only.
                ggloblsym(i.lsym, int32(o), int16(obj.DUPOK|obj.RODATA))
+               i.lsym.Set(obj.AttrContentAddressable, true)
                ilink := itablinkpkg.Lookup(i.t.ShortString() + "," + i.itype.ShortString()).Linksym()
                dsymptr(ilink, 0, i.lsym, 0)
                ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
index 6740f422208c20ffd3668472e4e8e54a816d7918..74f4fc63bae2997a521d77533c0478c69fed2035 100644 (file)
@@ -367,7 +367,8 @@ func contentHash64(s *LSym) goobj2.Hash64Type {
 // consistent.
 // - For referenced content-addressable symbol, its content hash
 //   is globally consistent.
-// - For package symbol, its local index is globally consistent.
+// - For package symbol and builtin symbol, its local index is
+//   globally consistent.
 // - For non-package symbol, its fully-expanded name is globally
 //   consistent. For now, we require we know the current package
 //   path so we can always expand symbol names. (Otherwise,
@@ -398,11 +399,13 @@ func (w *writer) contentHash(s *LSym) goobj2.HashType {
                        h.Write([]byte{1})
                        t := w.contentHash(rs)
                        h.Write(t[:])
-               case goobj2.PkgIdxBuiltin:
-                       panic("unsupported")
                case goobj2.PkgIdxNone:
                        h.Write([]byte{2})
                        io.WriteString(h, rs.Name) // name is already expanded at this point
+               case goobj2.PkgIdxBuiltin:
+                       h.Write([]byte{3})
+                       binary.LittleEndian.PutUint32(tmp[:4], uint32(rs.SymIdx))
+                       h.Write(tmp[:4])
                case goobj2.PkgIdxSelf:
                        io.WriteString(h, w.pkgpath)
                        binary.LittleEndian.PutUint32(tmp[:4], uint32(rs.SymIdx))
index d34e6fdf6b2e9d04024d311462ec577ae9cd0b0b..2f4a0efbf4c88300140b641b340a5ba03738fd2c 100644 (file)
@@ -277,6 +277,8 @@ type Loader struct {
 
        flags uint32
 
+       hasUnknownPkgPath bool // if any Go object has unknown package path
+
        strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled
 
        elfsetstring elfsetstringFunc
@@ -378,6 +380,9 @@ func (l *Loader) addObj(pkg string, r *oReader) Sym {
        i := Sym(len(l.objSyms))
        l.start[r] = i
        l.objs = append(l.objs, objIdx{r, i})
+       if r.NeedNameExpansion() && !r.FromAssembly() {
+               l.hasUnknownPkgPath = true
+       }
        return i
 }
 
@@ -2086,6 +2091,16 @@ func (l *Loader) preloadSyms(r *oReader, kind int) {
        case hashedDef:
                start = uint32(r.ndef + r.nhashed64def)
                end = uint32(r.ndef + r.nhashed64def + r.nhasheddef)
+               if l.hasUnknownPkgPath {
+                       // The content hash depends on symbol name expansion. If any package is
+                       // built without fully expanded names, the content hash is unreliable.
+                       // Treat them as named symbols.
+                       // This is rare.
+                       // (We don't need to do this for hashed64Def case, as there the hash
+                       // function is simply the identity function, which doesn't depend on
+                       // name expansion.)
+                       kind = nonPkgDef
+               }
        case nonPkgDef:
                start = uint32(r.ndef + r.nhashed64def + r.nhasheddef)
                end = uint32(r.ndef + r.nhashed64def + r.nhasheddef + r.NNonpkgdef())