
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.
59 lines
1.6 KiB
Go
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
|
|
}
|