[dev.link] cmd/link: convert symtab pass to new style

This is more or less a direct translation, to get things going.
There are more things we can do to make it better, especially on
the handling of container symbols.

Change-Id: I11a0087e402be8d42b9d06869385ead531755272
Reviewed-on: https://go-review.googlesource.com/c/go/+/229125
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
This commit is contained in:
Cherry Zhang 2020-04-20 18:42:35 -04:00
parent 5cccd7a724
commit 47cac82e36
7 changed files with 292 additions and 248 deletions

View file

@ -1145,26 +1145,26 @@ func Addstring(s *sym.Symbol, str string) int64 {
// addgostring adds str, as a Go string value, to s. symname is the name of the // addgostring adds str, as a Go string value, to s. symname is the name of the
// symbol used to define the string data and must be unique per linked object. // symbol used to define the string data and must be unique per linked object.
func addgostring(ctxt *Link, s *sym.Symbol, symname, str string) { func addgostring(ctxt *Link, ldr *loader.Loader, s *loader.SymbolBuilder, symname, str string) {
sdata := ctxt.Syms.Lookup(symname, 0) sdata := ldr.CreateSymForUpdate(symname, 0)
if sdata.Type != sym.Sxxx { if sdata.Type() != sym.Sxxx {
Errorf(s, "duplicate symname in addgostring: %s", symname) ctxt.Errorf(s.Sym(), "duplicate symname in addgostring: %s", symname)
} }
sdata.Attr |= sym.AttrReachable sdata.SetReachable(true)
sdata.Attr |= sym.AttrLocal sdata.SetLocal(true)
sdata.Type = sym.SRODATA sdata.SetType(sym.SRODATA)
sdata.Size = int64(len(str)) sdata.SetSize(int64(len(str)))
sdata.P = []byte(str) sdata.SetData([]byte(str))
s.AddAddr(ctxt.Arch, sdata) s.AddAddr(ctxt.Arch, sdata.Sym())
s.AddUint(ctxt.Arch, uint64(len(str))) s.AddUint(ctxt.Arch, uint64(len(str)))
} }
func addinitarrdata(ctxt *Link, s *sym.Symbol) { func addinitarrdata(ctxt *Link, ldr *loader.Loader, s loader.Sym) {
p := s.Name + ".ptr" p := ldr.SymName(s) + ".ptr"
sp := ctxt.Syms.Lookup(p, 0) sp := ldr.CreateSymForUpdate(p, 0)
sp.Type = sym.SINITARR sp.SetType(sym.SINITARR)
sp.Size = 0 sp.SetSize(0)
sp.Attr |= sym.AttrDuplicateOK sp.SetDuplicateOK(true)
sp.AddAddr(ctxt.Arch, s) sp.AddAddr(ctxt.Arch, s)
} }

View file

@ -2627,6 +2627,16 @@ func (ctxt *Link) xdefine(p string, t sym.SymKind, v int64) {
s.Attr |= sym.AttrLocal s.Attr |= sym.AttrLocal
} }
func (ctxt *Link) xdefine2(p string, t sym.SymKind, v int64) {
ldr := ctxt.loader
s := ldr.CreateSymForUpdate(p, 0)
s.SetType(t)
s.SetValue(v)
s.SetReachable(true)
s.SetSpecial(true)
s.SetLocal(true)
}
func datoff(s *sym.Symbol, addr int64) int64 { func datoff(s *sym.Symbol, addr int64) int64 {
if uint64(addr) >= Segdata.Vaddr { if uint64(addr) >= Segdata.Vaddr {
return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff) return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
@ -2816,10 +2826,6 @@ func (ctxt *Link) loadlibfull() {
// Set special global symbols. // Set special global symbols.
ctxt.setArchSyms(AfterLoadlibFull) ctxt.setArchSyms(AfterLoadlibFull)
// Convert special symbols created by pcln.
pclntabFirstFunc = ctxt.loader.Syms[pclntabFirstFunc2]
pclntabLastFunc = ctxt.loader.Syms[pclntabLastFunc2]
// Populate dwarfp from dwarfp2. If we see a symbol index // Populate dwarfp from dwarfp2. If we see a symbol index
// whose loader.Syms entry is nil, something went wrong. // whose loader.Syms entry is nil, something went wrong.
for _, si := range dwarfp2 { for _, si := range dwarfp2 {
@ -2834,11 +2840,27 @@ func (ctxt *Link) loadlibfull() {
} }
dwarfp = append(dwarfp, dwarfSecInfo2{syms: syms}) dwarfp = append(dwarfp, dwarfSecInfo2{syms: syms})
} }
// For now, overwrite symbol type with its "group" type, as dodata
// expected. Once we converted dodata, this will probably not be
// needed.
for i, t := range symGroupType {
if t != sym.Sxxx {
ctxt.loader.Syms[i].Type = t
}
}
symGroupType = nil
if ctxt.Debugvlog > 1 {
// loadlibfull is likely a good place to dump.
// Only dump under -v=2 and above.
ctxt.dumpsyms()
}
} }
func (ctxt *Link) dumpsyms() { func (ctxt *Link) dumpsyms() {
for _, s := range ctxt.Syms.Allsym { for _, s := range ctxt.Syms.Allsym {
fmt.Printf("%s %s %p %v %v\n", s, s.Type, s, s.Attr.Reachable(), s.Attr.OnList()) fmt.Printf("%s %s reachable=%v onlist=%v outer=%v sub=%v\n", s, s.Type, s.Attr.Reachable(), s.Attr.OnList(), s.Outer, s.Sub)
for i := range s.R { for i := range s.R {
fmt.Println("\t", s.R[i].Type, s.R[i].Sym) fmt.Println("\t", s.R[i].Type, s.R[i].Sym)
} }

View file

@ -300,10 +300,10 @@ func Main(arch *sys.Arch, theArch Arch) {
ctxt.findfunctab(container) ctxt.findfunctab(container)
bench.Start("dwarfGenerateDebugSyms") bench.Start("dwarfGenerateDebugSyms")
dwarfGenerateDebugSyms(ctxt) dwarfGenerateDebugSyms(ctxt)
bench.Start("loadlibfull")
ctxt.loadlibfull() // XXX do it here for now
bench.Start("symtab") bench.Start("symtab")
ctxt.symtab() ctxt.symtab()
bench.Start("loadlibfull")
ctxt.loadlibfull() // XXX do it here for now
bench.Start("dodata") bench.Start("dodata")
ctxt.dodata() ctxt.dodata()
bench.Start("address") bench.Start("address")

View file

@ -234,10 +234,8 @@ func (state *pclnState) genInlTreeSym(fi loader.FuncInfo, arch *sys.Arch) loader
var pclntabNfunc int32 var pclntabNfunc int32
var pclntabFiletabOffset int32 var pclntabFiletabOffset int32
var pclntabPclntabOffset int32 var pclntabPclntabOffset int32
var pclntabFirstFunc *sym.Symbol var pclntabFirstFunc loader.Sym
var pclntabLastFunc *sym.Symbol var pclntabLastFunc loader.Sym
var pclntabFirstFunc2 loader.Sym
var pclntabLastFunc2 loader.Sym
// pclntab generates the pcln table for the link output. Return value // pclntab generates the pcln table for the link output. Return value
// is a bitmap indexed by global symbol that marks 'container' text // is a bitmap indexed by global symbol that marks 'container' text
@ -276,8 +274,8 @@ func (ctxt *Link) pclntab() loader.Bitmap {
continue continue
} }
nfunc++ nfunc++
if pclntabFirstFunc2 == 0 { if pclntabFirstFunc == 0 {
pclntabFirstFunc2 = s pclntabFirstFunc = s
} }
ss := ldr.SymSect(s) ss := ldr.SymSect(s)
if ss != prevSect { if ss != prevSect {
@ -527,7 +525,7 @@ func (ctxt *Link) pclntab() loader.Bitmap {
} }
last := ctxt.Textp2[len(ctxt.Textp2)-1] last := ctxt.Textp2[len(ctxt.Textp2)-1]
pclntabLastFunc2 = last pclntabLastFunc = last
// Final entry of table is just end pc. // Final entry of table is just end pc.
setAddr(ftab, ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), last, ldr.SymSize(last)) setAddr(ftab, ctxt.Arch, 8+int64(ctxt.Arch.PtrSize)+int64(nfunc)*2*int64(ctxt.Arch.PtrSize), last, ldr.SymSize(last))

View file

@ -33,6 +33,7 @@ package ld
import ( import (
"cmd/internal/objabi" "cmd/internal/objabi"
"cmd/internal/sys" "cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym" "cmd/link/internal/sym"
"fmt" "fmt"
"path/filepath" "path/filepath"
@ -271,12 +272,12 @@ func (libs byPkg) Swap(a, b int) {
} }
// Create a table with information on the text sections. // Create a table with information on the text sections.
// Return the symbol of the table, and number of sections.
func textsectionmap(ctxt *Link) uint32 { func textsectionmap(ctxt *Link) (loader.Sym, uint32) {
ldr := ctxt.loader
t := ctxt.Syms.Lookup("runtime.textsectionmap", 0) t := ldr.CreateSymForUpdate("runtime.textsectionmap", 0)
t.Type = sym.SRODATA t.SetType(sym.SRODATA)
t.Attr |= sym.AttrReachable t.SetReachable(true)
nsections := int64(0) nsections := int64(0)
for _, sect := range Segtext.Sections { for _, sect := range Segtext.Sections {
@ -308,107 +309,106 @@ func textsectionmap(ctxt *Link) uint32 {
off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase) off = t.SetUint(ctxt.Arch, off, sect.Vaddr-textbase)
off = t.SetUint(ctxt.Arch, off, sect.Length) off = t.SetUint(ctxt.Arch, off, sect.Length)
if n == 0 { if n == 0 {
s := ctxt.Syms.ROLookup("runtime.text", 0) s := ldr.Lookup("runtime.text", 0)
if s == nil { if s == 0 {
Errorf(nil, "Unable to find symbol runtime.text\n") ctxt.Errorf(s, "Unable to find symbol runtime.text\n")
} }
off = t.SetAddr(ctxt.Arch, off, s) off = t.SetAddr(ctxt.Arch, off, s)
} else { } else {
s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0) s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
if s == nil { if s == 0 {
Errorf(nil, "Unable to find symbol runtime.text.%d\n", n) ctxt.Errorf(s, "Unable to find symbol runtime.text.%d\n", n)
} }
off = t.SetAddr(ctxt.Arch, off, s) off = t.SetAddr(ctxt.Arch, off, s)
} }
n++ n++
} }
return uint32(n) return t.Sym(), uint32(n)
} }
var symGroupType []sym.SymKind // temporarily assign a symbol's "group" type
func (ctxt *Link) symtab() { func (ctxt *Link) symtab() {
if ctxt.HeadType != objabi.Haix { ldr := ctxt.loader
if !ctxt.IsAIX() {
switch ctxt.BuildMode { switch ctxt.BuildMode {
case BuildModeCArchive, BuildModeCShared: case BuildModeCArchive, BuildModeCShared:
s := ctxt.Syms.ROLookup(*flagEntrySymbol, sym.SymVerABI0) s := ldr.Lookup(*flagEntrySymbol, sym.SymVerABI0)
if s != nil { if s != 0 {
addinitarrdata(ctxt, s) addinitarrdata(ctxt, ldr, s)
} }
} }
} }
// Define these so that they'll get put into the symbol table. // Define these so that they'll get put into the symbol table.
// data.c:/^address will provide the actual values. // data.c:/^address will provide the actual values.
ctxt.xdefine("runtime.text", sym.STEXT, 0) ctxt.xdefine2("runtime.text", sym.STEXT, 0)
ctxt.xdefine2("runtime.etext", sym.STEXT, 0)
ctxt.xdefine("runtime.etext", sym.STEXT, 0) ctxt.xdefine2("runtime.itablink", sym.SRODATA, 0)
ctxt.xdefine("runtime.itablink", sym.SRODATA, 0) ctxt.xdefine2("runtime.eitablink", sym.SRODATA, 0)
ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0) ctxt.xdefine2("runtime.rodata", sym.SRODATA, 0)
ctxt.xdefine("runtime.rodata", sym.SRODATA, 0) ctxt.xdefine2("runtime.erodata", sym.SRODATA, 0)
ctxt.xdefine("runtime.erodata", sym.SRODATA, 0) ctxt.xdefine2("runtime.types", sym.SRODATA, 0)
ctxt.xdefine("runtime.types", sym.SRODATA, 0) ctxt.xdefine2("runtime.etypes", sym.SRODATA, 0)
ctxt.xdefine("runtime.etypes", sym.SRODATA, 0) ctxt.xdefine2("runtime.noptrdata", sym.SNOPTRDATA, 0)
ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0) ctxt.xdefine2("runtime.enoptrdata", sym.SNOPTRDATA, 0)
ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0) ctxt.xdefine2("runtime.data", sym.SDATA, 0)
ctxt.xdefine("runtime.data", sym.SDATA, 0) ctxt.xdefine2("runtime.edata", sym.SDATA, 0)
ctxt.xdefine("runtime.edata", sym.SDATA, 0) ctxt.xdefine2("runtime.bss", sym.SBSS, 0)
ctxt.xdefine("runtime.bss", sym.SBSS, 0) ctxt.xdefine2("runtime.ebss", sym.SBSS, 0)
ctxt.xdefine("runtime.ebss", sym.SBSS, 0) ctxt.xdefine2("runtime.noptrbss", sym.SNOPTRBSS, 0)
ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0) ctxt.xdefine2("runtime.enoptrbss", sym.SNOPTRBSS, 0)
ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0) ctxt.xdefine2("runtime.end", sym.SBSS, 0)
ctxt.xdefine("runtime.end", sym.SBSS, 0) ctxt.xdefine2("runtime.epclntab", sym.SRODATA, 0)
ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0) ctxt.xdefine2("runtime.esymtab", sym.SRODATA, 0)
ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
// garbage collection symbols // garbage collection symbols
s := ctxt.Syms.Lookup("runtime.gcdata", 0) s := ldr.CreateSymForUpdate("runtime.gcdata", 0)
s.SetType(sym.SRODATA)
s.SetSize(0)
s.SetReachable(true)
ctxt.xdefine2("runtime.egcdata", sym.SRODATA, 0)
s.Type = sym.SRODATA s = ldr.CreateSymForUpdate("runtime.gcbss", 0)
s.Size = 0 s.SetType(sym.SRODATA)
s.Attr |= sym.AttrReachable s.SetSize(0)
ctxt.xdefine("runtime.egcdata", sym.SRODATA, 0) s.SetReachable(true)
ctxt.xdefine2("runtime.egcbss", sym.SRODATA, 0)
s = ctxt.Syms.Lookup("runtime.gcbss", 0)
s.Type = sym.SRODATA
s.Size = 0
s.Attr |= sym.AttrReachable
ctxt.xdefine("runtime.egcbss", sym.SRODATA, 0)
// pseudo-symbols to mark locations of type, string, and go string data. // pseudo-symbols to mark locations of type, string, and go string data.
var symtype *sym.Symbol var symtype, symtyperel loader.Sym
var symtyperel *sym.Symbol
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) { if ctxt.UseRelro() && (ctxt.BuildMode == BuildModeCArchive || ctxt.BuildMode == BuildModeCShared || ctxt.BuildMode == BuildModePIE) {
s = ctxt.Syms.Lookup("type.*", 0) s = ldr.CreateSymForUpdate("type.*", 0)
s.SetType(sym.STYPE)
s.SetSize(0)
s.SetReachable(true)
symtype = s.Sym()
s.Type = sym.STYPE s = ldr.CreateSymForUpdate("typerel.*", 0)
s.Size = 0 s.SetType(sym.STYPERELRO)
s.Attr |= sym.AttrReachable s.SetSize(0)
symtype = s s.SetReachable(true)
symtyperel = s.Sym()
s = ctxt.Syms.Lookup("typerel.*", 0)
s.Type = sym.STYPERELRO
s.Size = 0
s.Attr |= sym.AttrReachable
symtyperel = s
} else { } else {
s = ctxt.Syms.Lookup("type.*", 0) s = ldr.CreateSymForUpdate("type.*", 0)
s.SetType(sym.STYPE)
s.Type = sym.STYPE s.SetSize(0)
s.Size = 0 s.SetReachable(true)
s.Attr |= sym.AttrReachable symtype = s.Sym()
symtype = s symtyperel = s.Sym()
symtyperel = s
} }
} }
groupSym := func(name string, t sym.SymKind) *sym.Symbol { groupSym := func(name string, t sym.SymKind) loader.Sym {
s := ctxt.Syms.Lookup(name, 0) s := ldr.CreateSymForUpdate(name, 0)
s.Type = t s.SetType(t)
s.Size = 0 s.SetSize(0)
s.Attr |= sym.AttrLocal | sym.AttrReachable s.SetLocal(true)
return s s.SetReachable(true)
return s.Sym()
} }
var ( var (
symgostring = groupSym("go.string.*", sym.SGOSTRING) symgostring = groupSym("go.string.*", sym.SGOSTRING)
@ -416,7 +416,7 @@ func (ctxt *Link) symtab() {
symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS) symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS)
) )
var symgofuncrel *sym.Symbol var symgofuncrel loader.Sym
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
if ctxt.UseRelro() { if ctxt.UseRelro() {
symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO) symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
@ -425,14 +425,14 @@ func (ctxt *Link) symtab() {
} }
} }
symitablink := ctxt.Syms.Lookup("runtime.itablink", 0) symitablink := ldr.CreateSymForUpdate("runtime.itablink", 0)
symitablink.Type = sym.SITABLINK symitablink.SetType(sym.SITABLINK)
symt := ctxt.Syms.Lookup("runtime.symtab", 0) symt := ldr.CreateSymForUpdate("runtime.symtab", 0)
symt.Attr |= sym.AttrLocal symt.SetType(sym.SSYMTAB)
symt.Type = sym.SSYMTAB symt.SetSize(0)
symt.Size = 0 symt.SetReachable(true)
symt.Attr |= sym.AttrReachable symt.SetLocal(true)
nitablinks := 0 nitablinks := 0
@ -440,147 +440,150 @@ func (ctxt *Link) symtab() {
// within a type they sort by size, so the .* symbols // within a type they sort by size, so the .* symbols
// just defined above will be first. // just defined above will be first.
// hide the specific symbols. // hide the specific symbols.
for _, s := range ctxt.Syms.Allsym { nsym := loader.Sym(ldr.NSym())
if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) { symGroupType = make([]sym.SymKind, nsym)
s.Attr |= sym.AttrNotInSymbolTable for s := loader.Sym(1); s < nsym; s++ {
name := ldr.SymName(s)
if !ctxt.IsExternal() && isStaticTemp(name) {
ldr.SetAttrNotInSymbolTable(s, true)
} }
if !s.Attr.Reachable() || s.Attr.Special() || if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) {
(s.Type != sym.SRODATA && s.Type != sym.SGOFUNC) {
continue continue
} }
switch { switch {
case strings.HasPrefix(s.Name, "type."): case strings.HasPrefix(name, "type."):
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
s.Attr |= sym.AttrNotInSymbolTable ldr.SetAttrNotInSymbolTable(s, true)
} }
if ctxt.UseRelro() { if ctxt.UseRelro() {
s.Type = sym.STYPERELRO symGroupType[s] = sym.STYPERELRO
s.Outer = symtyperel ldr.SetOuterSym(s, symtyperel)
} else { } else {
s.Type = sym.STYPE symGroupType[s] = sym.STYPE
s.Outer = symtype ldr.SetOuterSym(s, symtype)
} }
case strings.HasPrefix(s.Name, "go.importpath.") && ctxt.UseRelro(): case strings.HasPrefix(name, "go.importpath.") && ctxt.UseRelro():
// Keep go.importpath symbols in the same section as types and // Keep go.importpath symbols in the same section as types and
// names, as they can be referred to by a section offset. // names, as they can be referred to by a section offset.
s.Type = sym.STYPERELRO symGroupType[s] = sym.STYPERELRO
case strings.HasPrefix(s.Name, "go.itablink."): case strings.HasPrefix(name, "go.itablink."):
nitablinks++ nitablinks++
s.Type = sym.SITABLINK symGroupType[s] = sym.SITABLINK
s.Attr |= sym.AttrNotInSymbolTable ldr.SetAttrNotInSymbolTable(s, true)
s.Outer = symitablink ldr.SetOuterSym(s, symitablink.Sym())
case strings.HasPrefix(s.Name, "go.string."): case strings.HasPrefix(name, "go.string."):
s.Type = sym.SGOSTRING symGroupType[s] = sym.SGOSTRING
s.Attr |= sym.AttrNotInSymbolTable ldr.SetAttrNotInSymbolTable(s, true)
s.Outer = symgostring ldr.SetOuterSym(s, symgostring)
case strings.HasPrefix(s.Name, "runtime.gcbits."): case strings.HasPrefix(name, "runtime.gcbits."):
s.Type = sym.SGCBITS symGroupType[s] = sym.SGCBITS
s.Attr |= sym.AttrNotInSymbolTable ldr.SetAttrNotInSymbolTable(s, true)
s.Outer = symgcbits ldr.SetOuterSym(s, symgcbits)
case strings.HasSuffix(s.Name, "·f"): case strings.HasSuffix(name, "·f"):
if !ctxt.DynlinkingGo() { if !ctxt.DynlinkingGo() {
s.Attr |= sym.AttrNotInSymbolTable ldr.SetAttrNotInSymbolTable(s, true)
} }
if ctxt.UseRelro() { if ctxt.UseRelro() {
s.Type = sym.SGOFUNCRELRO symGroupType[s] = sym.SGOFUNCRELRO
s.Outer = symgofuncrel ldr.SetOuterSym(s, symgofuncrel)
} else { } else {
s.Type = sym.SGOFUNC symGroupType[s] = sym.SGOFUNC
s.Outer = symgofunc ldr.SetOuterSym(s, symgofunc)
} }
case strings.HasPrefix(s.Name, "gcargs."), case strings.HasPrefix(name, "gcargs."),
strings.HasPrefix(s.Name, "gclocals."), strings.HasPrefix(name, "gclocals."),
strings.HasPrefix(s.Name, "gclocals·"), strings.HasPrefix(name, "gclocals·"),
s.Type == sym.SGOFUNC && s != symgofunc, ldr.SymType(s) == sym.SGOFUNC && s != symgofunc,
strings.HasSuffix(s.Name, ".opendefer"): strings.HasSuffix(name, ".opendefer"):
s.Type = sym.SGOFUNC symGroupType[s] = sym.SGOFUNC
s.Attr |= sym.AttrNotInSymbolTable ldr.SetAttrNotInSymbolTable(s, true)
s.Outer = symgofunc ldr.SetOuterSym(s, symgofunc)
s.Align = 4 const align = 4
liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) ldr.SetSymAlign(s, align)
liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)
} }
} }
if ctxt.BuildMode == BuildModeShared { if ctxt.BuildMode == BuildModeShared {
abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0) abihashgostr := ldr.CreateSymForUpdate("go.link.abihash."+filepath.Base(*flagOutfile), 0)
abihashgostr.Attr |= sym.AttrReachable abihashgostr.SetReachable(true)
abihashgostr.Type = sym.SRODATA abihashgostr.SetType(sym.SRODATA)
hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0) hashsym := ldr.LookupOrCreateSym("go.link.abihashbytes", 0)
abihashgostr.AddAddr(ctxt.Arch, hashsym) abihashgostr.AddAddr(ctxt.Arch, hashsym)
abihashgostr.AddUint(ctxt.Arch, uint64(hashsym.Size)) abihashgostr.AddUint(ctxt.Arch, uint64(ldr.SymSize(hashsym)))
} }
if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() { if ctxt.BuildMode == BuildModePlugin || ctxt.CanUsePlugins() {
for _, l := range ctxt.Library { for _, l := range ctxt.Library {
s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0) s := ldr.CreateSymForUpdate("go.link.pkghashbytes."+l.Pkg, 0)
s.Attr |= sym.AttrReachable s.SetReachable(true)
s.Type = sym.SRODATA s.SetType(sym.SRODATA)
s.Size = int64(len(l.Hash)) s.SetSize(int64(len(l.Hash)))
s.P = []byte(l.Hash) s.SetData([]byte(l.Hash))
str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0) str := ldr.CreateSymForUpdate("go.link.pkghash."+l.Pkg, 0)
str.Attr |= sym.AttrReachable str.SetReachable(true)
str.Type = sym.SRODATA str.SetType(sym.SRODATA)
str.AddAddr(ctxt.Arch, s) str.AddAddr(ctxt.Arch, s.Sym())
str.AddUint(ctxt.Arch, uint64(len(l.Hash))) str.AddUint(ctxt.Arch, uint64(len(l.Hash)))
} }
} }
nsections := textsectionmap(ctxt) textsectionmapSym, nsections := textsectionmap(ctxt)
// Information about the layout of the executable image for the // Information about the layout of the executable image for the
// runtime to use. Any changes here must be matched by changes to // runtime to use. Any changes here must be matched by changes to
// the definition of moduledata in runtime/symtab.go. // the definition of moduledata in runtime/symtab.go.
// This code uses several global variables that are set by pcln.go:pclntab. // This code uses several global variables that are set by pcln.go:pclntab.
moduledata := ctxt.Moduledata moduledata := ldr.MakeSymbolUpdater(ctxt.Moduledata2)
pclntab := ldr.Lookup("runtime.pclntab", 0)
// The pclntab slice // The pclntab slice
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0)) moduledata.AddAddr(ctxt.Arch, pclntab)
moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pclntab)))
moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size)) moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pclntab)))
// The ftab slice // The ftab slice
moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabPclntabOffset)) moduledata.AddAddrPlus(ctxt.Arch, pclntab, int64(pclntabPclntabOffset))
moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1)) moduledata.AddUint(ctxt.Arch, uint64(pclntabNfunc+1))
// The filetab slice // The filetab slice
moduledata.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0), int64(pclntabFiletabOffset)) moduledata.AddAddrPlus(ctxt.Arch, pclntab, int64(pclntabFiletabOffset))
moduledata.AddUint(ctxt.Arch, uint64(ctxt.NumFilesyms)+1) moduledata.AddUint(ctxt.Arch, uint64(ctxt.NumFilesyms)+1)
moduledata.AddUint(ctxt.Arch, uint64(ctxt.NumFilesyms)+1) moduledata.AddUint(ctxt.Arch, uint64(ctxt.NumFilesyms)+1)
// findfunctab // findfunctab
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.findfunctab", 0))
// minpc, maxpc // minpc, maxpc
moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc) moduledata.AddAddr(ctxt.Arch, pclntabFirstFunc)
moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, pclntabLastFunc.Size) moduledata.AddAddrPlus(ctxt.Arch, pclntabLastFunc, ldr.SymSize(pclntabLastFunc))
// pointers to specific parts of the module // pointers to specific parts of the module
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.text", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etext", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrdata", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrdata", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.edata", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.bss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ebss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrbss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrbss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.end", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcdata", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0))
if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal { if ctxt.IsAIX() && ctxt.IsExternal() {
// Add R_REF relocation to prevent ld's garbage collection of // Add R_XCOFFREF relocation to prevent ld's garbage collection of
// runtime.rodata, runtime.erodata and runtime.epclntab. // runtime.rodata, runtime.erodata and runtime.epclntab.
addRef := func(name string) { addRef := func(name string) {
r := moduledata.AddRel() r, _ := moduledata.AddRel(objabi.R_XCOFFREF)
r.Sym = ctxt.Syms.Lookup(name, 0) r.SetSym(ldr.Lookup(name, 0))
r.Type = objabi.R_XCOFFREF r.SetSiz(uint8(ctxt.Arch.PtrSize))
r.Siz = uint8(ctxt.Arch.PtrSize)
} }
addRef("runtime.rodata") addRef("runtime.rodata")
addRef("runtime.erodata") addRef("runtime.erodata")
@ -588,26 +591,27 @@ func (ctxt *Link) symtab() {
} }
// text section information // text section information
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.textsectionmap", 0)) moduledata.AddAddr(ctxt.Arch, textsectionmapSym)
moduledata.AddUint(ctxt.Arch, uint64(nsections)) moduledata.AddUint(ctxt.Arch, uint64(nsections))
moduledata.AddUint(ctxt.Arch, uint64(nsections)) moduledata.AddUint(ctxt.Arch, uint64(nsections))
// The typelinks slice // The typelinks slice
typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0) typelinkSym := ldr.Lookup("runtime.typelink", 0)
ntypelinks := uint64(typelinkSym.Size) / 4 ntypelinks := uint64(ldr.SymSize(typelinkSym)) / 4
moduledata.AddAddr(ctxt.Arch, typelinkSym) moduledata.AddAddr(ctxt.Arch, typelinkSym)
moduledata.AddUint(ctxt.Arch, ntypelinks) moduledata.AddUint(ctxt.Arch, ntypelinks)
moduledata.AddUint(ctxt.Arch, ntypelinks) moduledata.AddUint(ctxt.Arch, ntypelinks)
// The itablinks slice // The itablinks slice
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.itablink", 0)) moduledata.AddAddr(ctxt.Arch, symitablink.Sym())
moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
moduledata.AddUint(ctxt.Arch, uint64(nitablinks)) moduledata.AddUint(ctxt.Arch, uint64(nitablinks))
// The ptab slice // The ptab slice
if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() { if ptab := ldr.Lookup("go.plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) {
ptab.Attr |= sym.AttrLocal ldr.SetAttrLocal(ptab, true)
ptab.Type = sym.SRODATA if ldr.SymType(ptab) != sym.SRODATA {
panic(fmt.Sprintf("go.plugin.tabs is %v, not SRODATA", ldr.SymType(ptab)))
nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff) }
nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff)
moduledata.AddAddr(ctxt.Arch, ptab) moduledata.AddAddr(ctxt.Arch, ptab)
moduledata.AddUint(ctxt.Arch, nentries) moduledata.AddUint(ctxt.Arch, nentries)
moduledata.AddUint(ctxt.Arch, nentries) moduledata.AddUint(ctxt.Arch, nentries)
@ -617,23 +621,23 @@ func (ctxt *Link) symtab() {
moduledata.AddUint(ctxt.Arch, 0) moduledata.AddUint(ctxt.Arch, 0)
} }
if ctxt.BuildMode == BuildModePlugin { if ctxt.BuildMode == BuildModePlugin {
addgostring(ctxt, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath)) addgostring(ctxt, ldr, moduledata, "go.link.thispluginpath", objabi.PathToPrefix(*flagPluginPath))
pkghashes := ctxt.Syms.Lookup("go.link.pkghashes", 0) pkghashes := ldr.CreateSymForUpdate("go.link.pkghashes", 0)
pkghashes.Attr |= sym.AttrReachable pkghashes.SetReachable(true)
pkghashes.Attr |= sym.AttrLocal pkghashes.SetLocal(true)
pkghashes.Type = sym.SRODATA pkghashes.SetType(sym.SRODATA)
for i, l := range ctxt.Library { for i, l := range ctxt.Library {
// pkghashes[i].name // pkghashes[i].name
addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg) addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkgname.%d", i), l.Pkg)
// pkghashes[i].linktimehash // pkghashes[i].linktimehash
addgostring(ctxt, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash) addgostring(ctxt, ldr, pkghashes, fmt.Sprintf("go.link.pkglinkhash.%d", i), l.Hash)
// pkghashes[i].runtimehash // pkghashes[i].runtimehash
hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0) hash := ldr.Lookup("go.link.pkghash."+l.Pkg, 0)
pkghashes.AddAddr(ctxt.Arch, hash) pkghashes.AddAddr(ctxt.Arch, hash)
} }
moduledata.AddAddr(ctxt.Arch, pkghashes) moduledata.AddAddr(ctxt.Arch, pkghashes.Sym())
moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library))) moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Library)))
} else { } else {
@ -651,28 +655,28 @@ func (ctxt *Link) symtab() {
// it something slightly more comprehensible. // it something slightly more comprehensible.
thismodulename = "the executable" thismodulename = "the executable"
} }
addgostring(ctxt, moduledata, "go.link.thismodulename", thismodulename) addgostring(ctxt, ldr, moduledata, "go.link.thismodulename", thismodulename)
modulehashes := ctxt.Syms.Lookup("go.link.abihashes", 0) modulehashes := ldr.CreateSymForUpdate("go.link.abihashes", 0)
modulehashes.Attr |= sym.AttrReachable modulehashes.SetReachable(true)
modulehashes.Attr |= sym.AttrLocal modulehashes.SetLocal(true)
modulehashes.Type = sym.SRODATA modulehashes.SetType(sym.SRODATA)
for i, shlib := range ctxt.Shlibs { for i, shlib := range ctxt.Shlibs {
// modulehashes[i].modulename // modulehashes[i].modulename
modulename := filepath.Base(shlib.Path) modulename := filepath.Base(shlib.Path)
addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename) addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go.link.libname.%d", i), modulename)
// modulehashes[i].linktimehash // modulehashes[i].linktimehash
addgostring(ctxt, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash)) addgostring(ctxt, ldr, modulehashes, fmt.Sprintf("go.link.linkhash.%d", i), string(shlib.Hash))
// modulehashes[i].runtimehash // modulehashes[i].runtimehash
abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0) abihash := ldr.LookupOrCreateSym("go.link.abihash."+modulename, 0)
abihash.Attr |= sym.AttrReachable ldr.SetAttrReachable(abihash, true)
modulehashes.AddAddr(ctxt.Arch, abihash) modulehashes.AddAddr(ctxt.Arch, abihash)
} }
moduledata.AddAddr(ctxt.Arch, modulehashes) moduledata.AddAddr(ctxt.Arch, modulehashes.Sym())
moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs))) moduledata.AddUint(ctxt.Arch, uint64(len(ctxt.Shlibs)))
} else { } else {
@ -694,15 +698,16 @@ func (ctxt *Link) symtab() {
// When linking an object that does not contain the runtime we are // When linking an object that does not contain the runtime we are
// creating the moduledata from scratch and it does not have a // creating the moduledata from scratch and it does not have a
// compiler-provided size, so read it from the type data. // compiler-provided size, so read it from the type data.
moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0) moduledatatype := ldr.Lookup("type.runtime.moduledata", 0)
moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype.P) moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype)))
moduledata.Grow(moduledata.Size) moduledata.Grow(moduledata.Size())
lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0) lastmoduledatap := ldr.CreateSymForUpdate("runtime.lastmoduledatap", 0)
if lastmoduledatap.Type != sym.SDYNIMPORT { if lastmoduledatap.Type() != sym.SDYNIMPORT {
lastmoduledatap.Type = sym.SNOPTRDATA lastmoduledatap.SetType(sym.SNOPTRDATA)
lastmoduledatap.Size = 0 // overwrite existing value lastmoduledatap.SetSize(0) // overwrite existing value
lastmoduledatap.AddAddr(ctxt.Arch, moduledata) lastmoduledatap.SetData(nil)
lastmoduledatap.AddAddr(ctxt.Arch, moduledata.Sym())
} }
} }

View file

@ -1398,6 +1398,16 @@ func (l *Loader) SubSym(i Sym) Sym {
return l.sub[i] 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. // Initialize Reachable bitmap and its siblings for running deadcode pass.
func (l *Loader) InitReachable() { func (l *Loader) InitReachable() {
l.growAttrBitmaps(l.NSym() + 1) l.growAttrBitmaps(l.NSym() + 1)
@ -2225,8 +2235,7 @@ func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
continue continue
} }
s := l.addNewSym(gi, name, ver, r.unit, t) l.addNewSym(gi, name, ver, r.unit, t)
l.migrateAttributes(gi, s)
nr += r.NReloc(i) nr += r.NReloc(i)
} }
return nr return nr
@ -2378,10 +2387,19 @@ func (l *Loader) migrateAttributes(src Sym, dst *sym.Symbol) {
dst.Sub = l.Syms[sub] dst.Sub = l.Syms[sub]
} }
// Set sub-symbol attribute. FIXME: would be better to do away // Set sub-symbol attribute.
// with this and just use l.OuterSymbol() != 0 elsewhere within //
// the linker. // In sym.Symbols world, it uses Outer to record container symbols.
dst.Attr.Set(sym.AttrSubSymbol, dst.Outer != nil) // Currently there are two kinds
// - 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!)
//
// FIXME: would be better to do away with this and have a better way
// to represent container symbols.
dst.Attr.Set(sym.AttrSubSymbol, l.outer[src] != 0 && l.sub[l.outer[src]] != 0)
// Copy over dynimplib, dynimpvers, extname. // Copy over dynimplib, dynimpvers, extname.
if name, ok := l.extname[src]; ok { if name, ok := l.extname[src]; ok {
@ -2448,10 +2466,11 @@ func loadObjFull(l *Loader, r *oReader) {
continue continue
} }
l.migrateAttributes(gi, s)
// Be careful not to overwrite attributes set by the linker.
// Don't use the attributes from the object file.
osym := r.Sym(i) osym := r.Sym(i)
dupok := osym.Dupok()
local := osym.Local()
makeTypelink := osym.Typelink()
size := osym.Siz() size := osym.Siz()
// Symbol data // Symbol data
@ -2485,14 +2504,9 @@ func loadObjFull(l *Loader, r *oReader) {
} }
s.File = r.pkgprefix[:len(r.pkgprefix)-1] s.File = r.pkgprefix[:len(r.pkgprefix)-1]
if dupok {
s.Attr |= sym.AttrDuplicateOK
}
if s.Size < int64(size) { if s.Size < int64(size) {
s.Size = int64(size) s.Size = int64(size)
} }
s.Attr.Set(sym.AttrLocal, local)
s.Attr.Set(sym.AttrMakeTypelink, makeTypelink)
} }
} }

View file

@ -107,6 +107,7 @@ func (sb *SymbolBuilder) SetDynimpvers(value string) { sb.l.SetSymDynimpvers(sb.
func (sb *SymbolBuilder) SetPlt(value int32) { sb.l.SetPlt(sb.symIdx, value) } func (sb *SymbolBuilder) SetPlt(value int32) { sb.l.SetPlt(sb.symIdx, value) }
func (sb *SymbolBuilder) SetGot(value int32) { sb.l.SetGot(sb.symIdx, value) } func (sb *SymbolBuilder) SetGot(value int32) { sb.l.SetGot(sb.symIdx, value) }
func (sb *SymbolBuilder) SetSpecial(value bool) { sb.l.SetAttrSpecial(sb.symIdx, value) } func (sb *SymbolBuilder) SetSpecial(value bool) { sb.l.SetAttrSpecial(sb.symIdx, value) }
func (sb *SymbolBuilder) SetLocal(value bool) { sb.l.SetAttrLocal(sb.symIdx, value) }
func (sb *SymbolBuilder) SetVisibilityHidden(value bool) { func (sb *SymbolBuilder) SetVisibilityHidden(value bool) {
sb.l.SetAttrVisibilityHidden(sb.symIdx, value) sb.l.SetAttrVisibilityHidden(sb.symIdx, value)
} }
@ -334,6 +335,10 @@ func (sb *SymbolBuilder) SetAddrPlus(arch *sys.Arch, off int64, tgt Sym, add int
return off + int64(r.Size) return off + int64(r.Size)
} }
func (sb *SymbolBuilder) SetAddr(arch *sys.Arch, off int64, tgt Sym) int64 {
return sb.SetAddrPlus(arch, off, tgt, 0)
}
func (sb *SymbolBuilder) Addstring(str string) int64 { func (sb *SymbolBuilder) Addstring(str string) int64 {
sb.setReachable() sb.setReachable()
if sb.kind == 0 { if sb.kind == 0 {