Skip to content

Commit

Permalink
fix: use moduledata text address as base pc
Browse files Browse the repository at this point in the history
  • Loading branch information
Zxilly committed Jan 26, 2024
1 parent 27b5286 commit d1b3f8d
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 80 deletions.
45 changes: 5 additions & 40 deletions elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"debug/gosym"
"errors"
"fmt"
"math"
"os"
)

Expand All @@ -37,41 +36,14 @@ func openELF(fp string) (*elfFile, error) {
return nil, fmt.Errorf("error when parsing the ELF file: %w", err)
}

ret := &elfFile{file: f, osFile: osFile}

err = ret.trySetTextStart()
if err != nil {
return nil, fmt.Errorf("error when getting the text start: %w", err)
}

return ret, nil
return &elfFile{file: f, osFile: osFile}, nil
}

var _ fileHandler = (*elfFile)(nil)

type elfFile struct {
file *elf.File
osFile *os.File
textStart uint64
}

func (e *elfFile) trySetTextStart() error {
smybol, err := e.file.Symbols()
if err != nil {
if errors.Is(err, elf.ErrNoSymbols) {
e.textStart = math.MaxUint64
return nil
}
}
addr := uint64(math.MaxUint64)
for _, s := range smybol {
if s.Name == "runtime.text" {
addr = s.Value
break
}
}
e.textStart = addr
return nil
file *elf.File
osFile *os.File
}

func (e *elfFile) GetParsedFile() any {
Expand Down Expand Up @@ -114,7 +86,7 @@ func (e *elfFile) getSymbolData(start, end string) ([]byte, error) {
return nil, fmt.Errorf("could not find the symbol %s", start)
}

func (e *elfFile) getPCLNTab() (*gosym.Table, error) {
func (e *elfFile) getPCLNTab(pc uint64) (*gosym.Table, error) {
pclnSection := e.file.Section(".gopclntab")
if pclnSection == nil {
// No section found. Check if the PIE section exist instead.
Expand All @@ -136,14 +108,7 @@ func (e *elfFile) getPCLNTab() (*gosym.Table, error) {
}
}

var pcln *gosym.LineTable
if e.textStart != math.MaxUint64 {
pcln = gosym.NewLineTable(pclndat, e.textStart)
} else {
// FIXME: pc can be wrong if the binary linked with external linker
pcln = gosym.NewLineTable(pclndat, e.file.Section(".text").Addr)
}

pcln := gosym.NewLineTable(pclndat, pc)
return gosym.NewTable(make([]byte, 0), pcln)
}

Expand Down
8 changes: 6 additions & 2 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,11 @@ func (f *GoFile) Close() error {

// PCLNTab returns the PCLN table.
func (f *GoFile) PCLNTab() (*gosym.Table, error) {
return f.fh.getPCLNTab()
md, err := f.Moduledata()
if err != nil {
return nil, err
}
return f.fh.getPCLNTab(md.Text().Address)
}

// GetTypes returns a map of all types found in the binary file.
Expand Down Expand Up @@ -375,7 +379,7 @@ func sortTypes(types map[uint64]*GoType) []*GoType {

type fileHandler interface {
io.Closer
getPCLNTab() (*gosym.Table, error)
getPCLNTab(pc uint64) (*gosym.Table, error)
getRData() ([]byte, error)
getCodeSection() ([]byte, error)
getSectionDataFromOffset(uint64) (uint64, []byte, error)
Expand Down
2 changes: 1 addition & 1 deletion file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ func (m *mockFileHandler) Close() error {
panic("not implemented")
}

func (m *mockFileHandler) getPCLNTab() (*gosym.Table, error) {
func (m *mockFileHandler) getPCLNTab(uint64) (*gosym.Table, error) {
panic("not implemented")
}

Expand Down
12 changes: 7 additions & 5 deletions goversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,11 @@ func buildSemVerString(v string) string {

func findGoCompilerVersion(f *GoFile) (*GoVersion, error) {
// Try to determine the version based on the schedinit function.
if v := tryFromSchedInit(f); v != nil {
return v, nil
}
// FIXME: tryFromSchedInit relies on the pclntab, but the pclntab relies on the moduledata to
// get the accurate address, not way to solve this cycle dependency right now.
// if v := tryFromSchedInit(f); v != nil {
// return v, nil
// }

// If no version was found, search the sections for the
// version string.
Expand All @@ -92,8 +94,8 @@ func findGoCompilerVersion(f *GoFile) (*GoVersion, error) {
if err != nil {
return nil, err
}
notfound := false
for !notfound {

for {
version := matchGoVersionString(data)
if version == "" {
return nil, ErrNoGoVersionFound
Expand Down
9 changes: 3 additions & 6 deletions macho.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,8 @@ func openMachO(fp string) (*machoFile, error) {
if err != nil {
return nil, fmt.Errorf("error when parsing the Mach-O file: %w", err)
}
ret := &machoFile{file: f, osFile: osFile}

ret.trySetTextStart()

return ret, nil
return &machoFile{file: f, osFile: osFile}, nil
}

var _ fileHandler = (*machoFile)(nil)
Expand Down Expand Up @@ -79,7 +76,7 @@ func (m *machoFile) Close() error {
return m.osFile.Close()
}

func (m *machoFile) getPCLNTab() (*gosym.Table, error) {
func (m *machoFile) getPCLNTab(pc uint64) (*gosym.Table, error) {
section := m.file.Section("__gopclntab")
if section == nil {
return nil, ErrNoPCLNTab
Expand All @@ -88,7 +85,7 @@ func (m *machoFile) getPCLNTab() (*gosym.Table, error) {
if data == nil {
return nil, err
}
pcln := gosym.NewLineTable(data, m.file.Section("__text").Addr)
pcln := gosym.NewLineTable(data, pc)
return gosym.NewTable(nil, pcln)
}

Expand Down
28 changes: 2 additions & 26 deletions pe.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"debug/pe"
"encoding/binary"
"fmt"
"math"
"os"
)

Expand Down Expand Up @@ -57,21 +56,6 @@ type peFile struct {
file *pe.File
osFile *os.File
imageBase uint64
textStart uint32
}

func (p *peFile) trySetTextStart() {
symbols := p.file.Symbols

addr := uint32(math.MaxUint32)

for _, s := range symbols {
if s.Name == "runtime.text" {
p.textStart = s.Value
}
}

p.textStart = addr
}

func (p *peFile) GetParsedFile() any {
Expand All @@ -82,21 +66,13 @@ func (p *peFile) GetFile() *os.File {
return p.osFile
}

func (p *peFile) getPCLNTab() (*gosym.Table, error) {
func (p *peFile) getPCLNTab(pc uint64) (*gosym.Table, error) {
_, pclndat, err := searchFileForPCLNTab(p.file)
if err != nil {
return nil, err
}

var pcln *gosym.LineTable
if p.textStart != math.MaxUint32 {
pcln = gosym.NewLineTable(pclndat, uint64(p.textStart))
} else {
// FIXME: pc can be wrong if the binary linked with external linker
pcln = gosym.NewLineTable(pclndat, uint64(p.file.Section(".text").VirtualAddress)+p.imageBase)
}

return gosym.NewTable(make([]byte, 0), pcln)
return gosym.NewTable(make([]byte, 0), gosym.NewLineTable(pclndat, pc))
}

func (p *peFile) Close() error {
Expand Down

0 comments on commit d1b3f8d

Please sign in to comment.