"cmd/link/internal/sym"
"debug/elf"
"fmt"
+ "internal/abi"
"io"
"log"
"math/bits"
// Sym encapsulates a global symbol index, used to identify a specific
// Go symbol. The 0-valued Sym is corresponds to an invalid symbol.
-type Sym int
+type Sym = sym.LoaderSym
// Relocs encapsulates the set of relocations on a given symbol; an
// instance of this type is returned by the Loader Relocs() method.
attrLocal Bitmap // "local" symbols, indexed by global index
attrNotInSymbolTable Bitmap // "not in symtab" symbols, indexed by global idx
attrUsedInIface Bitmap // "used in interface" symbols, indexed by global idx
+ attrSpecial Bitmap // "special" frame symbols, indexed by global idx
attrVisibilityHidden Bitmap // hidden symbols, indexed by ext sym index
attrDuplicateOK Bitmap // dupOK symbols, indexed by ext sym index
attrShared Bitmap // shared symbols, indexed by ext sym index
attrExternal Bitmap // external symbols, indexed by ext sym index
+ generatedSyms Bitmap // symbols that generate their content, indexed by ext sym idx
attrReadOnly map[Sym]bool // readonly data for this sym
- attrSpecial map[Sym]struct{} // "special" frame symbols
attrCgoExportDynamic map[Sym]struct{} // "cgo_export_dynamic" symbols
attrCgoExportStatic map[Sym]struct{} // "cgo_export_static" symbols
- generatedSyms map[Sym]struct{} // symbols that generate their content
// Outer and Sub relations for symbols.
- // TODO: figure out whether it's more efficient to just have these
- // as fields on extSymPayload (note that this won't be a viable
- // strategy if somewhere in the linker we set sub/outer for a
- // non-external sym).
- outer map[Sym]Sym
+ outer []Sym // indexed by global index
sub map[Sym]Sym
dynimplib map[Sym]string // stores Dynimplib symbol attribute
strictDupMsgs int // number of strict-dup warning/errors, when FlagStrictDups is enabled
- elfsetstring elfsetstringFunc
-
errorReporter *ErrorReporter
npkgsyms int // number of package symbols, for accounting
goObjStart
)
-type elfsetstringFunc func(str string, off int)
-
// extSymPayload holds the payload (data + relocations) for linker-synthesized
// external symbols (note that symbol value is stored in a separate slice).
type extSymPayload struct {
FlagStrictDups = 1 << iota
)
-func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorReporter) *Loader {
+func NewLoader(flags uint32, reporter *ErrorReporter) *Loader {
nbuiltin := goobj.NBuiltin()
extReader := &oReader{objidx: extObj}
ldr := &Loader{
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]uint32),
- outer: make(map[Sym]Sym),
sub: make(map[Sym]Sym),
dynimplib: make(map[Sym]string),
dynimpvers: make(map[Sym]string),
plt: make(map[Sym]int32),
got: make(map[Sym]int32),
dynid: make(map[Sym]int32),
- attrSpecial: make(map[Sym]struct{}),
attrCgoExportDynamic: make(map[Sym]struct{}),
attrCgoExportStatic: make(map[Sym]struct{}),
- generatedSyms: make(map[Sym]struct{}),
deferReturnTramp: make(map[Sym]bool),
extStaticSyms: make(map[nameVer]Sym),
builtinSyms: make([]Sym, nbuiltin),
flags: flags,
- elfsetstring: elfsetstring,
errorReporter: reporter,
sects: []*sym.Section{nil}, // reserve index 0 for nil section
}
panic("addSym called after external symbol is created")
}
i := Sym(len(l.objSyms))
+ if int(i) != len(l.objSyms) { // overflow
+ panic("too many symbols")
+ }
addToGlobal := func() {
l.objSyms = append(l.objSyms, objSym{r.objidx, li})
}
// name/version.
func (l *Loader) newExtSym(name string, ver int) Sym {
i := Sym(len(l.objSyms))
+ if int(i) != len(l.objSyms) { // overflow
+ panic("too many symbols")
+ }
if l.extStart == 0 {
l.extStart = i
}
l.growValues(int(i) + 1)
+ l.growOuter(int(i) + 1)
l.growAttrBitmaps(int(i) + 1)
pi := l.newPayload(name, ver)
l.objSyms = append(l.objSyms, objSym{l.extReader.objidx, uint32(pi)})
// address (i.e. Value) computed by the usual mechanism of
// data.go:dodata() & data.go:address().
func (l *Loader) AttrSpecial(i Sym) bool {
- _, ok := l.attrSpecial[i]
- return ok
+ return l.attrSpecial.Has(i)
}
// SetAttrSpecial sets the "special" property for a symbol (see
// AttrSpecial).
func (l *Loader) SetAttrSpecial(i Sym, v bool) {
if v {
- l.attrSpecial[i] = struct{}{}
+ l.attrSpecial.Set(i)
} else {
- delete(l.attrSpecial, i)
+ l.attrSpecial.Unset(i)
}
}
}
}
-// ForAllAttrCgoExportDynamic calls f for every symbol that has been
+// ForAllCgoExportDynamic calls f for every symbol that has been
// marked with the "cgo_export_dynamic" compiler directive.
func (l *Loader) ForAllCgoExportDynamic(f func(Sym)) {
for s := range l.attrCgoExportDynamic {
// generator symbol through the SetIsGeneratedSym. The functions for generator
// symbols are kept in the Link context.
func (l *Loader) IsGeneratedSym(i Sym) bool {
- _, ok := l.generatedSyms[i]
- return ok
+ if !l.IsExternal(i) {
+ return false
+ }
+ return l.generatedSyms.Has(l.extIndex(i))
}
// SetIsGeneratedSym marks symbols as generated symbols. Data shouldn't be
panic("only external symbols can be generated")
}
if v {
- l.generatedSyms[i] = struct{}{}
+ l.generatedSyms.Set(l.extIndex(i))
} else {
- delete(l.generatedSyms, i)
+ l.generatedSyms.Unset(l.extIndex(i))
}
}
//
// - Outer symbol covers the address ranges of its sub-symbols.
// Outer.Sub is set in this case.
-// - Outer symbol doesn't conver the address ranges. It is zero-sized
+// - Outer symbol doesn't cover the address ranges. It is zero-sized
// and doesn't have sub-symbols. In the case, the inner symbol is
// not actually a "SubSymbol". (Tricky!)
//
return r.Data(li)
}
+// Returns the symbol content of the i-th symbol as a string. i is global index.
+func (l *Loader) DataString(i Sym) string {
+ if l.IsExternal(i) {
+ pp := l.getPayload(i)
+ return string(pp.data)
+ }
+ r, li := l.toLocal(i)
+ return r.DataString(li)
+}
+
// FreeData clears the symbol data of an external symbol, allowing the memory
// to be freed earlier. No-op for non-external symbols.
// i is global index.
l.symSects[i] = sect.Index
}
-// growSects grows the slice used to store symbol sections.
-func (l *Loader) growSects(reqLen int) {
- curLen := len(l.symSects)
- if reqLen > curLen {
- l.symSects = append(l.symSects, make([]uint16, reqLen+1-curLen)...)
- }
-}
-
// NewSection creates a new (output) section.
func (l *Loader) NewSection() *sym.Section {
sect := new(sym.Section)
}
// SymLocalentry returns an offset in bytes of the "local entry" of a symbol.
+//
+// On PPC64, a value of 1 indicates the symbol does not use or preserve a TOC
+// pointer in R2, nor does it have a distinct local entry.
func (l *Loader) SymLocalentry(i Sym) uint8 {
return l.localentry[i]
}
return 0, false
}
+// SEHUnwindSym returns the auxiliary SEH unwind symbol associated with
+// a given function symbol.
+func (l *Loader) SEHUnwindSym(fnSymIdx Sym) Sym {
+ if l.SymType(fnSymIdx) != sym.STEXT {
+ log.Fatalf("error: non-function sym %d/%s t=%s passed to SEHUnwindSym", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String())
+ }
+
+ return l.aux1(fnSymIdx, goobj.AuxSehUnwindInfo)
+}
+
// GetFuncDwarfAuxSyms collects and returns the auxiliary DWARF
// symbols associated with a given function symbol. Prior to the
// introduction of the loader, this was done purely using name
return
}
+func (l *Loader) GetVarDwarfAuxSym(i Sym) Sym {
+ aux := l.aux1(i, goobj.AuxDwarfInfo)
+ if aux != 0 && l.SymType(aux) != sym.SDWARFVAR {
+ fmt.Println(l.SymName(i), l.SymType(i), l.SymType(aux), sym.SDWARFVAR)
+ panic("aux dwarf info sym with wrong type")
+ }
+ return aux
+}
+
// AddInteriorSym sets up 'interior' as an interior symbol of
// container/payload symbol 'container'. An interior symbol does not
// itself have data, but gives a name to a subrange of the data in its
l.outer[interior] = container
}
-// OuterSym gets the outer symbol for host object loaded symbols.
+// OuterSym gets the outer/container symbol.
func (l *Loader) OuterSym(i Sym) Sym {
- // FIXME: add check for isExternal?
return l.outer[i]
}
// SubSym gets the subsymbol for host object loaded symbols.
func (l *Loader) SubSym(i Sym) Sym {
- // NB: note -- no check for l.isExternal(), since I am pretty sure
- // that later phases in the linker set subsym for "type:" syms
return l.sub[i]
}
+// growOuter grows the slice used to store outer symbol.
+func (l *Loader) growOuter(reqLen int) {
+ curLen := len(l.outer)
+ if reqLen > curLen {
+ l.outer = append(l.outer, make([]Sym, reqLen-curLen)...)
+ }
+}
+
// SetCarrierSym declares that 'c' is the carrier or container symbol
// for 's'. Carrier symbols are used in the linker to as a container
// for a collection of sub-symbols where the content of the
l.attrLocal = growBitmap(reqLen, l.attrLocal)
l.attrNotInSymbolTable = growBitmap(reqLen, l.attrNotInSymbolTable)
l.attrUsedInIface = growBitmap(reqLen, l.attrUsedInIface)
+ l.attrSpecial = growBitmap(reqLen, l.attrSpecial)
}
l.growExtAttrBitmaps()
}
l.attrDuplicateOK = growBitmap(extReqLen, l.attrDuplicateOK)
l.attrShared = growBitmap(extReqLen, l.attrShared)
l.attrExternal = growBitmap(extReqLen, l.attrExternal)
+ l.generatedSyms = growBitmap(extReqLen, l.generatedSyms)
}
}
return int((*goobj.FuncInfo)(nil).ReadLocals(fi.data))
}
-func (fi *FuncInfo) FuncID() objabi.FuncID {
+func (fi *FuncInfo) FuncID() abi.FuncID {
return (*goobj.FuncInfo)(nil).ReadFuncID(fi.data)
}
-func (fi *FuncInfo) FuncFlag() objabi.FuncFlag {
+func (fi *FuncInfo) FuncFlag() abi.FuncFlag {
return (*goobj.FuncInfo)(nil).ReadFuncFlag(fi.data)
}
// is an entry point, meaning that unwinders should stop when they hit
// this function.
func (fi *FuncInfo) TopFrame() bool {
- return (fi.FuncFlag() & objabi.FuncFlag_TOPFRAME) != 0
+ return (fi.FuncFlag() & abi.FuncFlagTopFrame) != 0
}
type InlTreeNode struct {
loadObjRefs(l, o.r, arch)
}
l.values = make([]int64, l.NSym(), l.NSym()+1000) // +1000 make some room for external symbols
+ l.outer = make([]Sym, l.NSym(), l.NSym()+1000)
}
func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {