proc: correctly set G struct offset for 1.11

The offset of G changed in go1.11 from 0x8a0 to 0x30. See:
https://github.com/golang/go/issues/23617
This commit is contained in:
aarzilli 2018-04-14 11:04:14 +02:00 committed by Derek Parker
parent 5155ef047f
commit 42747a0951
3 changed files with 57 additions and 10 deletions

@ -161,3 +161,18 @@ func VersionAfterOrEqual(version string, major, minor int) bool {
}
return ver.AfterOrEqual(GoVersion{major, minor, -1, 0, 0, ""})
}
const producerVersionPrefix = "Go cmd/compile "
// ProducerAfterOrEqual checks that the DW_AT_producer version is
// major.minor or a later version, or a development version.
func ProducerAfterOrEqual(producer string, major, minor int) bool {
if strings.HasPrefix(producer, producerVersionPrefix) {
producer = producer[len(producerVersionPrefix):]
}
ver, _ := Parse(producer)
if ver.IsDevel() {
return true
}
return ver.AfterOrEqual(GoVersion{major, minor, -1, 0, 0, ""})
}

@ -21,6 +21,7 @@ import (
"github.com/derekparker/delve/pkg/dwarf/line"
"github.com/derekparker/delve/pkg/dwarf/op"
"github.com/derekparker/delve/pkg/dwarf/reader"
"github.com/derekparker/delve/pkg/goversion"
)
type BinaryInfo struct {
@ -75,7 +76,8 @@ type compileUnit struct {
Name string // univocal name for non-go compile units
lineInfo *line.DebugLineInfo // debug_line segment associated with this compile unit
LowPC, HighPC uint64
optimized bool // this compile unit is optimized
optimized bool // this compile unit is optimized
producer string // producer attribute
}
type partialUnitConstant struct {
@ -365,7 +367,7 @@ func (bi *BinaryInfo) LoadFromData(dwdata *dwarf.Data, debugFrameBytes, debugLin
bi.loclistInit(debugLocBytes)
bi.loadDebugInfoMaps(debugLineBytes, nil)
bi.loadDebugInfoMaps(debugLineBytes, nil, nil)
}
func (bi *BinaryInfo) loclistInit(data []byte) {
@ -440,6 +442,15 @@ func (bi *BinaryInfo) findCompileUnit(pc uint64) *compileUnit {
return nil
}
func (bi *BinaryInfo) Producer() string {
for _, cu := range bi.compileUnits {
if cu.isgo && cu.producer != "" {
return cu.producer
}
}
return ""
}
// ELF ///////////////////////////////////////////////////////////////
func (bi *BinaryInfo) LoadBinaryInfoElf(path string, wg *sync.WaitGroup) error {
@ -470,7 +481,7 @@ func (bi *BinaryInfo) LoadBinaryInfoElf(path string, wg *sync.WaitGroup) error {
wg.Add(3)
go bi.parseDebugFrameElf(elfFile, wg)
go bi.loadDebugInfoMaps(debugLineBytes, wg)
go bi.loadDebugInfoMaps(debugLineBytes, wg, nil)
go bi.setGStructOffsetElf(elfFile, wg)
return nil
}
@ -582,7 +593,7 @@ func (bi *BinaryInfo) LoadBinaryInfoPE(path string, wg *sync.WaitGroup) error {
wg.Add(2)
go bi.parseDebugFramePE(peFile, wg)
go bi.loadDebugInfoMaps(debugLineBytes, wg)
go bi.loadDebugInfoMaps(debugLineBytes, wg, nil)
// Use ArbitraryUserPointer (0x28) as pointer to pointer
// to G struct per:
@ -750,11 +761,22 @@ func (bi *BinaryInfo) LoadBinaryInfoMacho(path string, wg *sync.WaitGroup) error
wg.Add(2)
go bi.parseDebugFrameMacho(exe, wg)
go bi.loadDebugInfoMaps(debugLineBytes, wg)
bi.gStructOffset = 0x8a0
go bi.loadDebugInfoMaps(debugLineBytes, wg, bi.setGStructOffsetMacho)
return nil
}
func (bi *BinaryInfo) setGStructOffsetMacho() {
// In go1.11 it's 0x30, before 0x8a0, see:
// https://github.com/golang/go/issues/23617
// and go commit b3a854c733257c5249c3435ffcee194f8439676a
producer := bi.Producer()
if producer != "" && goversion.ProducerAfterOrEqual(producer, 1, 11) {
bi.gStructOffset = 0x30
return
}
bi.gStructOffset = 0x8a0
}
func (bi *BinaryInfo) parseDebugFrameMacho(exe *macho.File, wg *sync.WaitGroup) {
defer wg.Done()

@ -178,7 +178,7 @@ func (v packageVarsByAddr) Len() int { return len(v) }
func (v packageVarsByAddr) Less(i int, j int) bool { return v[i].addr < v[j].addr }
func (v packageVarsByAddr) Swap(i int, j int) { v[i], v[j] = v[j], v[i] }
func (bi *BinaryInfo) loadDebugInfoMaps(debugLineBytes []byte, wg *sync.WaitGroup) {
func (bi *BinaryInfo) loadDebugInfoMaps(debugLineBytes []byte, wg *sync.WaitGroup, cont func()) {
if wg != nil {
defer wg.Done()
}
@ -220,9 +220,15 @@ func (bi *BinaryInfo) loadDebugInfoMaps(debugLineBytes []byte, wg *sync.WaitGrou
cu.lineInfo = line.Parse(compdir, bytes.NewBuffer(debugLineBytes[lineInfoOffset:]))
cu.lineInfo.LogSuppressedErrors(logflags.DebugLineErrors())
}
if producer, _ := entry.Val(dwarf.AttrProducer).(string); cu.isgo && producer != "" {
semicolon := strings.Index(producer, ";")
cu.optimized = semicolon < 0 || !strings.Contains(producer[semicolon:], "-N") || !strings.Contains(producer[semicolon:], "-l")
cu.producer, _ = entry.Val(dwarf.AttrProducer).(string)
if cu.isgo {
semicolon := strings.Index(cu.producer, ";")
if semicolon < 0 {
cu.optimized = true
} else {
cu.optimized = !strings.Contains(cu.producer[semicolon:], "-N") || !strings.Contains(cu.producer[semicolon:], "-l")
cu.producer = cu.producer[:semicolon]
}
}
bi.compileUnits = append(bi.compileUnits, cu)
@ -395,6 +401,10 @@ func (bi *BinaryInfo) loadDebugInfoMaps(debugLineBytes []byte, wg *sync.WaitGrou
}
sort.Strings(bi.Sources)
bi.Sources = uniq(bi.Sources)
if cont != nil {
cont()
}
}
func uniq(s []string) []string {