diff options
| author | Katie Hockman <katie@golang.org> | 2020-12-14 10:03:05 -0500 |
|---|---|---|
| committer | Katie Hockman <katie@golang.org> | 2020-12-14 10:06:13 -0500 |
| commit | 0345ede87ee12698988973884cfc0fd3d499dffd (patch) | |
| tree | 7123cff141ee5661208d2f5f437b8f5252ac7f6a /src/cmd/link/internal/loader/loader.go | |
| parent | 4651d6b267818b0e0d128a5443289717c4bb8cbc (diff) | |
| parent | 0a02371b0576964e81c3b40d328db9a3ef3b031b (diff) | |
| download | go-0345ede87ee12698988973884cfc0fd3d499dffd.tar.xz | |
[dev.fuzz] all: merge master into dev.fuzz
Change-Id: I5d8c8329ccc9d747bd81ade6b1cb7cb8ae2e94b2
Diffstat (limited to 'src/cmd/link/internal/loader/loader.go')
| -rw-r--r-- | src/cmd/link/internal/loader/loader.go | 161 |
1 files changed, 106 insertions, 55 deletions
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 8fd10b0848..971cc432ff 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -63,6 +63,7 @@ type Reloc struct { func (rel Reloc) Type() objabi.RelocType { return objabi.RelocType(rel.Reloc.Type()) + rel.typ } func (rel Reloc) Sym() Sym { return rel.l.resolve(rel.r, rel.Reloc.Sym()) } func (rel Reloc) SetSym(s Sym) { rel.Reloc.SetSym(goobj.SymRef{PkgIdx: 0, SymIdx: uint32(s)}) } +func (rel Reloc) IsMarker() bool { return rel.Siz() == 0 } func (rel Reloc) SetType(t objabi.RelocType) { if t != objabi.RelocType(uint8(t)) { @@ -93,11 +94,12 @@ type oReader struct { version int // version of static symbol flags uint32 // read from object file pkgprefix string - syms []Sym // Sym's global index, indexed by local index - ndef int // cache goobj.Reader.NSym() - nhashed64def int // cache goobj.Reader.NHashed64Def() - nhasheddef int // cache goobj.Reader.NHashedDef() - objidx uint32 // index of this reader in the objs slice + syms []Sym // Sym's global index, indexed by local index + pkg []uint32 // indices of referenced package by PkgIdx (index into loader.objs array) + ndef int // cache goobj.Reader.NSym() + nhashed64def int // cache goobj.Reader.NHashed64Def() + nhasheddef int // cache goobj.Reader.NHashedDef() + objidx uint32 // index of this reader in the objs slice } // Total number of defined symbols (package symbols, hashed symbols, and @@ -219,7 +221,7 @@ type Loader struct { deferReturnTramp map[Sym]bool // whether the symbol is a trampoline of a deferreturn call - objByPkg map[string]*oReader // map package path to its Go object reader + objByPkg map[string]uint32 // map package path to the index of its Go object reader anonVersion int // most recently assigned ext static sym pseudo-version @@ -328,10 +330,10 @@ func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorRepor ldr := &Loader{ start: make(map[*oReader]Sym), objs: []objIdx{{}, {extReader, 0}}, // reserve index 0 for nil symbol, 1 for external symbols - objSyms: make([]objSym, 1, 100000), // reserve index 0 for nil symbol + objSyms: make([]objSym, 1, 1), // This will get overwritten later. extReader: extReader, symsByName: [2]map[string]Sym{make(map[string]Sym, 80000), make(map[string]Sym, 50000)}, // preallocate ~2MB for ABI0 and ~1MB for ABI1 symbols - objByPkg: make(map[string]*oReader), + objByPkg: make(map[string]uint32), outer: make(map[Sym]Sym), sub: make(map[Sym]Sym), dynimplib: make(map[Sym]string), @@ -370,7 +372,7 @@ func (l *Loader) addObj(pkg string, r *oReader) Sym { } pkg = objabi.PathToPrefix(pkg) // the object file contains escaped package path if _, ok := l.objByPkg[pkg]; !ok { - l.objByPkg[pkg] = r + l.objByPkg[pkg] = r.objidx } i := Sym(len(l.objSyms)) l.start[r] = i @@ -631,20 +633,42 @@ func (l *Loader) resolve(r *oReader, s goobj.SymRef) Sym { i := int(s.SymIdx) + r.ndef + r.nhashed64def + r.nhasheddef return r.syms[i] case goobj.PkgIdxBuiltin: - return l.builtinSyms[s.SymIdx] + if bi := l.builtinSyms[s.SymIdx]; bi != 0 { + return bi + } + l.reportMissingBuiltin(int(s.SymIdx), r.unit.Lib.Pkg) + return 0 case goobj.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) - } + rr = l.objs[r.pkg[p]].r } return l.toGlobal(rr, s.SymIdx) } +// reportMissingBuiltin issues an error in the case where we have a +// relocation against a runtime builtin whose definition is not found +// when the runtime package is built. The canonical example is +// "runtime.racefuncenter" -- currently if you do something like +// +// go build -gcflags=-race myprogram.go +// +// the compiler will insert calls to the builtin runtime.racefuncenter, +// but the version of the runtime used for linkage won't actually contain +// definitions of that symbol. See issue #42396 for details. +// +// As currently implemented, this is a fatal error. This has drawbacks +// in that if there are multiple missing builtins, the error will only +// cite the first one. On the plus side, terminating the link here has +// advantages in that we won't run the risk of panics or crashes later +// on in the linker due to R_CALL relocations with 0-valued target +// symbols. +func (l *Loader) reportMissingBuiltin(bsym int, reflib string) { + bname, _ := goobj.BuiltinName(bsym) + log.Fatalf("reference to undefined builtin %q from package %q", + bname, reflib) +} + // 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. @@ -1794,6 +1818,11 @@ func (l *Loader) SortSub(s Sym) Sym { return sl[0].s } +// SortSyms sorts a list of symbols by their value. +func (l *Loader) SortSyms(ss []Sym) { + sort.SliceStable(ss, func(i, j int) bool { return l.SymValue(ss[i]) < l.SymValue(ss[j]) }) +} + // Insure that reachable bitmap and its siblings have enough size. func (l *Loader) growAttrBitmaps(reqLen int) { if reqLen > l.attrReachable.Len() { @@ -1878,19 +1907,24 @@ func (fi *FuncInfo) FuncID() objabi.FuncID { return objabi.FuncID((*goobj.FuncInfo)(nil).ReadFuncID(fi.data)) } -func (fi *FuncInfo) Pcsp() []byte { - pcsp, end := (*goobj.FuncInfo)(nil).ReadPcsp(fi.data) - return fi.r.BytesAt(fi.r.PcdataBase()+pcsp, int(end-pcsp)) +func (fi *FuncInfo) Pcsp() Sym { + sym := (*goobj.FuncInfo)(nil).ReadPcsp(fi.data) + return fi.l.resolve(fi.r, sym) } -func (fi *FuncInfo) Pcfile() []byte { - pcf, end := (*goobj.FuncInfo)(nil).ReadPcfile(fi.data) - return fi.r.BytesAt(fi.r.PcdataBase()+pcf, int(end-pcf)) +func (fi *FuncInfo) Pcfile() Sym { + sym := (*goobj.FuncInfo)(nil).ReadPcfile(fi.data) + return fi.l.resolve(fi.r, sym) } -func (fi *FuncInfo) Pcline() []byte { - pcln, end := (*goobj.FuncInfo)(nil).ReadPcline(fi.data) - return fi.r.BytesAt(fi.r.PcdataBase()+pcln, int(end-pcln)) +func (fi *FuncInfo) Pcline() Sym { + sym := (*goobj.FuncInfo)(nil).ReadPcline(fi.data) + return fi.l.resolve(fi.r, sym) +} + +func (fi *FuncInfo) Pcinline() Sym { + sym := (*goobj.FuncInfo)(nil).ReadPcinline(fi.data) + return fi.l.resolve(fi.r, sym) } // Preload has to be called prior to invoking the various methods @@ -1899,27 +1933,16 @@ func (fi *FuncInfo) Preload() { fi.lengths = (*goobj.FuncInfo)(nil).ReadFuncInfoLengths(fi.data) } -func (fi *FuncInfo) Pcinline() []byte { - if !fi.lengths.Initialized { - panic("need to call Preload first") - } - pcinl, end := (*goobj.FuncInfo)(nil).ReadPcinline(fi.data, fi.lengths.PcdataOff) - return fi.r.BytesAt(fi.r.PcdataBase()+pcinl, int(end-pcinl)) -} - -func (fi *FuncInfo) NumPcdata() uint32 { +func (fi *FuncInfo) Pcdata() []Sym { if !fi.lengths.Initialized { panic("need to call Preload first") } - return fi.lengths.NumPcdata -} - -func (fi *FuncInfo) Pcdata(k int) []byte { - if !fi.lengths.Initialized { - panic("need to call Preload first") + syms := (*goobj.FuncInfo)(nil).ReadPcdata(fi.data) + ret := make([]Sym, len(syms)) + for i := range ret { + ret[i] = fi.l.resolve(fi.r, syms[i]) } - pcdat, end := (*goobj.FuncInfo)(nil).ReadPcdata(fi.data, fi.lengths.PcdataOff, uint32(k)) - return fi.r.BytesAt(fi.r.PcdataBase()+pcdat, int(end-pcdat)) + return ret } func (fi *FuncInfo) NumFuncdataoff() uint32 { @@ -2022,8 +2045,9 @@ func (l *Loader) FuncInfo(i Sym) FuncInfo { return FuncInfo{} } -// Preload a package: add autolibs, add defined package symbols to the symbol table. -// Does not add non-package symbols yet, which will be done in LoadNonpkgSyms. +// Preload a package: adds autolib. +// Does not add defined package or non-packaged symbols to the symbol table. +// These are done in LoadSyms. // Does not read symbol data. // Returns the fingerprint of the object. func (l *Loader) Preload(localSymVersion int, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64) goobj.FingerprintType { @@ -2066,8 +2090,6 @@ func (l *Loader) Preload(localSymVersion int, f *bio.Reader, lib *sym.Library, u } l.addObj(lib.Pkg, or) - st := loadState{l: l} - st.preloadSyms(or, pkgDef) // The caller expects us consuming all the data f.MustSeek(length, os.SEEK_CUR) @@ -2150,17 +2172,30 @@ func (st *loadState) preloadSyms(r *oReader, kind int) { } } -// Add hashed (content-addressable) symbols, non-package symbols, and +// Add syms, hashed (content-addressable) symbols, non-package symbols, and // references to external symbols (which are always named). -func (l *Loader) LoadNonpkgSyms(arch *sys.Arch) { +func (l *Loader) LoadSyms(arch *sys.Arch) { + // Allocate space for symbols, making a guess as to how much space we need. + // This function was determined empirically by looking at the cmd/compile on + // Darwin, and picking factors for hashed and hashed64 syms. + var symSize, hashedSize, hashed64Size int + for _, o := range l.objs[goObjStart:] { + symSize += o.r.ndef + o.r.nhasheddef/2 + o.r.nhashed64def/2 + o.r.NNonpkgdef() + hashedSize += o.r.nhasheddef / 2 + hashed64Size += o.r.nhashed64def / 2 + } + // Index 0 is invalid for symbols. + l.objSyms = make([]objSym, 1, symSize) + l.npkgsyms = l.NSym() - // Preallocate some space (a few hundreds KB) for some symbols. - // As of Go 1.15, linking cmd/compile has ~8000 hashed64 symbols and - // ~13000 hashed symbols. st := loadState{ l: l, - hashed64Syms: make(map[uint64]symAndSize, 10000), - hashedSyms: make(map[goobj.HashType]symAndSize, 15000), + hashed64Syms: make(map[uint64]symAndSize, hashed64Size), + hashedSyms: make(map[goobj.HashType]symAndSize, hashedSize), + } + + for _, o := range l.objs[goObjStart:] { + st.preloadSyms(o.r, pkgDef) } for _, o := range l.objs[goObjStart:] { st.preloadSyms(o.r, hashed64Def) @@ -2195,6 +2230,18 @@ func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) { } } + // referenced packages + npkg := r.NPkg() + r.pkg = make([]uint32, npkg) + for i := 1; i < npkg; i++ { // PkgIdx 0 is a dummy invalid package + pkg := r.Pkg(i) + objidx, ok := l.objByPkg[pkg] + if !ok { + log.Fatalf("reference of nonexisted package %s, from %v", pkg, r.unit.Lib) + } + r.pkg[i] = objidx + } + // load flags of package refs for i, n := 0, r.NRefFlags(); i < n; i++ { rf := r.RefFlags(i) @@ -2602,11 +2649,15 @@ func (l *Loader) Dump() { fmt.Println("Nsyms:", len(l.objSyms)) fmt.Println("syms") for i := Sym(1); i < Sym(len(l.objSyms)); i++ { - pi := interface{}("") + pi := "" if l.IsExternal(i) { pi = fmt.Sprintf("<ext %d>", l.extIndex(i)) } - fmt.Println(i, l.SymName(i), l.SymType(i), pi) + sect := "" + if l.SymSect(i) != nil { + sect = l.SymSect(i).Name + } + fmt.Printf("%v %v %v %v %x %v\n", i, l.SymName(i), l.SymType(i), pi, l.SymValue(i), sect) } fmt.Println("symsByName") for name, i := range l.symsByName[0] { |
