cmd/internal/obj: index pcdata symbols in NumberSyms

When writing an object file, most symbols are indexed in
NumberSyms. Currently, pcdata symbols are indexed late and
separately. This is not really necessary, as pcdata symbols
already exist at the time of NumberSyms. Just do it there.

As pcdata symbols are laid out in the pclntab in a special way at
link time, distinguish them from other symbols in the content
hash. (In the old code this was partly achieved by indexing them
late.)

Change-Id: Ie9e721382b0af2cfb39350d031e2e66d79095a3c
Reviewed-on: https://go-review.googlesource.com/c/go/+/352611
Trust: Cherry Mui <cherryyz@google.com>
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Cherry Mui 2021-09-27 15:35:46 -04:00
parent 02d56a1584
commit df63673d6a
4 changed files with 34 additions and 26 deletions

View file

@ -700,6 +700,9 @@ const (
// convert between ABI0 and ABIInternal calling conventions. // convert between ABI0 and ABIInternal calling conventions.
AttrABIWrapper AttrABIWrapper
// IsPcdata indicates this is a pcdata symbol.
AttrPcdata
// attrABIBase is the value at which the ABI is encoded in // attrABIBase is the value at which the ABI is encoded in
// Attribute. This must be last; all bits after this are // Attribute. This must be last; all bits after this are
// assumed to be an ABI value. // assumed to be an ABI value.
@ -727,6 +730,7 @@ func (a *Attribute) Indexed() bool { return a.load()&AttrIndexed != 0
func (a *Attribute) UsedInIface() bool { return a.load()&AttrUsedInIface != 0 } func (a *Attribute) UsedInIface() bool { return a.load()&AttrUsedInIface != 0 }
func (a *Attribute) ContentAddressable() bool { return a.load()&AttrContentAddressable != 0 } func (a *Attribute) ContentAddressable() bool { return a.load()&AttrContentAddressable != 0 }
func (a *Attribute) ABIWrapper() bool { return a.load()&AttrABIWrapper != 0 } func (a *Attribute) ABIWrapper() bool { return a.load()&AttrABIWrapper != 0 }
func (a *Attribute) IsPcdata() bool { return a.load()&AttrPcdata != 0 }
func (a *Attribute) Set(flag Attribute, value bool) { func (a *Attribute) Set(flag Attribute, value bool) {
for { for {

View file

@ -391,7 +391,9 @@ func (w *writer) Hash(s *LSym) {
// TODO: instead of duplicating them, have the compiler decide where symbols go. // TODO: instead of duplicating them, have the compiler decide where symbols go.
func contentHashSection(s *LSym) byte { func contentHashSection(s *LSym) byte {
name := s.Name name := s.Name
if strings.HasPrefix(name, "type.") { if s.IsPcdata() {
return 'P'
} else if strings.HasPrefix(name, "type.") {
return 'T' return 'T'
} }
return 0 return 0
@ -655,16 +657,6 @@ func nAuxSym(s *LSym) int {
func genFuncInfoSyms(ctxt *Link) { func genFuncInfoSyms(ctxt *Link) {
infosyms := make([]*LSym, 0, len(ctxt.Text)) infosyms := make([]*LSym, 0, len(ctxt.Text))
hashedsyms := make([]*LSym, 0, 4*len(ctxt.Text)) hashedsyms := make([]*LSym, 0, 4*len(ctxt.Text))
preparePcSym := func(s *LSym) *LSym {
if s == nil {
return s
}
s.PkgIdx = goobj.PkgIdxHashed
s.SymIdx = int32(len(hashedsyms) + len(ctxt.hasheddefs))
s.Set(AttrIndexed, true)
hashedsyms = append(hashedsyms, s)
return s
}
var b bytes.Buffer var b bytes.Buffer
symidx := int32(len(ctxt.defs)) symidx := int32(len(ctxt.defs))
for _, s := range ctxt.Text { for _, s := range ctxt.Text {
@ -679,13 +671,13 @@ func genFuncInfoSyms(ctxt *Link) {
FuncFlag: fn.FuncFlag, FuncFlag: fn.FuncFlag,
} }
pc := &fn.Pcln pc := &fn.Pcln
o.Pcsp = makeSymRef(preparePcSym(pc.Pcsp)) o.Pcsp = makeSymRef(pc.Pcsp)
o.Pcfile = makeSymRef(preparePcSym(pc.Pcfile)) o.Pcfile = makeSymRef(pc.Pcfile)
o.Pcline = makeSymRef(preparePcSym(pc.Pcline)) o.Pcline = makeSymRef(pc.Pcline)
o.Pcinline = makeSymRef(preparePcSym(pc.Pcinline)) o.Pcinline = makeSymRef(pc.Pcinline)
o.Pcdata = make([]goobj.SymRef, len(pc.Pcdata)) o.Pcdata = make([]goobj.SymRef, len(pc.Pcdata))
for i, pcSym := range pc.Pcdata { for i, pcSym := range pc.Pcdata {
o.Pcdata[i] = makeSymRef(preparePcSym(pcSym)) o.Pcdata[i] = makeSymRef(pcSym)
} }
o.Funcdataoff = make([]uint32, len(pc.Funcdataoff)) o.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
for i, x := range pc.Funcdataoff { for i, x := range pc.Funcdataoff {

View file

@ -26,7 +26,7 @@ func funcpctab(ctxt *Link, func_ *LSym, desc string, valfunc func(*Link, *LSym,
dst := []byte{} dst := []byte{}
sym := &LSym{ sym := &LSym{
Type: objabi.SRODATA, Type: objabi.SRODATA,
Attribute: AttrContentAddressable, Attribute: AttrContentAddressable | AttrPcdata,
} }
if dbg { if dbg {
@ -337,7 +337,7 @@ func linkpcln(ctxt *Link, cursym *LSym) {
// use an empty symbol. // use an empty symbol.
pcln.Pcdata[i] = &LSym{ pcln.Pcdata[i] = &LSym{
Type: objabi.SRODATA, Type: objabi.SRODATA,
Attribute: AttrContentAddressable, Attribute: AttrContentAddressable | AttrPcdata,
} }
} else { } else {
pcln.Pcdata[i] = funcpctab(ctxt, cursym, "pctopcdata", pctopcdata, interface{}(uint32(i))) pcln.Pcdata[i] = funcpctab(ctxt, cursym, "pctopcdata", pctopcdata, interface{}(uint32(i)))

View file

@ -201,7 +201,7 @@ func (ctxt *Link) NumberSyms() {
ctxt.nonpkgdefs = []*LSym{} ctxt.nonpkgdefs = []*LSym{}
var idx, hashedidx, hashed64idx, nonpkgidx int32 var idx, hashedidx, hashed64idx, nonpkgidx int32
ctxt.traverseSyms(traverseDefs, func(s *LSym) { ctxt.traverseSyms(traverseDefs|traversePcdata, func(s *LSym) {
// if Pkgpath is unknown, cannot hash symbols with relocations, as it // if Pkgpath is unknown, cannot hash symbols with relocations, as it
// may reference named symbols whose names are not fully expanded. // may reference named symbols whose names are not fully expanded.
if s.ContentAddressable() && (ctxt.Pkgpath != "" || len(s.R) == 0) { if s.ContentAddressable() && (ctxt.Pkgpath != "" || len(s.R) == 0) {
@ -324,12 +324,18 @@ const (
traverseDefs traverseFlag = 1 << iota traverseDefs traverseFlag = 1 << iota
traverseRefs traverseRefs
traverseAux traverseAux
traversePcdata
traverseAll = traverseDefs | traverseRefs | traverseAux traverseAll = traverseDefs | traverseRefs | traverseAux | traversePcdata
) )
// Traverse symbols based on flag, call fn for each symbol. // Traverse symbols based on flag, call fn for each symbol.
func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) { func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) {
fnNoNil := func(s *LSym) {
if s != nil {
fn(s)
}
}
lists := [][]*LSym{ctxt.Text, ctxt.Data} lists := [][]*LSym{ctxt.Text, ctxt.Data}
for _, list := range lists { for _, list := range lists {
for _, s := range list { for _, s := range list {
@ -338,15 +344,11 @@ func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) {
} }
if flag&traverseRefs != 0 { if flag&traverseRefs != 0 {
for _, r := range s.R { for _, r := range s.R {
if r.Sym != nil { fnNoNil(r.Sym)
fn(r.Sym)
}
} }
} }
if flag&traverseAux != 0 { if flag&traverseAux != 0 {
if s.Gotype != nil { fnNoNil(s.Gotype)
fn(s.Gotype)
}
if s.Type == objabi.STEXT { if s.Type == objabi.STEXT {
f := func(parent *LSym, aux *LSym) { f := func(parent *LSym, aux *LSym) {
fn(aux) fn(aux)
@ -354,6 +356,16 @@ func (ctxt *Link) traverseSyms(flag traverseFlag, fn func(*LSym)) {
ctxt.traverseFuncAux(flag, s, f) ctxt.traverseFuncAux(flag, s, f)
} }
} }
if flag&traversePcdata != 0 && s.Type == objabi.STEXT {
fi := s.Func().Pcln
fnNoNil(fi.Pcsp)
fnNoNil(fi.Pcfile)
fnNoNil(fi.Pcline)
fnNoNil(fi.Pcinline)
for _, d := range fi.Pcdata {
fnNoNil(d)
}
}
} }
} }
} }