pkg/proc: improve stripped binary support with PIE (#3421)
Take into account static base for PIE binaries.
This commit is contained in:
parent
14d9c1881d
commit
656c4f13df
@ -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)
|
return fn.cu.lineInfo.AllPCsBetween(fn.Entry, fn.End-1, excludeFile, excludeLine)
|
||||||
}
|
}
|
||||||
var pcs []uint64
|
var pcs []uint64
|
||||||
fnFile, lastLine, _ := fn.cu.image.symTable.PCToLine(fn.Entry)
|
fnFile, lastLine, _ := fn.cu.image.symTable.PCToLine(fn.Entry - fn.cu.image.StaticBase)
|
||||||
for pc := fn.Entry; pc < fn.End; pc++ {
|
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)
|
f, line, pcfn := fn.cu.image.symTable.PCToLine(pc)
|
||||||
if pcfn == nil {
|
if pcfn == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if f == fnFile && line > lastLine {
|
if f == fnFile && line > lastLine {
|
||||||
lastLine = line
|
lastLine = line
|
||||||
pcs = append(pcs, pc)
|
pcs = append(pcs, pc+fn.cu.image.StaticBase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pcs, nil
|
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) {
|
func (bi *BinaryInfo) pcToLine(fn *Function, pc uint64) (string, int) {
|
||||||
if fn.cu.lineInfo == nil {
|
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
|
return f, l
|
||||||
}
|
}
|
||||||
f, l := fn.cu.lineInfo.PCToLine(fn.Entry, pc)
|
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 {
|
for _, f := range image.symTable.Funcs {
|
||||||
cu := &compileUnit{}
|
cu := &compileUnit{}
|
||||||
cu.image = image
|
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)
|
bi.Functions = append(bi.Functions, fn)
|
||||||
}
|
}
|
||||||
for f := range image.symTable.Files {
|
for f := range image.symTable.Files {
|
||||||
|
|||||||
@ -1,40 +1,11 @@
|
|||||||
package proc
|
package proc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"debug/buildinfo"
|
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"debug/gosym"
|
"debug/gosym"
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"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) {
|
func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, error) {
|
||||||
// Default section label is .gopclntab
|
// Default section label is .gopclntab
|
||||||
sectionLabel := ".gopclntab"
|
sectionLabel := ".gopclntab"
|
||||||
@ -42,7 +13,7 @@ func readPcLnTableElf(exe *elf.File, path string) (*gosym.Table, error) {
|
|||||||
section := exe.Section(sectionLabel)
|
section := exe.Section(sectionLabel)
|
||||||
if section == nil {
|
if section == nil {
|
||||||
// binary may be built with -pie
|
// binary may be built with -pie
|
||||||
sectionLabel = ".data.rel.ro"
|
sectionLabel = ".data.rel.ro.gopclntab"
|
||||||
section = exe.Section(sectionLabel)
|
section = exe.Section(sectionLabel)
|
||||||
if section == nil {
|
if section == nil {
|
||||||
return nil, fmt.Errorf("could not read section .gopclntab")
|
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")
|
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
|
addr := exe.Section(".text").Addr
|
||||||
lineTable := gosym.NewLineTable(tableData, addr)
|
lineTable := gosym.NewLineTable(tableData, addr)
|
||||||
symTable, err := gosym.NewTable([]byte{}, lineTable)
|
symTable, err := gosym.NewTable([]byte{}, lineTable)
|
||||||
|
|||||||
@ -3169,7 +3169,6 @@ func TestDebugStripped(t *testing.T) {
|
|||||||
// Currently only implemented for Linux ELF executables.
|
// Currently only implemented for Linux ELF executables.
|
||||||
// TODO(derekparker): Add support for Mach-O and PE.
|
// TODO(derekparker): Add support for Mach-O and PE.
|
||||||
skipUnlessOn(t, "linux only", "linux")
|
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) {
|
withTestProcessArgs("testnextprog", t, "", []string{}, protest.LinkStrip, func(p *proc.Target, grp *proc.TargetGroup, f protest.Fixture) {
|
||||||
setFunctionBreakpoint(p, t, "main.main")
|
setFunctionBreakpoint(p, t, "main.main")
|
||||||
assertNoError(grp.Continue(), t, "Continue")
|
assertNoError(grp.Continue(), t, "Continue")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user