Skip to content

Commit

Permalink
cmd/link: merge branch 'dev.link' into master
Browse files Browse the repository at this point in the history
no conflicts.

Change-Id: Ic40ad81f1e491d6ceb72fbb66ad7919ad2b34a3e
  • Loading branch information
jeremyfaller committed Oct 1, 2020
2 parents 7347907 + 91e4d2d commit 97b46b4
Show file tree
Hide file tree
Showing 19 changed files with 907 additions and 585 deletions.
82 changes: 44 additions & 38 deletions src/cmd/internal/goobj/funcinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ type FuncInfo struct {
Locals uint32
FuncID objabi.FuncID

Pcsp uint32
Pcfile uint32
Pcline uint32
Pcinline uint32
Pcdata []uint32
PcdataEnd uint32
Pcsp SymRef
Pcfile SymRef
Pcline SymRef
Pcinline SymRef
Pcdata []SymRef
Funcdataoff []uint32
File []CUFileIndex

Expand All @@ -41,20 +40,24 @@ func (a *FuncInfo) Write(w *bytes.Buffer) {
binary.LittleEndian.PutUint32(b[:], x)
w.Write(b[:])
}
writeSymRef := func(s SymRef) {
writeUint32(s.PkgIdx)
writeUint32(s.SymIdx)
}

writeUint32(a.Args)
writeUint32(a.Locals)
writeUint32(uint32(a.FuncID))

writeUint32(a.Pcsp)
writeUint32(a.Pcfile)
writeUint32(a.Pcline)
writeUint32(a.Pcinline)
writeSymRef(a.Pcsp)
writeSymRef(a.Pcfile)
writeSymRef(a.Pcline)
writeSymRef(a.Pcinline)
writeUint32(uint32(len(a.Pcdata)))
for _, x := range a.Pcdata {
writeUint32(x)
for _, sym := range a.Pcdata {
writeSymRef(sym)
}
writeUint32(a.PcdataEnd)

writeUint32(uint32(len(a.Funcdataoff)))
for _, x := range a.Funcdataoff {
writeUint32(x)
Expand All @@ -75,21 +78,23 @@ func (a *FuncInfo) Read(b []byte) {
b = b[4:]
return x
}
readSymIdx := func() SymRef {
return SymRef{readUint32(), readUint32()}
}

a.Args = readUint32()
a.Locals = readUint32()
a.FuncID = objabi.FuncID(readUint32())

a.Pcsp = readUint32()
a.Pcfile = readUint32()
a.Pcline = readUint32()
a.Pcinline = readUint32()
pcdatalen := readUint32()
a.Pcdata = make([]uint32, pcdatalen)
a.Pcsp = readSymIdx()
a.Pcfile = readSymIdx()
a.Pcline = readSymIdx()
a.Pcinline = readSymIdx()
a.Pcdata = make([]SymRef, readUint32())
for i := range a.Pcdata {
a.Pcdata[i] = readUint32()
a.Pcdata[i] = readSymIdx()
}
a.PcdataEnd = readUint32()

funcdataofflen := readUint32()
a.Funcdataoff = make([]uint32, funcdataofflen)
for i := range a.Funcdataoff {
Expand Down Expand Up @@ -127,11 +132,13 @@ type FuncInfoLengths struct {
func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths {
var result FuncInfoLengths

const numpcdataOff = 28
// Offset to the number of pcdata values. This value is determined by counting
// the number of bytes until we write pcdata to the file.
const numpcdataOff = 44
result.NumPcdata = binary.LittleEndian.Uint32(b[numpcdataOff:])
result.PcdataOff = numpcdataOff + 4

numfuncdataoffOff := result.PcdataOff + 4*(result.NumPcdata+1)
numfuncdataoffOff := result.PcdataOff + 8*result.NumPcdata
result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:])
result.FuncdataoffOff = numfuncdataoffOff + 4

Expand All @@ -154,29 +161,28 @@ func (*FuncInfo) ReadLocals(b []byte) uint32 { return binary.LittleEndian.Uint32

func (*FuncInfo) ReadFuncID(b []byte) uint32 { return binary.LittleEndian.Uint32(b[8:]) }

// return start and end offsets.
func (*FuncInfo) ReadPcsp(b []byte) (uint32, uint32) {
return binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])
func (*FuncInfo) ReadPcsp(b []byte) SymRef {
return SymRef{binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])}
}

// return start and end offsets.
func (*FuncInfo) ReadPcfile(b []byte) (uint32, uint32) {
return binary.LittleEndian.Uint32(b[16:]), binary.LittleEndian.Uint32(b[20:])
func (*FuncInfo) ReadPcfile(b []byte) SymRef {
return SymRef{binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])}
}

// return start and end offsets.
func (*FuncInfo) ReadPcline(b []byte) (uint32, uint32) {
return binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])
func (*FuncInfo) ReadPcline(b []byte) SymRef {
return SymRef{binary.LittleEndian.Uint32(b[28:]), binary.LittleEndian.Uint32(b[32:])}
}

// return start and end offsets.
func (*FuncInfo) ReadPcinline(b []byte, pcdataoffset uint32) (uint32, uint32) {
return binary.LittleEndian.Uint32(b[24:]), binary.LittleEndian.Uint32(b[pcdataoffset:])
func (*FuncInfo) ReadPcinline(b []byte) SymRef {
return SymRef{binary.LittleEndian.Uint32(b[36:]), binary.LittleEndian.Uint32(b[40:])}
}

// return start and end offsets.
func (*FuncInfo) ReadPcdata(b []byte, pcdataoffset uint32, k uint32) (uint32, uint32) {
return binary.LittleEndian.Uint32(b[pcdataoffset+4*k:]), binary.LittleEndian.Uint32(b[pcdataoffset+4+4*k:])
func (*FuncInfo) ReadPcdata(b []byte) []SymRef {
syms := make([]SymRef, binary.LittleEndian.Uint32(b[44:]))
for i := range syms {
syms[i] = SymRef{binary.LittleEndian.Uint32(b[48+i*8:]), binary.LittleEndian.Uint32(b[52+i*8:])}
}
return syms
}

func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 {
Expand Down
12 changes: 5 additions & 7 deletions src/cmd/internal/goobj/objfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,8 +433,11 @@ const (
AuxDwarfLoc
AuxDwarfRanges
AuxDwarfLines

// TODO: more. Pcdata?
AuxPcsp
AuxPcfile
AuxPcline
AuxPcinline
AuxPcdata
)

func (a *Aux) Type() uint8 { return a[0] }
Expand Down Expand Up @@ -839,11 +842,6 @@ func (r *Reader) Data(i uint32) []byte {
return r.BytesAt(base+off, int(end-off))
}

// AuxDataBase returns the base offset of the aux data block.
func (r *Reader) PcdataBase() uint32 {
return r.h.Offsets[BlkPcdata]
}

// NRefName returns the number of referenced symbol names.
func (r *Reader) NRefName() int {
return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize
Expand Down
15 changes: 6 additions & 9 deletions src/cmd/internal/obj/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -634,11 +634,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
Expand All @@ -660,10 +661,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 {
Expand Down
85 changes: 67 additions & 18 deletions src/cmd/internal/obj/objfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -372,6 +376,19 @@ func contentHash64(s *LSym) goobj.Hash64Type {
// hashed symbols.
func (w *writer) contentHash(s *LSym) goobj.HashType {
h := sha1.New()
var tmp [14]byte

// Include the size of the symbol in the hash.
// This preserves the length of symbols, preventing the following two symbols
// from hashing the same:
//
// [2]int{1,2} ≠ [10]int{1,2,0,0,0...}
//
// In this case, if the smaller symbol is alive, the larger is not kept unless
// needed.
binary.LittleEndian.PutUint64(tmp[:8], uint64(s.Size))
h.Write(tmp[:8])

// Don't dedup type symbols with others, as they are in a different
// section.
if strings.HasPrefix(s.Name, "type.") {
Expand All @@ -382,7 +399,6 @@ func (w *writer) contentHash(s *LSym) goobj.HashType {
// The compiler trims trailing zeros _sometimes_. We just do
// it always.
h.Write(bytes.TrimRight(s.P, "\x00"))
var tmp [14]byte
for i := range s.R {
r := &s.R[i]
binary.LittleEndian.PutUint32(tmp[:4], uint32(r.Off))
Expand Down Expand Up @@ -473,6 +489,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)
}

}
}

Expand Down Expand Up @@ -554,14 +586,37 @@ 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
}

// 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 {
Expand All @@ -574,20 +629,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.PcdataEnd = pcdataoff
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.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
for i, x := range pc.Funcdataoff {
o.Funcdataoff[i] = uint32(x)
Expand Down Expand Up @@ -637,9 +686,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.
Expand Down
Loading

0 comments on commit 97b46b4

Please sign in to comment.