Newer
Older
// container symbol C, but don't set Sub(C). Thus we have two
// distinct scenarios:
//
// - 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
// and doesn't have sub-symbols. In the case, the inner symbol is
// not actually a "SubSymbol". (Tricky!)
//
// This method returns TRUE only for sub-symbols in the first scenario.
//
// FIXME: would be better to do away with this and have a better way
// to represent container symbols.
func (l *Loader) AttrSubSymbol(i Sym) bool {
// we don't explicitly store this attribute any more -- return
// a value based on the sub-symbol setting.
o := l.OuterSym(i)
if o == 0 {
return false
}
return l.SubSym(o) != 0
}
Than McIntosh
committed
// Note that we don't have a 'SetAttrSubSymbol' method in the loader;
// clients should instead use the PrependSub method to establish
// outer/sub relationships for host object symbols.
// Returns whether the i-th symbol has ReflectMethod attribute set.
func (l *Loader) IsReflectMethod(i Sym) bool {
return l.SymAttr(i)&goobj2.SymFlagReflectMethod != 0
}
// Returns whether the i-th symbol is nosplit.
func (l *Loader) IsNoSplit(i Sym) bool {
return l.SymAttr(i)&goobj2.SymFlagNoSplit != 0
}
// Returns whether this is a Go type symbol.
func (l *Loader) IsGoType(i Sym) bool {
return l.SymAttr(i)&goobj2.SymFlagGoType != 0
}
// Returns whether this symbol should be included in typelink.
func (l *Loader) IsTypelink(i Sym) bool {
return l.SymAttr(i)&goobj2.SymFlagTypelink != 0
}
// Returns whether this is a "go.itablink.*" symbol.
func (l *Loader) IsItabLink(i Sym) bool {
if _, ok := l.itablink[i]; ok {
return true
}
return false
}
// growValues grows the slice used to store symbol values.
func (l *Loader) growValues(reqLen int) {
curLen := len(l.values)
if reqLen > curLen {
l.values = append(l.values, make([]int64, reqLen+1-curLen)...)
}
}
// SymValue returns the value of the i-th symbol. i is global index.
func (l *Loader) SymValue(i Sym) int64 {
return l.values[i]
}
// SetSymValue sets the value of the i-th symbol. i is global index.
func (l *Loader) SetSymValue(i Sym, val int64) {
l.values[i] = val
}
// AddToSymValue adds to the value of the i-th symbol. i is the global index.
func (l *Loader) AddToSymValue(i Sym, val int64) {
l.values[i] += val
}
// Returns the symbol content of the i-th symbol. i is global index.
func (l *Loader) Data(i Sym) []byte {
if l.IsExternal(i) {
Than McIntosh
committed
pp := l.getPayload(i)
if pp != nil {
return pp.data
}
return nil
}
r, li := l.toLocal(i)
return r.Data(li)
}
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
// Returns the data of the i-th symbol in the output buffer.
func (l *Loader) OutData(i Sym) []byte {
if int(i) < len(l.outdata) && l.outdata[i] != nil {
return l.outdata[i]
}
return l.Data(i)
}
// SetOutData sets the position of the data of the i-th symbol in the output buffer.
// i is global index.
func (l *Loader) SetOutData(i Sym, data []byte) {
if l.IsExternal(i) {
pp := l.getPayload(i)
if pp != nil {
pp.data = data
return
}
}
l.outdata[i] = data
}
// InitOutData initializes the slice used to store symbol output data.
func (l *Loader) InitOutData() {
l.outdata = make([][]byte, l.extStart)
}
// SetExtRelocs sets the section of the i-th symbol. i is global index.
func (l *Loader) SetExtRelocs(i Sym, relocs []ExtReloc) {
l.extRelocs[i] = relocs
}
// InitExtRelocs initialize the slice used to store external relocations.
func (l *Loader) InitExtRelocs() {
l.extRelocs = make([][]ExtReloc, l.NSym())
}
// SymAlign returns the alignment for a symbol.
func (l *Loader) SymAlign(i Sym) int32 {
// If an alignment has been recorded, return that.
if align, ok := l.align[i]; ok {
return align
}
// TODO: would it make sense to return an arch-specific
// alignment depending on section type? E.g. STEXT => 32,
// SDATA => 1, etc?
return 0
}
// SetSymAlign sets the alignment for a symbol.
func (l *Loader) SetSymAlign(i Sym, align int32) {
// reject bad synbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetSymAlign")
}
// Reject nonsense alignments.
// TODO: do we need this?
if align < 0 {
panic("bad alignment value")
}
if align == 0 {
delete(l.align, i)
} else {
// Alignment should be a power of 2.
if bits.OnesCount32(uint32(align)) != 1 {
panic("bad alignment value")
}
l.align[i] = align
}
}
// SymValue returns the section of the i-th symbol. i is global index.
func (l *Loader) SymSect(i Sym) *sym.Section {
if int(i) >= len(l.symSects) {
// symSects is extended lazily -- it the sym in question is
// outside the range of the existing slice, then we assume its
// section has not yet been set.
return nil
}
Cherry Zhang
committed
return l.sects[l.symSects[i]]
}
// SetSymValue sets the section of the i-th symbol. i is global index.
func (l *Loader) SetSymSect(i Sym, sect *sym.Section) {
Cherry Zhang
committed
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
if int(i) >= len(l.symSects) {
l.symSects = append(l.symSects, make([]uint16, l.NSym()-len(l.symSects))...)
}
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)
idx := len(l.sects)
if idx != int(uint16(idx)) {
panic("too many sections created")
}
sect.Index = uint16(idx)
l.sects = append(l.sects, sect)
return sect
}
// SymDynImplib returns the "dynimplib" attribute for the specified
// symbol, making up a portion of the info for a symbol specified
// on a "cgo_import_dynamic" compiler directive.
func (l *Loader) SymDynimplib(i Sym) string {
return l.dynimplib[i]
}
// SetSymDynimplib sets the "dynimplib" attribute for a symbol.
func (l *Loader) SetSymDynimplib(i Sym, value string) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetDynimplib")
}
if value == "" {
delete(l.dynimplib, i)
} else {
l.dynimplib[i] = value
}
}
// SymDynimpvers returns the "dynimpvers" attribute for the specified
// symbol, making up a portion of the info for a symbol specified
// on a "cgo_import_dynamic" compiler directive.
func (l *Loader) SymDynimpvers(i Sym) string {
return l.dynimpvers[i]
}
// SetSymDynimpvers sets the "dynimpvers" attribute for a symbol.
func (l *Loader) SetSymDynimpvers(i Sym, value string) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetDynimpvers")
}
if value == "" {
delete(l.dynimpvers, i)
} else {
l.dynimpvers[i] = value
}
}
// SymExtname returns the "extname" value for the specified
// symbol.
func (l *Loader) SymExtname(i Sym) string {
if s, ok := l.extname[i]; ok {
return s
}
return l.SymName(i)
}
// SetSymExtname sets the "extname" attribute for a symbol.
func (l *Loader) SetSymExtname(i Sym, value string) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetExtname")
}
if value == "" {
delete(l.extname, i)
} else {
l.extname[i] = value
}
}
// SymElfType returns the previously recorded ELF type for a symbol
// (used only for symbols read from shared libraries by ldshlibsyms).
// It is not set for symbols defined by the packages being linked or
// by symbols read by ldelf (and so is left as elf.STT_NOTYPE).
func (l *Loader) SymElfType(i Sym) elf.SymType {
if et, ok := l.elfType[i]; ok {
return et
}
return elf.STT_NOTYPE
}
// SetSymElfType sets the elf type attribute for a symbol.
func (l *Loader) SetSymElfType(i Sym, et elf.SymType) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetSymElfType")
}
if et == elf.STT_NOTYPE {
delete(l.elfType, i)
} else {
l.elfType[i] = et
}
}
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
// SymElfSym returns the ELF symbol index for a given loader
// symbol, assigned during ELF symtab generation.
func (l *Loader) SymElfSym(i Sym) int32 {
return l.elfSym[i]
}
// SetSymElfSym sets the elf symbol index for a symbol.
func (l *Loader) SetSymElfSym(i Sym, es int32) {
if i == 0 {
panic("bad sym index")
}
if es == 0 {
delete(l.elfSym, i)
} else {
l.elfSym[i] = es
}
}
// SymLocalElfSym returns the "local" ELF symbol index for a given loader
// symbol, assigned during ELF symtab generation.
func (l *Loader) SymLocalElfSym(i Sym) int32 {
return l.localElfSym[i]
}
// SetSymLocalElfSym sets the "local" elf symbol index for a symbol.
func (l *Loader) SetSymLocalElfSym(i Sym, es int32) {
if i == 0 {
panic("bad sym index")
}
if es == 0 {
delete(l.localElfSym, i)
} else {
l.localElfSym[i] = es
}
}
// SymPlt returns the plt value for pe symbols.
func (l *Loader) SymPlt(s Sym) int32 {
if v, ok := l.plt[s]; ok {
return v
}
return -1
}
// SetPlt sets the plt value for pe symbols.
func (l *Loader) SetPlt(i Sym, v int32) {
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol for SetPlt")
}
if v == -1 {
delete(l.plt, i)
} else {
l.plt[i] = v
}
}
// SymGot returns the got value for pe symbols.
func (l *Loader) SymGot(s Sym) int32 {
if v, ok := l.got[s]; ok {
return v
}
return -1
}
// SetGot sets the got value for pe symbols.
func (l *Loader) SetGot(i Sym, v int32) {
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol for SetGot")
if v == -1 {
delete(l.got, i)
} else {
l.got[i] = v
}
}
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
// SymDynid returns the "dynid" property for the specified symbol.
func (l *Loader) SymDynid(i Sym) int32 {
if s, ok := l.dynid[i]; ok {
return s
}
return -1
}
// SetSymDynid sets the "dynid" property for a symbol.
func (l *Loader) SetSymDynid(i Sym, val int32) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetSymDynid")
}
if val == -1 {
delete(l.dynid, i)
} else {
l.dynid[i] = val
}
}
// DynIdSyms returns the set of symbols for which dynID is set to an
// interesting (non-default) value. This is expected to be a fairly
// small set.
func (l *Loader) DynidSyms() []Sym {
sl := make([]Sym, 0, len(l.dynid))
for s := range l.dynid {
sl = append(sl, s)
}
sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] })
return sl
}
// SymGoType returns the 'Gotype' property for a given symbol (set by
// the Go compiler for variable symbols). This version relies on
// reading aux symbols for the target sym -- it could be that a faster
// approach would be to check for gotype during preload and copy the
// results in to a map (might want to try this at some point and see
// if it helps speed things up).
func (l *Loader) SymGoType(i Sym) Sym {
if l.IsExternal(i) {
pp := l.getPayload(i)
return pp.gotype
}
r, li := l.toLocal(i)
Cherry Zhang
committed
for j := range auxs {
a := &auxs[j]
switch a.Type() {
case goobj2.AuxGotype:
Cherry Zhang
committed
return l.resolve(r, a.Sym())
}
}
return 0
}
// SymUnit returns the compilation unit for a given symbol (which will
// typically be nil for external or linker-manufactured symbols).
func (l *Loader) SymUnit(i Sym) *sym.CompilationUnit {
if l.IsExternal(i) {
pp := l.getPayload(i)
if pp.objidx != 0 {
r := l.objs[pp.objidx].r
return r.unit
}
return nil
}
r, _ := l.toLocal(i)
return r.unit
}
// SymPkg returns the package where the symbol came from (for
// regular compiler-generated Go symbols), but in the case of
// building with "-linkshared" (when a symbol is read from a
// shared library), will hold the library name.
// NOTE: this correspondes to sym.Symbol.File field.
func (l *Loader) SymPkg(i Sym) string {
if f, ok := l.symPkg[i]; ok {
return f
}
if l.IsExternal(i) {
pp := l.getPayload(i)
if pp.objidx != 0 {
r := l.objs[pp.objidx].r
return r.unit.Lib.Pkg
}
return ""
}
r, _ := l.toLocal(i)
return r.unit.Lib.Pkg
}
// SetSymPkg sets the package/library for a symbol. This is
// needed mainly for external symbols, specifically those imported
// from shared libraries.
func (l *Loader) SetSymPkg(i Sym, pkg string) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetSymPkg")
}
// SymLocalentry returns the "local entry" value for the specified
// symbol.
func (l *Loader) SymLocalentry(i Sym) uint8 {
return l.localentry[i]
}
// SetSymLocalentry sets the "local entry" attribute for a symbol.
func (l *Loader) SetSymLocalentry(i Sym, value uint8) {
// reject bad symbols
if i >= Sym(len(l.objSyms)) || i == 0 {
panic("bad symbol index in SetSymLocalentry")
}
if value == 0 {
delete(l.localentry, i)
} else {
l.localentry[i] = value
}
}
// Returns the number of aux symbols given a global index.
func (l *Loader) NAux(i Sym) int {
if l.IsExternal(i) {
r, li := l.toLocal(i)
return r.NAux(li)
}
Cherry Zhang
committed
// Returns the "handle" to the j-th aux symbol of the i-th symbol.
func (l *Loader) Aux2(i Sym, j int) Aux2 {
if l.IsExternal(i) {
return Aux2{}
}
r, li := l.toLocal(i)
if j >= r.NAux(li) {
return Aux2{}
}
return Aux2{r.Aux(li, j), r, l}
Cherry Zhang
committed
}
// 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
// lookups, e.f. for function with name XYZ we would then look up
// go.info.XYZ, etc.
// FIXME: once all of dwarfgen is converted over to the loader,
// it would save some space to make these aux symbols nameless.
func (l *Loader) GetFuncDwarfAuxSyms(fnSymIdx Sym) (auxDwarfInfo, auxDwarfLoc, auxDwarfRanges, auxDwarfLines Sym) {
if l.SymType(fnSymIdx) != sym.STEXT {
log.Fatalf("error: non-function sym %d/%s t=%s passed to GetFuncDwarfAuxSyms", fnSymIdx, l.SymName(fnSymIdx), l.SymType(fnSymIdx).String())
}
if l.IsExternal(fnSymIdx) {
// Current expectation is that any external function will
// not have auxsyms.
return
}
r, li := l.toLocal(fnSymIdx)
for i := range auxs {
a := &auxs[i]
switch a.Type() {
case goobj2.AuxDwarfInfo:
auxDwarfInfo = l.resolve(r, a.Sym())
if l.SymType(auxDwarfInfo) != sym.SDWARFINFO {
panic("aux dwarf info sym with wrong type")
}
case goobj2.AuxDwarfLoc:
auxDwarfLoc = l.resolve(r, a.Sym())
if l.SymType(auxDwarfLoc) != sym.SDWARFLOC {
panic("aux dwarf loc sym with wrong type")
}
case goobj2.AuxDwarfRanges:
auxDwarfRanges = l.resolve(r, a.Sym())
if l.SymType(auxDwarfRanges) != sym.SDWARFRANGE {
panic("aux dwarf ranges sym with wrong type")
}
case goobj2.AuxDwarfLines:
auxDwarfLines = l.resolve(r, a.Sym())
if l.SymType(auxDwarfLines) != sym.SDWARFLINES {
panic("aux dwarf lines sym with wrong type")
}
}
}
return
}
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
// PrependSub prepends 'sub' onto the sub list for outer symbol 'outer'.
// Will panic if 'sub' already has an outer sym or sub sym.
// FIXME: should this be instead a method on SymbolBuilder?
func (l *Loader) PrependSub(outer Sym, sub Sym) {
// NB: this presupposes that an outer sym can't be a sub symbol of
// some other outer-outer sym (I'm assuming this is true, but I
// haven't tested exhaustively).
if l.OuterSym(outer) != 0 {
panic("outer has outer itself")
}
if l.SubSym(sub) != 0 {
panic("sub set for subsym")
}
if l.OuterSym(sub) != 0 {
panic("outer already set for subsym")
}
l.sub[sub] = l.sub[outer]
l.sub[outer] = sub
l.outer[sub] = outer
}
// OuterSym gets the outer symbol for host object loaded symbols.
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]
// SetOuterSym sets the outer symbol of i to o (without setting
// sub symbols).
func (l *Loader) SetOuterSym(i Sym, o Sym) {
if o != 0 {
l.outer[i] = o
} else {
delete(l.outer, i)
}
}
// Initialize Reachable bitmap and its siblings for running deadcode pass.
func (l *Loader) InitReachable() {
l.growAttrBitmaps(l.NSym() + 1)
Than McIntosh
committed
}
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
type symWithVal struct {
s Sym
v int64
}
type bySymValue []symWithVal
func (s bySymValue) Len() int { return len(s) }
func (s bySymValue) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s bySymValue) Less(i, j int) bool { return s[i].v < s[j].v }
// SortSub walks through the sub-symbols for 's' and sorts them
// in place by increasing value. Return value is the new
// sub symbol for the specified outer symbol.
func (l *Loader) SortSub(s Sym) Sym {
if s == 0 || l.sub[s] == 0 {
return s
}
// Sort symbols using a slice first. Use a stable sort on the off
// chance that there's more than once symbol with the same value,
// so as to preserve reproducible builds.
sl := []symWithVal{}
for ss := l.sub[s]; ss != 0; ss = l.sub[ss] {
sl = append(sl, symWithVal{s: ss, v: l.SymValue(ss)})
}
sort.Stable(bySymValue(sl))
// Then apply any changes needed to the sub map.
ns := Sym(0)
for i := len(sl) - 1; i >= 0; i-- {
s := sl[i].s
l.sub[s] = ns
ns = s
}
// Update sub for outer symbol, then return
l.sub[s] = sl[0].s
return sl[0].s
}
// Insure that reachable bitmap and its siblings have enough size.
func (l *Loader) growAttrBitmaps(reqLen int) {
if reqLen > l.attrReachable.Len() {
// These are indexed by global symbol
l.attrReachable = growBitmap(reqLen, l.attrReachable)
l.attrOnList = growBitmap(reqLen, l.attrOnList)
l.attrLocal = growBitmap(reqLen, l.attrLocal)
l.attrNotInSymbolTable = growBitmap(reqLen, l.attrNotInSymbolTable)
l.growExtAttrBitmaps()
}
func (l *Loader) growExtAttrBitmaps() {
// These are indexed by external symbol index (e.g. l.extIndex(i))
extReqLen := len(l.payloads)
if extReqLen > l.attrVisibilityHidden.Len() {
l.attrVisibilityHidden = growBitmap(extReqLen, l.attrVisibilityHidden)
l.attrDuplicateOK = growBitmap(extReqLen, l.attrDuplicateOK)
l.attrShared = growBitmap(extReqLen, l.attrShared)
l.attrExternal = growBitmap(extReqLen, l.attrExternal)
Than McIntosh
committed
}
func (relocs *Relocs) Count() int { return len(relocs.rs) }
// At2 returns the j-th reloc for a global symbol.
Cherry Zhang
committed
func (relocs *Relocs) At2(j int) Reloc2 {
if relocs.l.isExtReader(relocs.r) {
pp := relocs.l.payloads[relocs.li]
return Reloc2{&relocs.rs[j], relocs.r, relocs.l, pp.reltypes[j]}
Cherry Zhang
committed
}
Cherry Zhang
committed
return Reloc2{&relocs.rs[j], relocs.r, relocs.l, 0}
Cherry Zhang
committed
}
// Relocs returns a Relocs object for the given global sym.
func (l *Loader) Relocs(i Sym) Relocs {
r, li := l.toLocal(i)
Than McIntosh
committed
if r == nil {
panic(fmt.Sprintf("trying to get oreader for invalid sym %d\n\n", 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 {
if l.isExtReader(r) {
pp := l.payloads[li]
rs = pp.relocs
return Relocs{
rs: rs,
li: li,
r: r,
l: l,
}
}
// RelocByOff implements sort.Interface for sorting relocations by offset.
type RelocByOff []Reloc
func (x RelocByOff) Len() int { return len(x) }
func (x RelocByOff) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x RelocByOff) Less(i, j int) bool { return x[i].Off < x[j].Off }
Cherry Zhang
committed
// FuncInfo provides hooks to access goobj2.FuncInfo in the objects.
type FuncInfo struct {
l *Loader
r *oReader
data []byte
auxs []goobj2.Aux
lengths goobj2.FuncInfoLengths
Cherry Zhang
committed
}
func (fi *FuncInfo) Valid() bool { return fi.r != nil }
func (fi *FuncInfo) Args() int {
return int((*goobj2.FuncInfo)(nil).ReadArgs(fi.data))
}
Cherry Zhang
committed
func (fi *FuncInfo) Locals() int {
return int((*goobj2.FuncInfo)(nil).ReadLocals(fi.data))
}
func (fi *FuncInfo) Pcsp() []byte {
pcsp, end := (*goobj2.FuncInfo)(nil).ReadPcsp(fi.data)
return fi.r.BytesAt(fi.r.PcdataBase()+pcsp, int(end-pcsp))
}
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
func (fi *FuncInfo) Pcfile() []byte {
pcf, end := (*goobj2.FuncInfo)(nil).ReadPcfile(fi.data)
return fi.r.BytesAt(fi.r.PcdataBase()+pcf, int(end-pcf))
}
func (fi *FuncInfo) Pcline() []byte {
pcln, end := (*goobj2.FuncInfo)(nil).ReadPcline(fi.data)
return fi.r.BytesAt(fi.r.PcdataBase()+pcln, int(end-pcln))
}
// Preload has to be called prior to invoking the various methods
// below related to pcdata, funcdataoff, files, and inltree nodes.
func (fi *FuncInfo) Preload() {
fi.lengths = (*goobj2.FuncInfo)(nil).ReadFuncInfoLengths(fi.data)
}
func (fi *FuncInfo) Pcinline() []byte {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
pcinl, end := (*goobj2.FuncInfo)(nil).ReadPcinline(fi.data, fi.lengths.PcdataOff)
return fi.r.BytesAt(fi.r.PcdataBase()+pcinl, int(end-pcinl))
}
func (fi *FuncInfo) NumPcdata() uint32 {
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")
}
pcdat, end := (*goobj2.FuncInfo)(nil).ReadPcdata(fi.data, fi.lengths.PcdataOff, uint32(k))
return fi.r.BytesAt(fi.r.PcdataBase()+pcdat, int(end-pcdat))
}
func (fi *FuncInfo) NumFuncdataoff() uint32 {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
return fi.lengths.NumFuncdataoff
}
func (fi *FuncInfo) Funcdataoff(k int) int64 {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
return (*goobj2.FuncInfo)(nil).ReadFuncdataoff(fi.data, fi.lengths.FuncdataoffOff, uint32(k))
}
func (fi *FuncInfo) Funcdata(syms []Sym) []Sym {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
if int(fi.lengths.NumFuncdataoff) > cap(syms) {
syms = make([]Sym, 0, fi.lengths.NumFuncdataoff)
} else {
syms = syms[:0]
}
for j := range fi.auxs {
a := &fi.auxs[j]
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
if a.Type() == goobj2.AuxFuncdata {
syms = append(syms, fi.l.resolve(fi.r, a.Sym()))
}
}
return syms
}
func (fi *FuncInfo) NumFile() uint32 {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
return fi.lengths.NumFile
}
func (fi *FuncInfo) File(k int) Sym {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
sr := (*goobj2.FuncInfo)(nil).ReadFile(fi.data, fi.lengths.FileOff, uint32(k))
return fi.l.resolve(fi.r, sr)
}
type InlTreeNode struct {
Parent int32
File Sym
Line int32
Func Sym
ParentPC int32
}
func (fi *FuncInfo) NumInlTree() uint32 {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
return fi.lengths.NumInlTree
}
func (fi *FuncInfo) InlTree(k int) InlTreeNode {
if !fi.lengths.Initialized {
panic("need to call Preload first")
}
node := (*goobj2.FuncInfo)(nil).ReadInlTree(fi.data, fi.lengths.InlTreeOff, uint32(k))
return InlTreeNode{
Parent: node.Parent,
File: fi.l.resolve(fi.r, node.File),
Line: node.Line,
Func: fi.l.resolve(fi.r, node.Func),
ParentPC: node.ParentPC,
}
}
Cherry Zhang
committed
func (l *Loader) FuncInfo(i Sym) FuncInfo {
var r *oReader
Cherry Zhang
committed
if l.IsExternal(i) {
pp := l.getPayload(i)
if pp.objidx == 0 {
return FuncInfo{}
}
r = l.objs[pp.objidx].r
auxs = pp.auxs
} else {
var li int
r, li = l.toLocal(i)
Cherry Zhang
committed
}
Cherry Zhang
committed
for j := range auxs {
a := &auxs[j]
if a.Type() == goobj2.AuxFuncInfo {
b := r.Data(int(a.Sym().SymIdx))
return FuncInfo{l, r, b, auxs, goobj2.FuncInfoLengths{}}
Cherry Zhang
committed
}
}
return FuncInfo{}
}
Cherry Zhang
committed
// 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.
// Does not read symbol data.
// Returns the fingerprint of the object.
func (l *Loader) Preload(syms *sym.Symbols, f *bio.Reader, lib *sym.Library, unit *sym.CompilationUnit, length int64) goobj2.FingerprintType {
roObject, readonly, err := f.Slice(uint64(length))
if err != nil {
log.Fatal("cannot read object file:", err)
}
r := goobj2.NewReaderFromBytes(roObject, readonly)
if len(roObject) >= 8 && bytes.Equal(roObject[:8], []byte("\x00go114ld")) {
log.Fatalf("found object file %s in old format, but -go115newobj is true\nset -go115newobj consistently in all -gcflags, -asmflags, and -ldflags", f.File().Name())
}
panic("cannot read object file")
}
localSymVersion := syms.IncVersion()
pkgprefix := objabi.PathToPrefix(lib.Pkg) + "."
ndef := r.NSym()
nnonpkgdef := r.NNonpkgdef()
or := &oReader{r, unit, localSymVersion, r.Flags(), pkgprefix, make([]Sym, ndef+nnonpkgdef+r.NNonpkgref()), ndef, uint32(len(l.objs))}
lib.Autolib = append(lib.Autolib, r.Autolib()...)
Cherry Zhang
committed
// DWARF file table
nfile := r.NDwarfFile()
unit.DWARFFileTable = make([]string, nfile)
for i := range unit.DWARFFileTable {
unit.DWARFFileTable[i] = r.DwarfFile(i)
}
Cherry Zhang
committed
l.addObj(lib.Pkg, or)
l.preloadSyms(or, pkgDef)
// The caller expects us consuming all the data
f.MustSeek(length, os.SEEK_CUR)
return r.Fingerprint()
Cherry Zhang
committed
}
// Preload symbols of given kind from an object.
func (l *Loader) preloadSyms(r *oReader, kind int) {
ndef := r.NSym()
nnonpkgdef := r.NNonpkgdef()
var start, end int
switch kind {
case pkgDef:
start = 0
end = ndef
case nonPkgDef:
start = ndef
end = ndef + nnonpkgdef
default:
panic("preloadSyms: bad kind")
}
l.growSyms(len(l.objSyms) + end - start)
l.growAttrBitmaps(len(l.objSyms) + end - start)
for i := start; i < end; i++ {
name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
v := abiToVer(osym.ABI(), r.version)
dupok := osym.Dupok()
gi, added := l.AddSym(name, v, r, i, kind, dupok, sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type())])
Cherry Zhang
committed
r.syms[i] = gi
if !added {
continue
}
if osym.TopFrame() {
l.SetAttrTopFrame(gi, true)
}
if osym.Local() {
l.SetAttrLocal(gi, true)
}
if strings.HasPrefix(name, "go.itablink.") {
l.itablink[gi] = struct{}{}
}
if 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] = gi
}
}
if strings.HasPrefix(name, "go.string.") ||
strings.HasPrefix(name, "gclocals·") ||
strings.HasPrefix(name, "runtime.gcbits.") {
l.SetAttrNotInSymbolTable(gi, true)
if a := osym.Align(); a != 0 {
l.SetSymAlign(gi, int32(a))
}
Cherry Zhang
committed
// Add non-package symbols and references to external symbols (which are always
// named).
func (l *Loader) LoadNonpkgSyms(arch *sys.Arch) {
Cherry Zhang
committed
for _, o := range l.objs[1:] {
l.preloadSyms(o.r, nonPkgDef)
}
Cherry Zhang
committed
for _, o := range l.objs[1:] {
loadObjRefs(l, o.r, arch)
Cherry Zhang
committed
}
}
func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {
ndef := r.NSym() + r.NNonpkgdef()
for i, n := 0, r.NNonpkgref(); i < n; i++ {
name := strings.Replace(osym.Name(r.Reader), "\"\".", r.pkgprefix, -1)
v := abiToVer(osym.ABI(), r.version)
r.syms[ndef+i] = l.LookupOrCreateSym(name, v)
gi := r.syms[ndef+i]
if osym.Local() {
l.SetAttrLocal(gi, true)
}
l.preprocess(arch, gi, name)
}
}
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 {