[dev.link] cmd/internal/goobj2, cmd/link: add and use new Sym accessors

Along the line with Reloc and Aux, use new-style accessors for
the Sym type. They avoid reading unnecessary fields, and also
look nicer (to me).

Change-Id: Ie37c5149a6edb2184724b3dfa26952015e74c085
Reviewed-on: https://go-review.googlesource.com/c/go/+/226798
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/src/cmd/internal/goobj2/objfile.go b/src/cmd/internal/goobj2/objfile.go
index db84e8a..54316cd 100644
--- a/src/cmd/internal/goobj2/objfile.go
+++ b/src/cmd/internal/goobj2/objfile.go
@@ -253,6 +253,30 @@
 func (s *Sym) IsGoType() bool      { return s.Flag&SymFlagGoType != 0 }
 func (s *Sym) TopFrame() bool      { return s.Flag&SymFlagTopFrame != 0 }
 
+const SymSize = stringRefSize + 2 + 1 + 1 + 4
+
+type Sym2 [SymSize]byte
+
+func (s *Sym2) Name(r *Reader) string {
+	len := binary.LittleEndian.Uint32(s[:])
+	off := binary.LittleEndian.Uint32(s[4:])
+	return r.StringAt(off, len)
+}
+
+func (s *Sym2) ABI() uint16 { return binary.LittleEndian.Uint16(s[8:]) }
+func (s *Sym2) Type() uint8 { return s[10] }
+func (s *Sym2) Flag() uint8 { return s[11] }
+func (s *Sym2) Siz() uint32 { return binary.LittleEndian.Uint32(s[12:]) }
+
+func (s *Sym2) Dupok() bool         { return s.Flag()&SymFlagDupok != 0 }
+func (s *Sym2) Local() bool         { return s.Flag()&SymFlagLocal != 0 }
+func (s *Sym2) Typelink() bool      { return s.Flag()&SymFlagTypelink != 0 }
+func (s *Sym2) Leaf() bool          { return s.Flag()&SymFlagLeaf != 0 }
+func (s *Sym2) NoSplit() bool       { return s.Flag()&SymFlagNoSplit != 0 }
+func (s *Sym2) ReflectMethod() bool { return s.Flag()&SymFlagReflectMethod != 0 }
+func (s *Sym2) IsGoType() bool      { return s.Flag()&SymFlagGoType != 0 }
+func (s *Sym2) TopFrame() bool      { return s.Flag()&SymFlagTopFrame != 0 }
+
 // Symbol reference.
 type SymRef struct {
 	PkgIdx uint32
@@ -593,6 +617,12 @@
 	return r.h.Offsets[BlkSymdef] + uint32(i*symsiz)
 }
 
+// Sym2 returns a pointer to the i-th symbol.
+func (r *Reader) Sym2(i int) *Sym2 {
+	off := r.SymOff(i)
+	return (*Sym2)(unsafe.Pointer(&r.b[off]))
+}
+
 // NReloc returns the number of relocations of the i-th symbol.
 func (r *Reader) NReloc(i int) int {
 	relocIdxOff := r.h.Offsets[BlkRelocIdx] + uint32(i*4)
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index bf40f5b..5f12874 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -387,15 +387,14 @@
 		return oldi, false
 	}
 	oldr, oldli := l.toLocal(oldi)
-	oldsym := goobj2.Sym{}
-	oldsym.ReadWithoutName(oldr.Reader, oldr.SymOff(oldli))
+	oldsym := oldr.Sym2(oldli)
 	if oldsym.Dupok() {
 		return oldi, false
 	}
 	overwrite := r.DataSize(li) != 0
 	if overwrite {
 		// new symbol overwrites old symbol.
-		oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type)]
+		oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type())]
 		if !(oldtyp.IsData() && oldr.DataSize(oldli) == 0) {
 			log.Fatalf("duplicated definition of symbol " + name)
 		}
@@ -617,9 +616,7 @@
 		return pp.name
 	}
 	r, li := l.toLocal(i)
-	osym := goobj2.Sym{}
-	osym.Read(r.Reader, r.SymOff(li))
-	return osym.Name
+	return r.Sym2(li).Name(r.Reader)
 }
 
 // Returns the (patched) name of the i-th symbol.
@@ -629,9 +626,7 @@
 		return pp.name
 	}
 	r, li := l.toLocal(i)
-	osym := goobj2.Sym{}
-	osym.Read(r.Reader, r.SymOff(li))
-	return strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
+	return strings.Replace(r.Sym2(li).Name(r.Reader), "\"\".", r.pkgprefix, -1)
 }
 
 // Returns the version of the i-th symbol.
@@ -641,9 +636,7 @@
 		return pp.ver
 	}
 	r, li := l.toLocal(i)
-	osym := goobj2.Sym{}
-	osym.ReadWithoutName(r.Reader, r.SymOff(li))
-	return int(abiToVer(osym.ABI, r.version))
+	return int(abiToVer(r.Sym2(li).ABI(), r.version))
 }
 
 // Returns the type of the i-th symbol.
@@ -656,9 +649,7 @@
 		return 0
 	}
 	r, li := l.toLocal(i)
-	osym := goobj2.Sym{}
-	osym.ReadWithoutName(r.Reader, r.SymOff(li))
-	return sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
+	return sym.AbiSymKindToSymKind[objabi.SymKind(r.Sym2(li).Type())]
 }
 
 // Returns the attributes of the i-th symbol.
@@ -668,9 +659,7 @@
 		return 0
 	}
 	r, li := l.toLocal(i)
-	osym := goobj2.Sym{}
-	osym.ReadFlag(r.Reader, r.SymOff(li))
-	return osym.Flag
+	return r.Sym2(li).Flag()
 }
 
 // AttrReachable returns true for symbols that are transitively
@@ -772,9 +761,7 @@
 		// might make more sense to copy the flag value out of the object
 		// into a larger bitmap during preload.
 		r, li := l.toLocal(i)
-		osym := goobj2.Sym{}
-		osym.ReadFlag(r.Reader, r.SymOff(li))
-		return osym.Dupok()
+		return r.Sym2(li).Dupok()
 	}
 	return l.attrDuplicateOK.Has(l.extIndex(i))
 }
@@ -1302,18 +1289,6 @@
 	return r.NAux(li)
 }
 
-// Returns the referred symbol of the j-th aux symbol of the i-th
-// symbol.
-func (l *Loader) AuxSym(i Sym, j int) Sym {
-	if l.IsExternal(i) {
-		return 0
-	}
-	r, li := l.toLocal(i)
-	a := goobj2.Aux{}
-	a.Read(r.Reader, r.AuxOff(li, j))
-	return l.resolve(r, a.Sym)
-}
-
 // Returns the "handle" to the j-th aux symbol of the i-th symbol.
 func (l *Loader) Aux2(i Sym, j int) Aux2 {
 	if l.IsExternal(i) {
@@ -1612,12 +1587,11 @@
 	l.growSyms(len(l.objSyms) + end - start)
 	l.growAttrBitmaps(len(l.objSyms) + end - start)
 	for i := start; i < end; i++ {
-		osym := goobj2.Sym{}
-		osym.Read(r.Reader, r.SymOff(i))
-		name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
-		v := abiToVer(osym.ABI, r.version)
+		osym := r.Sym2(i)
+		name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+		v := abiToVer(osym.ABI(), r.version)
 		dupok := osym.Dupok()
-		gi, added := l.AddSym(name, v, r, i, kind, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
+		gi, added := l.AddSym(name, v, r, i, kind, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())])
 		r.syms[i] = gi
 		if !added {
 			continue
@@ -1659,10 +1633,9 @@
 func loadObjRefs(l *Loader, r *oReader, syms *sym.Symbols) {
 	ndef := r.NSym() + r.NNonpkgdef()
 	for i, n := 0, r.NNonpkgref(); i < n; i++ {
-		osym := goobj2.Sym{}
-		osym.Read(r.Reader, r.SymOff(ndef+i))
-		name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
-		v := abiToVer(osym.ABI, r.version)
+		osym := r.Sym2(ndef + i)
+		name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+		v := abiToVer(osym.ABI(), r.version)
 		r.syms[ndef+i] = l.LookupOrCreateSym(name, v)
 		if osym.Local() {
 			gi := r.syms[ndef+i]
@@ -2079,10 +2052,9 @@
 		if r2, i2 := l.toLocal(gi); r2 != r || i2 != i {
 			continue // come from a different object
 		}
-		osym := goobj2.Sym{}
-		osym.Read(r.Reader, r.SymOff(i))
-		name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
-		t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
+		osym := r.Sym2(i)
+		name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+		t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
 		// NB: for the test below, we can skip most anonymous symbols
 		// since they will never be turned into sym.Symbols (ex:
 		// funcdata), however DWARF subprogram DIE symbols (which are
@@ -2092,7 +2064,7 @@
 		if name == "" && t != sym.SDWARFINFO {
 			continue
 		}
-		ver := abiToVer(osym.ABI, r.version)
+		ver := abiToVer(osym.ABI(), r.version)
 		if t == sym.SXREF {
 			log.Fatalf("bad sxref")
 		}
@@ -2117,9 +2089,9 @@
 // We use this to delay populating FuncInfo until we can batch-allocate
 // slices for their sub-objects.
 type funcInfoSym struct {
-	s    *sym.Symbol // sym.Symbol for a live function
-	osym goobj2.Sym  // object file symbol data for that function
-	isym int         // global symbol index of FuncInfo aux sym for func
+	s    *sym.Symbol  // sym.Symbol for a live function
+	osym *goobj2.Sym2 // object file symbol data for that function
+	isym int          // global symbol index of FuncInfo aux sym for func
 }
 
 // funcAllocInfo records totals/counts for all functions in an objfile;
@@ -2146,19 +2118,18 @@
 	l.growSyms(int(symIdx))
 
 	// Read the particulars from object.
-	osym := goobj2.Sym{}
 	r, li := l.toLocal(symIdx)
-	osym.Read(r.Reader, r.SymOff(li))
-	sname := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
-	sver := abiToVer(osym.ABI, r.version)
-	skind := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
+	osym := r.Sym2(li)
+	sname := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
+	sver := abiToVer(osym.ABI(), r.version)
+	skind := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
 
 	// Create new symbol, update version and kind.
 	pi := l.newPayload(sname, sver)
 	pp := l.payloads[pi]
 	pp.kind = skind
 	pp.ver = sver
-	pp.size = int64(osym.Siz)
+	pp.size = int64(osym.Siz())
 	pp.objidx = r.objidx
 
 	// If this is a def, then copy the guts. We expect this case
@@ -2346,8 +2317,7 @@
 			isdup = true
 		}
 
-		osym := goobj2.Sym{}
-		osym.ReadWithoutName(r.Reader, r.SymOff(i))
+		osym := r.Sym2(i)
 		dupok := osym.Dupok()
 		if dupok && isdup {
 			if l.attrReachable.Has(gi) {
@@ -2372,7 +2342,7 @@
 
 		local := osym.Local()
 		makeTypelink := osym.Typelink()
-		size := osym.Siz
+		size := osym.Siz()
 
 		// Symbol data
 		s.P = r.Data(i)
@@ -2655,9 +2625,8 @@
 			if !l.attrReachable.Has(gi) {
 				continue
 			}
-			osym := goobj2.Sym{}
-			osym.ReadWithoutName(r.Reader, r.SymOff(i))
-			st := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
+			osym := r.Sym2(i)
+			st := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())]
 			if st != sym.STEXT {
 				continue
 			}