Skip to content

Commit 4a72c52

Browse files
authored
pkg/proc: remove usage of gore dependency (#3664)
1 parent f32818c commit 4a72c52

30 files changed

+78
-6849
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ require (
77
github.com/cosiner/argv v0.1.0
88
github.com/creack/pty v1.1.20
99
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d
10-
github.com/go-delve/gore v0.11.8
1110
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62
1211
github.com/google/go-dap v0.11.0
1312
github.com/hashicorp/golang-lru v1.0.2
@@ -29,6 +28,7 @@ require (
2928
github.com/mattn/go-runewidth v0.0.13 // indirect
3029
github.com/rivo/uniseg v0.2.0 // indirect
3130
github.com/russross/blackfriday/v2 v2.1.0 // indirect
31+
github.com/stretchr/testify v1.8.4 // indirect
3232
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
3333
golang.org/x/mod v0.14.0 // indirect
3434
gopkg.in/yaml.v3 v3.0.1 // indirect

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d h1:hUWoLdw5kvo2xC
1313
github.com/derekparker/trie v0.0.0-20230829180723-39f4de51ef7d/go.mod h1:C7Es+DLenIpPc9J6IYw4jrK0h7S9bKj4DNl8+KxGEXU=
1414
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
1515
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
16-
github.com/go-delve/gore v0.11.8 h1:gn1rkroo/RheojBjqCwzIxEVkK3OuwYtla+0GssbYmI=
17-
github.com/go-delve/gore v0.11.8/go.mod h1:6RBVnEUxVGkztpRY0UDUnEzS4GqETQjWrw8rhegmN4I=
1816
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62 h1:IGtvsNyIuRjl04XAOFGACozgUD7A82UffYxZt4DWbvA=
1917
github.com/go-delve/liner v1.2.3-0.20231231155935-4726ab1d7f62/go.mod h1:biJCRbqp51wS+I92HMqn5H8/A0PAhxn2vyOT+JqhiGI=
2018
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=

pkg/proc/bininfo.go

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import (
3333
"github.com/go-delve/delve/pkg/internal/gosym"
3434
"github.com/go-delve/delve/pkg/logflags"
3535
"github.com/go-delve/delve/pkg/proc/debuginfod"
36-
"github.com/go-delve/gore"
3736
"github.com/hashicorp/golang-lru/simplelru"
3837
)
3938

@@ -1458,25 +1457,30 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
14581457
}
14591458
cu := &compileUnit{}
14601459
cu.image = image
1461-
symTable, _, err := readPcLnTableElf(elfFile, path)
1460+
symTable, symTabAddr, err := readPcLnTableElf(elfFile, path)
14621461
if err != nil {
14631462
return fmt.Errorf("could not read debug info (%v) and could not read go symbol table (%v)", dwerr, err)
14641463
}
14651464
image.symTable = symTable
1466-
gorefile, err := gore.Open(path)
1465+
noPtrSectionData, err := elfFile.Section(".noptrdata").Data()
14671466
if err != nil {
14681467
return err
14691468
}
1470-
md, err := gorefile.Moduledata()
1469+
md, err := parseModuleData(noPtrSectionData, symTabAddr)
14711470
if err != nil {
14721471
return err
14731472
}
1474-
prog := gosym.ProgContaining(elfFile, md.GoFuncValue())
1473+
roDataAddr := elfFile.Section(".rodata").Addr
1474+
goFuncVal, err := findGoFuncVal(md, roDataAddr, bi.Arch.ptrSize)
1475+
if err != nil {
1476+
return err
1477+
}
1478+
prog := gosym.ProgContaining(elfFile, goFuncVal)
14751479
inlFuncs := make(map[string]*Function)
14761480
for _, f := range image.symTable.Funcs {
14771481
fnEntry := f.Entry + image.StaticBase
14781482
if prog != nil {
1479-
inlCalls, err := image.symTable.GetInlineTree(&f, md.GoFuncValue(), prog.Vaddr, prog.ReaderAt)
1483+
inlCalls, err := image.symTable.GetInlineTree(&f, goFuncVal, prog.Vaddr, prog.ReaderAt)
14801484
if err != nil {
14811485
return err
14821486
}
@@ -1549,6 +1553,53 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
15491553
return nil
15501554
}
15511555

1556+
func findGoFuncVal(moduleData []byte, roDataAddr uint64, ptrsize int) (uint64, error) {
1557+
buf := new(bytes.Buffer)
1558+
err := binary.Write(buf, binary.LittleEndian, &roDataAddr)
1559+
if err != nil {
1560+
return 0, err
1561+
}
1562+
// Here we search for the value of `go.func.*` by searching through the raw bytes of the
1563+
// runtime.moduledata structure. Since we don't know the value that we are looking for,
1564+
// we use a known value, in this case the address of the .rodata section.
1565+
// This is because in the layout of the struct, the rodata member is right next to
1566+
// the value we need, making the math trivial once we find that member.
1567+
// We use `bytes.LastIndex` specifically because the `types` struct member can also
1568+
// contain the address of the .rodata section, so this pointer can appear multiple times
1569+
// in the raw bytes.
1570+
// Yes, this is very ill-advised low-level hackery but it works fine until
1571+
// https://github.com/golang/go/issues/58474#issuecomment-1785681472 happens.
1572+
// This code path also only runs in stripped binaries, so the whole implementation is
1573+
// best effort anyways.
1574+
rodata := bytes.LastIndex(moduleData, buf.Bytes()[:ptrsize])
1575+
if rodata == -1 {
1576+
return 0, errors.New("could not find rodata struct member")
1577+
}
1578+
// Layout of struct members is:
1579+
// type moduledata struct {
1580+
// ...
1581+
// rodata uintptr
1582+
// gofunc uintptr
1583+
// ...
1584+
// }
1585+
// So do some pointer arithmetic to get the value we need.
1586+
gofuncval := binary.LittleEndian.Uint64(moduleData[rodata+(1*ptrsize) : rodata+(2*ptrsize)])
1587+
return gofuncval, nil
1588+
}
1589+
1590+
func parseModuleData(dataSection []byte, tableAddr uint64) ([]byte, error) {
1591+
buf := new(bytes.Buffer)
1592+
err := binary.Write(buf, binary.LittleEndian, &tableAddr)
1593+
if err != nil {
1594+
return nil, err
1595+
}
1596+
off := bytes.Index(dataSection, buf.Bytes()[:4])
1597+
if off == -1 {
1598+
return nil, errors.New("could not find moduledata")
1599+
}
1600+
return dataSection[off : off+0x300], nil
1601+
}
1602+
15521603
// _STT_FUNC is a code object, see /usr/include/elf.h for a full definition.
15531604
const _STT_FUNC = 2
15541605

@@ -1866,27 +1917,32 @@ func loadBinaryInfoMacho(bi *BinaryInfo, image *Image, path string, entryPoint u
18661917
if len(bi.Images) <= 1 {
18671918
fmt.Fprintln(os.Stderr, "Warning: no debug info found, some functionality will be missing such as stack traces and variable evaluation.")
18681919
}
1869-
symTable, err := readPcLnTableMacho(exe, path)
1920+
symTable, symTabAddr, err := readPcLnTableMacho(exe, path)
18701921
if err != nil {
18711922
return fmt.Errorf("could not read debug info (%v) and could not read go symbol table (%v)", dwerr, err)
18721923
}
18731924
image.symTable = symTable
18741925
cu := &compileUnit{}
18751926
cu.image = image
1876-
gorefile, err := gore.Open(path)
1927+
noPtrSectionData, err := exe.Section("__noptrdata").Data()
1928+
if err != nil {
1929+
return err
1930+
}
1931+
md, err := parseModuleData(noPtrSectionData, symTabAddr)
18771932
if err != nil {
18781933
return err
18791934
}
1880-
md, err := gorefile.Moduledata()
1935+
roDataAddr := exe.Section("__rodata").Addr
1936+
goFuncVal, err := findGoFuncVal(md, roDataAddr, bi.Arch.ptrSize)
18811937
if err != nil {
18821938
return err
18831939
}
1884-
seg := gosym.SegmentContaining(exe, md.GoFuncValue())
1940+
seg := gosym.SegmentContaining(exe, goFuncVal)
18851941
inlFuncs := make(map[string]*Function)
18861942
for _, f := range image.symTable.Funcs {
18871943
fnEntry := f.Entry + image.StaticBase
18881944
if seg != nil {
1889-
inlCalls, err := image.symTable.GetInlineTree(&f, md.GoFuncValue(), seg.Addr, seg.ReaderAt)
1945+
inlCalls, err := image.symTable.GetInlineTree(&f, goFuncVal, seg.Addr, seg.ReaderAt)
18901946
if err != nil {
18911947
return err
18921948
}

pkg/proc/pclntab.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,24 @@ func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, uint64, error)
3535
return symTable, section.Addr, nil
3636
}
3737

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

4242
section := exe.Section(sectionLabel)
4343
if section == nil {
44-
return nil, fmt.Errorf("could not read section __gopclntab")
44+
return nil, 0, fmt.Errorf("could not read section __gopclntab")
4545
}
4646
tableData, err := section.Data()
4747
if err != nil {
48-
return nil, fmt.Errorf("found section but could not read __gopclntab")
48+
return nil, 0, fmt.Errorf("found section but could not read __gopclntab")
4949
}
5050

5151
addr := exe.Section("__text").Addr
5252
lineTable := gosym.NewLineTable(tableData, addr)
5353
symTable, err := gosym.NewTable([]byte{}, lineTable)
5454
if err != nil {
55-
return nil, fmt.Errorf("could not create symbol table from %s ", path)
55+
return nil, 0, fmt.Errorf("could not create symbol table from %s ", path)
5656
}
57-
return symTable, nil
57+
return symTable, section.Addr, nil
5858
}

pkg/proc/proc_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3217,6 +3217,9 @@ func TestDebugStripped2(t *testing.T) {
32173217
if ver.IsDevel() {
32183218
t.Skip("not supported")
32193219
}
3220+
if ver.Major > 0 && ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 22, Rev: -1}) {
3221+
skipOn(t, "not working on linux/arm64 with Go 1.22", "linux", "arm64")
3222+
}
32203223
withTestProcessArgs("inlinestripped", t, "", []string{}, protest.EnableInlining|protest.LinkStrip|protest.LinkDisableDWARF, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {
32213224
setFunctionBreakpointAll(p, t, "fmt.Println")
32223225

service/debugger/debugger.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2089,7 +2089,6 @@ func (d *Debugger) ListDynamicLibraries() []*proc.Image {
20892089
d.targetMutex.Lock()
20902090
defer d.targetMutex.Unlock()
20912091
return d.target.Selected.BinInfo().Images[1:] // skips the first image because it's the executable file
2092-
20932092
}
20942093

20952094
// ExamineMemory returns the raw memory stored at the given address.

vendor/github.com/go-delve/gore/.gitignore

Lines changed: 0 additions & 15 deletions
This file was deleted.

vendor/github.com/go-delve/gore/.gitmodules

Lines changed: 0 additions & 3 deletions
This file was deleted.

vendor/github.com/go-delve/gore/CONTRIBUTING.md

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)