Skip to content

Commit

Permalink
pkg/proc: improve stripped binary support with PIE (#3421)
Browse files Browse the repository at this point in the history
Take into account static base for PIE binaries.
  • Loading branch information
derekparker committed Jun 16, 2023
1 parent 14d9c18 commit 656c4f1
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 47 deletions.
10 changes: 5 additions & 5 deletions pkg/proc/bininfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down
42 changes: 1 addition & 41 deletions pkg/proc/pclntab.go
Original file line number Diff line number Diff line change
@@ -1,48 +1,19 @@
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"

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")
Expand All @@ -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)
Expand Down
1 change: 0 additions & 1 deletion pkg/proc/proc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down

0 comments on commit 656c4f1

Please sign in to comment.