1
0
mirror of https://github.com/golang/go synced 2024-11-23 20:00:04 -07:00

[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
// symbol used to define the string data and must be unique per linked object.
func addgostring(ctxt *Link, s *sym.Symbol, symname, str string) {
sdata := ctxt.Syms.Lookup(symname, 0)
if sdata.Type != sym.Sxxx {
Errorf(s, "duplicate symname in addgostring: %s", symname)
func addgostring(ctxt *Link, ldr *loader.Loader, s *loader.SymbolBuilder, symname, str string) {
sdata := ldr.CreateSymForUpdate(symname, 0)
if sdata.Type() != sym.Sxxx {
ctxt.Errorf(s.Sym(), "duplicate symname in addgostring: %s", symname)
}
sdata.Attr |= sym.AttrReachable
sdata.Attr |= sym.AttrLocal
sdata.Type = sym.SRODATA
sdata.Size = int64(len(str))
sdata.P = []byte(str)
s.AddAddr(ctxt.Arch, sdata)
sdata.SetReachable(true)
sdata.SetLocal(true)
sdata.SetType(sym.SRODATA)
sdata.SetSize(int64(len(str)))
sdata.SetData([]byte(str))
s.AddAddr(ctxt.Arch, sdata.Sym())
s.AddUint(ctxt.Arch, uint64(len(str)))
}
func addinitarrdata(ctxt *Link, s *sym.Symbol) {
p := s.Name + ".ptr"
sp := ctxt.Syms.Lookup(p, 0)
sp.Type = sym.SINITARR
sp.Size = 0
sp.Attr |= sym.AttrDuplicateOK
func addinitarrdata(ctxt *Link, ldr *loader.Loader, s loader.Sym) {
p := ldr.SymName(s) + ".ptr"
sp := ldr.CreateSymForUpdate(p, 0)
sp.SetType(sym.SINITARR)
sp.SetSize(0)
sp.SetDuplicateOK(true)
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
}
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 {
if uint64(addr) >= Segdata.Vaddr {
return int64(uint64(addr) - Segdata.Vaddr + Segdata.Fileoff)
@ -2816,10 +2826,6 @@ func (ctxt *Link) loadlibfull() {
// Set special global symbols.
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
// whose loader.Syms entry is nil, something went wrong.
for _, si := range dwarfp2 {
@ -2834,11 +2840,27 @@ func (ctxt *Link) loadlibfull() {
}
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() {
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 {
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)
bench.Start("dwarfGenerateDebugSyms")
dwarfGenerateDebugSyms(ctxt)
bench.Start("loadlibfull")
ctxt.loadlibfull() // XXX do it here for now
bench.Start("symtab")
ctxt.symtab()
bench.Start("loadlibfull")
ctxt.loadlibfull() // XXX do it here for now
bench.Start("dodata")
ctxt.dodata()
bench.Start("address")

View File

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

View File

@ -33,6 +33,7 @@ package ld
import (
"cmd/internal/objabi"
"cmd/internal/sys"
"cmd/link/internal/loader"
"cmd/link/internal/sym"
"fmt"
"path/filepath"
@ -271,12 +272,12 @@ func (libs byPkg) Swap(a, b int) {
}
// Create a table with information on the text sections.
func textsectionmap(ctxt *Link) uint32 {
t := ctxt.Syms.Lookup("runtime.textsectionmap", 0)
t.Type = sym.SRODATA
t.Attr |= sym.AttrReachable
// Return the symbol of the table, and number of sections.
func textsectionmap(ctxt *Link) (loader.Sym, uint32) {
ldr := ctxt.loader
t := ldr.CreateSymForUpdate("runtime.textsectionmap", 0)
t.SetType(sym.SRODATA)
t.SetReachable(true)
nsections := int64(0)
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.Length)
if n == 0 {
s := ctxt.Syms.ROLookup("runtime.text", 0)
if s == nil {
Errorf(nil, "Unable to find symbol runtime.text\n")
s := ldr.Lookup("runtime.text", 0)
if s == 0 {
ctxt.Errorf(s, "Unable to find symbol runtime.text\n")
}
off = t.SetAddr(ctxt.Arch, off, s)
} else {
s := ctxt.Syms.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
if s == nil {
Errorf(nil, "Unable to find symbol runtime.text.%d\n", n)
s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n), 0)
if s == 0 {
ctxt.Errorf(s, "Unable to find symbol runtime.text.%d\n", n)
}
off = t.SetAddr(ctxt.Arch, off, s)
}
n++
}
return uint32(n)
return t.Sym(), uint32(n)
}
var symGroupType []sym.SymKind // temporarily assign a symbol's "group" type
func (ctxt *Link) symtab() {
if ctxt.HeadType != objabi.Haix {
ldr := ctxt.loader
if !ctxt.IsAIX() {
switch ctxt.BuildMode {
case BuildModeCArchive, BuildModeCShared:
s := ctxt.Syms.ROLookup(*flagEntrySymbol, sym.SymVerABI0)
if s != nil {
addinitarrdata(ctxt, s)
s := ldr.Lookup(*flagEntrySymbol, sym.SymVerABI0)
if s != 0 {
addinitarrdata(ctxt, ldr, s)
}
}
}
// Define these so that they'll get put into the symbol table.
// data.c:/^address will provide the actual values.
ctxt.xdefine("runtime.text", sym.STEXT, 0)
ctxt.xdefine("runtime.etext", sym.STEXT, 0)
ctxt.xdefine("runtime.itablink", sym.SRODATA, 0)
ctxt.xdefine("runtime.eitablink", sym.SRODATA, 0)
ctxt.xdefine("runtime.rodata", sym.SRODATA, 0)
ctxt.xdefine("runtime.erodata", sym.SRODATA, 0)
ctxt.xdefine("runtime.types", sym.SRODATA, 0)
ctxt.xdefine("runtime.etypes", sym.SRODATA, 0)
ctxt.xdefine("runtime.noptrdata", sym.SNOPTRDATA, 0)
ctxt.xdefine("runtime.enoptrdata", sym.SNOPTRDATA, 0)
ctxt.xdefine("runtime.data", sym.SDATA, 0)
ctxt.xdefine("runtime.edata", sym.SDATA, 0)
ctxt.xdefine("runtime.bss", sym.SBSS, 0)
ctxt.xdefine("runtime.ebss", sym.SBSS, 0)
ctxt.xdefine("runtime.noptrbss", sym.SNOPTRBSS, 0)
ctxt.xdefine("runtime.enoptrbss", sym.SNOPTRBSS, 0)
ctxt.xdefine("runtime.end", sym.SBSS, 0)
ctxt.xdefine("runtime.epclntab", sym.SRODATA, 0)
ctxt.xdefine("runtime.esymtab", sym.SRODATA, 0)
ctxt.xdefine2("runtime.text", sym.STEXT, 0)
ctxt.xdefine2("runtime.etext", sym.STEXT, 0)
ctxt.xdefine2("runtime.itablink", sym.SRODATA, 0)
ctxt.xdefine2("runtime.eitablink", sym.SRODATA, 0)
ctxt.xdefine2("runtime.rodata", sym.SRODATA, 0)
ctxt.xdefine2("runtime.erodata", sym.SRODATA, 0)
ctxt.xdefine2("runtime.types", sym.SRODATA, 0)
ctxt.xdefine2("runtime.etypes", sym.SRODATA, 0)
ctxt.xdefine2("runtime.noptrdata", sym.SNOPTRDATA, 0)
ctxt.xdefine2("runtime.enoptrdata", sym.SNOPTRDATA, 0)
ctxt.xdefine2("runtime.data", sym.SDATA, 0)
ctxt.xdefine2("runtime.edata", sym.SDATA, 0)
ctxt.xdefine2("runtime.bss", sym.SBSS, 0)
ctxt.xdefine2("runtime.ebss", sym.SBSS, 0)
ctxt.xdefine2("runtime.noptrbss", sym.SNOPTRBSS, 0)
ctxt.xdefine2("runtime.enoptrbss", sym.SNOPTRBSS, 0)
ctxt.xdefine2("runtime.end", sym.SBSS, 0)
ctxt.xdefine2("runtime.epclntab", sym.SRODATA, 0)
ctxt.xdefine2("runtime.esymtab", sym.SRODATA, 0)
// 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.Size = 0
s.Attr |= sym.AttrReachable
ctxt.xdefine("runtime.egcdata", 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)
s = ldr.CreateSymForUpdate("runtime.gcbss", 0)
s.SetType(sym.SRODATA)
s.SetSize(0)
s.SetReachable(true)
ctxt.xdefine2("runtime.egcbss", sym.SRODATA, 0)
// pseudo-symbols to mark locations of type, string, and go string data.
var symtype *sym.Symbol
var symtyperel *sym.Symbol
var symtype, symtyperel loader.Sym
if !ctxt.DynlinkingGo() {
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.Size = 0
s.Attr |= sym.AttrReachable
symtype = s
s = ctxt.Syms.Lookup("typerel.*", 0)
s.Type = sym.STYPERELRO
s.Size = 0
s.Attr |= sym.AttrReachable
symtyperel = s
s = ldr.CreateSymForUpdate("typerel.*", 0)
s.SetType(sym.STYPERELRO)
s.SetSize(0)
s.SetReachable(true)
symtyperel = s.Sym()
} else {
s = ctxt.Syms.Lookup("type.*", 0)
s.Type = sym.STYPE
s.Size = 0
s.Attr |= sym.AttrReachable
symtype = s
symtyperel = s
s = ldr.CreateSymForUpdate("type.*", 0)
s.SetType(sym.STYPE)
s.SetSize(0)
s.SetReachable(true)
symtype = s.Sym()
symtyperel = s.Sym()
}
}
groupSym := func(name string, t sym.SymKind) *sym.Symbol {
s := ctxt.Syms.Lookup(name, 0)
s.Type = t
s.Size = 0
s.Attr |= sym.AttrLocal | sym.AttrReachable
return s
groupSym := func(name string, t sym.SymKind) loader.Sym {
s := ldr.CreateSymForUpdate(name, 0)
s.SetType(t)
s.SetSize(0)
s.SetLocal(true)
s.SetReachable(true)
return s.Sym()
}
var (
symgostring = groupSym("go.string.*", sym.SGOSTRING)
@ -416,7 +416,7 @@ func (ctxt *Link) symtab() {
symgcbits = groupSym("runtime.gcbits.*", sym.SGCBITS)
)
var symgofuncrel *sym.Symbol
var symgofuncrel loader.Sym
if !ctxt.DynlinkingGo() {
if ctxt.UseRelro() {
symgofuncrel = groupSym("go.funcrel.*", sym.SGOFUNCRELRO)
@ -425,14 +425,14 @@ func (ctxt *Link) symtab() {
}
}
symitablink := ctxt.Syms.Lookup("runtime.itablink", 0)
symitablink.Type = sym.SITABLINK
symitablink := ldr.CreateSymForUpdate("runtime.itablink", 0)
symitablink.SetType(sym.SITABLINK)
symt := ctxt.Syms.Lookup("runtime.symtab", 0)
symt.Attr |= sym.AttrLocal
symt.Type = sym.SSYMTAB
symt.Size = 0
symt.Attr |= sym.AttrReachable
symt := ldr.CreateSymForUpdate("runtime.symtab", 0)
symt.SetType(sym.SSYMTAB)
symt.SetSize(0)
symt.SetReachable(true)
symt.SetLocal(true)
nitablinks := 0
@ -440,147 +440,150 @@ func (ctxt *Link) symtab() {
// within a type they sort by size, so the .* symbols
// just defined above will be first.
// hide the specific symbols.
for _, s := range ctxt.Syms.Allsym {
if ctxt.LinkMode != LinkExternal && isStaticTemp(s.Name) {
s.Attr |= sym.AttrNotInSymbolTable
nsym := loader.Sym(ldr.NSym())
symGroupType = make([]sym.SymKind, nsym)
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() ||
(s.Type != sym.SRODATA && s.Type != sym.SGOFUNC) {
if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) {
continue
}
switch {
case strings.HasPrefix(s.Name, "type."):
case strings.HasPrefix(name, "type."):
if !ctxt.DynlinkingGo() {
s.Attr |= sym.AttrNotInSymbolTable
ldr.SetAttrNotInSymbolTable(s, true)
}
if ctxt.UseRelro() {
s.Type = sym.STYPERELRO
s.Outer = symtyperel
symGroupType[s] = sym.STYPERELRO
ldr.SetOuterSym(s, symtyperel)
} else {
s.Type = sym.STYPE
s.Outer = symtype
symGroupType[s] = sym.STYPE
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
// 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++
s.Type = sym.SITABLINK
s.Attr |= sym.AttrNotInSymbolTable
s.Outer = symitablink
symGroupType[s] = sym.SITABLINK
ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetOuterSym(s, symitablink.Sym())
case strings.HasPrefix(s.Name, "go.string."):
s.Type = sym.SGOSTRING
s.Attr |= sym.AttrNotInSymbolTable
s.Outer = symgostring
case strings.HasPrefix(name, "go.string."):
symGroupType[s] = sym.SGOSTRING
ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetOuterSym(s, symgostring)
case strings.HasPrefix(s.Name, "runtime.gcbits."):
s.Type = sym.SGCBITS
s.Attr |= sym.AttrNotInSymbolTable
s.Outer = symgcbits
case strings.HasPrefix(name, "runtime.gcbits."):
symGroupType[s] = sym.SGCBITS
ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetOuterSym(s, symgcbits)
case strings.HasSuffix(s.Name, "·f"):
case strings.HasSuffix(name, "·f"):
if !ctxt.DynlinkingGo() {
s.Attr |= sym.AttrNotInSymbolTable
ldr.SetAttrNotInSymbolTable(s, true)
}
if ctxt.UseRelro() {
s.Type = sym.SGOFUNCRELRO
s.Outer = symgofuncrel
symGroupType[s] = sym.SGOFUNCRELRO
ldr.SetOuterSym(s, symgofuncrel)
} else {
s.Type = sym.SGOFUNC
s.Outer = symgofunc
symGroupType[s] = sym.SGOFUNC
ldr.SetOuterSym(s, symgofunc)
}
case strings.HasPrefix(s.Name, "gcargs."),
strings.HasPrefix(s.Name, "gclocals."),
strings.HasPrefix(s.Name, "gclocals·"),
s.Type == sym.SGOFUNC && s != symgofunc,
strings.HasSuffix(s.Name, ".opendefer"):
s.Type = sym.SGOFUNC
s.Attr |= sym.AttrNotInSymbolTable
s.Outer = symgofunc
s.Align = 4
liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
case strings.HasPrefix(name, "gcargs."),
strings.HasPrefix(name, "gclocals."),
strings.HasPrefix(name, "gclocals·"),
ldr.SymType(s) == sym.SGOFUNC && s != symgofunc,
strings.HasSuffix(name, ".opendefer"):
symGroupType[s] = sym.SGOFUNC
ldr.SetAttrNotInSymbolTable(s, true)
ldr.SetOuterSym(s, symgofunc)
const align = 4
ldr.SetSymAlign(s, align)
liveness += (ldr.SymSize(s) + int64(align) - 1) &^ (int64(align) - 1)
}
}
if ctxt.BuildMode == BuildModeShared {
abihashgostr := ctxt.Syms.Lookup("go.link.abihash."+filepath.Base(*flagOutfile), 0)
abihashgostr.Attr |= sym.AttrReachable
abihashgostr.Type = sym.SRODATA
hashsym := ctxt.Syms.Lookup("go.link.abihashbytes", 0)
abihashgostr := ldr.CreateSymForUpdate("go.link.abihash."+filepath.Base(*flagOutfile), 0)
abihashgostr.SetReachable(true)
abihashgostr.SetType(sym.SRODATA)
hashsym := ldr.LookupOrCreateSym("go.link.abihashbytes", 0)
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() {
for _, l := range ctxt.Library {
s := ctxt.Syms.Lookup("go.link.pkghashbytes."+l.Pkg, 0)
s.Attr |= sym.AttrReachable
s.Type = sym.SRODATA
s.Size = int64(len(l.Hash))
s.P = []byte(l.Hash)
str := ctxt.Syms.Lookup("go.link.pkghash."+l.Pkg, 0)
str.Attr |= sym.AttrReachable
str.Type = sym.SRODATA
str.AddAddr(ctxt.Arch, s)
s := ldr.CreateSymForUpdate("go.link.pkghashbytes."+l.Pkg, 0)
s.SetReachable(true)
s.SetType(sym.SRODATA)
s.SetSize(int64(len(l.Hash)))
s.SetData([]byte(l.Hash))
str := ldr.CreateSymForUpdate("go.link.pkghash."+l.Pkg, 0)
str.SetReachable(true)
str.SetType(sym.SRODATA)
str.AddAddr(ctxt.Arch, s.Sym())
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
// runtime to use. Any changes here must be matched by changes to
// the definition of moduledata in runtime/symtab.go.
// 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
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.pclntab", 0))
moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
moduledata.AddUint(ctxt.Arch, uint64(ctxt.Syms.Lookup("runtime.pclntab", 0).Size))
moduledata.AddAddr(ctxt.Arch, pclntab)
moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pclntab)))
moduledata.AddUint(ctxt.Arch, uint64(ldr.SymSize(pclntab)))
// 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))
// 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)
// findfunctab
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.findfunctab", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.findfunctab", 0))
// minpc, maxpc
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
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.text", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etext", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrdata", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrdata", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.data", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.edata", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.bss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.ebss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.noptrbss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.enoptrbss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.end", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcdata", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.gcbss", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.types", 0))
moduledata.AddAddr(ctxt.Arch, ctxt.Syms.Lookup("runtime.etypes", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.text", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etext", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrdata", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrdata", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.edata", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.bss", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.ebss", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.noptrbss", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.enoptrbss", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.end", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcdata", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.gcbss", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0))
moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0))
if ctxt.HeadType == objabi.Haix && ctxt.LinkMode == LinkExternal {
// Add R_REF relocation to prevent ld's garbage collection of
if ctxt.IsAIX() && ctxt.IsExternal() {
// Add R_XCOFFREF relocation to prevent ld's garbage collection of
// runtime.rodata, runtime.erodata and runtime.epclntab.
addRef := func(name string) {
r := moduledata.AddRel()
r.Sym = ctxt.Syms.Lookup(name, 0)
r.Type = objabi.R_XCOFFREF
r.Siz = uint8(ctxt.Arch.PtrSize)
r, _ := moduledata.AddRel(objabi.R_XCOFFREF)
r.SetSym(ldr.Lookup(name, 0))
r.SetSiz(uint8(ctxt.Arch.PtrSize))
}
addRef("runtime.rodata")
addRef("runtime.erodata")
@ -588,26 +591,27 @@ func (ctxt *Link) symtab() {
}
// 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))
// The typelinks slice
typelinkSym := ctxt.Syms.Lookup("runtime.typelink", 0)
ntypelinks := uint64(typelinkSym.Size) / 4
typelinkSym := ldr.Lookup("runtime.typelink", 0)
ntypelinks := uint64(ldr.SymSize(typelinkSym)) / 4
moduledata.AddAddr(ctxt.Arch, typelinkSym)
moduledata.AddUint(ctxt.Arch, ntypelinks)
moduledata.AddUint(ctxt.Arch, ntypelinks)
// 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))
// The ptab slice
if ptab := ctxt.Syms.ROLookup("go.plugin.tabs", 0); ptab != nil && ptab.Attr.Reachable() {
ptab.Attr |= sym.AttrLocal
ptab.Type = sym.SRODATA
nentries := uint64(len(ptab.P) / 8) // sizeof(nameOff) + sizeof(typeOff)
if ptab := ldr.Lookup("go.plugin.tabs", 0); ptab != 0 && ldr.AttrReachable(ptab) {
ldr.SetAttrLocal(ptab, true)
if ldr.SymType(ptab) != sym.SRODATA {
panic(fmt.Sprintf("go.plugin.tabs is %v, not SRODATA", ldr.SymType(ptab)))
}
nentries := uint64(len(ldr.Data(ptab)) / 8) // sizeof(nameOff) + sizeof(typeOff)
moduledata.AddAddr(ctxt.Arch, ptab)
moduledata.AddUint(ctxt.Arch, nentries)
moduledata.AddUint(ctxt.Arch, nentries)
@ -617,23 +621,23 @@ func (ctxt *Link) symtab() {
moduledata.AddUint(ctxt.Arch, 0)
}
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.Attr |= sym.AttrReachable
pkghashes.Attr |= sym.AttrLocal
pkghashes.Type = sym.SRODATA
pkghashes := ldr.CreateSymForUpdate("go.link.pkghashes", 0)
pkghashes.SetReachable(true)
pkghashes.SetLocal(true)
pkghashes.SetType(sym.SRODATA)
for i, l := range ctxt.Library {
// 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
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
hash := ctxt.Syms.ROLookup("go.link.pkghash."+l.Pkg, 0)
hash := ldr.Lookup("go.link.pkghash."+l.Pkg, 0)
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)))
} else {
@ -651,28 +655,28 @@ func (ctxt *Link) symtab() {
// it something slightly more comprehensible.
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.Attr |= sym.AttrReachable
modulehashes.Attr |= sym.AttrLocal
modulehashes.Type = sym.SRODATA
modulehashes := ldr.CreateSymForUpdate("go.link.abihashes", 0)
modulehashes.SetReachable(true)
modulehashes.SetLocal(true)
modulehashes.SetType(sym.SRODATA)
for i, shlib := range ctxt.Shlibs {
// modulehashes[i].modulename
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
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
abihash := ctxt.Syms.Lookup("go.link.abihash."+modulename, 0)
abihash.Attr |= sym.AttrReachable
abihash := ldr.LookupOrCreateSym("go.link.abihash."+modulename, 0)
ldr.SetAttrReachable(abihash, true)
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)))
} else {
@ -694,15 +698,16 @@ func (ctxt *Link) symtab() {
// When linking an object that does not contain the runtime we are
// creating the moduledata from scratch and it does not have a
// compiler-provided size, so read it from the type data.
moduledatatype := ctxt.Syms.ROLookup("type.runtime.moduledata", 0)
moduledata.Size = decodetypeSize(ctxt.Arch, moduledatatype.P)
moduledata.Grow(moduledata.Size)
moduledatatype := ldr.Lookup("type.runtime.moduledata", 0)
moduledata.SetSize(decodetypeSize(ctxt.Arch, ldr.Data(moduledatatype)))
moduledata.Grow(moduledata.Size())
lastmoduledatap := ctxt.Syms.Lookup("runtime.lastmoduledatap", 0)
if lastmoduledatap.Type != sym.SDYNIMPORT {
lastmoduledatap.Type = sym.SNOPTRDATA
lastmoduledatap.Size = 0 // overwrite existing value
lastmoduledatap.AddAddr(ctxt.Arch, moduledata)
lastmoduledatap := ldr.CreateSymForUpdate("runtime.lastmoduledatap", 0)
if lastmoduledatap.Type() != sym.SDYNIMPORT {
lastmoduledatap.SetType(sym.SNOPTRDATA)
lastmoduledatap.SetSize(0) // overwrite existing value
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]
}
// 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)
@ -2225,8 +2235,7 @@ func loadObjSyms(l *Loader, syms *sym.Symbols, r *oReader) int {
continue
}
s := l.addNewSym(gi, name, ver, r.unit, t)
l.migrateAttributes(gi, s)
l.addNewSym(gi, name, ver, r.unit, t)
nr += r.NReloc(i)
}
return nr
@ -2378,10 +2387,19 @@ func (l *Loader) migrateAttributes(src Sym, dst *sym.Symbol) {
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)
// Set sub-symbol attribute.
//
// In sym.Symbols world, it uses Outer to record container symbols.
// 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.
if name, ok := l.extname[src]; ok {
@ -2448,10 +2466,11 @@ func loadObjFull(l *Loader, r *oReader) {
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)
dupok := osym.Dupok()
local := osym.Local()
makeTypelink := osym.Typelink()
size := osym.Siz()
// Symbol data
@ -2485,14 +2504,9 @@ func loadObjFull(l *Loader, r *oReader) {
}
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)
}
}

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) SetGot(value int32) { sb.l.SetGot(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) {
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)
}
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 {
sb.setReachable()
if sb.kind == 0 {