Skip to content

Commit

Permalink
pkg/proc: use gore to obtain info from stripped binaries (#3577)
Browse files Browse the repository at this point in the history
This patch switches from using a forked version of one of the libraries
of goretk/gore to using the module directly. This is possible now that
certain functionality has been exposed / fixed within that module making
it usable for Delve.
  • Loading branch information
derekparker authored Nov 23, 2023
1 parent 08eced2 commit 6e8e1ce
Show file tree
Hide file tree
Showing 33 changed files with 6,899 additions and 300 deletions.
16 changes: 8 additions & 8 deletions Documentation/backend_test_health.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ Tests skipped by each supported backend:
* 1 broken - cgo stacktraces
* darwin/lldb skipped = 1
* 1 upstream issue
* freebsd skipped = 9
* freebsd skipped = 10
* 2 flaky
* 2 follow exec not implemented on freebsd
* 4 not implemented
* 1 not working on freebsd
* linux/386 skipped = 1
* 1 not working on linux/386
* 2 not working on freebsd
* linux/386 skipped = 2
* 2 not working on linux/386
* linux/386/pie skipped = 1
* 1 broken
* linux/ppc64le skipped = 2
* linux/ppc64le skipped = 3
* 1 broken - cgo stacktraces
* 1 not working on linux/ppc64le when -gcflags=-N -l is passed
* 2 not working on linux/ppc64le when -gcflags=-N -l is passed
* linux/ppc64le/native skipped = 1
* 1 broken in linux ppc64le
* linux/ppc64le/native/pie skipped = 3
Expand All @@ -35,9 +35,9 @@ Tests skipped by each supported backend:
* 6 broken
* 1 broken - global variable symbolication
* 4 not implemented
* windows skipped = 5
* windows skipped = 6
* 1 broken
* 1 not working on windows
* 2 not working on windows
* 3 see https://github.com/go-delve/delve/issues/2768
* windows/arm64 skipped = 5
* 3 broken
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ require (
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d
github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d
github.com/google/go-dap v0.11.0
github.com/goretk/gore v0.11.3
github.com/hashicorp/golang-lru v1.0.2
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.20
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
go.starlark.net v0.0.0-20231101134539-556fd59b42f6
golang.org/x/arch v0.5.0
golang.org/x/arch v0.6.0
golang.org/x/sys v0.13.0
golang.org/x/tools v0.14.0
gopkg.in/yaml.v2 v2.4.0
Expand All @@ -29,6 +30,6 @@ require (
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/mod v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
131 changes: 8 additions & 123 deletions go.sum

Large diffs are not rendered by default.

Binary file added inlinestripped
Binary file not shown.
10 changes: 10 additions & 0 deletions pkg/internal/gosym/symtab.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package gosym
import (
"bytes"
"debug/elf"
"debug/macho"
"encoding/binary"
"fmt"
"io"
Expand Down Expand Up @@ -150,6 +151,15 @@ func ProgContaining(elfFile *elf.File, addr uint64) *elf.Prog {
return nil
}

func SegmentContaining(exe *macho.File, addr uint64) *macho.Segment {
for _, l := range exe.Loads {
if s, ok := l.(*macho.Segment); ok && s.Addr <= addr && addr < s.Addr+s.Filesz {
return s
}
}
return nil
}

// An Obj represents a collection of functions in a symbol table.
//
// The exact method of division of a binary into separate Objs is an internal detail
Expand Down
86 changes: 0 additions & 86 deletions pkg/internal/moduledata/moduledata.go

This file was deleted.

67 changes: 0 additions & 67 deletions pkg/internal/moduledata/moduledata_test.go

This file was deleted.

58 changes: 50 additions & 8 deletions pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ import (
"github.com/go-delve/delve/pkg/dwarf/reader"
"github.com/go-delve/delve/pkg/goversion"
"github.com/go-delve/delve/pkg/internal/gosym"
"github.com/go-delve/delve/pkg/internal/moduledata"
"github.com/go-delve/delve/pkg/logflags"
"github.com/go-delve/delve/pkg/proc/debuginfod"
"github.com/goretk/gore"
"github.com/hashicorp/golang-lru/simplelru"
)

Expand Down Expand Up @@ -1458,21 +1458,25 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
}
cu := &compileUnit{}
cu.image = image
symTable, pcLnTabAddr, err := readPcLnTableElf(elfFile, path)
symTable, _, err := readPcLnTableElf(elfFile, path)
if err != nil {
return fmt.Errorf("could not read debug info (%v) and could not read go symbol table (%v)", dwerr, err)
}
image.symTable = symTable
goFuncVal, err := moduledata.GetGoFuncValue(elfFile, pcLnTabAddr)
gorefile, err := gore.Open(path)
if err != nil {
return err
}
prog := gosym.ProgContaining(elfFile, goFuncVal)
md, err := gorefile.Moduledata()
if err != nil {
return err
}
prog := gosym.ProgContaining(elfFile, md.GoFuncValue())
inlFuncs := make(map[string]*Function)
for _, f := range image.symTable.Funcs {
fnEntry := f.Entry + image.StaticBase
if prog != nil {
inlCalls, err := image.symTable.GetInlineTree(&f, goFuncVal, prog.Vaddr, prog.ReaderAt)
inlCalls, err := image.symTable.GetInlineTree(&f, md.GoFuncValue(), prog.Vaddr, prog.ReaderAt)
if err != nil {
return err
}
Expand Down Expand Up @@ -1867,15 +1871,53 @@ func loadBinaryInfoMacho(bi *BinaryInfo, image *Image, path string, entryPoint u
return fmt.Errorf("could not read debug info (%v) and could not read go symbol table (%v)", dwerr, err)
}
image.symTable = symTable
cu := &compileUnit{}
cu.image = image
gorefile, err := gore.Open(path)
if err != nil {
return err
}
md, err := gorefile.Moduledata()
if err != nil {
return err
}
seg := gosym.SegmentContaining(exe, md.GoFuncValue())
inlFuncs := make(map[string]*Function)
for _, f := range image.symTable.Funcs {
cu := &compileUnit{}
cu.image = image
fn := Function{Name: f.Name, Entry: f.Entry + image.StaticBase, End: f.End + image.StaticBase, cu: cu}
fnEntry := f.Entry + image.StaticBase
if seg != nil {
inlCalls, err := image.symTable.GetInlineTree(&f, md.GoFuncValue(), seg.Addr, seg.ReaderAt)
if err != nil {
return err
}
for _, inlfn := range inlCalls {
newInlinedCall := InlinedCall{cu: cu, LowPC: fnEntry + uint64(inlfn.ParentPC)}
if fn, ok := inlFuncs[inlfn.Name]; ok {
fn.InlinedCalls = append(fn.InlinedCalls, newInlinedCall)
continue
}
inlFuncs[inlfn.Name] = &Function{
Name: inlfn.Name,
Entry: 0, End: 0,
cu: cu,
InlinedCalls: []InlinedCall{
newInlinedCall,
},
}
}
}
fn := Function{Name: f.Name, Entry: fnEntry, End: f.End + image.StaticBase, cu: cu}
bi.Functions = append(bi.Functions, fn)
}
for i := range inlFuncs {
bi.Functions = append(bi.Functions, *inlFuncs[i])
}
sort.Sort(functionsDebugInfoByEntry(bi.Functions))
for f := range image.symTable.Files {
bi.Sources = append(bi.Sources, f)
}
sort.Strings(bi.Sources)
bi.Sources = uniq(bi.Sources)
return nil
}
debugInfoBytes, err := godwarf.GetDebugSectionMacho(exe, "info")
Expand Down
9 changes: 6 additions & 3 deletions pkg/proc/proc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3204,12 +3204,15 @@ func TestDebugStripped(t *testing.T) {

func TestDebugStripped2(t *testing.T) {
// Currently only implemented for Linux ELF executables.
// TODO(derekparker): Add support for Mach-O and PE.
skipUnlessOn(t, "linux/amd64 only", "linux", "amd64")
// TODO(derekparker): Add support for PE.
skipOn(t, "not working on windows", "windows")
skipOn(t, "not working on freebsd", "freebsd")
skipOn(t, "not working on linux/386", "linux", "386")
skipOn(t, "not working on linux/ppc64le when -gcflags=-N -l is passed", "linux", "ppc64le")
if !goversion.VersionAfterOrEqual(runtime.Version(), 1, 20) {
t.Skip("temporarily disabled on Go versions < 1.20")
}
withTestProcessArgs("inlinestripped", t, "", []string{}, protest.EnableInlining|protest.LinkStrip, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {
withTestProcessArgs("inlinestripped", t, "", []string{}, protest.EnableInlining|protest.LinkStrip|protest.LinkDisableDWARF, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {
setFunctionBreakpointAll(p, t, "fmt.Println")

for i, line := range []int{12, 13, 14} {
Expand Down
15 changes: 15 additions & 0 deletions vendor/github.com/goretk/gore/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions vendor/github.com/goretk/gore/.gitmodules

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6e8e1ce

Please sign in to comment.