Skip to content

Instantly share code, notes, and snippets.

@prashantv
Created September 2, 2021 02:56
Show Gist options
  • Save prashantv/07d8d8a46322127cc9c4ff1001476265 to your computer and use it in GitHub Desktop.
Save prashantv/07d8d8a46322127cc9c4ff1001476265 to your computer and use it in GitHub Desktop.
elf symbol lookup file offset
package elfsym
import (
"bytes"
"debug/elf"
"fmt"
"io/ioutil"
)
type Symbol struct {
elfSym elf.Symbol
fileOffset uint64
}
func (s *Symbol) Name() string {
return s.elfSym.Name
}
func (s *Symbol) FileOffset() uint64 {
return s.fileOffset
}
func Lookup(binary, symbol string) (*Symbol, error) {
bs, err := ioutil.ReadFile(binary)
if err != nil {
return nil, fmt.Errorf("load file: %w", err)
}
e, err := elf.NewFile(bytes.NewReader(bs))
if err != nil {
return nil, fmt.Errorf("parse ELF: %w", err)
}
syms, err := e.Symbols()
if err != nil {
return nil, fmt.Errorf("load symbols: %w", err)
}
for _, s := range syms {
if s.Name == symbol {
return createSymbol(s, e.Progs)
}
}
return nil, fmt.Errorf("could not find symbol %q", symbol)
}
func createSymbol(sym elf.Symbol, progs []*elf.Prog) (*Symbol, error) {
// sym.Value is the virtual address, but we want the physical offset
// so we map to the physical offset using any PT_LOAD program headers
// that apply to this location.
var offsetFix uint64
for _, p := range progs {
if p.Type != elf.PT_LOAD {
continue
}
if sym.Value >= p.Vaddr && sym.Value <= (p.Vaddr+p.Filesz) {
offsetFix += p.Off - p.Vaddr
}
}
return &Symbol{
elfSym: sym,
fileOffset: sym.Value + offsetFix,
}, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment