Newer
Older
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
return s
}
s := l.allocSym(name, ver)
l.installSym(i, s)
syms.Allsym = append(syms.Allsym, s) // XXX see above
return s
}
syms.ROLookup = func(name string, ver int) *sym.Symbol {
i := l.Lookup(name, ver)
return l.Syms[i]
}
syms.Rename = func(old, new string, ver int) {
// annoying... maybe there is a better way to do this
if ver >= 2 {
panic("cannot rename static symbol")
}
i := l.Lookup(old, ver)
s := l.Syms[i]
s.Name = new
if s.Extname() == old {
s.SetExtname(new)
}
delete(l.symsByName[ver], old)
// This mirrors the old code. But I'm not sure if the logic of
// handling dup in the old code actually works, or necessary.
dupi := l.symsByName[ver][new]
dup := l.Syms[dupi]
if dup == nil {
l.symsByName[ver][new] = i
} else {
if s.Type == 0 {
dup.Attr |= s.Attr
*s = *dup
} else if dup.Type == 0 {
s.Attr |= dup.Attr
*dup = *s
l.symsByName[ver][new] = i
}
}
}
// allocSym allocates a new symbol backing.
func (l *Loader) allocSym(name string, version int) *sym.Symbol {
batch := l.symBatch
if len(batch) == 0 {
batch = make([]sym.Symbol, 1000)
}
s := &batch[0]
l.symBatch = batch[1:]
s.Dynid = -1
s.Name = name
s.Version = int16(version)
return s
}
Than McIntosh
committed
// installSym sets the underlying sym.Symbol for the specified sym index.
func (l *Loader) installSym(i Sym, s *sym.Symbol) {
if s == nil {
panic("installSym nil symbol")
}
if l.Syms[i] != nil {
panic("sym already present in installSym")
Than McIntosh
committed
}
l.Syms[i] = s
}
// addNewSym adds a new sym.Symbol to the i-th index in the list of symbols.
func (l *Loader) addNewSym(i Sym, name string, ver int, unit *sym.CompilationUnit, t sym.SymKind) *sym.Symbol {
s := l.allocSym(name, ver)
if s.Type != 0 && s.Type != sym.SXREF {
fmt.Println("symbol already processed:", unit.Lib, i, s)
panic("symbol already processed")
}
if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
t = s.Type
}
s.Type = t
s.Unit = unit
l.growSyms(int(i))
Than McIntosh
committed
l.installSym(i, s)
return s
}
// loadObjSyms creates sym.Symbol objects for the live Syms in the
// object corresponding to object reader "r". Return value is the
// number of sym.Reloc entries required for all the new symbols.
func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
nr := 0
for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
if r2, i2 := l.toLocal(gi); r2 != r || i2 != i {
continue // come from a different object
}
osym := goobj2.Sym{}
Cherry Zhang
committed
osym.Read(r.Reader, r.SymOff(i))
name := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
if name == "" {
continue
ver := abiToVer(osym.ABI, r.version)
t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
if t == sym.SXREF {
log.Fatalf("bad sxref")
}
if t == 0 {
log.Fatalf("missing type for %s in %s", name, r.unit.Lib)
if !l.attrReachable.Has(gi) && name != "runtime.addmoduledata" && name != "runtime.lastmoduledatap" {
// No need to load unreachable symbols.
// XXX reference to runtime.addmoduledata may be generated later by the linker in plugin mode.
s := l.addNewSym(gi, name, ver, r.unit, t)
l.migrateAttributes(gi, s)
nr += r.NReloc(i)
return nr
}
// funcInfoSym records the sym.Symbol for a function, along with a copy
// of the corresponding goobj2.Sym and the index of its FuncInfo aux sym.
// We use this to delay populating FuncInfo until we can batch-allocate
// slices for their sub-objects.
type funcInfoSym struct {
s *sym.Symbol // sym.Symbol for a live function
osym goobj2.Sym // object file symbol data for that function
isym int // global symbol index of FuncInfo aux sym for func
}
// funcAllocInfo records totals/counts for all functions in an objfile;
// used to help with bulk allocation of sym.Symbol sub-objects.
type funcAllocInfo struct {
symPtr uint32 // number of *sym.Symbol's needed in file slices
inlCall uint32 // number of sym.InlinedCall's needed in inltree slices
pcData uint32 // number of sym.Pcdata's needed in pdata slices
fdOff uint32 // number of int64's needed in all Funcdataoff slices
}
// cloneToExternal takes the existing object file symbol (symIdx)
// and creates a new external symbol payload that is a clone with
// respect to name, version, type, relocations, etc. The idea here
// is that if the linker decides it wants to update the contents of
// a symbol originally discovered as part of an object file, it's
// easier to do this if we make the updates to an external symbol
// payload.
// XXX maybe rename? makeExtPayload?
func (l *Loader) cloneToExternal(symIdx Sym) {
if l.IsExternal(symIdx) {
panic("sym is already external, no need for clone")
}
l.growSyms(int(symIdx))
// Read the particulars from object.
osym := goobj2.Sym{}
r, li := l.toLocal(symIdx)
osym.Read(r.Reader, r.SymOff(li))
sname := strings.Replace(osym.Name, "\"\".", r.pkgprefix, -1)
sver := abiToVer(osym.ABI, r.version)
skind := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
// Create new symbol, update version and kind.
pi := l.newPayload(sname, sver)
pp := l.payloads[pi]
pp.kind = skind
pp.ver = sver
pp.size = int64(osym.Siz)
pp.objidx = r.objidx
// If this is a def, then copy the guts. We expect this case
// to be very rare (one case it may come up is with -X).
if li < (r.NSym() + r.NNonpkgdef()) {
// Copy relocations
relocs := l.Relocs(symIdx)
pp.relocs = relocs.ReadAll(nil)
// Copy data
pp.data = r.Data(li)
}
// If we're overriding a data symbol, collect the associated
// Gotype, so as to propagate it to the new symbol.
naux := r.NAux(li)
for j := 0; j < naux; j++ {
a := goobj2.Aux{}
a.Read(r.Reader, r.AuxOff(li, j))
switch a.Type {
case goobj2.AuxGotype:
pp.gotype = l.resolve(r, a.Sym)
default:
log.Fatalf("internal error: cloneToExternal applied to %s symbol %s with non-gotype aux data %d", skind.String(), sname, a.Type)
}
}
// Install new payload to global index space.
// (This needs to happen at the end, as the accessors above
// need to access the old symbol content.)
l.objSyms[symIdx] = objSym{l.extReader, pi}
l.extReader.syms = append(l.extReader.syms, symIdx)
}
// copyAttributes copies over all of the attributes of symbol 'src' to
// symbol 'dst'. The assumption is that 'dst' is an external symbol.
func (l *Loader) copyAttributes(src Sym, dst Sym) {
l.SetAttrReachable(dst, l.AttrReachable(src))
l.SetAttrOnList(dst, l.AttrOnList(src))
l.SetAttrLocal(dst, l.AttrLocal(src))
l.SetAttrNotInSymbolTable(dst, l.AttrNotInSymbolTable(src))
l.SetAttrVisibilityHidden(dst, l.AttrVisibilityHidden(src))
l.SetAttrDuplicateOK(dst, l.AttrDuplicateOK(src))
l.SetAttrShared(dst, l.AttrShared(src))
l.SetAttrExternal(dst, l.AttrExternal(src))
l.SetAttrTopFrame(dst, l.AttrTopFrame(src))
l.SetAttrSpecial(dst, l.AttrSpecial(src))
l.SetAttrCgoExportDynamic(dst, l.AttrCgoExportDynamic(src))
l.SetAttrCgoExportStatic(dst, l.AttrCgoExportStatic(src))
l.SetAttrReadOnly(dst, l.AttrReadOnly(src))
}
// migrateAttributes copies over all of the attributes of symbol 'src' to
// sym.Symbol 'dst'.
func (l *Loader) migrateAttributes(src Sym, dst *sym.Symbol) {
dst.Attr.Set(sym.AttrReachable, l.AttrReachable(src))
dst.Attr.Set(sym.AttrOnList, l.AttrOnList(src))
dst.Attr.Set(sym.AttrLocal, l.AttrLocal(src))
dst.Attr.Set(sym.AttrNotInSymbolTable, l.AttrNotInSymbolTable(src))
dst.Attr.Set(sym.AttrNoSplit, l.IsNoSplit(src))
dst.Attr.Set(sym.AttrVisibilityHidden, l.AttrVisibilityHidden(src))
dst.Attr.Set(sym.AttrDuplicateOK, l.AttrDuplicateOK(src))
dst.Attr.Set(sym.AttrShared, l.AttrShared(src))
dst.Attr.Set(sym.AttrExternal, l.AttrExternal(src))
dst.Attr.Set(sym.AttrTopFrame, l.AttrTopFrame(src))
dst.Attr.Set(sym.AttrSpecial, l.AttrSpecial(src))
dst.Attr.Set(sym.AttrCgoExportDynamic, l.AttrCgoExportDynamic(src))
dst.Attr.Set(sym.AttrCgoExportStatic, l.AttrCgoExportStatic(src))
dst.Attr.Set(sym.AttrReadOnly, l.AttrReadOnly(src))
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
// Convert outer/sub relationships
if outer, ok := l.outer[src]; ok {
dst.Outer = l.Syms[outer]
}
if sub, ok := l.sub[src]; ok {
dst.Sub = l.Syms[sub]
}
// Set sub-symbol attribute. FIXME: would be better to do away
// with this and just use l.OuterSymbol() != 0 elsewhere within
// the linker.
dst.Attr.Set(sym.AttrSubSymbol, dst.Outer != nil)
// Copy over dynimplib, dynimpvers, extname.
if l.SymExtname(src) != "" {
dst.SetExtname(l.SymExtname(src))
}
if l.SymDynimplib(src) != "" {
dst.SetDynimplib(l.SymDynimplib(src))
}
if l.SymDynimpvers(src) != "" {
dst.SetDynimpvers(l.SymDynimpvers(src))
}
// Copy ELF type if set.
if et, ok := l.elfType[src]; ok {
dst.SetElfType(et)
}
// Copy pe objects values if set.
if plt, ok := l.plt[src]; ok {
dst.SetPlt(plt)
}
if got, ok := l.got[src]; ok {
dst.SetGot(got)
}
}
Than McIntosh
committed
// CreateExtSym creates a new external symbol with the specified name
// without adding it to any lookup tables, returning a Sym index for it.
func (l *Loader) CreateExtSym(name string) Sym {
// Assign a new unique negative version -- this is to mark the
// symbol so that it can be skipped when ExtractSymbols is adding
// ext syms to the sym.Symbols hash.
l.anonVersion--
return l.newExtSym(name, l.anonVersion)
Than McIntosh
committed
}
func loadObjFull(l *Loader, r *oReader) {
lib := r.unit.Lib
resolveSymRef := func(s goobj2.SymRef) *sym.Symbol {
i := l.resolve(r, s)
return l.Syms[i]
}
funcs := []funcInfoSym{}
fdsyms := []*sym.Symbol{}
var funcAllocCounts funcAllocInfo
pcdataBase := r.PcdataBase()
rslice := []Reloc{}
for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
// A symbol may be a dup or overwritten. In this case, its
// content will actually be provided by a different object
// (to which its global index points). Skip those symbols.
gi := l.toGlobal(r, i)
var isdup bool
if r2, i2 := l.toLocal(gi); r2 != r || i2 != i {
isdup = true
}
osym := goobj2.Sym{}
osym.ReadWithoutName(r.Reader, r.SymOff(i))
dupok := osym.Dupok()
if dupok && isdup {
if l.attrReachable.Has(gi) {
// A dupok symbol is resolved to another package. We still need
// to record its presence in the current package, as the trampoline
// pass expects packages are laid out in dependency order.
s := l.Syms[gi]
if s.Type == sym.STEXT {
lib.DupTextSyms = append(lib.DupTextSyms, s)
}
}
}
continue // come from a different object
}
s := l.Syms[gi]
if s == nil {
continue
}
local := osym.Local()
makeTypelink := osym.Typelink()
size := osym.Siz
// Symbol data
s.P = r.Data(i)
s.Attr.Set(sym.AttrReadOnly, r.ReadOnly())
// Relocs
relocs := l.relocs(r, i)
rslice = relocs.ReadAll(rslice)
batch := l.relocBatch
s.R = batch[:relocs.Count:relocs.Count]
l.relocBatch = batch[relocs.Count:]
l.convertRelocations(rslice, s, false)
// Aux symbol info
isym := -1
naux := r.NAux(i)
for j := 0; j < naux; j++ {
a := goobj2.Aux{}
Cherry Zhang
committed
a.Read(r.Reader, r.AuxOff(i, j))
switch a.Type {
case goobj2.AuxGotype:
typ := resolveSymRef(a.Sym)
if typ != nil {
s.Gotype = typ
}
case goobj2.AuxFuncdata:
fdsyms = append(fdsyms, resolveSymRef(a.Sym))
case goobj2.AuxFuncInfo:
if a.Sym.PkgIdx != goobj2.PkgIdxSelf {
panic("funcinfo symbol not defined in current package")
}
isym = int(a.Sym.SymIdx)
case goobj2.AuxDwarfInfo, goobj2.AuxDwarfLoc, goobj2.AuxDwarfRanges, goobj2.AuxDwarfLines:
// ignored for now
default:
panic("unknown aux type")
}
}
s.File = r.pkgprefix[:len(r.pkgprefix)-1]
if dupok {
s.Attr |= sym.AttrDuplicateOK
}
if s.Size < int64(size) {
s.Size = int64(size)
}
s.Attr.Set(sym.AttrLocal, local)
s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
if s.Type != sym.STEXT {
continue
}
if isym == -1 {
continue
}
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
// Record function sym and associated info for additional
// processing in the loop below.
fwis := funcInfoSym{s: s, isym: isym, osym: osym}
funcs = append(funcs, fwis)
// Read the goobj2.FuncInfo for this text symbol so that we can
// collect allocation counts. We'll read it again in the loop
// below.
b := r.Data(isym)
info := goobj2.FuncInfo{}
info.Read(b)
funcAllocCounts.symPtr += uint32(len(info.File))
funcAllocCounts.pcData += uint32(len(info.Pcdata))
funcAllocCounts.inlCall += uint32(len(info.InlTree))
funcAllocCounts.fdOff += uint32(len(info.Funcdataoff))
}
// At this point we can do batch allocation of the sym.FuncInfo's,
// along with the slices of sub-objects they use.
fiBatch := make([]sym.FuncInfo, len(funcs))
inlCallBatch := make([]sym.InlinedCall, funcAllocCounts.inlCall)
symPtrBatch := make([]*sym.Symbol, funcAllocCounts.symPtr)
pcDataBatch := make([]sym.Pcdata, funcAllocCounts.pcData)
fdOffBatch := make([]int64, funcAllocCounts.fdOff)
// Populate FuncInfo contents for func symbols.
for fi := 0; fi < len(funcs); fi++ {
s := funcs[fi].s
isym := funcs[fi].isym
osym := funcs[fi].osym
s.FuncInfo = &fiBatch[0]
fiBatch = fiBatch[1:]
Cherry Zhang
committed
b := r.Data(isym)
info := goobj2.FuncInfo{}
info.Read(b)
if osym.NoSplit() {
s.Attr |= sym.AttrNoSplit
}
if osym.ReflectMethod() {
s.Attr |= sym.AttrReflectMethod
}
if r.Flags()&goobj2.ObjFlagShared != 0 {
s.Attr |= sym.AttrShared
}
if osym.TopFrame() {
s.Attr |= sym.AttrTopFrame
}
pc := s.FuncInfo
if len(info.Funcdataoff) != 0 {
nfd := len(info.Funcdataoff)
pc.Funcdata = fdsyms[:nfd:nfd]
fdsyms = fdsyms[nfd:]
info.Pcdata = append(info.Pcdata, info.PcdataEnd) // for the ease of knowing where it ends
pc.Args = int32(info.Args)
pc.Locals = int32(info.Locals)
npc := len(info.Pcdata) - 1 // -1 as we appended one above
pc.Pcdata = pcDataBatch[:npc:npc]
pcDataBatch = pcDataBatch[npc:]
nfd := len(info.Funcdataoff)
pc.Funcdataoff = fdOffBatch[:nfd:nfd]
fdOffBatch = fdOffBatch[nfd:]
nsp := len(info.File)
pc.File = symPtrBatch[:nsp:nsp]
symPtrBatch = symPtrBatch[nsp:]
nic := len(info.InlTree)
pc.InlTree = inlCallBatch[:nic:nic]
inlCallBatch = inlCallBatch[nic:]
pc.Pcsp.P = r.BytesAt(pcdataBase+info.Pcsp, int(info.Pcfile-info.Pcsp))
pc.Pcfile.P = r.BytesAt(pcdataBase+info.Pcfile, int(info.Pcline-info.Pcfile))
pc.Pcline.P = r.BytesAt(pcdataBase+info.Pcline, int(info.Pcinline-info.Pcline))
pc.Pcinline.P = r.BytesAt(pcdataBase+info.Pcinline, int(info.Pcdata[0]-info.Pcinline))
for k := range pc.Pcdata {
pc.Pcdata[k].P = r.BytesAt(pcdataBase+info.Pcdata[k], int(info.Pcdata[k+1]-info.Pcdata[k]))
}
for k := range pc.Funcdataoff {
pc.Funcdataoff[k] = int64(info.Funcdataoff[k])
}
for k := range pc.File {
pc.File[k] = resolveSymRef(info.File[k])
}
for k := range pc.InlTree {
inl := &info.InlTree[k]
pc.InlTree[k] = sym.InlinedCall{
Parent: inl.Parent,
File: resolveSymRef(inl.File),
Line: inl.Line,
Func: l.SymName(l.resolve(r, inl.Func)),
ParentPC: inl.ParentPC,
}
}
dupok := osym.Dupok()
if !dupok {
if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr.Set(sym.AttrOnList, true)
lib.Textp = append(lib.Textp, s)
} else {
// there may be a dup in another package
// put into a temp list and add to text later
lib.DupTextSyms = append(lib.DupTextSyms, s)
}
Cherry Zhang
committed
// convertRelocations takes a vector of loader.Reloc relocations and
// translates them into an equivalent set of sym.Reloc relocations on
// the symbol "dst", performing fixups along the way for ABI aliases,
// etc. It is assumed that the caller has pre-allocated the dst symbol
// relocations slice. If 'strict' is set, then this method will
// panic if it finds a relocation targeting a nil symbol.
func (l *Loader) convertRelocations(src []Reloc, dst *sym.Symbol, strict bool) {
for j := range dst.R {
r := src[j]
rs := r.Sym
sz := r.Size
rt := r.Type
if rt == objabi.R_METHODOFF {
if l.attrReachable.Has(rs) {
rt = objabi.R_ADDROFF
} else {
sz = 0
rs = 0
}
}
if rt == objabi.R_WEAKADDROFF && !l.attrReachable.Has(rs) {
rs = 0
sz = 0
}
if rs != 0 && l.Syms[rs] != nil && l.Syms[rs].Type == sym.SABIALIAS {
rsrelocs := l.Relocs(rs)
rs = rsrelocs.At(0).Sym
}
if strict && rs != 0 && l.Syms[rs] == nil && rt != objabi.R_USETYPE {
panic("nil reloc target in convertRelocations")
}
dst.R[j] = sym.Reloc{
Off: r.Off,
Siz: sz,
Type: rt,
Add: r.Add,
Sym: l.Syms[rs],
}
}
}
// UndefinedRelocTargets iterates through the global symbol index
// space, looking for symbols with relocations targeting undefined
// references. The linker's loadlib method uses this to determine if
// there are unresolved references to functions in system libraries
// (for example, libgcc.a), presumably due to CGO code. Return
// value is a list of loader.Sym's corresponding to the undefined
// cross-refs. The "limit" param controls the maximum number of
// results returned; if "limit" is -1, then all undefs are returned.
func (l *Loader) UndefinedRelocTargets(limit int) []Sym {
result := []Sym{}
rslice := []Reloc{}
for si := Sym(1); si < Sym(len(l.objSyms)); si++ {
relocs := l.Relocs(si)
rslice = relocs.ReadSyms(rslice)
for ri := 0; ri < relocs.Count; ri++ {
r := &rslice[ri]
if r.Sym != 0 && l.SymType(r.Sym) == sym.SXREF && l.RawSymName(r.Sym) != ".got" {
result = append(result, r.Sym)
if limit != -1 && len(result) >= limit {
break
}
}
}
}
return result
}
// AssignTextSymbolOrder populates the Textp2 slices within each
// library and compilation unit, insuring that packages are laid down
// in dependency order (internal first, then everything else). Return value
// is a slice of all text syms.
func (l *Loader) AssignTextSymbolOrder(libs []*sym.Library, intlibs []bool, extsyms []Sym) []Sym {
// Library Textp2 lists should be empty at this point.
for _, lib := range libs {
if len(lib.Textp2) != 0 {
panic("expected empty Textp2 slice for library")
}
if len(lib.DupTextSyms2) != 0 {
panic("expected empty DupTextSyms2 slice for library")
}
}
// Used to record which dupok symbol we've assigned to a unit.
// Can't use the onlist attribute here because it will need to
// clear for the later assignment of the sym.Symbol to a unit.
// NB: we can convert to using onList once we no longer have to
// call the regular addToTextp.
assignedToUnit := MakeBitmap(l.NSym() + 1)
// Start off textp2 with reachable external syms.
textp2 := []Sym{}
for _, sym := range extsyms {
if !l.attrReachable.Has(sym) {
continue
}
textp2 = append(textp2, sym)
}
// Walk through all text symbols from Go object files and append
// them to their corresponding library's textp2 list.
for _, o := range l.objs[1:] {
r := o.r
lib := r.unit.Lib
for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
gi := l.toGlobal(r, i)
if !l.attrReachable.Has(gi) {
continue
}
osym := goobj2.Sym{}
osym.ReadWithoutName(r.Reader, r.SymOff(i))
st := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
if st != sym.STEXT {
continue
}
dupok := osym.Dupok()
if r2, i2 := l.toLocal(gi); r2 != r || i2 != i {
// A dupok text symbol is resolved to another package.
// We still need to record its presence in the current
// package, as the trampoline pass expects packages
// are laid out in dependency order.
lib.DupTextSyms2 = append(lib.DupTextSyms2, sym.LoaderSym(gi))
continue // symbol in different object
}
if dupok {
lib.DupTextSyms2 = append(lib.DupTextSyms2, sym.LoaderSym(gi))
}
lib.Textp2 = append(lib.Textp2, sym.LoaderSym(gi))
}
}
// Now redo the assignment of text symbols to libs/units.
for _, doInternal := range [2]bool{true, false} {
for idx, lib := range libs {
if intlibs[idx] != doInternal {
continue
}
libtextp2 := []sym.LoaderSym{}
lists := [2][]sym.LoaderSym{lib.Textp2, lib.DupTextSyms2}
for _, list := range lists {
for _, s := range list {
sym := Sym(s)
if l.attrReachable.Has(sym) && !assignedToUnit.Has(sym) {
libtextp2 = append(libtextp2, s)
textp2 = append(textp2, sym)
unit := l.SymUnit(sym)
if unit != nil {
unit.Textp2 = append(unit.Textp2, s)
assignedToUnit.Set(sym)
}
}
}
}
lib.Textp2 = libtextp2
}
}
return textp2
}
// For debugging.
func (l *Loader) Dump() {
fmt.Println("objs")
for _, obj := range l.objs {
if obj.r != nil {
fmt.Println(obj.i, obj.r.unit.Lib)
}
}
Than McIntosh
committed
fmt.Println("extStart:", l.extStart)
fmt.Println("Nsyms:", len(l.objSyms))
fmt.Println("syms")
for i := Sym(1); i < Sym(len(l.objSyms)); i++ {
pi := interface{}("")
if l.IsExternal(i) {
pi = fmt.Sprintf("<ext %d>", l.extIndex(i))
}
var s *sym.Symbol
if int(i) < len(l.Syms) {
s = l.Syms[i]
}
if s != nil {
fmt.Println(i, s, s.Type, pi)
} else {
fmt.Println(i, l.SymName(i), "<not loaded>", pi)
}
}
fmt.Println("symsByName")
for name, i := range l.symsByName[0] {
fmt.Println(i, name, 0)
}
for name, i := range l.symsByName[1] {
fmt.Println(i, name, 1)
fmt.Println("payloads:")
for i := range l.payloads {
pp := l.payloads[i]
fmt.Println(i, pp.name, pp.ver, pp.kind)
}