w.Bytes(b[:])
}
+// contentHashSection returns a mnemonic for s's section.
+// The goal is to prevent content-addressability from moving symbols between sections.
+// contentHashSection only distinguishes between sets of sections for which this matters.
+// Allowing flexibility increases the effectiveness of content-addressibility.
+// But in some cases, such as doing addressing based on a base symbol,
+// we need to ensure that a symbol is always in a prticular section.
+// Some of these conditions are duplicated in cmd/link/internal/ld.(*Link).symtab.
+// TODO: instead of duplicating them, have the compiler decide where symbols go.
+func contentHashSection(s *LSym) byte {
+ name := s.Name
+ if strings.HasPrefix(name, "type.") {
+ return 'T'
+ }
+ return 0
+}
+
func contentHash64(s *LSym) goobj.Hash64Type {
+ if contentHashSection(s) != 0 {
+ panic("short hash of non-default-section sym " + s.Name)
+ }
var b goobj.Hash64Type
copy(b[:], s.P)
return b
// In this case, if the smaller symbol is alive, the larger is not kept unless
// needed.
binary.LittleEndian.PutUint64(tmp[:8], uint64(s.Size))
- h.Write(tmp[:8])
+ // Some symbols require being in separate sections.
+ tmp[8] = contentHashSection(s)
+ h.Write(tmp[:9])
- // Don't dedup type symbols with others, as they are in a different
- // section.
- if strings.HasPrefix(s.Name, "type.") {
- h.Write([]byte{'T'})
- } else {
- h.Write([]byte{0})
- }
// The compiler trims trailing zeros _sometimes_. We just do
// it always.
h.Write(bytes.TrimRight(s.P, "\x00"))
"log"
"math"
"sort"
- "strings"
)
func Linknew(arch *LinkArch) *Link {
// if Pkgpath is unknown, cannot hash symbols with relocations, as it
// may reference named symbols whose names are not fully expanded.
if s.ContentAddressable() && (ctxt.Pkgpath != "" || len(s.R) == 0) {
- if s.Size <= 8 && len(s.R) == 0 && !strings.HasPrefix(s.Name, "type.") {
+ if s.Size <= 8 && len(s.R) == 0 && contentHashSection(s) == 0 {
// We can use short hash only for symbols without relocations.
- // Don't use short hash for type symbols, as they need special handling.
+ // Don't use short hash for symbols that belong in a particular section
+ // or require special handling (such as type symbols).
s.PkgIdx = goobj.PkgIdxHashed64
s.SymIdx = hashed64idx
if hashed64idx != int32(len(ctxt.hashed64defs)) {
// within a type they sort by size, so the .* symbols
// just defined above will be first.
// hide the specific symbols.
+ // Some of these symbol section conditions are duplicated
+ // in cmd/internal/obj.contentHashSection.
nsym := loader.Sym(ldr.NSym())
symGroupType := make([]sym.SymKind, nsym)
for s := loader.Sym(1); s < nsym; s++ {