aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/oldlink/internal/loader/loader.go771
1 files changed, 25 insertions, 746 deletions
diff --git a/src/cmd/oldlink/internal/loader/loader.go b/src/cmd/oldlink/internal/loader/loader.go
index ed533c99c4..8c618bfe4d 100644
--- a/src/cmd/oldlink/internal/loader/loader.go
+++ b/src/cmd/oldlink/internal/loader/loader.go
@@ -8,14 +8,11 @@ import (
"bytes"
"cmd/internal/bio"
"cmd/internal/dwarf"
- "cmd/internal/goobj2"
- "cmd/internal/obj"
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/oldlink/internal/sym"
"fmt"
"log"
- "os"
"sort"
"strconv"
"strings"
@@ -54,7 +51,7 @@ type Reloc struct {
// extra information.
// TODO: rename to objReader once the old one is gone?
type oReader struct {
- *goobj2.Reader
+ //*goobj2.Reader
unit *sym.CompilationUnit
version int // version of static symbol
flags uint32 // read from object file
@@ -133,18 +130,8 @@ const (
)
func NewLoader(flags uint32) *Loader {
- nbuiltin := goobj2.NBuiltin()
- return &Loader{
- start: make(map[*oReader]Sym),
- objs: []objIdx{{nil, 0, 0}},
- symsByName: [2]map[string]Sym{make(map[string]Sym), make(map[string]Sym)},
- objByPkg: make(map[string]*oReader),
- overwrite: make(map[Sym]Sym),
- itablink: make(map[Sym]struct{}),
- extStaticSyms: make(map[nameVer]Sym),
- builtinSyms: make([]Sym, nbuiltin),
- flags: flags,
- }
+ log.Fatal("-newobj in oldlink should not be used")
+ panic("unreachable")
}
// Return the start index in the global index space for a given object file.
@@ -152,66 +139,9 @@ func (l *Loader) startIndex(r *oReader) Sym {
return l.start[r]
}
-// Add object file r, return the start index.
-func (l *Loader) addObj(pkg string, r *oReader) Sym {
- if _, ok := l.start[r]; ok {
- panic("already added")
- }
- pkg = objabi.PathToPrefix(pkg) // the object file contains escaped package path
- if _, ok := l.objByPkg[pkg]; !ok {
- l.objByPkg[pkg] = r
- }
- n := r.NSym() + r.NNonpkgdef()
- i := l.max + 1
- l.start[r] = i
- l.objs = append(l.objs, objIdx{r, i, i + Sym(n) - 1})
- l.max += Sym(n)
- return i
-}
-
// Add a symbol with a given index, return if it is added.
func (l *Loader) AddSym(name string, ver int, i Sym, r *oReader, dupok bool, typ sym.SymKind) bool {
- if l.extStart != 0 {
- panic("AddSym called after AddExtSym is called")
- }
- if ver == r.version {
- // Static symbol. Add its global index but don't
- // add to name lookup table, as it cannot be
- // referenced by name.
- return true
- }
- if oldi, ok := l.symsByName[ver][name]; ok {
- if dupok {
- if l.flags&FlagStrictDups != 0 {
- l.checkdup(name, i, r, oldi)
- }
- return false
- }
- oldr, li := l.toLocal(oldi)
- oldsym := goobj2.Sym{}
- oldsym.Read(oldr.Reader, oldr.SymOff(li))
- if oldsym.Dupok() {
- return false
- }
- overwrite := r.DataSize(int(i-l.startIndex(r))) != 0
- if overwrite {
- // new symbol overwrites old symbol.
- oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type)]
- if !oldtyp.IsData() && r.DataSize(li) == 0 {
- log.Fatalf("duplicated definition of symbol " + name)
- }
- l.overwrite[oldi] = i
- } else {
- // old symbol overwrites new symbol.
- if typ != sym.SDATA && typ != sym.SNOPTRDATA && typ != sym.SBSS && typ != sym.SNOPTRBSS { // only allow overwriting data symbol
- log.Fatalf("duplicated definition of symbol " + name)
- }
- l.overwrite[i] = oldi
- return false
- }
- }
- l.symsByName[ver][name] = i
- return true
+ panic("unreachable")
}
// Add an external symbol (without index). Return the index of newly added
@@ -286,65 +216,6 @@ func (l *Loader) toLocal(i Sym) (*oReader, int) {
return l.objs[k-1].r, int(i - l.objs[k-1].i)
}
-// rcacheGet checks for a valid entry for 's' in the readers cache,
-// where 's' is a local PkgIdxNone ref or def, or zero if
-// the cache is empty or doesn't contain a value for 's'.
-func (or *oReader) rcacheGet(symIdx uint32) Sym {
- if len(or.rcache) > 0 {
- return or.rcache[symIdx]
- }
- return 0
-}
-
-// rcacheSet installs a new entry in the oReader's PkgNone
-// resolver cache for the specified PkgIdxNone ref or def,
-// allocating a new cache if needed.
-func (or *oReader) rcacheSet(symIdx uint32, gsym Sym) {
- if len(or.rcache) == 0 {
- or.rcache = make([]Sym, or.NNonpkgdef()+or.NNonpkgref())
- }
- or.rcache[symIdx] = gsym
-}
-
-// Resolve a local symbol reference. Return global index.
-func (l *Loader) resolve(r *oReader, s goobj2.SymRef) Sym {
- var rr *oReader
- switch p := s.PkgIdx; p {
- case goobj2.PkgIdxInvalid:
- if s.SymIdx != 0 {
- panic("bad sym ref")
- }
- return 0
- case goobj2.PkgIdxNone:
- // Check for cached version first
- if cached := r.rcacheGet(s.SymIdx); cached != 0 {
- return cached
- }
- // Resolve by name
- i := int(s.SymIdx) + r.NSym()
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(i))
- name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
- v := abiToVer(osym.ABI, r.version)
- gsym := l.Lookup(name, v)
- // Add to cache, then return.
- r.rcacheSet(s.SymIdx, gsym)
- return gsym
- case goobj2.PkgIdxBuiltin:
- return l.builtinSyms[s.SymIdx]
- case goobj2.PkgIdxSelf:
- rr = r
- default:
- pkg := r.Pkg(int(p))
- var ok bool
- rr, ok = l.objByPkg[pkg]
- if !ok {
- log.Fatalf("reference of nonexisted package %s, from %v", pkg, r.unit.Lib)
- }
- }
- return l.toGlobal(rr, int(s.SymIdx))
-}
-
// Look up a symbol by name, return global index, or 0 if not found.
// This is more like Syms.ROLookup than Lookup -- it doesn't create
// new symbol.
@@ -358,61 +229,12 @@ func (l *Loader) Lookup(name string, ver int) Sym {
// Returns whether i is a dup of another symbol, and i is not
// "primary", i.e. Lookup i by name will not return i.
func (l *Loader) IsDup(i Sym) bool {
- if _, ok := l.overwrite[i]; ok {
- return true
- }
- if l.IsExternal(i) {
- return false
- }
- r, li := l.toLocal(i)
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(li))
- if !osym.Dupok() {
- return false
- }
- if osym.Name == "" {
- return false // Unnamed aux symbol cannot be dup.
- }
- if osym.ABI == goobj2.SymABIstatic {
- return false // Static symbol cannot be dup.
- }
- name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
- ver := abiToVer(osym.ABI, r.version)
- return l.symsByName[ver][name] != i
+ panic("unreachable")
}
// Check that duplicate symbols have same contents.
func (l *Loader) checkdup(name string, i Sym, r *oReader, dup Sym) {
- li := int(i - l.startIndex(r))
- p := r.Data(li)
- if strings.HasPrefix(name, "go.info.") {
- p, _ = patchDWARFName1(p, r)
- }
- rdup, ldup := l.toLocal(dup)
- pdup := rdup.Data(ldup)
- if strings.HasPrefix(name, "go.info.") {
- pdup, _ = patchDWARFName1(pdup, rdup)
- }
- if bytes.Equal(p, pdup) {
- return
- }
- reason := "same length but different contents"
- if len(p) != len(pdup) {
- reason = fmt.Sprintf("new length %d != old length %d", len(p), len(pdup))
- }
- fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason)
-
- // For the moment, whitelist DWARF subprogram DIEs for
- // auto-generated wrapper functions. What seems to happen
- // here is that we get different line numbers on formal
- // params; I am guessing that the pos is being inherited
- // from the spot where the wrapper is needed.
- whitelist := strings.HasPrefix(name, "go.info.go.interface") ||
- strings.HasPrefix(name, "go.info.go.builtin") ||
- strings.HasPrefix(name, "go.debuglines")
- if !whitelist {
- l.strictDupMsgs++
- }
+ panic("unreachable")
}
func (l *Loader) NStrictDupMsgs() int { return l.strictDupMsgs }
@@ -429,66 +251,32 @@ func (l *Loader) NDef() int {
// Returns the raw (unpatched) name of the i-th symbol.
func (l *Loader) RawSymName(i Sym) string {
- if l.IsExternal(i) {
- if s := l.Syms[i]; s != nil {
- return s.Name
- }
- return ""
- }
- r, li := l.toLocal(i)
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(li))
- return osym.Name
+ panic("unreachable")
}
// Returns the (patched) name of the i-th symbol.
func (l *Loader) SymName(i Sym) string {
- if l.IsExternal(i) {
- if s := l.Syms[i]; s != nil {
- return s.Name // external name should already be patched?
- }
- return ""
- }
- r, li := l.toLocal(i)
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(li))
- return strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
+ panic("unreachable")
}
// Returns the type of the i-th symbol.
func (l *Loader) SymType(i Sym) sym.SymKind {
- if l.IsExternal(i) {
- if s := l.Syms[i]; s != nil {
- return s.Type
- }
- return 0
- }
- r, li := l.toLocal(i)
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(li))
- return sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
+ panic("unreachable")
}
// Returns the attributes of the i-th symbol.
func (l *Loader) SymAttr(i Sym) uint8 {
- if l.IsExternal(i) {
- // TODO: do something? External symbols have different representation of attributes. For now, ReflectMethod is the only thing matters and it cannot be set by external symbol.
- return 0
- }
- r, li := l.toLocal(i)
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(li))
- return osym.Flag
+ panic("unreachable")
}
// Returns whether the i-th symbol has ReflectMethod attribute set.
func (l *Loader) IsReflectMethod(i Sym) bool {
- return l.SymAttr(i)&goobj2.SymFlagReflectMethod != 0
+ panic("unreachable")
}
// Returns whether this is a Go type symbol.
func (l *Loader) IsGoType(i Sym) bool {
- return l.SymAttr(i)&goobj2.SymFlagGoType != 0
+ panic("unreachable")
}
// Returns whether this is a "go.itablink.*" symbol.
@@ -501,62 +289,25 @@ func (l *Loader) IsItabLink(i Sym) bool {
// Returns the symbol content of the i-th symbol. i is global index.
func (l *Loader) Data(i Sym) []byte {
- if l.IsExternal(i) {
- if s := l.Syms[i]; s != nil {
- return s.P
- }
- return nil
- }
- r, li := l.toLocal(i)
- return r.Data(li)
+ panic("unreachable")
}
// Returns the number of aux symbols given a global index.
func (l *Loader) NAux(i Sym) int {
- if l.IsExternal(i) {
- return 0
- }
- r, li := l.toLocal(i)
- return r.NAux(li)
+ panic("unreachable")
}
// 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)
+ panic("unreachable")
}
// ReadAuxSyms reads the aux symbol ids for the specified symbol into the
// slice passed as a parameter. If the slice capacity is not large enough, a new
// larger slice will be allocated. Final slice is returned.
func (l *Loader) ReadAuxSyms(symIdx Sym, dst []Sym) []Sym {
- if l.IsExternal(symIdx) {
- return dst[:0]
- }
- naux := l.NAux(symIdx)
- if naux == 0 {
- return dst[:0]
- }
-
- if cap(dst) < naux {
- dst = make([]Sym, naux)
- }
- dst = dst[:0]
-
- r, li := l.toLocal(symIdx)
- for i := 0; i < naux; i++ {
- a := goobj2.Aux{}
- a.Read(r.Reader, r.AuxOff(li, i))
- dst = append(dst, l.resolve(r, a.Sym))
- }
-
- return dst
+ panic("unreachable")
}
// OuterSym gets the outer symbol for host object loaded symbols.
@@ -586,147 +337,25 @@ func (l *Loader) InitReachable() {
// At method returns the j-th reloc for a global symbol.
func (relocs *Relocs) At(j int) Reloc {
- if relocs.ext != nil {
- rel := &relocs.ext.R[j]
- return Reloc{
- Off: rel.Off,
- Size: rel.Siz,
- Type: rel.Type,
- Add: rel.Add,
- Sym: relocs.l.Lookup(rel.Sym.Name, int(rel.Sym.Version)),
- }
- }
- rel := goobj2.Reloc{}
- rel.Read(relocs.r.Reader, relocs.r.RelocOff(relocs.li, j))
- target := relocs.l.resolve(relocs.r, rel.Sym)
- return Reloc{
- Off: rel.Off,
- Size: rel.Siz,
- Type: objabi.RelocType(rel.Type),
- Add: rel.Add,
- Sym: target,
- }
+ panic("unreachable")
}
// ReadAll method reads all relocations for a symbol into the
// specified slice. If the slice capacity is not large enough, a new
// larger slice will be allocated. Final slice is returned.
func (relocs *Relocs) ReadAll(dst []Reloc) []Reloc {
- if relocs.Count == 0 {
- return dst[:0]
- }
-
- if cap(dst) < relocs.Count {
- dst = make([]Reloc, relocs.Count)
- }
- dst = dst[:0]
-
- if relocs.ext != nil {
- for i := 0; i < relocs.Count; i++ {
- erel := &relocs.ext.R[i]
- rel := Reloc{
- Off: erel.Off,
- Size: erel.Siz,
- Type: erel.Type,
- Add: erel.Add,
- Sym: relocs.l.Lookup(erel.Sym.Name, int(erel.Sym.Version)),
- }
- dst = append(dst, rel)
- }
- return dst
- }
-
- off := relocs.r.RelocOff(relocs.li, 0)
- for i := 0; i < relocs.Count; i++ {
- rel := goobj2.Reloc{}
- rel.Read(relocs.r.Reader, off)
- off += uint32(rel.Size())
- target := relocs.l.resolve(relocs.r, rel.Sym)
- dst = append(dst, Reloc{
- Off: rel.Off,
- Size: rel.Siz,
- Type: objabi.RelocType(rel.Type),
- Add: rel.Add,
- Sym: target,
- })
- }
- return dst
+ panic("unreachable")
}
// Relocs returns a Relocs object for the given global sym.
func (l *Loader) Relocs(i Sym) Relocs {
- if l.IsExternal(i) {
- if s := l.Syms[i]; s != nil {
- return Relocs{Count: len(s.R), l: l, ext: s}
- }
- return Relocs{}
- }
- r, li := l.toLocal(i)
- return l.relocs(r, li)
-}
-
-// Relocs returns a Relocs object given a local sym index and reader.
-func (l *Loader) relocs(r *oReader, li int) Relocs {
- return Relocs{
- Count: r.NReloc(li),
- li: li,
- r: r,
- l: l,
- }
+ panic("unreachable")
}
// Preload a package: add autolibs, add symbols to the symbol table.
// Does not read symbol data yet.
func (l *Loader) Preload(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64, pn string, flags int) {
- roObject, readonly, err := f.Slice(uint64(length))
- if err != nil {
- log.Fatal("cannot read object file:", err)
- }
- r := goobj2.NewReaderFromBytes(roObject, readonly)
- if r == nil {
- panic("cannot read object file")
- }
- localSymVersion := syms.IncVersion()
- pkgprefix := objabi.PathToPrefix(lib.Pkg) + "."
- or := &oReader{r, unit, localSymVersion, r.Flags(), pkgprefix, nil}
-
- // Autolib
- lib.ImportStrings = append(lib.ImportStrings, r.Autolib()...)
-
- // DWARF file table
- nfile := r.NDwarfFile()
- unit.DWARFFileTable = make([]string, nfile)
- for i := range unit.DWARFFileTable {
- unit.DWARFFileTable[i] = r.DwarfFile(i)
- }
-
- istart := l.addObj(lib.Pkg, or)
-
- ndef := r.NSym()
- nnonpkgdef := r.NNonpkgdef()
- for i, n := 0, ndef+nnonpkgdef; i < n; i++ {
- osym := goobj2.Sym{}
- osym.Read(r, r.SymOff(i))
- name := strings.Replace(osym.Name, "\"\".", pkgprefix, -1)
- if name == "" {
- continue // don't add unnamed aux symbol
- }
- v := abiToVer(osym.ABI, localSymVersion)
- dupok := osym.Dupok()
- added := l.AddSym(name, v, istart+Sym(i), or, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
- if added && strings.HasPrefix(name, "go.itablink.") {
- l.itablink[istart+Sym(i)] = struct{}{}
- }
- if added && strings.HasPrefix(name, "runtime.") {
- if bi := goobj2.BuiltinIdx(name, v); bi != -1 {
- // This is a definition of a builtin symbol. Record where it is.
- l.builtinSyms[bi] = istart + Sym(i)
- }
- }
- }
-
- // The caller expects us consuming all the data
- f.MustSeek(length, os.SEEK_CUR)
+ panic("unreachable")
}
// Make sure referenced symbols are added. Most of them should already be added.
@@ -738,28 +367,11 @@ func (l *Loader) LoadRefs(arch *sys.Arch, syms *sym.Symbols) {
}
func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch, 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)
- l.AddExtSym(name, v)
- }
+ panic("unreachable")
}
func abiToVer(abi uint16, localSymVersion int) int {
- var v int
- if abi == goobj2.SymABIstatic {
- // Static
- v = localSymVersion
- } else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 {
- // Note that data symbols are "ABI0", which maps to version 0.
- v = abiver
- } else {
- log.Fatalf("invalid symbol ABI: %d", abi)
- }
- return v
+ panic("unreachable")
}
func preprocess(arch *sys.Arch, s *sym.Symbol) {
@@ -885,90 +497,14 @@ func (l *Loader) addNewSym(i Sym, syms *sym.Symbols, name string, ver int, unit
// object corresponding to object reader "r". Return value is the
// number of sym.Reloc entries required for all the new symbols.
func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
- istart := l.startIndex(r)
- nr := 0
-
- for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
- // If it's been previously loaded in host object loading, we don't need to do it again.
- if s := l.Syms[istart+Sym(i)]; s != nil {
- // Mark symbol as reachable as it wasn't marked as such before.
- s.Attr.Set(sym.AttrReachable, l.Reachable.Has(istart+Sym(i)))
- nr += r.NReloc(i)
- continue
- }
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(i))
- name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
- if name == "" {
- continue
- }
- ver := abiToVer(osym.ABI, r.version)
- if osym.ABI != goobj2.SymABIstatic && l.symsByName[ver][name] != istart+Sym(i) {
- continue
- }
-
- t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
- if t == sym.SXREF {
- log.Fatalf("bad sxref")
- }
- if t == 0 {
- log.Fatalf("missing type for %s in %s", name, r.unit.Lib)
- }
- if !l.Reachable.Has(istart+Sym(i)) && !(t == sym.SRODATA && strings.HasPrefix(name, "type.")) && name != "runtime.addmoduledata" && name != "runtime.lastmoduledatap" {
- // No need to load unreachable symbols.
- // XXX some type symbol's content may be needed in DWARF code, but they are not marked.
- // XXX reference to runtime.addmoduledata may be generated later by the linker in plugin mode.
- continue
- }
-
- s := l.addNewSym(istart+Sym(i), syms, name, ver, r.unit, t)
- s.Attr.Set(sym.AttrReachable, l.Reachable.Has(istart+Sym(i)))
- nr += r.NReloc(i)
- }
- return nr
-}
-
-// funcInfoSym records the sym.Symbol for a function, along with a copy
-// of the corresponding goobj2.Sym and the index of its FuncInfo aux sym.
-// 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
-}
-
-// funcAllocInfo records totals/counts for all functions in an objfile;
-// used to help with bulk allocation of sym.Symbol sub-objects.
-type funcAllocInfo struct {
- symPtr uint32 // number of *sym.Symbol's needed in file slices
- inlCall uint32 // number of sym.InlinedCall's needed in inltree slices
- pcData uint32 // number of sym.Pcdata's needed in pdata slices
- fdOff uint32 // number of int64's needed in all Funcdataoff slices
+ panic("unreachable")
}
// LoadSymbol loads a single symbol by name.
// This function should only be used by the host object loaders.
// NB: This function does NOT set the symbol as reachable.
func (l *Loader) LoadSymbol(name string, version int, syms *sym.Symbols) *sym.Symbol {
- global := l.Lookup(name, version)
-
- // If we're already loaded, bail.
- if global != 0 && int(global) < len(l.Syms) && l.Syms[global] != nil {
- return l.Syms[global]
- }
-
- // Read the symbol.
- r, i := l.toLocal(global)
- istart := l.startIndex(r)
-
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(int(i)))
- if l.symsByName[version][name] != istart+Sym(i) {
- return nil
- }
-
- return l.addNewSym(istart+Sym(i), syms, name, version, r.unit, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
+ panic("unreachable")
}
// LookupOrCreate looks up a symbol by name, and creates one if not found.
@@ -1023,264 +559,7 @@ func (l *Loader) Create(name string, syms *sym.Symbols) *sym.Symbol {
}
func loadObjFull(l *Loader, r *oReader) {
- lib := r.unit.Lib
- istart := l.startIndex(r)
-
- resolveSymRef := func(s goobj2.SymRef) *sym.Symbol {
- i := l.resolve(r, s)
- return l.Syms[i]
- }
-
- funcs := []funcInfoSym{}
- fdsyms := []*sym.Symbol{}
- var funcAllocCounts funcAllocInfo
- pcdataBase := r.PcdataBase()
- rslice := []Reloc{}
- for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
- osym := goobj2.Sym{}
- osym.Read(r.Reader, r.SymOff(i))
- name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
- if name == "" {
- continue
- }
- ver := abiToVer(osym.ABI, r.version)
- dupok := osym.Dupok()
- if dupok {
- if dupsym := l.symsByName[ver][name]; dupsym != istart+Sym(i) {
- if l.Reachable.Has(dupsym) {
- // A dupok symbol is resolved to another package. We still need
- // to record its presence in the current package, as the trampoline
- // pass expects packages are laid out in dependency order.
- s := l.Syms[dupsym]
- if s.Type == sym.STEXT {
- lib.DupTextSyms = append(lib.DupTextSyms, s)
- }
- }
- continue
- }
- }
-
- s := l.Syms[istart+Sym(i)]
- if s == nil {
- continue
- }
- if s.Name != name { // Sanity check. We can remove it in the final version.
- fmt.Println("name mismatch:", lib, i, s.Name, name)
- panic("name mismatch")
- }
-
- local := osym.Local()
- makeTypelink := osym.Typelink()
- size := osym.Siz
-
- // Symbol data
- s.P = r.Data(i)
- s.Attr.Set(sym.AttrReadOnly, r.ReadOnly())
-
- // Relocs
- relocs := l.relocs(r, i)
- rslice = relocs.ReadAll(rslice)
- batch := l.relocBatch
- s.R = batch[:relocs.Count:relocs.Count]
- l.relocBatch = batch[relocs.Count:]
- for j := range s.R {
- r := rslice[j]
- rs := r.Sym
- sz := r.Size
- rt := r.Type
- if rt == objabi.R_METHODOFF {
- if l.Reachable.Has(rs) {
- rt = objabi.R_ADDROFF
- } else {
- sz = 0
- rs = 0
- }
- }
- if rt == objabi.R_WEAKADDROFF && !l.Reachable.Has(rs) {
- rs = 0
- sz = 0
- }
- if rs != 0 && l.SymType(rs) == sym.SABIALIAS {
- rsrelocs := l.Relocs(rs)
- rs = rsrelocs.At(0).Sym
- }
- s.R[j] = sym.Reloc{
- Off: r.Off,
- Siz: sz,
- Type: rt,
- Add: r.Add,
- Sym: l.Syms[rs],
- }
- }
-
- // Aux symbol info
- isym := -1
- naux := r.NAux(i)
- for j := 0; j < naux; j++ {
- a := goobj2.Aux{}
- a.Read(r.Reader, r.AuxOff(i, j))
- switch a.Type {
- case goobj2.AuxGotype:
- typ := resolveSymRef(a.Sym)
- if typ != nil {
- s.Gotype = typ
- }
- case goobj2.AuxFuncdata:
- fdsyms = append(fdsyms, resolveSymRef(a.Sym))
- case goobj2.AuxFuncInfo:
- if a.Sym.PkgIdx != goobj2.PkgIdxSelf {
- panic("funcinfo symbol not defined in current package")
- }
- isym = int(a.Sym.SymIdx)
- case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
- // ignored for now
- default:
- panic("unknown aux type")
- }
- }
-
- s.File = r.pkgprefix[:len(r.pkgprefix)-1]
- if dupok {
- s.Attr |= sym.AttrDuplicateOK
- }
- if s.Size < int64(size) {
- s.Size = int64(size)
- }
- s.Attr.Set(sym.AttrLocal, local)
- s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
-
- if s.Type == sym.SDWARFINFO {
- // For DWARF symbols, replace `"".` to actual package prefix
- // in the symbol content.
- // TODO: maybe we should do this in the compiler and get rid
- // of this.
- patchDWARFName(s, r)
- }
-
- if s.Type != sym.STEXT {
- continue
- }
-
- if isym == -1 {
- continue
- }
-
- // Record function sym and associated info for additional
- // processing in the loop below.
- fwis := funcInfoSym{s: s, isym: isym, osym: osym}
- funcs = append(funcs, fwis)
-
- // Read the goobj2.FuncInfo for this text symbol so that we can
- // collect allocation counts. We'll read it again in the loop
- // below.
- b := r.Data(isym)
- info := goobj2.FuncInfo{}
- info.Read(b)
- funcAllocCounts.symPtr += uint32(len(info.File))
- funcAllocCounts.pcData += uint32(len(info.Pcdata))
- funcAllocCounts.inlCall += uint32(len(info.InlTree))
- funcAllocCounts.fdOff += uint32(len(info.Funcdataoff))
- }
-
- // At this point we can do batch allocation of the sym.FuncInfo's,
- // along with the slices of sub-objects they use.
- fiBatch := make([]sym.FuncInfo, len(funcs))
- inlCallBatch := make([]sym.InlinedCall, funcAllocCounts.inlCall)
- symPtrBatch := make([]*sym.Symbol, funcAllocCounts.symPtr)
- pcDataBatch := make([]sym.Pcdata, funcAllocCounts.pcData)
- fdOffBatch := make([]int64, funcAllocCounts.fdOff)
-
- // Populate FuncInfo contents for func symbols.
- for fi := 0; fi < len(funcs); fi++ {
- s := funcs[fi].s
- isym := funcs[fi].isym
- osym := funcs[fi].osym
-
- s.FuncInfo = &fiBatch[0]
- fiBatch = fiBatch[1:]
-
- b := r.Data(isym)
- info := goobj2.FuncInfo{}
- info.Read(b)
-
- if osym.NoSplit() {
- s.Attr |= sym.AttrNoSplit
- }
- if osym.ReflectMethod() {
- s.Attr |= sym.AttrReflectMethod
- }
- if r.Flags()&goobj2.ObjFlagShared != 0 {
- s.Attr |= sym.AttrShared
- }
- if osym.TopFrame() {
- s.Attr |= sym.AttrTopFrame
- }
-
- pc := s.FuncInfo
-
- if len(info.Funcdataoff) != 0 {
- nfd := len(info.Funcdataoff)
- pc.Funcdata = fdsyms[:nfd:nfd]
- fdsyms = fdsyms[nfd:]
- }
-
- info.Pcdata = append(info.Pcdata, info.PcdataEnd) // for the ease of knowing where it ends
- pc.Args = int32(info.Args)
- pc.Locals = int32(info.Locals)
-
- npc := len(info.Pcdata) - 1 // -1 as we appended one above
- pc.Pcdata = pcDataBatch[:npc:npc]
- pcDataBatch = pcDataBatch[npc:]
-
- nfd := len(info.Funcdataoff)
- pc.Funcdataoff = fdOffBatch[:nfd:nfd]
- fdOffBatch = fdOffBatch[nfd:]
-
- nsp := len(info.File)
- pc.File = symPtrBatch[:nsp:nsp]
- symPtrBatch = symPtrBatch[nsp:]
-
- nic := len(info.InlTree)
- pc.InlTree = inlCallBatch[:nic:nic]
- inlCallBatch = inlCallBatch[nic:]
-
- pc.Pcsp.P = r.BytesAt(pcdataBase+info.Pcsp, int(info.Pcfile-info.Pcsp))
- pc.Pcfile.P = r.BytesAt(pcdataBase+info.Pcfile, int(info.Pcline-info.Pcfile))
- pc.Pcline.P = r.BytesAt(pcdataBase+info.Pcline, int(info.Pcinline-info.Pcline))
- pc.Pcinline.P = r.BytesAt(pcdataBase+info.Pcinline, int(info.Pcdata[0]-info.Pcinline))
- for k := range pc.Pcdata {
- pc.Pcdata[k].P = r.BytesAt(pcdataBase+info.Pcdata[k], int(info.Pcdata[k+1]-info.Pcdata[k]))
- }
- for k := range pc.Funcdataoff {
- pc.Funcdataoff[k] = int64(info.Funcdataoff[k])
- }
- for k := range pc.File {
- pc.File[k] = resolveSymRef(info.File[k])
- }
- for k := range pc.InlTree {
- inl := &info.InlTree[k]
- pc.InlTree[k] = sym.InlinedCall{
- Parent: inl.Parent,
- File: resolveSymRef(inl.File),
- Line: inl.Line,
- Func: l.SymName(l.resolve(r, inl.Func)),
- ParentPC: inl.ParentPC,
- }
- }
-
- dupok := osym.Dupok()
- if !dupok {
- if s.Attr.OnList() {
- log.Fatalf("symbol %s listed multiple times", s.Name)
- }
- s.Attr.Set(sym.AttrOnList, true)
- lib.Textp = append(lib.Textp, s)
- } else {
- // there may be a dup in another package
- // put into a temp list and add to text later
- lib.DupTextSyms = append(lib.DupTextSyms, s)
- }
- }
+ panic("unreachable")
}
var emptyPkg = []byte(`"".`)