Skip to content

Commit e6e7aeb

Browse files
authored
dwarf,proc: various fixes to support DWARFv5 (#3893)
Miscellaneous fixes to our DWARFv5 implementation, several contributed by @thanm.
1 parent 1df310a commit e6e7aeb

File tree

7 files changed

+34
-12
lines changed

7 files changed

+34
-12
lines changed

pkg/dwarf/line/line_parser.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,11 @@ func Parse(compdir string, buf *bytes.Buffer, debugLineStr []byte, logfn func(st
116116
// - dbl.Prologue.UnitLength is the length of the entire unit, not including the 4 bytes to represent that length.
117117
// - dbl.Prologue.Length is the length of the prologue not including unit length, version or prologue length itself.
118118
// - So you have UnitLength - PrologueLength - (version_length_bytes(2) + prologue_length_bytes(4)).
119-
dbl.Instructions = buf.Next(int(dbl.Prologue.UnitLength - dbl.Prologue.Length - 6))
119+
verDelta := uint32(6)
120+
if dbl.Prologue.Version >= 5 {
121+
verDelta = uint32(8)
122+
}
123+
dbl.Instructions = buf.Next(int(dbl.Prologue.UnitLength - dbl.Prologue.Length - verDelta))
120124

121125
return dbl
122126
}

pkg/dwarf/line/line_parser_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const (
6363
lineRangeGo18 uint8 = 10
6464
versionGo14 uint16 = 2
6565
versionGo111 uint16 = 3
66+
versionGo125 uint16 = 5
6667
opcodeBaseGo14 uint8 = 10
6768
opcodeBaseGo111 uint8 = 11
6869
)
@@ -79,7 +80,7 @@ func testDebugLinePrologueParser(p string, t *testing.T) {
7980
for _, dbl := range debugLines {
8081
prologue := dbl.Prologue
8182

82-
if prologue.Version != versionGo14 && prologue.Version != versionGo111 {
83+
if prologue.Version != versionGo14 && prologue.Version != versionGo111 && prologue.Version != versionGo125 {
8384
t.Fatal("Version not parsed correctly", prologue.Version)
8485
}
8586

pkg/dwarf/line/state_machine.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func newStateMachine(dbl *DebugLineInfo, instructions []byte, ptrSize int) *Stat
106106
}
107107
var file string
108108
if len(dbl.FileNames) > 0 {
109-
file = dbl.FileNames[0].Path
109+
file = dbl.defaultFile()
110110
}
111111
dbl.endSeqIsValid = true
112112
sm := &StateMachine{
@@ -123,6 +123,22 @@ func newStateMachine(dbl *DebugLineInfo, instructions []byte, ptrSize int) *Stat
123123
return sm
124124
}
125125

126+
func (dbl *DebugLineInfo) defaultFile() string {
127+
// The default file is always file 1, however DWARFv5 starts numbering the
128+
// entries of the files table from 0 but prior versions started with 1
129+
// which means that for DWARFv4 and earlier the default file is the first
130+
// entry of the table where in DWARFv5 the default is the second entry.
131+
// See DWARFv4 and DWARFv5 section 6.2.4 at the end.
132+
if dbl.Prologue.Version < 5 {
133+
return dbl.FileNames[0].Path
134+
}
135+
if len(dbl.FileNames) == 1 {
136+
// DWARFv5 doesn't say what should happen in this case.
137+
return dbl.FileNames[0].Path
138+
}
139+
return dbl.FileNames[1].Path
140+
}
141+
126142
// AllPCsForFileLines Adds all PCs for a given file and set (domain of map) of lines
127143
// to the map value corresponding to each line.
128144
func (lineInfo *DebugLineInfo) AllPCsForFileLines(f string, m map[int][]uint64) {
@@ -390,7 +406,7 @@ func (sm *StateMachine) next() error {
390406
}
391407
if sm.endSeq {
392408
sm.endSeq = false
393-
sm.file = sm.dbl.FileNames[0].Path
409+
sm.file = sm.dbl.defaultFile()
394410
sm.line = 1
395411
sm.column = 0
396412
sm.isa = 0

pkg/dwarf/parseutil.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func ReadUnitVersions(data []byte) map[dwarf.Offset]uint8 {
131131

132132
switch unitType {
133133
case _DW_UT_compile, _DW_UT_partial:
134-
headerSize = 5 + secoffsz
134+
headerSize = 4 + secoffsz
135135

136136
case _DW_UT_skeleton, _DW_UT_split_compile:
137137
headerSize = 4 + secoffsz + 8

pkg/proc/bininfo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import (
4242

4343
const (
4444
dwarfGoLanguage = 22 // DW_LANG_Go (from DWARF v5, section 7.12, page 231)
45-
dwarfAttrAddrBase = 0x74 // debug/dwarf.AttrAddrBase in Go 1.14, defined here for compatibility with Go < 1.14
45+
dwarfAttrAddrBase = 0x73 // debug/dwarf.AttrAddrBase in Go 1.14, defined here for compatibility with Go < 1.14
4646
dwarfTreeCacheSize = 512 // size of the dwarfTree cache of each image
4747
)
4848

pkg/proc/proc_general_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func TestDwarfVersion(t *testing.T) {
136136
const fakeEntryPoint = 1
137137
assertNoError(bi.LoadBinaryInfo(fixture.Path, fakeEntryPoint, nil), t, "LoadBinaryInfo")
138138
for _, cu := range bi.Images[0].compileUnits {
139-
if cu.Version != 4 {
139+
if cu.Version != 4 && cu.Version != 5 {
140140
t.Errorf("compile unit %q at %#x has bad version %d", cu.name, cu.entry.Offset, cu.Version)
141141
}
142142
}

pkg/proc/proc_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -720,13 +720,13 @@ func TestStacktrace(t *testing.T) {
720720
locations, err := proc.ThreadStacktrace(p, p.CurrentThread(), 40)
721721
assertNoError(err, t, "Stacktrace()")
722722

723-
if len(locations) != len(stacks[i])+2 {
724-
t.Fatalf("Wrong stack trace size %d %d\n", len(locations), len(stacks[i])+2)
725-
}
726-
727723
t.Logf("Stacktrace %d:\n", i)
728724
for i := range locations {
729-
t.Logf("\t%s:%d\n", locations[i].Call.File, locations[i].Call.Line)
725+
t.Logf("\t%s (%#x) %s:%d\n", locations[i].Call.Fn.Name, locations[i].Call.PC, locations[i].Call.File, locations[i].Call.Line)
726+
}
727+
728+
if len(locations) != len(stacks[i])+2 {
729+
t.Fatalf("Wrong stack trace size %d %d\n", len(locations), len(stacks[i])+2)
730730
}
731731

732732
for j := range stacks[i] {
@@ -3193,6 +3193,7 @@ func testDeclLineCount(t *testing.T, p *proc.Target, lineno int, tgtvars []strin
31933193

31943194
assertLineNumber(p, t, lineno, "Program did not continue to correct next location")
31953195
scope, err := proc.GoroutineScope(p, p.CurrentThread())
3196+
t.Logf("scope PC: %#x\n", scope.PC)
31963197
assertNoError(err, t, fmt.Sprintf("GoroutineScope (:%d)", lineno))
31973198
vars, err := scope.Locals(0, "")
31983199
assertNoError(err, t, fmt.Sprintf("Locals (:%d)", lineno))

0 commit comments

Comments
 (0)