aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj
diff options
context:
space:
mode:
authorJeremy Faller <jeremy@golang.org>2020-08-07 11:31:20 -0400
committerJeremy Faller <jeremy@golang.org>2020-08-13 16:47:08 +0000
commit5387cdcb24a07f5d0d49d5105ced2b69e6aafde9 (patch)
tree65241c32e5d26fb3916a80ff316a6b368ce2e6f9 /src/cmd/internal/obj
parent954db9fe51154e5d4663c0c1a62c82a99eef1ed4 (diff)
downloadgo-5387cdcb24a07f5d0d49d5105ced2b69e6aafde9.tar.xz
[dev.link] cmd/link, cmd/compile: create content addressable pcdata syms
Switch pcdata over to content addressable symbols. This is the last step before removing these from pclntab_old. No meaningful benchmarks changes come from this work. Change-Id: I3f74f3d6026a278babe437c8010e22992c92bd89 Reviewed-on: https://go-review.googlesource.com/c/go/+/247399 Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/cmd/internal/obj')
-rw-r--r--src/cmd/internal/obj/link.go15
-rw-r--r--src/cmd/internal/obj/objfile.go69
-rw-r--r--src/cmd/internal/obj/pcln.go55
3 files changed, 93 insertions, 46 deletions
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index dc47e51be9..11fab63065 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -624,11 +624,12 @@ func (s *LSym) CanBeAnSSASym() {
}
type Pcln struct {
- Pcsp Pcdata
- Pcfile Pcdata
- Pcline Pcdata
- Pcinline Pcdata
- Pcdata []Pcdata
+ // Aux symbols for pcln
+ Pcsp *LSym
+ Pcfile *LSym
+ Pcline *LSym
+ Pcinline *LSym
+ Pcdata []*LSym
Funcdata []*LSym
Funcdataoff []int64
UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile
@@ -650,10 +651,6 @@ type Auto struct {
Gotype *LSym
}
-type Pcdata struct {
- P []byte
-}
-
// Link holds the context for writing object code from a compiler
// to be linker input or for reading that input into the linker.
type Link struct {
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index 8234697d72..a2bbdff24e 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -185,7 +185,11 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) {
// Pcdata
h.Offsets[goobj.BlkPcdata] = w.Offset()
for _, s := range ctxt.Text { // iteration order must match genFuncInfoSyms
- if s.Func != nil {
+ // Because of the phase order, it's possible that we try to write an invalid
+ // object file, and the Pcln variables haven't been filled in. As such, we
+ // need to check that Pcsp exists, and assume the other pcln variables exist
+ // as well. Tests like test/fixedbugs/issue22200.go demonstrate this issue.
+ if s.Func != nil && s.Func.Pcln.Pcsp != nil {
pc := &s.Func.Pcln
w.Bytes(pc.Pcsp.P)
w.Bytes(pc.Pcfile.P)
@@ -478,6 +482,22 @@ func (w *writer) Aux(s *LSym) {
if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
w.aux1(goobj.AuxDwarfLines, s.Func.dwarfDebugLinesSym)
}
+ if s.Func.Pcln.Pcsp != nil && s.Func.Pcln.Pcsp.Size != 0 {
+ w.aux1(goobj.AuxPcsp, s.Func.Pcln.Pcsp)
+ }
+ if s.Func.Pcln.Pcfile != nil && s.Func.Pcln.Pcfile.Size != 0 {
+ w.aux1(goobj.AuxPcfile, s.Func.Pcln.Pcfile)
+ }
+ if s.Func.Pcln.Pcline != nil && s.Func.Pcln.Pcline.Size != 0 {
+ w.aux1(goobj.AuxPcline, s.Func.Pcln.Pcline)
+ }
+ if s.Func.Pcln.Pcinline != nil && s.Func.Pcln.Pcinline.Size != 0 {
+ w.aux1(goobj.AuxPcinline, s.Func.Pcln.Pcinline)
+ }
+ for _, pcSym := range s.Func.Pcln.Pcdata {
+ w.aux1(goobj.AuxPcdata, pcSym)
+ }
+
}
}
@@ -559,6 +579,19 @@ func nAuxSym(s *LSym) int {
if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
n++
}
+ if s.Func.Pcln.Pcsp != nil && s.Func.Pcln.Pcsp.Size != 0 {
+ n++
+ }
+ if s.Func.Pcln.Pcfile != nil && s.Func.Pcln.Pcfile.Size != 0 {
+ n++
+ }
+ if s.Func.Pcln.Pcline != nil && s.Func.Pcln.Pcline.Size != 0 {
+ n++
+ }
+ if s.Func.Pcln.Pcinline != nil && s.Func.Pcln.Pcinline.Size != 0 {
+ n++
+ }
+ n += len(s.Func.Pcln.Pcdata)
}
return n
}
@@ -566,7 +599,17 @@ func nAuxSym(s *LSym) int {
// generate symbols for FuncInfo.
func genFuncInfoSyms(ctxt *Link) {
infosyms := make([]*LSym, 0, len(ctxt.Text))
- var pcdataoff uint32
+ 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
symidx := int32(len(ctxt.defs))
for _, s := range ctxt.Text {
@@ -579,20 +622,14 @@ func genFuncInfoSyms(ctxt *Link) {
FuncID: objabi.FuncID(s.Func.FuncID),
}
pc := &s.Func.Pcln
- o.Pcsp = pcdataoff
- pcdataoff += uint32(len(pc.Pcsp.P))
- o.Pcfile = pcdataoff
- pcdataoff += uint32(len(pc.Pcfile.P))
- o.Pcline = pcdataoff
- pcdataoff += uint32(len(pc.Pcline.P))
- o.Pcinline = pcdataoff
- pcdataoff += uint32(len(pc.Pcinline.P))
- o.Pcdata = make([]uint32, len(pc.Pcdata))
- for i, pcd := range pc.Pcdata {
- o.Pcdata[i] = pcdataoff
- pcdataoff += uint32(len(pcd.P))
+ o.Pcsp = makeSymRef(preparePcSym(pc.Pcsp))
+ o.Pcfile = makeSymRef(preparePcSym(pc.Pcfile))
+ o.Pcline = makeSymRef(preparePcSym(pc.Pcline))
+ o.Pcinline = makeSymRef(preparePcSym(pc.Pcinline))
+ o.Pcdata = make([]goobj.SymRef, len(pc.Pcdata))
+ for i, pcSym := range pc.Pcdata {
+ o.Pcdata[i] = makeSymRef(preparePcSym(pcSym))
}
- o.PcdataEnd = pcdataoff
o.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
for i, x := range pc.Funcdataoff {
o.Funcdataoff[i] = uint32(x)
@@ -642,9 +679,9 @@ func genFuncInfoSyms(ctxt *Link) {
}
}
ctxt.defs = append(ctxt.defs, infosyms...)
+ ctxt.hasheddefs = append(ctxt.hasheddefs, hashedsyms...)
}
-// debugDumpAux is a dumper for selected aux symbols.
func writeAuxSymDebug(ctxt *Link, par *LSym, aux *LSym) {
// Most aux symbols (ex: funcdata) are not interesting--
// pick out just the DWARF ones for now.
diff --git a/src/cmd/internal/obj/pcln.go b/src/cmd/internal/obj/pcln.go
index 1f7ccf47ef..7750637796 100644
--- a/src/cmd/internal/obj/pcln.go
+++ b/src/cmd/internal/obj/pcln.go
@@ -6,6 +6,7 @@ package obj
import (
"cmd/internal/goobj"
+ "cmd/internal/objabi"
"encoding/binary"
"log"
)
@@ -14,16 +15,19 @@ import (
// returned by valfunc parameterized by arg. The invocation of valfunc to update the
// current value is, for each p,
//
-// val = valfunc(func, val, p, 0, arg);
-// record val as value at p->pc;
-// val = valfunc(func, val, p, 1, arg);
+// sym = valfunc(func, p, 0, arg);
+// record sym.P as value at p->pc;
+// sym = valfunc(func, p, 1, arg);
//
// where func is the function, val is the current value, p is the instruction being
// considered, and arg can be used to further parameterize valfunc.
-func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*Link, *LSym, int32, *Prog, int32, interface{}) int32, arg interface{}) {
+func funcpctab(ctxt *Link, func_ *LSym, desc string, valfunc func(*Link, *LSym, int32, *Prog, int32, interface{}) int32, arg interface{}) *LSym {
dbg := desc == ctxt.Debugpcln
-
- dst.P = dst.P[:0]
+ dst := []byte{}
+ sym := &LSym{
+ Type: objabi.SRODATA,
+ Attribute: AttrContentAddressable,
+ }
if dbg {
ctxt.Logf("funcpctab %s [valfunc=%s]\n", func_.Name, desc)
@@ -32,7 +36,8 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*
val := int32(-1)
oldval := val
if func_.Func.Text == nil {
- return
+ // Return the emtpy symbol we've built so far.
+ return sym
}
pc := func_.Func.Text.Pc
@@ -88,13 +93,13 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*
if started {
pcdelta := (p.Pc - pc) / int64(ctxt.Arch.MinLC)
n := binary.PutUvarint(buf, uint64(pcdelta))
- dst.P = append(dst.P, buf[:n]...)
+ dst = append(dst, buf[:n]...)
pc = p.Pc
}
delta := val - oldval
n := binary.PutVarint(buf, int64(delta))
- dst.P = append(dst.P, buf[:n]...)
+ dst = append(dst, buf[:n]...)
oldval = val
started = true
val = valfunc(ctxt, func_, val, p, 1, arg)
@@ -109,18 +114,22 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*
ctxt.Diag("negative pc offset: %v", v)
}
n := binary.PutUvarint(buf, uint64(v))
- dst.P = append(dst.P, buf[:n]...)
+ dst = append(dst, buf[:n]...)
// add terminating varint-encoded 0, which is just 0
- dst.P = append(dst.P, 0)
+ dst = append(dst, 0)
}
if dbg {
- ctxt.Logf("wrote %d bytes to %p\n", len(dst.P), dst)
- for _, p := range dst.P {
+ ctxt.Logf("wrote %d bytes to %p\n", len(dst), dst)
+ for _, p := range dst {
ctxt.Logf(" %02x", p)
}
ctxt.Logf("\n")
}
+
+ sym.Size = int64(len(dst))
+ sym.P = dst
+ return sym
}
// pctofileline computes either the file number (arg == 0)
@@ -268,18 +277,17 @@ func linkpcln(ctxt *Link, cursym *LSym) {
}
}
- pcln.Pcdata = make([]Pcdata, npcdata)
- pcln.Pcdata = pcln.Pcdata[:npcdata]
+ pcln.Pcdata = make([]*LSym, npcdata)
pcln.Funcdata = make([]*LSym, nfuncdata)
pcln.Funcdataoff = make([]int64, nfuncdata)
pcln.Funcdataoff = pcln.Funcdataoff[:nfuncdata]
- funcpctab(ctxt, &pcln.Pcsp, cursym, "pctospadj", pctospadj, nil)
- funcpctab(ctxt, &pcln.Pcfile, cursym, "pctofile", pctofileline, pcln)
- funcpctab(ctxt, &pcln.Pcline, cursym, "pctoline", pctofileline, nil)
+ pcln.Pcsp = funcpctab(ctxt, cursym, "pctospadj", pctospadj, nil)
+ pcln.Pcfile = funcpctab(ctxt, cursym, "pctofile", pctofileline, pcln)
+ pcln.Pcline = funcpctab(ctxt, cursym, "pctoline", pctofileline, nil)
pcinlineState := new(pcinlineState)
- funcpctab(ctxt, &pcln.Pcinline, cursym, "pctoinline", pcinlineState.pctoinline, nil)
+ pcln.Pcinline = funcpctab(ctxt, cursym, "pctoinline", pcinlineState.pctoinline, nil)
for _, inlMark := range cursym.Func.InlMarks {
pcinlineState.setParentPC(ctxt, int(inlMark.id), int32(inlMark.p.Pc))
}
@@ -309,9 +317,14 @@ func linkpcln(ctxt *Link, cursym *LSym) {
// pcdata.
for i := 0; i < npcdata; i++ {
if (havepc[i/32]>>uint(i%32))&1 == 0 {
- continue
+ // use an empty symbol.
+ pcln.Pcdata[i] = &LSym{
+ Type: objabi.SRODATA,
+ Attribute: AttrContentAddressable,
+ }
+ } else {
+ pcln.Pcdata[i] = funcpctab(ctxt, cursym, "pctopcdata", pctopcdata, interface{}(uint32(i)))
}
- funcpctab(ctxt, &pcln.Pcdata[i], cursym, "pctopcdata", pctopcdata, interface{}(uint32(i)))
}
// funcdata