Skip to content
Permalink
Browse files

proc: correctly set G struct offset for 1.11

The offset of G changed in go1.11 from 0x8a0 to 0x30. See:
golang/go#23617
  • Loading branch information...
aarzilli committed Apr 14, 2018
1 parent 5e8540c commit 116637f266f30adf614aba5c51f241c5e309ff08
Showing with 58 additions and 11 deletions.
  1. +16 −1 pkg/goversion/go_version.go
  2. +28 −6 pkg/proc/bininfo.go
  3. +14 −4 pkg/proc/types.go
@@ -153,11 +153,26 @@ func Installed() (GoVersion, bool) {
}

// RuntimeAfterOrEqual checks that the runtime version is major.minor or a
// later version or a development version.
// later version, or a development version.
func RuntimeAfterOrEqual(major, minor int) bool {
ver, _ := Parse(runtime.Version())
if ver.IsDevel() {
return true
}
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
}

// Function describes a function in the target program.
@@ -352,7 +354,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) {
@@ -427,6 +429,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 {
@@ -457,7 +468,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
}
@@ -569,7 +580,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:
@@ -737,11 +748,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()

@@ -177,7 +177,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()
}
@@ -212,9 +212,15 @@ func (bi *BinaryInfo) loadDebugInfoMaps(debugLineBytes []byte, wg *sync.WaitGrou
if lineInfoOffset >= 0 && lineInfoOffset < int64(len(debugLineBytes)) {
cu.lineInfo = line.Parse(compdir, bytes.NewBuffer(debugLineBytes[lineInfoOffset:]))
}
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)

@@ -302,6 +308,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 {

0 comments on commit 116637f

Please sign in to comment.
You can’t perform that action at this time.