Skip to content

Commit

Permalink
pkg/proc: remove usage of gore dependency (#3664)
Browse files Browse the repository at this point in the history
  • Loading branch information
derekparker authored Feb 21, 2024
1 parent f32818c commit 4a72c52
Show file tree
Hide file tree
Showing 30 changed files with 78 additions and 6,849 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
github.com/cosiner/argv v0.1.0
github.com/creack/pty v1.1.20
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d
github.com/go-delve/gore v0.11.8
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62
github.com/google/go-dap v0.11.0
github.com/hashicorp/golang-lru v1.0.2
Expand All @@ -29,6 +28,7 @@ require (
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/stretchr/testify v1.8.4 // indirect
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
golang.org/x/mod v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d h1:hUWoLdw5kvo2xC
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d/go.mod h1:C7Es+DLenIpPc9J6IYw4jrK0h7S9bKj4DNl8+KxGEXU=
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/go-delve/gore v0.11.8 h1:gn1rkroo/RheojBjqCwzIxEVkK3OuwYtla+0GssbYmI=
github.com/go-delve/gore v0.11.8/go.mod h1:6RBVnEUxVGkztpRY0UDUnEzS4GqETQjWrw8rhegmN4I=
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62 h1:IGtvsNyIuRjl04XAOFGACozgUD7A82UffYxZt4DWbvA=
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62/go.mod h1:biJCRbqp51wS+I92HMqn5H8/A0PAhxn2vyOT+JqhiGI=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
Expand Down
78 changes: 67 additions & 11 deletions pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import (
"github.com/go-delve/delve/pkg/internal/gosym"
"github.com/go-delve/delve/pkg/logflags"
"github.com/go-delve/delve/pkg/proc/debuginfod"
"github.com/go-delve/gore"
"github.com/hashicorp/golang-lru/simplelru"
)

Expand Down Expand Up @@ -1458,25 +1457,30 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
}
cu := &compileUnit{}
cu.image = image
symTable, _, err := readPcLnTableElf(elfFile, path)
symTable, symTabAddr, 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
gorefile, err := gore.Open(path)
noPtrSectionData, err := elfFile.Section(".noptrdata").Data()
if err != nil {
return err
}
md, err := gorefile.Moduledata()
md, err := parseModuleData(noPtrSectionData, symTabAddr)
if err != nil {
return err
}
prog := gosym.ProgContaining(elfFile, md.GoFuncValue())
roDataAddr := elfFile.Section(".rodata").Addr
goFuncVal, err := findGoFuncVal(md, roDataAddr, bi.Arch.ptrSize)
if err != nil {
return err
}
prog := gosym.ProgContaining(elfFile, goFuncVal)
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, md.GoFuncValue(), prog.Vaddr, prog.ReaderAt)
inlCalls, err := image.symTable.GetInlineTree(&f, goFuncVal, prog.Vaddr, prog.ReaderAt)
if err != nil {
return err
}
Expand Down Expand Up @@ -1549,6 +1553,53 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
return nil
}

func findGoFuncVal(moduleData []byte, roDataAddr uint64, ptrsize int) (uint64, error) {
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, &roDataAddr)
if err != nil {
return 0, err
}
// Here we search for the value of `go.func.*` by searching through the raw bytes of the
// runtime.moduledata structure. Since we don't know the value that we are looking for,
// we use a known value, in this case the address of the .rodata section.
// This is because in the layout of the struct, the rodata member is right next to
// the value we need, making the math trivial once we find that member.
// We use `bytes.LastIndex` specifically because the `types` struct member can also
// contain the address of the .rodata section, so this pointer can appear multiple times
// in the raw bytes.
// Yes, this is very ill-advised low-level hackery but it works fine until
// https://github.com/golang/go/issues/58474#issuecomment-1785681472 happens.
// This code path also only runs in stripped binaries, so the whole implementation is
// best effort anyways.
rodata := bytes.LastIndex(moduleData, buf.Bytes()[:ptrsize])
if rodata == -1 {
return 0, errors.New("could not find rodata struct member")
}
// Layout of struct members is:
// type moduledata struct {
// ...
// rodata uintptr
// gofunc uintptr
// ...
// }
// So do some pointer arithmetic to get the value we need.
gofuncval := binary.LittleEndian.Uint64(moduleData[rodata+(1*ptrsize) : rodata+(2*ptrsize)])
return gofuncval, nil
}

func parseModuleData(dataSection []byte, tableAddr uint64) ([]byte, error) {
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, &tableAddr)
if err != nil {
return nil, err
}
off := bytes.Index(dataSection, buf.Bytes()[:4])
if off == -1 {
return nil, errors.New("could not find moduledata")
}
return dataSection[off : off+0x300], nil
}

// _STT_FUNC is a code object, see /usr/include/elf.h for a full definition.
const _STT_FUNC = 2

Expand Down Expand Up @@ -1866,27 +1917,32 @@ func loadBinaryInfoMacho(bi *BinaryInfo, image *Image, path string, entryPoint u
if len(bi.Images) <= 1 {
fmt.Fprintln(os.Stderr, "Warning: no debug info found, some functionality will be missing such as stack traces and variable evaluation.")
}
symTable, err := readPcLnTableMacho(exe, path)
symTable, symTabAddr, err := readPcLnTableMacho(exe, 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
cu := &compileUnit{}
cu.image = image
gorefile, err := gore.Open(path)
noPtrSectionData, err := exe.Section("__noptrdata").Data()
if err != nil {
return err
}
md, err := parseModuleData(noPtrSectionData, symTabAddr)
if err != nil {
return err
}
md, err := gorefile.Moduledata()
roDataAddr := exe.Section("__rodata").Addr
goFuncVal, err := findGoFuncVal(md, roDataAddr, bi.Arch.ptrSize)
if err != nil {
return err
}
seg := gosym.SegmentContaining(exe, md.GoFuncValue())
seg := gosym.SegmentContaining(exe, goFuncVal)
inlFuncs := make(map[string]*Function)
for _, f := range image.symTable.Funcs {
fnEntry := f.Entry + image.StaticBase
if seg != nil {
inlCalls, err := image.symTable.GetInlineTree(&f, md.GoFuncValue(), seg.Addr, seg.ReaderAt)
inlCalls, err := image.symTable.GetInlineTree(&f, goFuncVal, seg.Addr, seg.ReaderAt)
if err != nil {
return err
}
Expand Down
10 changes: 5 additions & 5 deletions pkg/proc/pclntab.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,24 @@ func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, uint64, error)
return symTable, section.Addr, nil
}

func readPcLnTableMacho(exe *macho.File, path string) (*gosym.Table, error) {
func readPcLnTableMacho(exe *macho.File, path string) (*gosym.Table, uint64, error) {
// Default section label is __gopclntab
sectionLabel := "__gopclntab"

section := exe.Section(sectionLabel)
if section == nil {
return nil, fmt.Errorf("could not read section __gopclntab")
return nil, 0, fmt.Errorf("could not read section __gopclntab")
}
tableData, err := section.Data()
if err != nil {
return nil, fmt.Errorf("found section but could not read __gopclntab")
return nil, 0, fmt.Errorf("found section but could not read __gopclntab")
}

addr := exe.Section("__text").Addr
lineTable := gosym.NewLineTable(tableData, addr)
symTable, err := gosym.NewTable([]byte{}, lineTable)
if err != nil {
return nil, fmt.Errorf("could not create symbol table from %s ", path)
return nil, 0, fmt.Errorf("could not create symbol table from %s ", path)
}
return symTable, nil
return symTable, section.Addr, nil
}
3 changes: 3 additions & 0 deletions pkg/proc/proc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3217,6 +3217,9 @@ func TestDebugStripped2(t *testing.T) {
if ver.IsDevel() {
t.Skip("not supported")
}
if ver.Major > 0 && ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 22, Rev: -1}) {
skipOn(t, "not working on linux/arm64 with Go 1.22", "linux", "arm64")
}
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")

Expand Down
1 change: 0 additions & 1 deletion service/debugger/debugger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2089,7 +2089,6 @@ func (d *Debugger) ListDynamicLibraries() []*proc.Image {
d.targetMutex.Lock()
defer d.targetMutex.Unlock()
return d.target.Selected.BinInfo().Images[1:] // skips the first image because it's the executable file

}

// ExamineMemory returns the raw memory stored at the given address.
Expand Down
15 changes: 0 additions & 15 deletions vendor/github.com/go-delve/gore/.gitignore

This file was deleted.

3 changes: 0 additions & 3 deletions vendor/github.com/go-delve/gore/.gitmodules

This file was deleted.

27 changes: 0 additions & 27 deletions vendor/github.com/go-delve/gore/CONTRIBUTING.md

This file was deleted.

Loading

0 comments on commit 4a72c52

Please sign in to comment.