Skip to content

Commit

Permalink
dwarf/line: normalize backslashes for windows executables
Browse files Browse the repository at this point in the history
Starting with Go 1.14 the compiler sometimes emits backslashes as well
as forward slashes in debug_line, normalize everything to / for
conformity with the behavior of previous versions.
  • Loading branch information
aarzilli committed Jan 10, 2020
1 parent 2bd6183 commit 859c7e4
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 9 deletions.
17 changes: 13 additions & 4 deletions pkg/dwarf/line/line_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"encoding/binary"
"path/filepath"
"strings"

"github.com/go-delve/delve/pkg/dwarf/util"
)
Expand Down Expand Up @@ -34,9 +35,12 @@ type DebugLineInfo struct {

// lastMachineCache[pc] is a state machine stopped at an address after pc
lastMachineCache map[uint64]*StateMachine

// staticBase is the address at which the executable is loaded, 0 for non-PIEs
staticBase uint64

// if normalizeBackslash is true all backslashes (\) will be converted into forward slashes (/)
normalizeBackslash bool
}

type FileEntry struct {
Expand All @@ -49,23 +53,23 @@ type FileEntry struct {
type DebugLines []*DebugLineInfo

// ParseAll parses all debug_line segments found in data
func ParseAll(data []byte, logfn func(string, ...interface{}), staticBase uint64) DebugLines {
func ParseAll(data []byte, logfn func(string, ...interface{}), staticBase uint64, normalizeBackslash bool) DebugLines {
var (
lines = make(DebugLines, 0)
buf = bytes.NewBuffer(data)
)

// We have to parse multiple file name tables here.
for buf.Len() > 0 {
lines = append(lines, Parse("", buf, logfn, staticBase))
lines = append(lines, Parse("", buf, logfn, staticBase, normalizeBackslash))
}

return lines
}

// Parse parses a single debug_line segment from buf. Compdir is the
// DW_AT_comp_dir attribute of the associated compile unit.
func Parse(compdir string, buf *bytes.Buffer, logfn func(string, ...interface{}), staticBase uint64) *DebugLineInfo {
func Parse(compdir string, buf *bytes.Buffer, logfn func(string, ...interface{}), staticBase uint64, normalizeBackslash bool) *DebugLineInfo {
dbl := new(DebugLineInfo)
dbl.Logf = logfn
dbl.staticBase = staticBase
Expand All @@ -76,6 +80,7 @@ func Parse(compdir string, buf *bytes.Buffer, logfn func(string, ...interface{})

dbl.stateMachineCache = make(map[uint64]*StateMachine)
dbl.lastMachineCache = make(map[uint64]*StateMachine)
dbl.normalizeBackslash = normalizeBackslash

parseDebugLinePrologue(dbl, buf)
parseIncludeDirs(dbl, buf)
Expand Down Expand Up @@ -139,6 +144,10 @@ func readFileEntry(info *DebugLineInfo, buf *bytes.Buffer, exitOnEmptyPath bool)
return entry
}

if info.normalizeBackslash {
entry.Path = strings.Replace(entry.Path, "\\", "/", -1)
}

entry.DirIdx, _ = util.DecodeULEB128(buf)
entry.LastModTime, _ = util.DecodeULEB128(buf)
entry.Length, _ = util.DecodeULEB128(buf)
Expand Down
6 changes: 3 additions & 3 deletions pkg/dwarf/line/line_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const (

func testDebugLinePrologueParser(p string, t *testing.T) {
data := grabDebugLineSection(p, t)
debugLines := ParseAll(data, nil, 0)
debugLines := ParseAll(data, nil, 0, true)

mainFileFound := false

Expand Down Expand Up @@ -164,7 +164,7 @@ func BenchmarkLineParser(b *testing.B) {

b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = ParseAll(data, nil, 0)
_ = ParseAll(data, nil, 0, true)
}
}

Expand All @@ -179,7 +179,7 @@ func loadBenchmarkData(tb testing.TB) DebugLines {
tb.Fatal("Could not read test data", err)
}

return ParseAll(data, nil, 0)
return ParseAll(data, nil, 0, true)
}

func BenchmarkStateMachine(b *testing.B) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/dwarf/line/state_machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func TestGrafana(t *testing.T) {
}
cuname, _ := e.Val(dwarf.AttrName).(string)

lineInfo := Parse(e.Val(dwarf.AttrCompDir).(string), debugLineBuffer, t.Logf, 0)
lineInfo := Parse(e.Val(dwarf.AttrCompDir).(string), debugLineBuffer, t.Logf, 0, false)
sm := newStateMachine(lineInfo, lineInfo.Instructions)

lnrdr, err := data.LineReader(e)
Expand Down
2 changes: 1 addition & 1 deletion pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,7 @@ func (bi *BinaryInfo) loadDebugInfoMaps(image *Image, debugLineBytes []byte, wg
logger.Printf(fmt, args)
}
}
cu.lineInfo = line.Parse(compdir, bytes.NewBuffer(debugLineBytes[lineInfoOffset:]), logfn, image.StaticBase)
cu.lineInfo = line.Parse(compdir, bytes.NewBuffer(debugLineBytes[lineInfoOffset:]), logfn, image.StaticBase, bi.GOOS == "windows")
}
cu.producer, _ = entry.Val(dwarf.AttrProducer).(string)
if cu.isgo && cu.producer != "" {
Expand Down

0 comments on commit 859c7e4

Please sign in to comment.