pkg/proc: improve stripped binary support with PIE (#3421)

Take into account static base for PIE binaries.
This commit is contained in:
Derek Parker 2023-06-16 00:38:19 -07:00 committed by GitHub
parent 14d9c1881d
commit 656c4f13df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 6 additions and 47 deletions

@ -609,15 +609,15 @@ func (fn *Function) AllPCs(excludeFile string, excludeLine int) ([]uint64, error
return fn.cu.lineInfo.AllPCsBetween(fn.Entry, fn.End-1, excludeFile, excludeLine)
}
var pcs []uint64
fnFile, lastLine, _ := fn.cu.image.symTable.PCToLine(fn.Entry)
for pc := fn.Entry; pc < fn.End; pc++ {
fnFile, lastLine, _ := fn.cu.image.symTable.PCToLine(fn.Entry - fn.cu.image.StaticBase)
for pc := fn.Entry - fn.cu.image.StaticBase; pc < fn.End-fn.cu.image.StaticBase; pc++ {
f, line, pcfn := fn.cu.image.symTable.PCToLine(pc)
if pcfn == nil {
continue
}
if f == fnFile && line > lastLine {
lastLine = line
pcs = append(pcs, pc)
pcs = append(pcs, pc+fn.cu.image.StaticBase)
}
}
return pcs, nil
@ -762,7 +762,7 @@ func (bi *BinaryInfo) EntryLineForFunc(fn *Function) (string, int) {
func (bi *BinaryInfo) pcToLine(fn *Function, pc uint64) (string, int) {
if fn.cu.lineInfo == nil {
f, l, _ := fn.cu.image.symTable.PCToLine(pc)
f, l, _ := fn.cu.image.symTable.PCToLine(pc - fn.cu.image.StaticBase)
return f, l
}
f, l := fn.cu.lineInfo.PCToLine(fn.Entry, pc)
@ -1461,7 +1461,7 @@ func loadBinaryInfoElf(bi *BinaryInfo, image *Image, path string, addr uint64, w
for _, f := range image.symTable.Funcs {
cu := &compileUnit{}
cu.image = image
fn := Function{Name: f.Name, Entry: f.Entry, End: f.End, cu: cu}
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 {

@ -1,40 +1,11 @@
package proc
import (
"bytes"
"debug/buildinfo"
"debug/elf"
"debug/gosym"
"encoding/binary"
"fmt"
"strings"
)
// From go/src/debug/gosym/pclntab.go
const (
go12magic = 0xfffffffb
go116magic = 0xfffffffa
go118magic = 0xfffffff0
go120magic = 0xfffffff1
)
// Select the magic number based on the Go version
func magicNumber(goVersion string) []byte {
bs := make([]byte, 4)
var magic uint32
if strings.Compare(goVersion, "go1.20") >= 0 {
magic = go120magic
} else if strings.Compare(goVersion, "go1.18") >= 0 {
magic = go118magic
} else if strings.Compare(goVersion, "go1.16") >= 0 {
magic = go116magic
} else {
magic = go12magic
}
binary.LittleEndian.PutUint32(bs, magic)
return bs
}
func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, error) {
// Default section label is .gopclntab
sectionLabel := ".gopclntab"
@ -42,7 +13,7 @@ func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, error) {
section := exe.Section(sectionLabel)
if section == nil {
// binary may be built with -pie
sectionLabel = ".data.rel.ro"
sectionLabel = ".data.rel.ro.gopclntab"
section = exe.Section(sectionLabel)
if section == nil {
return nil, fmt.Errorf("could not read section .gopclntab")
@ -53,17 +24,6 @@ func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, error) {
return nil, fmt.Errorf("found section but could not read .gopclntab")
}
bi, err := buildinfo.ReadFile(path)
if err != nil {
return nil, err
}
// Find .gopclntab by magic number even if there is no section label
magic := magicNumber(bi.GoVersion)
pclntabIndex := bytes.Index(tableData, magic)
if pclntabIndex >= 0 {
tableData = tableData[pclntabIndex:]
}
addr := exe.Section(".text").Addr
lineTable := gosym.NewLineTable(tableData, addr)
symTable, err := gosym.NewTable([]byte{}, lineTable)

@ -3169,7 +3169,6 @@ 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")
skipOn(t, "does not work with PIE", "pie")
withTestProcessArgs("testnextprog", t, "", []string{}, protest.LinkStrip, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {
setFunctionBreakpoint(p, t, "main.main")
assertNoError(grp.Continue(), t, "Continue")