pkg/proc: macho: Enable debugging stripped binaries (#3511)

Load a symbol table from pclntab as when debugging stripped ELF
binaries.
This commit is contained in:
Pat Gavlin 2023-09-25 11:41:34 -07:00 committed by GitHub
parent bb59e23f2e
commit 224a2805a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 10 deletions

@ -11,13 +11,16 @@ Tests skipped by each supported backend:
* 2 broken - cgo stacktraces
* darwin/lldb skipped = 1
* 1 upstream issue
* freebsd skipped = 6
* freebsd skipped = 7
* 2 flaky
* 4 not implemented
* linux/386/pie skipped = 1
* 1 not working on freebsd
* linux/386/pie skipped = 2
* 1 broken
* linux/ppc64le skipped = 1
* 1 not working on linux/386 with PIE
* linux/ppc64le skipped = 2
* 1 broken - cgo stacktraces
* 1 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
@ -28,8 +31,9 @@ Tests skipped by each supported backend:
* 6 broken
* 1 broken - global variable symbolication
* 4 not implemented
* windows skipped = 4
* windows skipped = 5
* 1 broken
* 1 not working on windows
* 3 see https://github.com/go-delve/delve/issues/2768
* windows/arm64 skipped = 5
* 3 broken

@ -1822,9 +1822,27 @@ func loadBinaryInfoMacho(bi *BinaryInfo, image *Image, path string, entryPoint u
if !supportedDarwinArch[exe.Cpu] {
return &ErrUnsupportedArch{os: "darwin", cpuArch: exe.Cpu}
}
image.dwarf, err = exe.DWARF()
if err != nil {
return err
var dwerr error
image.dwarf, dwerr = exe.DWARF()
if dwerr != nil {
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)
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
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}
bi.Functions = append(bi.Functions, fn)
}
for f := range image.symTable.Files {
bi.Sources = append(bi.Sources, f)
}
return nil
}
debugInfoBytes, err := godwarf.GetDebugSectionMacho(exe, "info")
if err != nil {

@ -3,6 +3,7 @@ package proc
import (
"debug/elf"
"debug/gosym"
"debug/macho"
"fmt"
)
@ -32,3 +33,25 @@ func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, error) {
}
return symTable, nil
}
func readPcLnTableMacho(exe *macho.File, path string) (*gosym.Table, error) {
// Default section label is __gopclntab
sectionLabel := "__gopclntab"
section := exe.Section(sectionLabel)
if section == nil {
return nil, 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")
}
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 symTable, nil
}

@ -2331,7 +2331,7 @@ func TestStepCallPtr(t *testing.T) {
{6, 7},
{7, 11}}, "", t)
} else {
if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" && buildMode == "pie" {
if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" && buildMode == "pie" {
testseq("teststepprog", contStep, []nextTest{
{9, 10},
{10, 5},
@ -3179,8 +3179,9 @@ func TestShadowedFlag(t *testing.T) {
func TestDebugStripped(t *testing.T) {
// Currently only implemented for Linux ELF executables.
// TODO(derekparker): Add support for Mach-O and PE.
skipUnlessOn(t, "linux only", "linux")
// 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 with PIE", "linux", "386", "pie")
skipOn(t, "not working on linux/ppc64le when -gcflags=-N -l is passed", "linux", "ppc64le")
withTestProcessArgs("testnextprog", t, "", []string{}, protest.LinkStrip, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {