Skip to content

Commit

Permalink
proc: extend macOS workaround to amd64 (go-delve#3204)
Browse files Browse the repository at this point in the history
Go change 064f34f (which exists in Go 1.19.2 and following) removed the
pagezero_size option from linker calls (because it is deprecated). This
expanded the problem that exists on darwin/arm64 as well as PIE builds
on darwin/amd64 to all darwin/amd64 builds.

This problem is described on: golang/go#25841.

This commit extends the darwin/arm64 workaround to darwin/amd64.

Fixes go-delve#3194
  • Loading branch information
aarzilli authored Dec 5, 2022
1 parent 56eed89 commit 5ca60a8
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 5 deletions.
17 changes: 17 additions & 0 deletions _fixtures/issue3194.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

/*
#cgo LDFLAGS: -framework CoreFoundation
#cgo LDFLAGS: -framework CFNetwork
#include <CFNetwork/CFProxySupport.h>
*/
import "C"
import "fmt"

func main() {
f() // break here
}

func f() {
fmt.Println("ok")
}
28 changes: 23 additions & 5 deletions pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -1809,8 +1809,7 @@ func (bi *BinaryInfo) parseDebugFrameMacho(image *Image, exe *macho.File, debugI
//
// [golang/go#25841]: https://github.com/golang/go/issues/25841
func (bi *BinaryInfo) macOSDebugFrameBugWorkaround() {
//TODO: log extensively because of bugs in the field
if bi.GOOS != "darwin" || bi.Arch.Name != "arm64" {
if bi.GOOS != "darwin" {
return
}
if len(bi.Images) > 1 {
Expand All @@ -1823,9 +1822,28 @@ func (bi *BinaryInfo) macOSDebugFrameBugWorkaround() {
if !ok {
return
}
if exe.Flags&macho.FlagPIE == 0 {
bi.logger.Infof("debug_frame workaround not needed: not a PIE (%#x)", exe.Flags)
return
if bi.Arch.Name == "arm64" {
if exe.Flags&macho.FlagPIE == 0 {
bi.logger.Infof("debug_frame workaround not needed: not a PIE (%#x)", exe.Flags)
return
}
} else {
prod := goversion.ParseProducer(bi.Producer())
if !prod.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 19, Rev: 3}) && !prod.IsDevel() {
bi.logger.Infof("debug_frame workaround not needed (version %q on %s)", bi.Producer(), bi.Arch.Name)
return
}
found := false
for i := range bi.frameEntries {
if bi.frameEntries[i].CIE.CIE_id == ^uint32(0) && bi.frameEntries[i].Begin() < 0x4000000 {
found = true
break
}
}
if !found {
bi.logger.Infof("debug_frame workaround not needed (all FDEs above 0x4000000)")
return
}
}

// Find first Go function (first = lowest entry point)
Expand Down
16 changes: 16 additions & 0 deletions pkg/proc/proc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6012,3 +6012,19 @@ func TestGnuDebuglink(t *testing.T) {
}
}
}

func TestStacktraceExtlinkMac(t *testing.T) {
// Tests stacktrace for programs built using external linker.
// See issue #3194
skipUnlessOn(t, "darwin only", "darwin")
withTestProcess("issue3194", t, func(p *proc.Target, fixture protest.Fixture) {
setFunctionBreakpoint(p, t, "main.main")
assertNoError(p.Continue(), t, "First Continue()")
frames, err := proc.ThreadStacktrace(p.CurrentThread(), 10)
assertNoError(err, t, "ThreadStacktrace")
logStacktrace(t, p, frames)
if len(frames) < 2 || frames[0].Call.Fn.Name != "main.main" || frames[1].Call.Fn.Name != "runtime.main" {
t.Fatalf("bad stacktrace")
}
})
}

0 comments on commit 5ca60a8

Please sign in to comment.