delve/pkg/proc/pclntab.go
Derek Parker 6c77c35586
pkg/proc: add inline function support for stripped binaries (#3549)
This patch adds support for listing and setting breakpoints on inlined functions within stripped binaries. It uses a forked version of `debug/gosym` copied from golang.org/x/vuln/internal/vulncheck/internal/gosym which adds support for parsing the inline tree of the pclntab section. Parsing this section requires knowing the offset of the "go:func.*" symbol, which is not present in stripped binaries via the ``.symtab` section so instead, we search the `.noptrdata` section which contains `runtime.moduledatap` which contains the value of that missing symbol, which we then can use to find the inline tree for a given function.

Given all this we parse the inline tree for each function we find, and then add that information the the appropriate `Function` contained in `bi.Functions`, using a relatively empty `Function` struct as what would be the abstract origin.
2023-11-03 10:00:49 +01:00

59 lines
1.6 KiB
Go

package proc
import (
"debug/elf"
"debug/macho"
"fmt"
"github.com/go-delve/delve/pkg/internal/gosym"
)
func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, uint64, error) {
// Default section label is .gopclntab
sectionLabel := ".gopclntab"
section := exe.Section(sectionLabel)
if section == nil {
// binary may be built with -pie
sectionLabel = ".data.rel.ro.gopclntab"
section = exe.Section(sectionLabel)
if section == nil {
return nil, 0, fmt.Errorf("could not read section .gopclntab")
}
}
tableData, err := section.Data()
if err != nil {
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, 0, fmt.Errorf("could not create symbol table from %s ", path)
}
return symTable, section.Addr, 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
}