Skip to content

Commit 89f687d

Browse files
author
Gerrit Code Review
committed
Merge "cmd/link: merge branch 'dev.link' into master"
2 parents 2ca2e94 + 97b46b4 commit 89f687d

File tree

19 files changed

+907
-585
lines changed

19 files changed

+907
-585
lines changed

src/cmd/internal/goobj/funcinfo.go

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ type FuncInfo struct {
2323
Locals uint32
2424
FuncID objabi.FuncID
2525

26-
Pcsp uint32
27-
Pcfile uint32
28-
Pcline uint32
29-
Pcinline uint32
30-
Pcdata []uint32
31-
PcdataEnd uint32
26+
Pcsp SymRef
27+
Pcfile SymRef
28+
Pcline SymRef
29+
Pcinline SymRef
30+
Pcdata []SymRef
3231
Funcdataoff []uint32
3332
File []CUFileIndex
3433

@@ -41,20 +40,24 @@ func (a *FuncInfo) Write(w *bytes.Buffer) {
4140
binary.LittleEndian.PutUint32(b[:], x)
4241
w.Write(b[:])
4342
}
43+
writeSymRef := func(s SymRef) {
44+
writeUint32(s.PkgIdx)
45+
writeUint32(s.SymIdx)
46+
}
4447

4548
writeUint32(a.Args)
4649
writeUint32(a.Locals)
4750
writeUint32(uint32(a.FuncID))
4851

49-
writeUint32(a.Pcsp)
50-
writeUint32(a.Pcfile)
51-
writeUint32(a.Pcline)
52-
writeUint32(a.Pcinline)
52+
writeSymRef(a.Pcsp)
53+
writeSymRef(a.Pcfile)
54+
writeSymRef(a.Pcline)
55+
writeSymRef(a.Pcinline)
5356
writeUint32(uint32(len(a.Pcdata)))
54-
for _, x := range a.Pcdata {
55-
writeUint32(x)
57+
for _, sym := range a.Pcdata {
58+
writeSymRef(sym)
5659
}
57-
writeUint32(a.PcdataEnd)
60+
5861
writeUint32(uint32(len(a.Funcdataoff)))
5962
for _, x := range a.Funcdataoff {
6063
writeUint32(x)
@@ -75,21 +78,23 @@ func (a *FuncInfo) Read(b []byte) {
7578
b = b[4:]
7679
return x
7780
}
81+
readSymIdx := func() SymRef {
82+
return SymRef{readUint32(), readUint32()}
83+
}
7884

7985
a.Args = readUint32()
8086
a.Locals = readUint32()
8187
a.FuncID = objabi.FuncID(readUint32())
8288

83-
a.Pcsp = readUint32()
84-
a.Pcfile = readUint32()
85-
a.Pcline = readUint32()
86-
a.Pcinline = readUint32()
87-
pcdatalen := readUint32()
88-
a.Pcdata = make([]uint32, pcdatalen)
89+
a.Pcsp = readSymIdx()
90+
a.Pcfile = readSymIdx()
91+
a.Pcline = readSymIdx()
92+
a.Pcinline = readSymIdx()
93+
a.Pcdata = make([]SymRef, readUint32())
8994
for i := range a.Pcdata {
90-
a.Pcdata[i] = readUint32()
95+
a.Pcdata[i] = readSymIdx()
9196
}
92-
a.PcdataEnd = readUint32()
97+
9398
funcdataofflen := readUint32()
9499
a.Funcdataoff = make([]uint32, funcdataofflen)
95100
for i := range a.Funcdataoff {
@@ -127,11 +132,13 @@ type FuncInfoLengths struct {
127132
func (*FuncInfo) ReadFuncInfoLengths(b []byte) FuncInfoLengths {
128133
var result FuncInfoLengths
129134

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

134-
numfuncdataoffOff := result.PcdataOff + 4*(result.NumPcdata+1)
141+
numfuncdataoffOff := result.PcdataOff + 8*result.NumPcdata
135142
result.NumFuncdataoff = binary.LittleEndian.Uint32(b[numfuncdataoffOff:])
136143
result.FuncdataoffOff = numfuncdataoffOff + 4
137144

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

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

157-
// return start and end offsets.
158-
func (*FuncInfo) ReadPcsp(b []byte) (uint32, uint32) {
159-
return binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])
164+
func (*FuncInfo) ReadPcsp(b []byte) SymRef {
165+
return SymRef{binary.LittleEndian.Uint32(b[12:]), binary.LittleEndian.Uint32(b[16:])}
160166
}
161167

162-
// return start and end offsets.
163-
func (*FuncInfo) ReadPcfile(b []byte) (uint32, uint32) {
164-
return binary.LittleEndian.Uint32(b[16:]), binary.LittleEndian.Uint32(b[20:])
168+
func (*FuncInfo) ReadPcfile(b []byte) SymRef {
169+
return SymRef{binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])}
165170
}
166171

167-
// return start and end offsets.
168-
func (*FuncInfo) ReadPcline(b []byte) (uint32, uint32) {
169-
return binary.LittleEndian.Uint32(b[20:]), binary.LittleEndian.Uint32(b[24:])
172+
func (*FuncInfo) ReadPcline(b []byte) SymRef {
173+
return SymRef{binary.LittleEndian.Uint32(b[28:]), binary.LittleEndian.Uint32(b[32:])}
170174
}
171175

172-
// return start and end offsets.
173-
func (*FuncInfo) ReadPcinline(b []byte, pcdataoffset uint32) (uint32, uint32) {
174-
return binary.LittleEndian.Uint32(b[24:]), binary.LittleEndian.Uint32(b[pcdataoffset:])
176+
func (*FuncInfo) ReadPcinline(b []byte) SymRef {
177+
return SymRef{binary.LittleEndian.Uint32(b[36:]), binary.LittleEndian.Uint32(b[40:])}
175178
}
176179

177-
// return start and end offsets.
178-
func (*FuncInfo) ReadPcdata(b []byte, pcdataoffset uint32, k uint32) (uint32, uint32) {
179-
return binary.LittleEndian.Uint32(b[pcdataoffset+4*k:]), binary.LittleEndian.Uint32(b[pcdataoffset+4+4*k:])
180+
func (*FuncInfo) ReadPcdata(b []byte) []SymRef {
181+
syms := make([]SymRef, binary.LittleEndian.Uint32(b[44:]))
182+
for i := range syms {
183+
syms[i] = SymRef{binary.LittleEndian.Uint32(b[48+i*8:]), binary.LittleEndian.Uint32(b[52+i*8:])}
184+
}
185+
return syms
180186
}
181187

182188
func (*FuncInfo) ReadFuncdataoff(b []byte, funcdataofffoff uint32, k uint32) int64 {

src/cmd/internal/goobj/objfile.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,11 @@ const (
433433
AuxDwarfLoc
434434
AuxDwarfRanges
435435
AuxDwarfLines
436-
437-
// TODO: more. Pcdata?
436+
AuxPcsp
437+
AuxPcfile
438+
AuxPcline
439+
AuxPcinline
440+
AuxPcdata
438441
)
439442

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

842-
// AuxDataBase returns the base offset of the aux data block.
843-
func (r *Reader) PcdataBase() uint32 {
844-
return r.h.Offsets[BlkPcdata]
845-
}
846-
847845
// NRefName returns the number of referenced symbol names.
848846
func (r *Reader) NRefName() int {
849847
return int(r.h.Offsets[BlkRefName+1]-r.h.Offsets[BlkRefName]) / RefNameSize

src/cmd/internal/obj/link.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -634,11 +634,12 @@ func (s *LSym) CanBeAnSSASym() {
634634
}
635635

636636
type Pcln struct {
637-
Pcsp Pcdata
638-
Pcfile Pcdata
639-
Pcline Pcdata
640-
Pcinline Pcdata
641-
Pcdata []Pcdata
637+
// Aux symbols for pcln
638+
Pcsp *LSym
639+
Pcfile *LSym
640+
Pcline *LSym
641+
Pcinline *LSym
642+
Pcdata []*LSym
642643
Funcdata []*LSym
643644
Funcdataoff []int64
644645
UsedFiles map[goobj.CUFileIndex]struct{} // file indices used while generating pcfile
@@ -660,10 +661,6 @@ type Auto struct {
660661
Gotype *LSym
661662
}
662663

663-
type Pcdata struct {
664-
P []byte
665-
}
666-
667664
// Link holds the context for writing object code from a compiler
668665
// to be linker input or for reading that input into the linker.
669666
type Link struct {

src/cmd/internal/obj/objfile.go

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,11 @@ func WriteObjFile(ctxt *Link, b *bio.Writer) {
185185
// Pcdata
186186
h.Offsets[goobj.BlkPcdata] = w.Offset()
187187
for _, s := range ctxt.Text { // iteration order must match genFuncInfoSyms
188-
if s.Func != nil {
188+
// Because of the phase order, it's possible that we try to write an invalid
189+
// object file, and the Pcln variables haven't been filled in. As such, we
190+
// need to check that Pcsp exists, and assume the other pcln variables exist
191+
// as well. Tests like test/fixedbugs/issue22200.go demonstrate this issue.
192+
if s.Func != nil && s.Func.Pcln.Pcsp != nil {
189193
pc := &s.Func.Pcln
190194
w.Bytes(pc.Pcsp.P)
191195
w.Bytes(pc.Pcfile.P)
@@ -372,6 +376,19 @@ func contentHash64(s *LSym) goobj.Hash64Type {
372376
// hashed symbols.
373377
func (w *writer) contentHash(s *LSym) goobj.HashType {
374378
h := sha1.New()
379+
var tmp [14]byte
380+
381+
// Include the size of the symbol in the hash.
382+
// This preserves the length of symbols, preventing the following two symbols
383+
// from hashing the same:
384+
//
385+
// [2]int{1,2} ≠ [10]int{1,2,0,0,0...}
386+
//
387+
// In this case, if the smaller symbol is alive, the larger is not kept unless
388+
// needed.
389+
binary.LittleEndian.PutUint64(tmp[:8], uint64(s.Size))
390+
h.Write(tmp[:8])
391+
375392
// Don't dedup type symbols with others, as they are in a different
376393
// section.
377394
if strings.HasPrefix(s.Name, "type.") {
@@ -382,7 +399,6 @@ func (w *writer) contentHash(s *LSym) goobj.HashType {
382399
// The compiler trims trailing zeros _sometimes_. We just do
383400
// it always.
384401
h.Write(bytes.TrimRight(s.P, "\x00"))
385-
var tmp [14]byte
386402
for i := range s.R {
387403
r := &s.R[i]
388404
binary.LittleEndian.PutUint32(tmp[:4], uint32(r.Off))
@@ -473,6 +489,22 @@ func (w *writer) Aux(s *LSym) {
473489
if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
474490
w.aux1(goobj.AuxDwarfLines, s.Func.dwarfDebugLinesSym)
475491
}
492+
if s.Func.Pcln.Pcsp != nil && s.Func.Pcln.Pcsp.Size != 0 {
493+
w.aux1(goobj.AuxPcsp, s.Func.Pcln.Pcsp)
494+
}
495+
if s.Func.Pcln.Pcfile != nil && s.Func.Pcln.Pcfile.Size != 0 {
496+
w.aux1(goobj.AuxPcfile, s.Func.Pcln.Pcfile)
497+
}
498+
if s.Func.Pcln.Pcline != nil && s.Func.Pcln.Pcline.Size != 0 {
499+
w.aux1(goobj.AuxPcline, s.Func.Pcln.Pcline)
500+
}
501+
if s.Func.Pcln.Pcinline != nil && s.Func.Pcln.Pcinline.Size != 0 {
502+
w.aux1(goobj.AuxPcinline, s.Func.Pcln.Pcinline)
503+
}
504+
for _, pcSym := range s.Func.Pcln.Pcdata {
505+
w.aux1(goobj.AuxPcdata, pcSym)
506+
}
507+
476508
}
477509
}
478510

@@ -554,14 +586,37 @@ func nAuxSym(s *LSym) int {
554586
if s.Func.dwarfDebugLinesSym != nil && s.Func.dwarfDebugLinesSym.Size != 0 {
555587
n++
556588
}
589+
if s.Func.Pcln.Pcsp != nil && s.Func.Pcln.Pcsp.Size != 0 {
590+
n++
591+
}
592+
if s.Func.Pcln.Pcfile != nil && s.Func.Pcln.Pcfile.Size != 0 {
593+
n++
594+
}
595+
if s.Func.Pcln.Pcline != nil && s.Func.Pcln.Pcline.Size != 0 {
596+
n++
597+
}
598+
if s.Func.Pcln.Pcinline != nil && s.Func.Pcln.Pcinline.Size != 0 {
599+
n++
600+
}
601+
n += len(s.Func.Pcln.Pcdata)
557602
}
558603
return n
559604
}
560605

561606
// generate symbols for FuncInfo.
562607
func genFuncInfoSyms(ctxt *Link) {
563608
infosyms := make([]*LSym, 0, len(ctxt.Text))
564-
var pcdataoff uint32
609+
hashedsyms := make([]*LSym, 0, 4*len(ctxt.Text))
610+
preparePcSym := func(s *LSym) *LSym {
611+
if s == nil {
612+
return s
613+
}
614+
s.PkgIdx = goobj.PkgIdxHashed
615+
s.SymIdx = int32(len(hashedsyms) + len(ctxt.hasheddefs))
616+
s.Set(AttrIndexed, true)
617+
hashedsyms = append(hashedsyms, s)
618+
return s
619+
}
565620
var b bytes.Buffer
566621
symidx := int32(len(ctxt.defs))
567622
for _, s := range ctxt.Text {
@@ -574,20 +629,14 @@ func genFuncInfoSyms(ctxt *Link) {
574629
FuncID: objabi.FuncID(s.Func.FuncID),
575630
}
576631
pc := &s.Func.Pcln
577-
o.Pcsp = pcdataoff
578-
pcdataoff += uint32(len(pc.Pcsp.P))
579-
o.Pcfile = pcdataoff
580-
pcdataoff += uint32(len(pc.Pcfile.P))
581-
o.Pcline = pcdataoff
582-
pcdataoff += uint32(len(pc.Pcline.P))
583-
o.Pcinline = pcdataoff
584-
pcdataoff += uint32(len(pc.Pcinline.P))
585-
o.Pcdata = make([]uint32, len(pc.Pcdata))
586-
for i, pcd := range pc.Pcdata {
587-
o.Pcdata[i] = pcdataoff
588-
pcdataoff += uint32(len(pcd.P))
589-
}
590-
o.PcdataEnd = pcdataoff
632+
o.Pcsp = makeSymRef(preparePcSym(pc.Pcsp))
633+
o.Pcfile = makeSymRef(preparePcSym(pc.Pcfile))
634+
o.Pcline = makeSymRef(preparePcSym(pc.Pcline))
635+
o.Pcinline = makeSymRef(preparePcSym(pc.Pcinline))
636+
o.Pcdata = make([]goobj.SymRef, len(pc.Pcdata))
637+
for i, pcSym := range pc.Pcdata {
638+
o.Pcdata[i] = makeSymRef(preparePcSym(pcSym))
639+
}
591640
o.Funcdataoff = make([]uint32, len(pc.Funcdataoff))
592641
for i, x := range pc.Funcdataoff {
593642
o.Funcdataoff[i] = uint32(x)
@@ -637,9 +686,9 @@ func genFuncInfoSyms(ctxt *Link) {
637686
}
638687
}
639688
ctxt.defs = append(ctxt.defs, infosyms...)
689+
ctxt.hasheddefs = append(ctxt.hasheddefs, hashedsyms...)
640690
}
641691

642-
// debugDumpAux is a dumper for selected aux symbols.
643692
func writeAuxSymDebug(ctxt *Link, par *LSym, aux *LSym) {
644693
// Most aux symbols (ex: funcdata) are not interesting--
645694
// pick out just the DWARF ones for now.

0 commit comments

Comments
 (0)