github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/link/internal/loader/loader.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package loader
     6  
     7  import (
     8  	"bytes"
     9  	"github.com/gagliardetto/golang-go/cmd/internal/bio"
    10  	"github.com/gagliardetto/golang-go/cmd/internal/dwarf"
    11  	"github.com/gagliardetto/golang-go/cmd/internal/goobj2"
    12  	"github.com/gagliardetto/golang-go/cmd/internal/obj"
    13  	"github.com/gagliardetto/golang-go/cmd/internal/objabi"
    14  	"github.com/gagliardetto/golang-go/cmd/internal/sys"
    15  	"github.com/gagliardetto/golang-go/cmd/link/internal/sym"
    16  	"fmt"
    17  	"log"
    18  	"os"
    19  	"sort"
    20  	"strconv"
    21  	"strings"
    22  )
    23  
    24  var _ = fmt.Print
    25  
    26  // Sym encapsulates a global symbol index, used to identify a specific
    27  // Go symbol. The 0-valued Sym is corresponds to an invalid symbol.
    28  type Sym int
    29  
    30  // Relocs encapsulates the set of relocations on a given symbol; an
    31  // instance of this type is returned by the Loader Relocs() method.
    32  type Relocs struct {
    33  	Count int // number of relocs
    34  
    35  	li int      // local index of symbol whose relocs we're examining
    36  	r  *oReader // object reader for containing package
    37  	l  *Loader  // loader
    38  
    39  	ext *sym.Symbol // external symbol if not nil
    40  }
    41  
    42  // Reloc contains the payload for a specific relocation.
    43  // TODO: replace this with sym.Reloc, once we change the
    44  // relocation target from "*sym.Symbol" to "loader.Sym" in sym.Reloc.
    45  type Reloc struct {
    46  	Off  int32            // offset to rewrite
    47  	Size uint8            // number of bytes to rewrite: 0, 1, 2, or 4
    48  	Type objabi.RelocType // the relocation type
    49  	Add  int64            // addend
    50  	Sym  Sym              // global index of symbol the reloc addresses
    51  }
    52  
    53  // oReader is a wrapper type of obj.Reader, along with some
    54  // extra information.
    55  // TODO: rename to objReader once the old one is gone?
    56  type oReader struct {
    57  	*goobj2.Reader
    58  	unit      *sym.CompilationUnit
    59  	version   int    // version of static symbol
    60  	flags     uint32 // read from object file
    61  	pkgprefix string
    62  	rcache    []Sym // cache mapping local PkgNone symbol to resolved Sym
    63  }
    64  
    65  type objIdx struct {
    66  	r *oReader
    67  	i Sym // start index
    68  	e Sym // end index
    69  }
    70  
    71  type nameVer struct {
    72  	name string
    73  	v    int
    74  }
    75  
    76  type bitmap []uint32
    77  
    78  // set the i-th bit.
    79  func (bm bitmap) Set(i Sym) {
    80  	n, r := uint(i)/32, uint(i)%32
    81  	bm[n] |= 1 << r
    82  }
    83  
    84  // whether the i-th bit is set.
    85  func (bm bitmap) Has(i Sym) bool {
    86  	n, r := uint(i)/32, uint(i)%32
    87  	return bm[n]&(1<<r) != 0
    88  }
    89  
    90  func makeBitmap(n int) bitmap {
    91  	return make(bitmap, (n+31)/32)
    92  }
    93  
    94  // A Loader loads new object files and resolves indexed symbol references.
    95  type Loader struct {
    96  	start       map[*oReader]Sym // map from object file to its start index
    97  	objs        []objIdx         // sorted by start index (i.e. objIdx.i)
    98  	max         Sym              // current max index
    99  	extStart    Sym              // from this index on, the symbols are externally defined
   100  	extSyms     []nameVer        // externally defined symbols
   101  	builtinSyms []Sym            // global index of builtin symbols
   102  	ocache      int              // index (into 'objs') of most recent lookup
   103  
   104  	symsByName    [2]map[string]Sym // map symbol name to index, two maps are for ABI0 and ABIInternal
   105  	extStaticSyms map[nameVer]Sym   // externally defined static symbols, keyed by name
   106  	overwrite     map[Sym]Sym       // overwrite[i]=j if symbol j overwrites symbol i
   107  
   108  	itablink map[Sym]struct{} // itablink[j] defined if j is go.itablink.*
   109  
   110  	objByPkg map[string]*oReader // map package path to its Go object reader
   111  
   112  	Syms []*sym.Symbol // indexed symbols. XXX we still make sym.Symbol for now.
   113  
   114  	anonVersion int // most recently assigned ext static sym pseudo-version
   115  
   116  	Reachable bitmap // bitmap of reachable symbols, indexed by global index
   117  
   118  	// Used to implement field tracking; created during deadcode if
   119  	// field tracking is enabled. Reachparent[K] contains the index of
   120  	// the symbol that triggered the marking of symbol K as live.
   121  	Reachparent []Sym
   122  
   123  	relocBatch []sym.Reloc // for bulk allocation of relocations
   124  
   125  	flags uint32
   126  
   127  	strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled
   128  }
   129  
   130  const (
   131  	// Loader.flags
   132  	FlagStrictDups = 1 << iota
   133  )
   134  
   135  func NewLoader(flags uint32) *Loader {
   136  	nbuiltin := goobj2.NBuiltin()
   137  	return &Loader{
   138  		start:         make(map[*oReader]Sym),
   139  		objs:          []objIdx{{nil, 0, 0}},
   140  		symsByName:    [2]map[string]Sym{make(map[string]Sym), make(map[string]Sym)},
   141  		objByPkg:      make(map[string]*oReader),
   142  		overwrite:     make(map[Sym]Sym),
   143  		itablink:      make(map[Sym]struct{}),
   144  		extStaticSyms: make(map[nameVer]Sym),
   145  		builtinSyms:   make([]Sym, nbuiltin),
   146  		flags:         flags,
   147  	}
   148  }
   149  
   150  // Return the start index in the global index space for a given object file.
   151  func (l *Loader) startIndex(r *oReader) Sym {
   152  	return l.start[r]
   153  }
   154  
   155  // Add object file r, return the start index.
   156  func (l *Loader) addObj(pkg string, r *oReader) Sym {
   157  	if _, ok := l.start[r]; ok {
   158  		panic("already added")
   159  	}
   160  	pkg = objabi.PathToPrefix(pkg) // the object file contains escaped package path
   161  	if _, ok := l.objByPkg[pkg]; !ok {
   162  		l.objByPkg[pkg] = r
   163  	}
   164  	n := r.NSym() + r.NNonpkgdef()
   165  	i := l.max + 1
   166  	l.start[r] = i
   167  	l.objs = append(l.objs, objIdx{r, i, i + Sym(n) - 1})
   168  	l.max += Sym(n)
   169  	return i
   170  }
   171  
   172  // Add a symbol with a given index, return if it is added.
   173  func (l *Loader) AddSym(name string, ver int, i Sym, r *oReader, dupok bool, typ sym.SymKind) bool {
   174  	if l.extStart != 0 {
   175  		panic("AddSym called after AddExtSym is called")
   176  	}
   177  	if ver == r.version {
   178  		// Static symbol. Add its global index but don't
   179  		// add to name lookup table, as it cannot be
   180  		// referenced by name.
   181  		return true
   182  	}
   183  	if oldi, ok := l.symsByName[ver][name]; ok {
   184  		if dupok {
   185  			if l.flags&FlagStrictDups != 0 {
   186  				l.checkdup(name, i, r, oldi)
   187  			}
   188  			return false
   189  		}
   190  		oldr, li := l.toLocal(oldi)
   191  		oldsym := goobj2.Sym{}
   192  		oldsym.Read(oldr.Reader, oldr.SymOff(li))
   193  		if oldsym.Dupok() {
   194  			return false
   195  		}
   196  		overwrite := r.DataSize(int(i-l.startIndex(r))) != 0
   197  		if overwrite {
   198  			// new symbol overwrites old symbol.
   199  			oldtyp := sym.AbiSymKindToSymKind[objabi.SymKind(oldsym.Type)]
   200  			if !oldtyp.IsData() && r.DataSize(li) == 0 {
   201  				log.Fatalf("duplicated definition of symbol " + name)
   202  			}
   203  			l.overwrite[oldi] = i
   204  		} else {
   205  			// old symbol overwrites new symbol.
   206  			if typ != sym.SDATA && typ != sym.SNOPTRDATA && typ != sym.SBSS && typ != sym.SNOPTRBSS { // only allow overwriting data symbol
   207  				log.Fatalf("duplicated definition of symbol " + name)
   208  			}
   209  			l.overwrite[i] = oldi
   210  			return false
   211  		}
   212  	}
   213  	l.symsByName[ver][name] = i
   214  	return true
   215  }
   216  
   217  // Add an external symbol (without index). Return the index of newly added
   218  // symbol, or 0 if not added.
   219  func (l *Loader) AddExtSym(name string, ver int) Sym {
   220  	static := ver >= sym.SymVerStatic
   221  	if static {
   222  		if _, ok := l.extStaticSyms[nameVer{name, ver}]; ok {
   223  			return 0
   224  		}
   225  	} else {
   226  		if _, ok := l.symsByName[ver][name]; ok {
   227  			return 0
   228  		}
   229  	}
   230  	i := l.max + 1
   231  	if static {
   232  		l.extStaticSyms[nameVer{name, ver}] = i
   233  	} else {
   234  		l.symsByName[ver][name] = i
   235  	}
   236  	l.max++
   237  	if l.extStart == 0 {
   238  		l.extStart = i
   239  	}
   240  	l.extSyms = append(l.extSyms, nameVer{name, ver})
   241  	l.growSyms(int(i))
   242  	return i
   243  }
   244  
   245  func (l *Loader) IsExternal(i Sym) bool {
   246  	return l.extStart != 0 && i >= l.extStart
   247  }
   248  
   249  // Ensure Syms slice has enough space.
   250  func (l *Loader) growSyms(i int) {
   251  	n := len(l.Syms)
   252  	if n > i {
   253  		return
   254  	}
   255  	l.Syms = append(l.Syms, make([]*sym.Symbol, i+1-n)...)
   256  }
   257  
   258  // Convert a local index to a global index.
   259  func (l *Loader) toGlobal(r *oReader, i int) Sym {
   260  	g := l.startIndex(r) + Sym(i)
   261  	if ov, ok := l.overwrite[g]; ok {
   262  		return ov
   263  	}
   264  	return g
   265  }
   266  
   267  // Convert a global index to a local index.
   268  func (l *Loader) toLocal(i Sym) (*oReader, int) {
   269  	if ov, ok := l.overwrite[i]; ok {
   270  		i = ov
   271  	}
   272  	if l.IsExternal(i) {
   273  		return nil, int(i - l.extStart)
   274  	}
   275  	oc := l.ocache
   276  	if oc != 0 && i >= l.objs[oc].i && i <= l.objs[oc].e {
   277  		return l.objs[oc].r, int(i - l.objs[oc].i)
   278  	}
   279  	// Search for the local object holding index i.
   280  	// Below k is the first one that has its start index > i,
   281  	// so k-1 is the one we want.
   282  	k := sort.Search(len(l.objs), func(k int) bool {
   283  		return l.objs[k].i > i
   284  	})
   285  	l.ocache = k - 1
   286  	return l.objs[k-1].r, int(i - l.objs[k-1].i)
   287  }
   288  
   289  // rcacheGet checks for a valid entry for 's' in the readers cache,
   290  // where 's' is a local PkgIdxNone ref or def, or zero if
   291  // the cache is empty or doesn't contain a value for 's'.
   292  func (or *oReader) rcacheGet(symIdx uint32) Sym {
   293  	if len(or.rcache) > 0 {
   294  		return or.rcache[symIdx]
   295  	}
   296  	return 0
   297  }
   298  
   299  // rcacheSet installs a new entry in the oReader's PkgNone
   300  // resolver cache for the specified PkgIdxNone ref or def,
   301  // allocating a new cache if needed.
   302  func (or *oReader) rcacheSet(symIdx uint32, gsym Sym) {
   303  	if len(or.rcache) == 0 {
   304  		or.rcache = make([]Sym, or.NNonpkgdef()+or.NNonpkgref())
   305  	}
   306  	or.rcache[symIdx] = gsym
   307  }
   308  
   309  // Resolve a local symbol reference. Return global index.
   310  func (l *Loader) resolve(r *oReader, s goobj2.SymRef) Sym {
   311  	var rr *oReader
   312  	switch p := s.PkgIdx; p {
   313  	case goobj2.PkgIdxInvalid:
   314  		if s.SymIdx != 0 {
   315  			panic("bad sym ref")
   316  		}
   317  		return 0
   318  	case goobj2.PkgIdxNone:
   319  		// Check for cached version first
   320  		if cached := r.rcacheGet(s.SymIdx); cached != 0 {
   321  			return cached
   322  		}
   323  		// Resolve by name
   324  		i := int(s.SymIdx) + r.NSym()
   325  		osym := goobj2.Sym{}
   326  		osym.Read(r.Reader, r.SymOff(i))
   327  		name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
   328  		v := abiToVer(osym.ABI, r.version)
   329  		gsym := l.Lookup(name, v)
   330  		// Add to cache, then return.
   331  		r.rcacheSet(s.SymIdx, gsym)
   332  		return gsym
   333  	case goobj2.PkgIdxBuiltin:
   334  		return l.builtinSyms[s.SymIdx]
   335  	case goobj2.PkgIdxSelf:
   336  		rr = r
   337  	default:
   338  		pkg := r.Pkg(int(p))
   339  		var ok bool
   340  		rr, ok = l.objByPkg[pkg]
   341  		if !ok {
   342  			log.Fatalf("reference of nonexisted package %s, from %v", pkg, r.unit.Lib)
   343  		}
   344  	}
   345  	return l.toGlobal(rr, int(s.SymIdx))
   346  }
   347  
   348  // Look up a symbol by name, return global index, or 0 if not found.
   349  // This is more like Syms.ROLookup than Lookup -- it doesn't create
   350  // new symbol.
   351  func (l *Loader) Lookup(name string, ver int) Sym {
   352  	if ver >= sym.SymVerStatic || ver < 0 {
   353  		return l.extStaticSyms[nameVer{name, ver}]
   354  	}
   355  	return l.symsByName[ver][name]
   356  }
   357  
   358  // Returns whether i is a dup of another symbol, and i is not
   359  // "primary", i.e. Lookup i by name will not return i.
   360  func (l *Loader) IsDup(i Sym) bool {
   361  	if _, ok := l.overwrite[i]; ok {
   362  		return true
   363  	}
   364  	if l.IsExternal(i) {
   365  		return false
   366  	}
   367  	r, li := l.toLocal(i)
   368  	osym := goobj2.Sym{}
   369  	osym.Read(r.Reader, r.SymOff(li))
   370  	if !osym.Dupok() {
   371  		return false
   372  	}
   373  	if osym.Name == "" {
   374  		return false // Unnamed aux symbol cannot be dup.
   375  	}
   376  	if osym.ABI == goobj2.SymABIstatic {
   377  		return false // Static symbol cannot be dup.
   378  	}
   379  	name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
   380  	ver := abiToVer(osym.ABI, r.version)
   381  	return l.symsByName[ver][name] != i
   382  }
   383  
   384  // Check that duplicate symbols have same contents.
   385  func (l *Loader) checkdup(name string, i Sym, r *oReader, dup Sym) {
   386  	li := int(i - l.startIndex(r))
   387  	p := r.Data(li)
   388  	if strings.HasPrefix(name, "go.info.") {
   389  		p, _ = patchDWARFName1(p, r)
   390  	}
   391  	rdup, ldup := l.toLocal(dup)
   392  	pdup := rdup.Data(ldup)
   393  	if strings.HasPrefix(name, "go.info.") {
   394  		pdup, _ = patchDWARFName1(pdup, rdup)
   395  	}
   396  	if bytes.Equal(p, pdup) {
   397  		return
   398  	}
   399  	reason := "same length but different contents"
   400  	if len(p) != len(pdup) {
   401  		reason = fmt.Sprintf("new length %d != old length %d", len(p), len(pdup))
   402  	}
   403  	fmt.Fprintf(os.Stderr, "github.com/gagliardetto/golang-go/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)
   404  
   405  	// For the moment, whitelist DWARF subprogram DIEs for
   406  	// auto-generated wrapper functions. What seems to happen
   407  	// here is that we get different line numbers on formal
   408  	// params; I am guessing that the pos is being inherited
   409  	// from the spot where the wrapper is needed.
   410  	whitelist := strings.HasPrefix(name, "go.info.go.interface") ||
   411  		strings.HasPrefix(name, "go.info.go.builtin") ||
   412  		strings.HasPrefix(name, "go.debuglines")
   413  	if !whitelist {
   414  		l.strictDupMsgs++
   415  	}
   416  }
   417  
   418  func (l *Loader) NStrictDupMsgs() int { return l.strictDupMsgs }
   419  
   420  // Number of total symbols.
   421  func (l *Loader) NSym() int {
   422  	return int(l.max + 1)
   423  }
   424  
   425  // Number of defined Go symbols.
   426  func (l *Loader) NDef() int {
   427  	return int(l.extStart)
   428  }
   429  
   430  // Returns the raw (unpatched) name of the i-th symbol.
   431  func (l *Loader) RawSymName(i Sym) string {
   432  	if l.IsExternal(i) {
   433  		if s := l.Syms[i]; s != nil {
   434  			return s.Name
   435  		}
   436  		return ""
   437  	}
   438  	r, li := l.toLocal(i)
   439  	osym := goobj2.Sym{}
   440  	osym.Read(r.Reader, r.SymOff(li))
   441  	return osym.Name
   442  }
   443  
   444  // Returns the (patched) name of the i-th symbol.
   445  func (l *Loader) SymName(i Sym) string {
   446  	if l.IsExternal(i) {
   447  		if s := l.Syms[i]; s != nil {
   448  			return s.Name // external name should already be patched?
   449  		}
   450  		return ""
   451  	}
   452  	r, li := l.toLocal(i)
   453  	osym := goobj2.Sym{}
   454  	osym.Read(r.Reader, r.SymOff(li))
   455  	return strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
   456  }
   457  
   458  // Returns the type of the i-th symbol.
   459  func (l *Loader) SymType(i Sym) sym.SymKind {
   460  	if l.IsExternal(i) {
   461  		if s := l.Syms[i]; s != nil {
   462  			return s.Type
   463  		}
   464  		return 0
   465  	}
   466  	r, li := l.toLocal(i)
   467  	osym := goobj2.Sym{}
   468  	osym.Read(r.Reader, r.SymOff(li))
   469  	return sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
   470  }
   471  
   472  // Returns the attributes of the i-th symbol.
   473  func (l *Loader) SymAttr(i Sym) uint8 {
   474  	if l.IsExternal(i) {
   475  		// 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.
   476  		return 0
   477  	}
   478  	r, li := l.toLocal(i)
   479  	osym := goobj2.Sym{}
   480  	osym.Read(r.Reader, r.SymOff(li))
   481  	return osym.Flag
   482  }
   483  
   484  // Returns whether the i-th symbol has ReflectMethod attribute set.
   485  func (l *Loader) IsReflectMethod(i Sym) bool {
   486  	return l.SymAttr(i)&goobj2.SymFlagReflectMethod != 0
   487  }
   488  
   489  // Returns whether this is a Go type symbol.
   490  func (l *Loader) IsGoType(i Sym) bool {
   491  	return l.SymAttr(i)&goobj2.SymFlagGoType != 0
   492  }
   493  
   494  // Returns whether this is a "go.itablink.*" symbol.
   495  func (l *Loader) IsItabLink(i Sym) bool {
   496  	if _, ok := l.itablink[i]; ok {
   497  		return true
   498  	}
   499  	return false
   500  }
   501  
   502  // Returns the symbol content of the i-th symbol. i is global index.
   503  func (l *Loader) Data(i Sym) []byte {
   504  	if l.IsExternal(i) {
   505  		if s := l.Syms[i]; s != nil {
   506  			return s.P
   507  		}
   508  		return nil
   509  	}
   510  	r, li := l.toLocal(i)
   511  	return r.Data(li)
   512  }
   513  
   514  // Returns the number of aux symbols given a global index.
   515  func (l *Loader) NAux(i Sym) int {
   516  	if l.IsExternal(i) {
   517  		return 0
   518  	}
   519  	r, li := l.toLocal(i)
   520  	return r.NAux(li)
   521  }
   522  
   523  // Returns the referred symbol of the j-th aux symbol of the i-th
   524  // symbol.
   525  func (l *Loader) AuxSym(i Sym, j int) Sym {
   526  	if l.IsExternal(i) {
   527  		return 0
   528  	}
   529  	r, li := l.toLocal(i)
   530  	a := goobj2.Aux{}
   531  	a.Read(r.Reader, r.AuxOff(li, j))
   532  	return l.resolve(r, a.Sym)
   533  }
   534  
   535  // ReadAuxSyms reads the aux symbol ids for the specified symbol into the
   536  // slice passed as a parameter. If the slice capacity is not large enough, a new
   537  // larger slice will be allocated. Final slice is returned.
   538  func (l *Loader) ReadAuxSyms(symIdx Sym, dst []Sym) []Sym {
   539  	if l.IsExternal(symIdx) {
   540  		return dst[:0]
   541  	}
   542  	naux := l.NAux(symIdx)
   543  	if naux == 0 {
   544  		return dst[:0]
   545  	}
   546  
   547  	if cap(dst) < naux {
   548  		dst = make([]Sym, naux)
   549  	}
   550  	dst = dst[:0]
   551  
   552  	r, li := l.toLocal(symIdx)
   553  	for i := 0; i < naux; i++ {
   554  		a := goobj2.Aux{}
   555  		a.Read(r.Reader, r.AuxOff(li, i))
   556  		dst = append(dst, l.resolve(r, a.Sym))
   557  	}
   558  
   559  	return dst
   560  }
   561  
   562  // OuterSym gets the outer symbol for host object loaded symbols.
   563  func (l *Loader) OuterSym(i Sym) Sym {
   564  	sym := l.Syms[i]
   565  	if sym != nil && sym.Outer != nil {
   566  		outer := sym.Outer
   567  		return l.Lookup(outer.Name, int(outer.Version))
   568  	}
   569  	return 0
   570  }
   571  
   572  // SubSym gets the subsymbol for host object loaded symbols.
   573  func (l *Loader) SubSym(i Sym) Sym {
   574  	sym := l.Syms[i]
   575  	if sym != nil && sym.Sub != nil {
   576  		sub := sym.Sub
   577  		return l.Lookup(sub.Name, int(sub.Version))
   578  	}
   579  	return 0
   580  }
   581  
   582  // Initialize Reachable bitmap for running deadcode pass.
   583  func (l *Loader) InitReachable() {
   584  	l.Reachable = makeBitmap(l.NSym())
   585  }
   586  
   587  // At method returns the j-th reloc for a global symbol.
   588  func (relocs *Relocs) At(j int) Reloc {
   589  	if relocs.ext != nil {
   590  		rel := &relocs.ext.R[j]
   591  		return Reloc{
   592  			Off:  rel.Off,
   593  			Size: rel.Siz,
   594  			Type: rel.Type,
   595  			Add:  rel.Add,
   596  			Sym:  relocs.l.Lookup(rel.Sym.Name, int(rel.Sym.Version)),
   597  		}
   598  	}
   599  	rel := goobj2.Reloc{}
   600  	rel.Read(relocs.r.Reader, relocs.r.RelocOff(relocs.li, j))
   601  	target := relocs.l.resolve(relocs.r, rel.Sym)
   602  	return Reloc{
   603  		Off:  rel.Off,
   604  		Size: rel.Siz,
   605  		Type: objabi.RelocType(rel.Type),
   606  		Add:  rel.Add,
   607  		Sym:  target,
   608  	}
   609  }
   610  
   611  // ReadAll method reads all relocations for a symbol into the
   612  // specified slice. If the slice capacity is not large enough, a new
   613  // larger slice will be allocated. Final slice is returned.
   614  func (relocs *Relocs) ReadAll(dst []Reloc) []Reloc {
   615  	if relocs.Count == 0 {
   616  		return dst[:0]
   617  	}
   618  
   619  	if cap(dst) < relocs.Count {
   620  		dst = make([]Reloc, relocs.Count)
   621  	}
   622  	dst = dst[:0]
   623  
   624  	if relocs.ext != nil {
   625  		for i := 0; i < relocs.Count; i++ {
   626  			erel := &relocs.ext.R[i]
   627  			rel := Reloc{
   628  				Off:  erel.Off,
   629  				Size: erel.Siz,
   630  				Type: erel.Type,
   631  				Add:  erel.Add,
   632  				Sym:  relocs.l.Lookup(erel.Sym.Name, int(erel.Sym.Version)),
   633  			}
   634  			dst = append(dst, rel)
   635  		}
   636  		return dst
   637  	}
   638  
   639  	off := relocs.r.RelocOff(relocs.li, 0)
   640  	for i := 0; i < relocs.Count; i++ {
   641  		rel := goobj2.Reloc{}
   642  		rel.Read(relocs.r.Reader, off)
   643  		off += uint32(rel.Size())
   644  		target := relocs.l.resolve(relocs.r, rel.Sym)
   645  		dst = append(dst, Reloc{
   646  			Off:  rel.Off,
   647  			Size: rel.Siz,
   648  			Type: objabi.RelocType(rel.Type),
   649  			Add:  rel.Add,
   650  			Sym:  target,
   651  		})
   652  	}
   653  	return dst
   654  }
   655  
   656  // Relocs returns a Relocs object for the given global sym.
   657  func (l *Loader) Relocs(i Sym) Relocs {
   658  	if l.IsExternal(i) {
   659  		if s := l.Syms[i]; s != nil {
   660  			return Relocs{Count: len(s.R), l: l, ext: s}
   661  		}
   662  		return Relocs{}
   663  	}
   664  	r, li := l.toLocal(i)
   665  	return l.relocs(r, li)
   666  }
   667  
   668  // Relocs returns a Relocs object given a local sym index and reader.
   669  func (l *Loader) relocs(r *oReader, li int) Relocs {
   670  	return Relocs{
   671  		Count: r.NReloc(li),
   672  		li:    li,
   673  		r:     r,
   674  		l:     l,
   675  	}
   676  }
   677  
   678  // Preload a package: add autolibs, add symbols to the symbol table.
   679  // Does not read symbol data yet.
   680  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) {
   681  	roObject, readonly, err := f.Slice(uint64(length))
   682  	if err != nil {
   683  		log.Fatal("cannot read object file:", err)
   684  	}
   685  	r := goobj2.NewReaderFromBytes(roObject, readonly)
   686  	if r == nil {
   687  		panic("cannot read object file")
   688  	}
   689  	localSymVersion := syms.IncVersion()
   690  	pkgprefix := objabi.PathToPrefix(lib.Pkg) + "."
   691  	or := &oReader{r, unit, localSymVersion, r.Flags(), pkgprefix, nil}
   692  
   693  	// Autolib
   694  	lib.ImportStrings = append(lib.ImportStrings, r.Autolib()...)
   695  
   696  	// DWARF file table
   697  	nfile := r.NDwarfFile()
   698  	unit.DWARFFileTable = make([]string, nfile)
   699  	for i := range unit.DWARFFileTable {
   700  		unit.DWARFFileTable[i] = r.DwarfFile(i)
   701  	}
   702  
   703  	istart := l.addObj(lib.Pkg, or)
   704  
   705  	ndef := r.NSym()
   706  	nnonpkgdef := r.NNonpkgdef()
   707  	for i, n := 0, ndef+nnonpkgdef; i < n; i++ {
   708  		osym := goobj2.Sym{}
   709  		osym.Read(r, r.SymOff(i))
   710  		name := strings.Replace(osym.Name, "\"\".", pkgprefix, -1)
   711  		if name == "" {
   712  			continue // don't add unnamed aux symbol
   713  		}
   714  		v := abiToVer(osym.ABI, localSymVersion)
   715  		dupok := osym.Dupok()
   716  		added := l.AddSym(name, v, istart+Sym(i), or, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
   717  		if added && strings.HasPrefix(name, "go.itablink.") {
   718  			l.itablink[istart+Sym(i)] = struct{}{}
   719  		}
   720  		if added && strings.HasPrefix(name, "runtime.") {
   721  			if bi := goobj2.BuiltinIdx(name, v); bi != -1 {
   722  				// This is a definition of a builtin symbol. Record where it is.
   723  				l.builtinSyms[bi] = istart + Sym(i)
   724  			}
   725  		}
   726  	}
   727  
   728  	// The caller expects us consuming all the data
   729  	f.MustSeek(length, os.SEEK_CUR)
   730  }
   731  
   732  // Make sure referenced symbols are added. Most of them should already be added.
   733  // This should only be needed for referenced external symbols.
   734  func (l *Loader) LoadRefs(arch *sys.Arch, syms *sym.Symbols) {
   735  	for _, o := range l.objs[1:] {
   736  		loadObjRefs(l, o.r, arch, syms)
   737  	}
   738  }
   739  
   740  func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch, syms *sym.Symbols) {
   741  	ndef := r.NSym() + r.NNonpkgdef()
   742  	for i, n := 0, r.NNonpkgref(); i < n; i++ {
   743  		osym := goobj2.Sym{}
   744  		osym.Read(r.Reader, r.SymOff(ndef+i))
   745  		name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
   746  		v := abiToVer(osym.ABI, r.version)
   747  		l.AddExtSym(name, v)
   748  	}
   749  }
   750  
   751  func abiToVer(abi uint16, localSymVersion int) int {
   752  	var v int
   753  	if abi == goobj2.SymABIstatic {
   754  		// Static
   755  		v = localSymVersion
   756  	} else if abiver := sym.ABIToVersion(obj.ABI(abi)); abiver != -1 {
   757  		// Note that data symbols are "ABI0", which maps to version 0.
   758  		v = abiver
   759  	} else {
   760  		log.Fatalf("invalid symbol ABI: %d", abi)
   761  	}
   762  	return v
   763  }
   764  
   765  func preprocess(arch *sys.Arch, s *sym.Symbol) {
   766  	if s.Name != "" && s.Name[0] == '$' && len(s.Name) > 5 && s.Type == 0 && len(s.P) == 0 {
   767  		x, err := strconv.ParseUint(s.Name[5:], 16, 64)
   768  		if err != nil {
   769  			log.Panicf("failed to parse $-symbol %s: %v", s.Name, err)
   770  		}
   771  		s.Type = sym.SRODATA
   772  		s.Attr |= sym.AttrLocal
   773  		switch s.Name[:5] {
   774  		case "$f32.":
   775  			if uint64(uint32(x)) != x {
   776  				log.Panicf("$-symbol %s too large: %d", s.Name, x)
   777  			}
   778  			s.AddUint32(arch, uint32(x))
   779  		case "$f64.", "$i64.":
   780  			s.AddUint64(arch, x)
   781  		default:
   782  			log.Panicf("unrecognized $-symbol: %s", s.Name)
   783  		}
   784  	}
   785  }
   786  
   787  // Load full contents.
   788  func (l *Loader) LoadFull(arch *sys.Arch, syms *sym.Symbols) {
   789  	// create all Symbols first.
   790  	l.growSyms(l.NSym())
   791  
   792  	nr := 0 // total number of sym.Reloc's we'll need
   793  	for _, o := range l.objs[1:] {
   794  		nr += loadObjSyms(l, syms, o.r)
   795  	}
   796  
   797  	// allocate a single large slab of relocations for all live symbols
   798  	l.relocBatch = make([]sym.Reloc, nr)
   799  
   800  	// external symbols
   801  	for i := l.extStart; i <= l.max; i++ {
   802  		if s := l.Syms[i]; s != nil {
   803  			s.Attr.Set(sym.AttrReachable, l.Reachable.Has(i))
   804  			continue // already loaded from external object
   805  		}
   806  		nv := l.extSyms[i-l.extStart]
   807  		if l.Reachable.Has(i) || strings.HasPrefix(nv.name, "gofile..") { // XXX file symbols are used but not marked
   808  			s := syms.Newsym(nv.name, nv.v)
   809  			preprocess(arch, s)
   810  			s.Attr.Set(sym.AttrReachable, l.Reachable.Has(i))
   811  			l.Syms[i] = s
   812  		}
   813  	}
   814  
   815  	// load contents of defined symbols
   816  	for _, o := range l.objs[1:] {
   817  		loadObjFull(l, o.r)
   818  	}
   819  
   820  	// Resolve ABI aliases for external symbols. This is only
   821  	// needed for internal cgo linking.
   822  	// (The old code does this in deadcode, but deadcode2 doesn't
   823  	// do this.)
   824  	for i := l.extStart; i <= l.max; i++ {
   825  		if s := l.Syms[i]; s != nil && s.Attr.Reachable() {
   826  			for ri := range s.R {
   827  				r := &s.R[ri]
   828  				if r.Sym != nil && r.Sym.Type == sym.SABIALIAS {
   829  					r.Sym = r.Sym.R[0].Sym
   830  				}
   831  			}
   832  		}
   833  	}
   834  }
   835  
   836  // ExtractSymbols grabs the symbols out of the loader for work that hasn't been
   837  // ported to the new symbol type.
   838  func (l *Loader) ExtractSymbols(syms *sym.Symbols) {
   839  	// Nil out overwritten symbols.
   840  	// Overwritten Go symbols aren't a problem (as they're lazy loaded), but
   841  	// symbols loaded from host object loaders are fully loaded, and we might
   842  	// have multiple symbols with the same name. This loop nils them out.
   843  	for oldI := range l.overwrite {
   844  		l.Syms[oldI] = nil
   845  	}
   846  
   847  	// Add symbols to the ctxt.Syms lookup table. This explicitly
   848  	// skips things created via loader.Create (marked with versions
   849  	// less than zero), since if we tried to add these we'd wind up
   850  	// with collisions. Along the way, update the version from the
   851  	// negative anon version to something larger than sym.SymVerStatic
   852  	// (needed so that sym.symbol.IsFileLocal() works properly).
   853  	anonVerReplacement := syms.IncVersion()
   854  	for _, s := range l.Syms {
   855  		if s == nil {
   856  			continue
   857  		}
   858  		if s.Name != "" && s.Version >= 0 {
   859  			syms.Add(s)
   860  		}
   861  		if s.Version < 0 {
   862  			s.Version = int16(anonVerReplacement)
   863  		}
   864  	}
   865  }
   866  
   867  // addNewSym adds a new sym.Symbol to the i-th index in the list of symbols.
   868  func (l *Loader) addNewSym(i Sym, syms *sym.Symbols, name string, ver int, unit *sym.CompilationUnit, t sym.SymKind) *sym.Symbol {
   869  	s := syms.Newsym(name, ver)
   870  	if s.Type != 0 && s.Type != sym.SXREF {
   871  		fmt.Println("symbol already processed:", unit.Lib, i, s)
   872  		panic("symbol already processed")
   873  	}
   874  	if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
   875  		t = s.Type
   876  	}
   877  	s.Type = t
   878  	s.Unit = unit
   879  	l.growSyms(int(i))
   880  	l.Syms[i] = s
   881  	return s
   882  }
   883  
   884  // loadObjSyms creates sym.Symbol objects for the live Syms in the
   885  // object corresponding to object reader "r". Return value is the
   886  // number of sym.Reloc entries required for all the new symbols.
   887  func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
   888  	istart := l.startIndex(r)
   889  	nr := 0
   890  
   891  	for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
   892  		// If it's been previously loaded in host object loading, we don't need to do it again.
   893  		if s := l.Syms[istart+Sym(i)]; s != nil {
   894  			// Mark symbol as reachable as it wasn't marked as such before.
   895  			s.Attr.Set(sym.AttrReachable, l.Reachable.Has(istart+Sym(i)))
   896  			nr += r.NReloc(i)
   897  			continue
   898  		}
   899  		osym := goobj2.Sym{}
   900  		osym.Read(r.Reader, r.SymOff(i))
   901  		name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
   902  		if name == "" {
   903  			continue
   904  		}
   905  		ver := abiToVer(osym.ABI, r.version)
   906  		if osym.ABI != goobj2.SymABIstatic && l.symsByName[ver][name] != istart+Sym(i) {
   907  			continue
   908  		}
   909  
   910  		t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
   911  		if t == sym.SXREF {
   912  			log.Fatalf("bad sxref")
   913  		}
   914  		if t == 0 {
   915  			log.Fatalf("missing type for %s in %s", name, r.unit.Lib)
   916  		}
   917  		if !l.Reachable.Has(istart+Sym(i)) && !(t == sym.SRODATA && strings.HasPrefix(name, "type.")) && name != "runtime.addmoduledata" && name != "runtime.lastmoduledatap" {
   918  			// No need to load unreachable symbols.
   919  			// XXX some type symbol's content may be needed in DWARF code, but they are not marked.
   920  			// XXX reference to runtime.addmoduledata may be generated later by the linker in plugin mode.
   921  			continue
   922  		}
   923  
   924  		s := l.addNewSym(istart+Sym(i), syms, name, ver, r.unit, t)
   925  		s.Attr.Set(sym.AttrReachable, l.Reachable.Has(istart+Sym(i)))
   926  		nr += r.NReloc(i)
   927  	}
   928  	return nr
   929  }
   930  
   931  // funcInfoSym records the sym.Symbol for a function, along with a copy
   932  // of the corresponding goobj2.Sym and the index of its FuncInfo aux sym.
   933  // We use this to delay populating FuncInfo until we can batch-allocate
   934  // slices for their sub-objects.
   935  type funcInfoSym struct {
   936  	s    *sym.Symbol // sym.Symbol for a live function
   937  	osym goobj2.Sym  // object file symbol data for that function
   938  	isym int         // global symbol index of FuncInfo aux sym for func
   939  }
   940  
   941  // funcAllocInfo records totals/counts for all functions in an objfile;
   942  // used to help with bulk allocation of sym.Symbol sub-objects.
   943  type funcAllocInfo struct {
   944  	symPtr  uint32 // number of *sym.Symbol's needed in file slices
   945  	inlCall uint32 // number of sym.InlinedCall's needed in inltree slices
   946  	pcData  uint32 // number of sym.Pcdata's needed in pdata slices
   947  	fdOff   uint32 // number of int64's needed in all Funcdataoff slices
   948  }
   949  
   950  // LoadSymbol loads a single symbol by name.
   951  // This function should only be used by the host object loaders.
   952  // NB: This function does NOT set the symbol as reachable.
   953  func (l *Loader) LoadSymbol(name string, version int, syms *sym.Symbols) *sym.Symbol {
   954  	global := l.Lookup(name, version)
   955  
   956  	// If we're already loaded, bail.
   957  	if global != 0 && int(global) < len(l.Syms) && l.Syms[global] != nil {
   958  		return l.Syms[global]
   959  	}
   960  
   961  	// Read the symbol.
   962  	r, i := l.toLocal(global)
   963  	istart := l.startIndex(r)
   964  
   965  	osym := goobj2.Sym{}
   966  	osym.Read(r.Reader, r.SymOff(int(i)))
   967  	if l.symsByName[version][name] != istart+Sym(i) {
   968  		return nil
   969  	}
   970  
   971  	return l.addNewSym(istart+Sym(i), syms, name, version, r.unit, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)])
   972  }
   973  
   974  // LookupOrCreate looks up a symbol by name, and creates one if not found.
   975  // Either way, it will also create a sym.Symbol for it, if not already.
   976  // This should only be called when interacting with parts of the linker
   977  // that still works on sym.Symbols (i.e. internal cgo linking, for now).
   978  func (l *Loader) LookupOrCreate(name string, version int, syms *sym.Symbols) *sym.Symbol {
   979  	i := l.Lookup(name, version)
   980  	if i != 0 {
   981  		// symbol exists
   982  		if int(i) < len(l.Syms) && l.Syms[i] != nil {
   983  			return l.Syms[i] // already loaded
   984  		}
   985  		if l.IsExternal(i) {
   986  			panic("Can't load an external symbol.")
   987  		}
   988  		return l.LoadSymbol(name, version, syms)
   989  	}
   990  	i = l.AddExtSym(name, version)
   991  	s := syms.Newsym(name, version)
   992  	l.Syms[i] = s
   993  	return s
   994  }
   995  
   996  // Create creates a symbol with the specified name, returning a
   997  // sym.Symbol object for it. This method is intended for static/hidden
   998  // symbols discovered while loading host objects. We can see more than
   999  // one instance of a given static symbol with the same name/version,
  1000  // so we can't add them to the lookup tables "as is". Instead assign
  1001  // them fictitious (unique) versions, starting at -1 and decreasing by
  1002  // one for each newly created symbol, and record them in the
  1003  // extStaticSyms hash.
  1004  func (l *Loader) Create(name string, syms *sym.Symbols) *sym.Symbol {
  1005  	i := l.max + 1
  1006  	l.max++
  1007  	if l.extStart == 0 {
  1008  		l.extStart = i
  1009  	}
  1010  
  1011  	// Assign a new unique negative version -- this is to mark the
  1012  	// symbol so that it can be skipped when ExtractSymbols is adding
  1013  	// ext syms to the sym.Symbols hash.
  1014  	l.anonVersion--
  1015  	ver := l.anonVersion
  1016  	l.extSyms = append(l.extSyms, nameVer{name, ver})
  1017  	l.growSyms(int(i))
  1018  	s := syms.Newsym(name, ver)
  1019  	l.Syms[i] = s
  1020  	l.extStaticSyms[nameVer{name, ver}] = i
  1021  
  1022  	return s
  1023  }
  1024  
  1025  func loadObjFull(l *Loader, r *oReader) {
  1026  	lib := r.unit.Lib
  1027  	istart := l.startIndex(r)
  1028  
  1029  	resolveSymRef := func(s goobj2.SymRef) *sym.Symbol {
  1030  		i := l.resolve(r, s)
  1031  		return l.Syms[i]
  1032  	}
  1033  
  1034  	funcs := []funcInfoSym{}
  1035  	fdsyms := []*sym.Symbol{}
  1036  	var funcAllocCounts funcAllocInfo
  1037  	pcdataBase := r.PcdataBase()
  1038  	rslice := []Reloc{}
  1039  	for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
  1040  		osym := goobj2.Sym{}
  1041  		osym.Read(r.Reader, r.SymOff(i))
  1042  		name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
  1043  		if name == "" {
  1044  			continue
  1045  		}
  1046  		ver := abiToVer(osym.ABI, r.version)
  1047  		dupok := osym.Dupok()
  1048  		if dupok {
  1049  			if dupsym := l.symsByName[ver][name]; dupsym != istart+Sym(i) {
  1050  				if l.Reachable.Has(dupsym) {
  1051  					// A dupok symbol is resolved to another package. We still need
  1052  					// to record its presence in the current package, as the trampoline
  1053  					// pass expects packages are laid out in dependency order.
  1054  					s := l.Syms[dupsym]
  1055  					if s.Type == sym.STEXT {
  1056  						lib.DupTextSyms = append(lib.DupTextSyms, s)
  1057  					}
  1058  				}
  1059  				continue
  1060  			}
  1061  		}
  1062  
  1063  		s := l.Syms[istart+Sym(i)]
  1064  		if s == nil {
  1065  			continue
  1066  		}
  1067  		if s.Name != name { // Sanity check. We can remove it in the final version.
  1068  			fmt.Println("name mismatch:", lib, i, s.Name, name)
  1069  			panic("name mismatch")
  1070  		}
  1071  
  1072  		local := osym.Local()
  1073  		makeTypelink := osym.Typelink()
  1074  		size := osym.Siz
  1075  
  1076  		// Symbol data
  1077  		s.P = r.Data(i)
  1078  		s.Attr.Set(sym.AttrReadOnly, r.ReadOnly())
  1079  
  1080  		// Relocs
  1081  		relocs := l.relocs(r, i)
  1082  		rslice = relocs.ReadAll(rslice)
  1083  		batch := l.relocBatch
  1084  		s.R = batch[:relocs.Count:relocs.Count]
  1085  		l.relocBatch = batch[relocs.Count:]
  1086  		for j := range s.R {
  1087  			r := rslice[j]
  1088  			rs := r.Sym
  1089  			sz := r.Size
  1090  			rt := r.Type
  1091  			if rt == objabi.R_METHODOFF {
  1092  				if l.Reachable.Has(rs) {
  1093  					rt = objabi.R_ADDROFF
  1094  				} else {
  1095  					sz = 0
  1096  					rs = 0
  1097  				}
  1098  			}
  1099  			if rt == objabi.R_WEAKADDROFF && !l.Reachable.Has(rs) {
  1100  				rs = 0
  1101  				sz = 0
  1102  			}
  1103  			if rs != 0 && l.SymType(rs) == sym.SABIALIAS {
  1104  				rsrelocs := l.Relocs(rs)
  1105  				rs = rsrelocs.At(0).Sym
  1106  			}
  1107  			s.R[j] = sym.Reloc{
  1108  				Off:  r.Off,
  1109  				Siz:  sz,
  1110  				Type: rt,
  1111  				Add:  r.Add,
  1112  				Sym:  l.Syms[rs],
  1113  			}
  1114  		}
  1115  
  1116  		// Aux symbol info
  1117  		isym := -1
  1118  		naux := r.NAux(i)
  1119  		for j := 0; j < naux; j++ {
  1120  			a := goobj2.Aux{}
  1121  			a.Read(r.Reader, r.AuxOff(i, j))
  1122  			switch a.Type {
  1123  			case goobj2.AuxGotype:
  1124  				typ := resolveSymRef(a.Sym)
  1125  				if typ != nil {
  1126  					s.Gotype = typ
  1127  				}
  1128  			case goobj2.AuxFuncdata:
  1129  				fdsyms = append(fdsyms, resolveSymRef(a.Sym))
  1130  			case goobj2.AuxFuncInfo:
  1131  				if a.Sym.PkgIdx != goobj2.PkgIdxSelf {
  1132  					panic("funcinfo symbol not defined in current package")
  1133  				}
  1134  				isym = int(a.Sym.SymIdx)
  1135  			case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
  1136  				// ignored for now
  1137  			default:
  1138  				panic("unknown aux type")
  1139  			}
  1140  		}
  1141  
  1142  		s.File = r.pkgprefix[:len(r.pkgprefix)-1]
  1143  		if dupok {
  1144  			s.Attr |= sym.AttrDuplicateOK
  1145  		}
  1146  		if s.Size < int64(size) {
  1147  			s.Size = int64(size)
  1148  		}
  1149  		s.Attr.Set(sym.AttrLocal, local)
  1150  		s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
  1151  
  1152  		if s.Type == sym.SDWARFINFO {
  1153  			// For DWARF symbols, replace `"".` to actual package prefix
  1154  			// in the symbol content.
  1155  			// TODO: maybe we should do this in the compiler and get rid
  1156  			// of this.
  1157  			patchDWARFName(s, r)
  1158  		}
  1159  
  1160  		if s.Type != sym.STEXT {
  1161  			continue
  1162  		}
  1163  
  1164  		if isym == -1 {
  1165  			continue
  1166  		}
  1167  
  1168  		// Record function sym and associated info for additional
  1169  		// processing in the loop below.
  1170  		fwis := funcInfoSym{s: s, isym: isym, osym: osym}
  1171  		funcs = append(funcs, fwis)
  1172  
  1173  		// Read the goobj2.FuncInfo for this text symbol so that we can
  1174  		// collect allocation counts. We'll read it again in the loop
  1175  		// below.
  1176  		b := r.Data(isym)
  1177  		info := goobj2.FuncInfo{}
  1178  		info.Read(b)
  1179  		funcAllocCounts.symPtr += uint32(len(info.File))
  1180  		funcAllocCounts.pcData += uint32(len(info.Pcdata))
  1181  		funcAllocCounts.inlCall += uint32(len(info.InlTree))
  1182  		funcAllocCounts.fdOff += uint32(len(info.Funcdataoff))
  1183  	}
  1184  
  1185  	// At this point we can do batch allocation of the sym.FuncInfo's,
  1186  	// along with the slices of sub-objects they use.
  1187  	fiBatch := make([]sym.FuncInfo, len(funcs))
  1188  	inlCallBatch := make([]sym.InlinedCall, funcAllocCounts.inlCall)
  1189  	symPtrBatch := make([]*sym.Symbol, funcAllocCounts.symPtr)
  1190  	pcDataBatch := make([]sym.Pcdata, funcAllocCounts.pcData)
  1191  	fdOffBatch := make([]int64, funcAllocCounts.fdOff)
  1192  
  1193  	// Populate FuncInfo contents for func symbols.
  1194  	for fi := 0; fi < len(funcs); fi++ {
  1195  		s := funcs[fi].s
  1196  		isym := funcs[fi].isym
  1197  		osym := funcs[fi].osym
  1198  
  1199  		s.FuncInfo = &fiBatch[0]
  1200  		fiBatch = fiBatch[1:]
  1201  
  1202  		b := r.Data(isym)
  1203  		info := goobj2.FuncInfo{}
  1204  		info.Read(b)
  1205  
  1206  		if info.NoSplit != 0 {
  1207  			s.Attr |= sym.AttrNoSplit
  1208  		}
  1209  		if osym.ReflectMethod() {
  1210  			s.Attr |= sym.AttrReflectMethod
  1211  		}
  1212  		if r.Flags()&goobj2.ObjFlagShared != 0 {
  1213  			s.Attr |= sym.AttrShared
  1214  		}
  1215  		if osym.TopFrame() {
  1216  			s.Attr |= sym.AttrTopFrame
  1217  		}
  1218  
  1219  		pc := s.FuncInfo
  1220  
  1221  		if len(info.Funcdataoff) != 0 {
  1222  			nfd := len(info.Funcdataoff)
  1223  			pc.Funcdata = fdsyms[:nfd:nfd]
  1224  			fdsyms = fdsyms[nfd:]
  1225  		}
  1226  
  1227  		info.Pcdata = append(info.Pcdata, info.PcdataEnd) // for the ease of knowing where it ends
  1228  		pc.Args = int32(info.Args)
  1229  		pc.Locals = int32(info.Locals)
  1230  
  1231  		npc := len(info.Pcdata) - 1 // -1 as we appended one above
  1232  		pc.Pcdata = pcDataBatch[:npc:npc]
  1233  		pcDataBatch = pcDataBatch[npc:]
  1234  
  1235  		nfd := len(info.Funcdataoff)
  1236  		pc.Funcdataoff = fdOffBatch[:nfd:nfd]
  1237  		fdOffBatch = fdOffBatch[nfd:]
  1238  
  1239  		nsp := len(info.File)
  1240  		pc.File = symPtrBatch[:nsp:nsp]
  1241  		symPtrBatch = symPtrBatch[nsp:]
  1242  
  1243  		nic := len(info.InlTree)
  1244  		pc.InlTree = inlCallBatch[:nic:nic]
  1245  		inlCallBatch = inlCallBatch[nic:]
  1246  
  1247  		pc.Pcsp.P = r.BytesAt(pcdataBase+info.Pcsp, int(info.Pcfile-info.Pcsp))
  1248  		pc.Pcfile.P = r.BytesAt(pcdataBase+info.Pcfile, int(info.Pcline-info.Pcfile))
  1249  		pc.Pcline.P = r.BytesAt(pcdataBase+info.Pcline, int(info.Pcinline-info.Pcline))
  1250  		pc.Pcinline.P = r.BytesAt(pcdataBase+info.Pcinline, int(info.Pcdata[0]-info.Pcinline))
  1251  		for k := range pc.Pcdata {
  1252  			pc.Pcdata[k].P = r.BytesAt(pcdataBase+info.Pcdata[k], int(info.Pcdata[k+1]-info.Pcdata[k]))
  1253  		}
  1254  		for k := range pc.Funcdataoff {
  1255  			pc.Funcdataoff[k] = int64(info.Funcdataoff[k])
  1256  		}
  1257  		for k := range pc.File {
  1258  			pc.File[k] = resolveSymRef(info.File[k])
  1259  		}
  1260  		for k := range pc.InlTree {
  1261  			inl := &info.InlTree[k]
  1262  			pc.InlTree[k] = sym.InlinedCall{
  1263  				Parent:   inl.Parent,
  1264  				File:     resolveSymRef(inl.File),
  1265  				Line:     inl.Line,
  1266  				Func:     l.SymName(l.resolve(r, inl.Func)),
  1267  				ParentPC: inl.ParentPC,
  1268  			}
  1269  		}
  1270  
  1271  		dupok := osym.Dupok()
  1272  		if !dupok {
  1273  			if s.Attr.OnList() {
  1274  				log.Fatalf("symbol %s listed multiple times", s.Name)
  1275  			}
  1276  			s.Attr.Set(sym.AttrOnList, true)
  1277  			lib.Textp = append(lib.Textp, s)
  1278  		} else {
  1279  			// there may be a dup in another package
  1280  			// put into a temp list and add to text later
  1281  			lib.DupTextSyms = append(lib.DupTextSyms, s)
  1282  		}
  1283  	}
  1284  }
  1285  
  1286  var emptyPkg = []byte(`"".`)
  1287  
  1288  func patchDWARFName1(p []byte, r *oReader) ([]byte, int) {
  1289  	// This is kind of ugly. Really the package name should not
  1290  	// even be included here.
  1291  	if len(p) < 1 || p[0] != dwarf.DW_ABRV_FUNCTION {
  1292  		return p, -1
  1293  	}
  1294  	e := bytes.IndexByte(p, 0)
  1295  	if e == -1 {
  1296  		return p, -1
  1297  	}
  1298  	if !bytes.Contains(p[:e], emptyPkg) {
  1299  		return p, -1
  1300  	}
  1301  	pkgprefix := []byte(r.pkgprefix)
  1302  	patched := bytes.Replace(p[:e], emptyPkg, pkgprefix, -1)
  1303  	return append(patched, p[e:]...), e
  1304  }
  1305  
  1306  func patchDWARFName(s *sym.Symbol, r *oReader) {
  1307  	patched, e := patchDWARFName1(s.P, r)
  1308  	if e == -1 {
  1309  		return
  1310  	}
  1311  	s.P = patched
  1312  	s.Attr.Set(sym.AttrReadOnly, false)
  1313  	delta := int64(len(s.P)) - s.Size
  1314  	s.Size = int64(len(s.P))
  1315  	for i := range s.R {
  1316  		r := &s.R[i]
  1317  		if r.Off > int32(e) {
  1318  			r.Off += int32(delta)
  1319  		}
  1320  	}
  1321  }
  1322  
  1323  // For debugging.
  1324  func (l *Loader) Dump() {
  1325  	fmt.Println("objs")
  1326  	for _, obj := range l.objs {
  1327  		if obj.r != nil {
  1328  			fmt.Println(obj.i, obj.r.unit.Lib)
  1329  		}
  1330  	}
  1331  	fmt.Println("syms")
  1332  	for i, s := range l.Syms {
  1333  		if i == 0 {
  1334  			continue
  1335  		}
  1336  		if s != nil {
  1337  			fmt.Println(i, s, s.Type)
  1338  		} else {
  1339  			fmt.Println(i, l.SymName(Sym(i)), "<not loaded>")
  1340  		}
  1341  	}
  1342  	fmt.Println("overwrite:", l.overwrite)
  1343  	fmt.Println("symsByName")
  1344  	for name, i := range l.symsByName[0] {
  1345  		fmt.Println(i, name, 0)
  1346  	}
  1347  	for name, i := range l.symsByName[1] {
  1348  		fmt.Println(i, name, 1)
  1349  	}
  1350  }