Commit 24950952 authored by Cherry Zhang's avatar Cherry Zhang

[dev.link] cmd/link: load full symbol contents after deadcode pass

If the new object file format is used, now we load full symbol
contents after the deadcode pass, for reachable symbols only.
We still load some informations early, like relocations and the
contents of type symbols, which are used in the deadcode pass.
If we rewrite deadcode to use index directly, we could delay more
of the loading (to sym.Symbol), and perhaps delay the creation of
sym.Symbol.

TODO: internal linking with host objects doesn't work yet.

Change-Id: I7d4880e8f150e8709ffac277e62191623440e4cf
Reviewed-on: https://go-review.googlesource.com/c/go/+/197258
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarThan McIntosh <thanm@google.com>
parent 48151b3f
...@@ -60,8 +60,8 @@ func deadcode(ctxt *Link) { ...@@ -60,8 +60,8 @@ func deadcode(ctxt *Link) {
d.init() d.init()
d.flood() d.flood()
callSym := ctxt.Syms.ROLookup("reflect.Value.Call", sym.SymVerABIInternal) callSym := ctxt.Lookup("reflect.Value.Call", sym.SymVerABIInternal)
methSym := ctxt.Syms.ROLookup("reflect.Value.Method", sym.SymVerABIInternal) methSym := ctxt.Lookup("reflect.Value.Method", sym.SymVerABIInternal)
reflectSeen := false reflectSeen := false
if ctxt.DynlinkingGo() { if ctxt.DynlinkingGo() {
...@@ -283,7 +283,7 @@ func (d *deadcodepass) init() { ...@@ -283,7 +283,7 @@ func (d *deadcodepass) init() {
// We don't keep the go.plugin.exports symbol, // We don't keep the go.plugin.exports symbol,
// but we do keep the symbols it refers to. // but we do keep the symbols it refers to.
exports := d.ctxt.Syms.ROLookup("go.plugin.exports", 0) exports := d.ctxt.Lookup("go.plugin.exports", 0)
if exports != nil { if exports != nil {
for i := range exports.R { for i := range exports.R {
d.mark(exports.R[i].Sym, nil) d.mark(exports.R[i].Sym, nil)
...@@ -298,9 +298,9 @@ func (d *deadcodepass) init() { ...@@ -298,9 +298,9 @@ func (d *deadcodepass) init() {
for _, name := range names { for _, name := range names {
// Mark symbol as an data/ABI0 symbol. // Mark symbol as an data/ABI0 symbol.
d.mark(d.ctxt.Syms.ROLookup(name, 0), nil) d.mark(d.ctxt.Lookup(name, 0), nil)
// Also mark any Go functions (internal ABI). // Also mark any Go functions (internal ABI).
d.mark(d.ctxt.Syms.ROLookup(name, sym.SymVerABIInternal), nil) d.mark(d.ctxt.Lookup(name, sym.SymVerABIInternal), nil)
} }
} }
......
...@@ -169,7 +169,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) { ...@@ -169,7 +169,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
if i := strings.Index(remote, "#"); i >= 0 { if i := strings.Index(remote, "#"); i >= 0 {
remote, q = remote[:i], remote[i+1:] remote, q = remote[:i], remote[i+1:]
} }
s := ctxt.Syms.Lookup(local, 0) s := ctxt.LookupOrCreate(local, 0)
if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SHOSTOBJ { if s.Type == 0 || s.Type == sym.SXREF || s.Type == sym.SHOSTOBJ {
s.SetDynimplib(lib) s.SetDynimplib(lib)
s.SetExtname(remote) s.SetExtname(remote)
...@@ -188,7 +188,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) { ...@@ -188,7 +188,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
} }
local := f[1] local := f[1]
s := ctxt.Syms.Lookup(local, 0) s := ctxt.LookupOrCreate(local, 0)
s.Type = sym.SHOSTOBJ s.Type = sym.SHOSTOBJ
s.Size = 0 s.Size = 0
continue continue
...@@ -209,7 +209,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) { ...@@ -209,7 +209,7 @@ func loadcgo(ctxt *Link, file string, pkg string, p string) {
// functions. Link.loadlib will resolve any // functions. Link.loadlib will resolve any
// ABI aliases we find here (since we may not // ABI aliases we find here (since we may not
// yet know it's an alias). // yet know it's an alias).
s := ctxt.Syms.Lookup(local, 0) s := ctxt.LookupOrCreate(local, 0)
switch ctxt.BuildMode { switch ctxt.BuildMode {
case BuildModeCShared, BuildModeCArchive, BuildModePlugin: case BuildModeCShared, BuildModeCArchive, BuildModePlugin:
......
...@@ -401,21 +401,24 @@ func (ctxt *Link) loadlib() { ...@@ -401,21 +401,24 @@ func (ctxt *Link) loadlib() {
} }
} }
// XXX do it here for now
if *flagNewobj { if *flagNewobj {
ctxt.loadlibfull() // Add references of externally defined symbols.
} for _, lib := range ctxt.Library {
for _, r := range lib.Readers {
for _, lib := range ctxt.Library { objfile.LoadRefs(ctxt.loader, r.Reader, lib, ctxt.Arch, ctxt.Syms, r.Version)
if lib.Shlib != "" {
if ctxt.Debugvlog > 1 {
ctxt.Logf("%5.2f autolib: %s (from %s)\n", Cputime(), lib.Shlib, lib.Objref)
} }
ldshlibsyms(ctxt, lib.Shlib) }
// Load cgo directives.
for _, p := range ctxt.cgodata {
loadcgo(ctxt, p[0], p[1], p[2])
} }
} }
iscgo = ctxt.Syms.ROLookup("x_cgo_init", 0) != nil iscgo = ctxt.Lookup("x_cgo_init", 0) != nil
// Record whether we can use plugins.
ctxt.canUsePlugins = (ctxt.Lookup("plugin.Open", sym.SymVerABIInternal) != nil)
// We now have enough information to determine the link mode. // We now have enough information to determine the link mode.
determineLinkMode(ctxt) determineLinkMode(ctxt)
...@@ -448,8 +451,34 @@ func (ctxt *Link) loadlib() { ...@@ -448,8 +451,34 @@ func (ctxt *Link) loadlib() {
dynexp[i] = t dynexp[i] = t
} }
for _, lib := range ctxt.Library {
if lib.Shlib != "" {
if ctxt.Debugvlog > 1 {
ctxt.Logf("%5.2f autolib: %s (from %s)\n", Cputime(), lib.Shlib, lib.Objref)
}
ldshlibsyms(ctxt, lib.Shlib)
}
}
if ctxt.LinkMode == LinkExternal && !iscgo && ctxt.LibraryByPkg["runtime/cgo"] == nil && !(objabi.GOOS == "darwin" && (ctxt.Arch.Family == sys.AMD64 || ctxt.Arch.Family == sys.I386)) {
// This indicates a user requested -linkmode=external.
// The startup code uses an import of runtime/cgo to decide
// whether to initialize the TLS. So give it one. This could
// be handled differently but it's an unusual case.
if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil {
if lib.Shlib != "" {
ldshlibsyms(ctxt, lib.Shlib)
} else {
if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
Exitf("cannot implicitly include runtime/cgo in a shared library")
}
loadobjfile(ctxt, lib)
}
}
}
// In internal link mode, read the host object files. // In internal link mode, read the host object files.
if ctxt.LinkMode == LinkInternal { if ctxt.LinkMode == LinkInternal && len(hostobj) != 0 {
// Drop all the cgo_import_static declarations. // Drop all the cgo_import_static declarations.
// Turns out we won't be needing them. // Turns out we won't be needing them.
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
...@@ -510,34 +539,23 @@ func (ctxt *Link) loadlib() { ...@@ -510,34 +539,23 @@ func (ctxt *Link) loadlib() {
*/ */
} }
} }
} else { } else if ctxt.LinkMode == LinkExternal {
hostlinksetup(ctxt) hostlinksetup(ctxt)
} }
// We've loaded all the code now. // We've loaded all the code now.
ctxt.Loaded = true ctxt.Loaded = true
// Record whether we can use plugins. importcycles()
ctxt.canUsePlugins = (ctxt.Syms.ROLookup("plugin.Open", sym.SymVerABIInternal) != nil)
if ctxt.LinkMode == LinkExternal && !iscgo && ctxt.LibraryByPkg["runtime/cgo"] == nil && !(objabi.GOOS == "darwin" && (ctxt.Arch.Family == sys.AMD64 || ctxt.Arch.Family == sys.I386)) { // For now, load relocations for dead-code elimination.
// This indicates a user requested -linkmode=external. if *flagNewobj {
// The startup code uses an import of runtime/cgo to decide for _, lib := range ctxt.Library {
// whether to initialize the TLS. So give it one. This could for _, r := range lib.Readers {
// be handled differently but it's an unusual case. objfile.LoadReloc(ctxt.loader, r.Reader, lib, r.Version, ctxt.LibraryByPkg)
if lib := loadinternal(ctxt, "runtime/cgo"); lib != nil {
if lib.Shlib != "" {
ldshlibsyms(ctxt, lib.Shlib)
} else {
if ctxt.BuildMode == BuildModeShared || ctxt.linkShared {
Exitf("cannot implicitly include runtime/cgo in a shared library")
}
loadobjfile(ctxt, lib)
} }
} }
} }
importcycles()
} }
// Set up flags and special symbols depending on the platform build mode. // Set up flags and special symbols depending on the platform build mode.
...@@ -1907,7 +1925,7 @@ func ldshlibsyms(ctxt *Link, shlib string) { ...@@ -1907,7 +1925,7 @@ func ldshlibsyms(ctxt *Link, shlib string) {
ver = sym.SymVerABIInternal ver = sym.SymVerABIInternal
} }
lsym := ctxt.Syms.Lookup(elfsym.Name, ver) lsym := ctxt.LookupOrCreate(elfsym.Name, ver)
// Because loadlib above loads all .a files before loading any shared // Because loadlib above loads all .a files before loading any shared
// libraries, any non-dynimport symbols we find that duplicate symbols // libraries, any non-dynimport symbols we find that duplicate symbols
// already loaded should be ignored (the symbols from the .a files // already loaded should be ignored (the symbols from the .a files
...@@ -2526,17 +2544,10 @@ func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library ...@@ -2526,17 +2544,10 @@ func dfs(lib *sym.Library, mark map[*sym.Library]markKind, order *[]*sym.Library
} }
func (ctxt *Link) loadlibfull() { func (ctxt *Link) loadlibfull() {
// Add references of externally defined symbols.
for _, lib := range ctxt.Library {
for _, r := range lib.Readers {
objfile.LoadRefs(ctxt.loader, r.Reader, lib, ctxt.Arch, ctxt.Syms, r.Version)
}
}
// Load full symbol contents, resolve indexed references. // Load full symbol contents, resolve indexed references.
for _, lib := range ctxt.Library { for _, lib := range ctxt.Library {
for _, r := range lib.Readers { for _, r := range lib.Readers {
objfile.LoadFull(ctxt.loader, r.Reader, lib, ctxt.Syms, r.Version, ctxt.LibraryByPkg) objfile.LoadFull(ctxt.loader, r.Reader, lib, r.Version, ctxt.LibraryByPkg)
} }
} }
...@@ -2546,11 +2557,6 @@ func (ctxt *Link) loadlibfull() { ...@@ -2546,11 +2557,6 @@ func (ctxt *Link) loadlibfull() {
ctxt.Syms.Add(s) ctxt.Syms.Add(s)
} }
} }
// Now load cgo directives.
for _, p := range ctxt.cgodata {
loadcgo(ctxt, p[0], p[1], p[2])
}
} }
func (ctxt *Link) dumpsyms() { func (ctxt *Link) dumpsyms() {
......
...@@ -176,3 +176,32 @@ func addImports(ctxt *Link, l *sym.Library, pn string) { ...@@ -176,3 +176,32 @@ func addImports(ctxt *Link, l *sym.Library, pn string) {
} }
l.ImportStrings = nil l.ImportStrings = nil
} }
// convenient helper during the transition period.
func (ctxt *Link) Lookup(name string, ver int) *sym.Symbol {
if *flagNewobj {
i := ctxt.loader.Lookup(name, ver)
if i == 0 {
return nil
}
return ctxt.loader.Syms[i]
} else {
return ctxt.Syms.ROLookup(name, ver)
}
}
// convenient helper during the transition period.
func (ctxt *Link) LookupOrCreate(name string, ver int) *sym.Symbol {
if *flagNewobj {
i := ctxt.loader.Lookup(name, ver)
if i != 0 {
return ctxt.loader.Syms[i]
}
ctxt.loader.AddExtSym(name, ver)
s := ctxt.Syms.Newsym(name, ver)
ctxt.loader.Syms = append(ctxt.loader.Syms, s)
return s
} else {
return ctxt.Syms.Lookup(name, ver)
}
}
...@@ -209,6 +209,9 @@ func Main(arch *sys.Arch, theArch Arch) { ...@@ -209,6 +209,9 @@ func Main(arch *sys.Arch, theArch Arch) {
ctxt.loadlib() ctxt.loadlib()
deadcode(ctxt) deadcode(ctxt)
if *flagNewobj {
ctxt.loadlibfull() // XXX do it here for now
}
ctxt.linksetup() ctxt.linksetup()
ctxt.dostrdata() ctxt.dostrdata()
......
...@@ -225,7 +225,10 @@ func preprocess(arch *sys.Arch, s *sym.Symbol) { ...@@ -225,7 +225,10 @@ func preprocess(arch *sys.Arch, s *sym.Symbol) {
} }
} }
func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, localSymVersion int, libByPkg map[string]*sym.Library) { // Load relocations for building the dependency graph in deadcode pass.
// For now, we load symbol types, relocations, gotype, and the contents
// of type symbols, which are needed in deadcode.
func LoadReloc(l *Loader, r *goobj2.Reader, lib *sym.Library, localSymVersion int, libByPkg map[string]*sym.Library) {
// PkgIdx // PkgIdx
pkglist := r.Pkglist() pkglist := r.Pkglist()
...@@ -262,7 +265,6 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, ...@@ -262,7 +265,6 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols,
return l.Syms[i] return l.Syms[i]
} }
pcdataBase := r.PcdataBase()
for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ { for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
s := l.Syms[istart+i] s := l.Syms[istart+i]
if s == nil || s.Name == "" { if s == nil || s.Name == "" {
...@@ -272,28 +274,30 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, ...@@ -272,28 +274,30 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols,
osym := goobj2.Sym{} osym := goobj2.Sym{}
osym.Read(r, r.SymOff(i)) osym.Read(r, r.SymOff(i))
name := strings.Replace(osym.Name, "\"\".", pkgprefix, -1) name := strings.Replace(osym.Name, "\"\".", pkgprefix, -1)
if s.Name != name { if s.Name != name { // Sanity check. We can remove it in the final version.
fmt.Println("name mismatch:", lib, i, s.Name, name) fmt.Println("name mismatch:", lib, i, s.Name, name)
panic("name mismatch") panic("name mismatch")
} }
dupok := osym.Flag&goobj2.SymFlagDupok != 0
local := osym.Flag&goobj2.SymFlagLocal != 0
makeTypelink := osym.Flag&goobj2.SymFlagTypelink != 0
nreloc := r.NReloc(i)
datasize := r.DataSize(i)
size := osym.Siz
t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
if s.Type != 0 && s.Type != sym.SXREF { if s.Type != 0 && s.Type != sym.SXREF {
fmt.Println("symbol already processed:", lib, i, s) fmt.Println("symbol already processed:", lib, i, s)
panic("symbol already processed") panic("symbol already processed")
} }
// Symbol data t := sym.AbiSymKindToSymKind[objabi.SymKind(osym.Type)]
s.P = r.BytesAt(r.DataOff(i), datasize) if t == sym.SXREF {
log.Fatalf("bad sxref")
}
if t == 0 {
log.Fatalf("missing type for %s in %s", s.Name, lib)
}
if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
t = s.Type
}
s.Type = t
// Reloc // Reloc
nreloc := r.NReloc(i)
s.R = make([]sym.Reloc, nreloc) s.R = make([]sym.Reloc, nreloc)
for j := range s.R { for j := range s.R {
rel := goobj2.Reloc{} rel := goobj2.Reloc{}
...@@ -307,9 +311,13 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, ...@@ -307,9 +311,13 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols,
} }
} }
// Aux symbol info // XXX deadcode needs symbol data for type symbols. Read it now.
isym := -1 if strings.HasPrefix(name, "type.") {
funcdata := make([]goobj2.SymRef, 0, 4) s.P = r.BytesAt(r.DataOff(i), r.DataSize(i))
s.Size = int64(osym.Siz)
}
// Aux symbol
naux := r.NAux(i) naux := r.NAux(i)
for j := 0; j < naux; j++ { for j := 0; j < naux; j++ {
a := goobj2.Aux{} a := goobj2.Aux{}
...@@ -320,13 +328,115 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, ...@@ -320,13 +328,115 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols,
if typ != nil { if typ != nil {
s.Gotype = typ s.Gotype = typ
} }
case goobj2.AuxFuncdata:
pc := s.FuncInfo
if pc == nil {
pc = &sym.FuncInfo{Funcdata: make([]*sym.Symbol, 0, 4)}
s.FuncInfo = pc
}
pc.Funcdata = append(pc.Funcdata, resolveSymRef(a.Sym))
}
}
if s.Type == sym.STEXT {
dupok := osym.Flag&goobj2.SymFlagDupok != 0
if !dupok {
if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr |= sym.AttrOnList
lib.Textp = append(lib.Textp, s)
} else {
// there may ba a dup in another package
// put into a temp list and add to text later
lib.DupTextSyms = append(lib.DupTextSyms, s)
}
}
}
}
// Load full contents.
// TODO: For now, some contents are already load in LoadReloc. Maybe
// we should combine LoadReloc back into this, once we rewrite deadcode
// pass to use index directly.
func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, localSymVersion int, libByPkg map[string]*sym.Library) {
// PkgIdx
pkglist := r.Pkglist()
pkgprefix := objabi.PathToPrefix(lib.Pkg) + "."
istart := l.StartIndex(r)
resolveSymRef := func(s goobj2.SymRef) *sym.Symbol {
var rr *goobj2.Reader
switch p := s.PkgIdx; p {
case goobj2.PkgIdxInvalid:
if s.SymIdx != 0 {
panic("bad sym ref")
}
return nil
case goobj2.PkgIdxNone:
// Resolve by name
i := int(s.SymIdx) + r.NSym()
osym := goobj2.Sym{}
osym.Read(r, r.SymOff(i))
name := strings.Replace(osym.Name, "\"\".", pkgprefix, -1)
v := abiToVer(osym.ABI, localSymVersion)
nv := nameVer{name, v}
i = l.symsByName[nv]
return l.Syms[i]
case goobj2.PkgIdxSelf:
rr = r
default:
pkg := pkglist[p]
rr = libByPkg[pkg].Readers[0].Reader // typically Readers[0] is go object (others are asm)
}
i := l.ToGlobal(rr, int(s.SymIdx))
return l.Syms[i]
}
pcdataBase := r.PcdataBase()
for i, n := 0, r.NSym()+r.NNonpkgdef(); i < n; i++ {
s := l.Syms[istart+i]
if s == nil || s.Name == "" {
continue
}
if !s.Attr.Reachable() && (s.Type < sym.SDWARFSECT || s.Type > sym.SDWARFLINES) {
// No need to load unreachable symbols.
// XXX DWARF symbols may be used but are not marked reachable.
continue
}
osym := goobj2.Sym{}
osym.Read(r, r.SymOff(i))
name := strings.Replace(osym.Name, "\"\".", pkgprefix, -1)
if s.Name != name { // Sanity check. We can remove it in the final version.
fmt.Println("name mismatch:", lib, i, s.Name, name)
panic("name mismatch")
}
dupok := osym.Flag&goobj2.SymFlagDupok != 0
local := osym.Flag&goobj2.SymFlagLocal != 0
makeTypelink := osym.Flag&goobj2.SymFlagTypelink != 0
datasize := r.DataSize(i)
size := osym.Siz
// Symbol data
s.P = r.BytesAt(r.DataOff(i), datasize)
// Aux symbol info
isym := -1
naux := r.NAux(i)
for j := 0; j < naux; j++ {
a := goobj2.Aux{}
a.Read(r, r.AuxOff(i, j))
switch a.Type {
case goobj2.AuxGotype, goobj2.AuxFuncdata:
// already loaded
case goobj2.AuxFuncInfo: case goobj2.AuxFuncInfo:
if a.Sym.PkgIdx != goobj2.PkgIdxSelf { if a.Sym.PkgIdx != goobj2.PkgIdxSelf {
panic("funcinfo symbol not defined in current package") panic("funcinfo symbol not defined in current package")
} }
isym = int(a.Sym.SymIdx) isym = int(a.Sym.SymIdx)
case goobj2.AuxFuncdata:
funcdata = append(funcdata, a.Sym)
default: default:
panic("unknown aux type") panic("unknown aux type")
} }
...@@ -336,16 +446,6 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, ...@@ -336,16 +446,6 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols,
if dupok { if dupok {
s.Attr |= sym.AttrDuplicateOK s.Attr |= sym.AttrDuplicateOK
} }
if t == sym.SXREF {
log.Fatalf("bad sxref")
}
if t == 0 {
log.Fatalf("missing type for %s in %s", s.Name, lib)
}
if t == sym.SBSS && (s.Type == sym.SRODATA || s.Type == sym.SNOPTRBSS) {
t = s.Type
}
s.Type = t
if s.Size < int64(size) { if s.Size < int64(size) {
s.Size = int64(size) s.Size = int64(size)
} }
...@@ -355,17 +455,6 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, ...@@ -355,17 +455,6 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols,
if s.Type != sym.STEXT { if s.Type != sym.STEXT {
continue continue
} }
if !dupok {
if s.Attr.OnList() {
log.Fatalf("symbol %s listed multiple times", s.Name)
}
s.Attr |= sym.AttrOnList
lib.Textp = append(lib.Textp, s)
} else {
// there may ba a dup in another package
// put into a temp list and add to text later
lib.DupTextSyms = append(lib.DupTextSyms, s)
}
// FuncInfo // FuncInfo
if isym == -1 { if isym == -1 {
...@@ -389,15 +478,16 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, ...@@ -389,15 +478,16 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols,
} }
info.Pcdata = append(info.Pcdata, info.PcdataEnd) // for the ease of knowing where it ends info.Pcdata = append(info.Pcdata, info.PcdataEnd) // for the ease of knowing where it ends
pc := &sym.FuncInfo{ pc := s.FuncInfo
Args: int32(info.Args), if pc == nil {
Locals: int32(info.Locals), pc = &sym.FuncInfo{}
Pcdata: make([]sym.Pcdata, len(info.Pcdata)-1), // -1 as we appended one above s.FuncInfo = pc
Funcdata: make([]*sym.Symbol, len(info.Funcdataoff)), }
Funcdataoff: make([]int64, len(info.Funcdataoff)), pc.Args = int32(info.Args)
File: make([]*sym.Symbol, len(info.File)), pc.Locals = int32(info.Locals)
} pc.Pcdata = make([]sym.Pcdata, len(info.Pcdata)-1) // -1 as we appended one above
s.FuncInfo = pc pc.Funcdataoff = make([]int64, len(info.Funcdataoff))
pc.File = make([]*sym.Symbol, len(info.File))
pc.Pcsp.P = r.BytesAt(pcdataBase+info.Pcsp, int(info.Pcfile-info.Pcsp)) 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.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.Pcline.P = r.BytesAt(pcdataBase+info.Pcline, int(info.Pcinline-info.Pcline))
...@@ -405,8 +495,7 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols, ...@@ -405,8 +495,7 @@ func LoadFull(l *Loader, r *goobj2.Reader, lib *sym.Library, syms *sym.Symbols,
for k := range pc.Pcdata { for k := range pc.Pcdata {
pc.Pcdata[k].P = r.BytesAt(pcdataBase+info.Pcdata[k], int(info.Pcdata[k+1]-info.Pcdata[k])) pc.Pcdata[k].P = r.BytesAt(pcdataBase+info.Pcdata[k], int(info.Pcdata[k+1]-info.Pcdata[k]))
} }
for k := range pc.Funcdata { for k := range pc.Funcdataoff {
pc.Funcdata[k] = resolveSymRef(funcdata[k])
pc.Funcdataoff[k] = int64(info.Funcdataoff[k]) pc.Funcdataoff[k] = int64(info.Funcdataoff[k])
} }
for k := range pc.File { for k := range pc.File {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment