binutils

Imports

Imports #

"bufio"
"encoding/json"
"fmt"
"io"
"os/exec"
"strconv"
"strings"
"sync"
"github.com/google/pprof/internal/plugin"
"bufio"
"bytes"
"io"
"os/exec"
"strconv"
"strings"
"github.com/google/pprof/internal/plugin"
"debug/elf"
"debug/macho"
"debug/pe"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"github.com/google/pprof/internal/elfexec"
"github.com/google/pprof/internal/plugin"
"bytes"
"io"
"regexp"
"strconv"
"strings"
"github.com/google/pprof/internal/plugin"
"github.com/ianlancetaylor/demangle"
"bufio"
"fmt"
"io"
"os/exec"
"strconv"
"strings"
"sync"
"github.com/google/pprof/internal/plugin"

Constants & Variables

defaultAddr2line const #

const defaultAddr2line = "addr2line"

defaultLLVMSymbolizer const #

const defaultLLVMSymbolizer = "llvm-symbolizer"

defaultNM const #

const defaultNM = "nm"

elfOpen var #

Defined for testing

var elfOpen = elf.Open

nmOutputRE var #

var nmOutputRE = *ast.CallExpr

objdumpAsmOutputRE var #

var objdumpAsmOutputRE = *ast.CallExpr

objdumpLLVMVerRE var #

var objdumpLLVMVerRE = *ast.CallExpr

objdumpOutputFileLine var #

var objdumpOutputFileLine = *ast.CallExpr

objdumpOutputFunction var #

var objdumpOutputFunction = *ast.CallExpr

objdumpOutputFunctionLLVM var #

var objdumpOutputFunctionLLVM = *ast.CallExpr

sentinel const #

addr2line may produce multiple lines of output. We use this sentinel to identify the end of the output.

const sentinel = *ast.UnaryExpr

Interfaces

lineReaderWriter interface #

lineReaderWriter is an interface to abstract the I/O to an addr2line process. It writes a line of input to the job, and reads its output one line at a time.

type lineReaderWriter interface {
write(string) error
readLine() (string, error)
close()
}

Structs

Binutils struct #

A Binutils implements plugin.ObjTool by invoking the GNU binutils.

type Binutils struct {
mu sync.Mutex
rep *binrep
}

addr2Liner struct #

addr2Liner is a connection to an addr2line command for obtaining address and line number information from a binary.

type addr2Liner struct {
mu sync.Mutex
rw lineReaderWriter
base uint64
nm *addr2LinerNM
}

addr2LinerJob struct #

type addr2LinerJob struct {
cmd *exec.Cmd
in io.WriteCloser
out *bufio.Reader
}

addr2LinerNM struct #

addr2LinerNM is a connection to an nm command for obtaining symbol information from a binary.

type addr2LinerNM struct {
m []symbolInfo
}

binrep struct #

binrep is an immutable representation for Binutils. It is atomically replaced on every mutation to provide thread-safe access.

type binrep struct {
llvmSymbolizer string
llvmSymbolizerFound bool
addr2line string
addr2lineFound bool
nm string
nmFound bool
objdump string
objdumpFound bool
isLLVMObjdump bool
fast bool
}

elfMapping struct #

elfMapping stores the parameters of a runtime mapping that are needed to identify the ELF segment associated with a mapping.

type elfMapping struct {
start uint64
limit uint64
offset uint64
kernelOffset *uint64
}

file struct #

file implements the binutils.ObjFile interface.

type file struct {
b *binrep
name string
buildID string
baseOnce sync.Once
base uint64
baseErr error
isData bool
m *elfMapping
}

fileAddr2Line struct #

fileAddr2Line implements the binutils.ObjFile interface, using llvm-symbolizer, if that's available, or addr2line to map addresses to symbols (with file/line number information). It can be slow for large binaries with debug information.

type fileAddr2Line struct {
once sync.Once
file
addr2liner *addr2Liner
llvmSymbolizer *llvmSymbolizer
isData bool
}

fileNM struct #

fileNM implements the binutils.ObjFile interface, using 'nm' to map addresses to symbols (without file/line number information). It is faster than fileAddr2Line.

type fileNM struct {
file
addr2linernm *addr2LinerNM
}

llvmSymbolizer struct #

llvmSymbolizer is a connection to an llvm-symbolizer command for obtaining address and line number information from a binary.

type llvmSymbolizer struct {
sync.Mutex
filename string
rw lineReaderWriter
base uint64
isData bool
}

llvmSymbolizerJob struct #

type llvmSymbolizerJob struct {
cmd *exec.Cmd
in io.WriteCloser
out *bufio.Reader
symType string
}

symbolInfo struct #

type symbolInfo struct {
address uint64
size uint64
name string
symType string
}

Functions

BuildID method #

func (f *file) BuildID() string

Close method #

func (f *fileAddr2Line) Close() error

Close method #

func (f *file) Close() error

Disasm method #

Disasm returns the assembly instructions for the specified address range of a binary.

func (bu *Binutils) Disasm(file string, start uint64, end uint64, intelSyntax bool) ([]plugin.Inst, error)

Name method #

func (f *file) Name() string

ObjAddr method #

func (f *file) ObjAddr(addr uint64) (uint64, error)

Open method #

Open satisfies the plugin.ObjTool interface.

func (bu *Binutils) Open(name string, start uint64, limit uint64, offset uint64, relocationSymbol string) (plugin.ObjFile, error)

SetFastSymbolization method #

SetFastSymbolization sets a toggle that makes binutils use fast symbolization (using nm), which is much faster than addr2line but provides only symbol name information (no file/line).

func (bu *Binutils) SetFastSymbolization(fast bool)

SetTools method #

SetTools processes the contents of the tools option. It expects a set of entries separated by commas; each entry is a pair of the form t:path, where cmd will be used to look only for the tool named t. If t is not specified, the path is searched for all tools.

func (bu *Binutils) SetTools(config string)

SourceLine method #

func (f *fileAddr2Line) SourceLine(addr uint64) ([]plugin.Frame, error)

SourceLine method #

func (f *fileNM) SourceLine(addr uint64) ([]plugin.Frame, error)

SourceLine method #

func (f *file) SourceLine(addr uint64) ([]plugin.Frame, error)

String method #

String returns string representation of the binutils state for debug logging.

func (bu *Binutils) String() string

Symbols method #

func (f *file) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error)

addrInfo method #

addrInfo returns the stack frame information for a specific program address. It returns nil if the address could not be identified.

func (a *addr2LinerNM) addrInfo(addr uint64) ([]plugin.Frame, error)

addrInfo method #

addrInfo returns the stack frame information for a specific program address. It returns nil if the address could not be identified.

func (d *llvmSymbolizer) addrInfo(addr uint64) ([]plugin.Frame, error)

addrInfo method #

addrInfo returns the stack frame information for a specific program address. It returns nil if the address could not be identified.

func (d *addr2Liner) addrInfo(addr uint64) ([]plugin.Frame, error)

chooseExe function #

chooseExe finds and returns path to preferred binary. names is a list of names to search on both Linux and OSX. osxNames is a list of names specific to OSX. names always has a higher priority than osxNames. The order of the name within each list decides its priority (e.g. the first name has a higher priority than the second name in the list). It returns a string with path to the binary and a boolean indicating if any acceptable binary was found.

func chooseExe(names []string, osxNames []string, paths []string) (string, bool)

close method #

close releases any resources used by the llvmSymbolizer object.

func (a *llvmSymbolizerJob) close()

close method #

close releases any resources used by the addr2liner object.

func (a *addr2LinerJob) close()

computeBase method #

computeBase computes the relocation base for the given binary file only if the elfMapping field is set. It populates the base and isData fields and returns an error.

func (f *file) computeBase(addr uint64) error

disassemble function #

disassemble parses the output of the objdump command and returns the assembly instructions in a slice.

func disassemble(asm []byte) ([]plugin.Inst, error)

findExe function #

findExe looks for an executable command on a set of paths. If it cannot find it, returns cmd.

func findExe(cmd string, paths []string) (string, bool)

findObjdump function #

findObjdump finds and returns path to preferred objdump binary. Order of preference is: llvm-objdump, objdump. On MacOS only, also looks for gobjdump with least preference. Accepts a list of paths and returns: a string with path to the preferred objdump binary if found, or an empty string if not found; a boolean if any acceptable objdump was found; a boolean indicating if it is an LLVM objdump.

func findObjdump(paths []string) (string, bool, bool)

findProgramHeader method #

findProgramHeader returns the program segment that matches the current mapping and the given address, or an error if it cannot find a unique program header.

func (m *elfMapping) findProgramHeader(ef *elf.File, addr uint64) (*elf.ProgHeader, error)

findSymbols function #

func findSymbols(syms []byte, file string, r *regexp.Regexp, address uint64) ([]*plugin.Sym, error)

get method #

get returns the current representation for bu, initializing it if necessary.

func (bu *Binutils) get() *binrep

init method #

func (f *fileAddr2Line) init()

initTools function #

func initTools(b *binrep, config string)

isBuObjdump function #

isBuObjdump accepts a string with path to an objdump binary, and returns a boolean indicating if the given binary is a GNU binutils objdump binary. No version check is performed.

func isBuObjdump(output string) bool

isData method #

isData returns if the symbol has a known data object symbol type.

func (s *symbolInfo) isData() bool

isLLVMObjdump function #

isLLVMObjdump accepts a string with path to an objdump binary, and returns a boolean indicating if the given binary is an LLVM objdump binary of an acceptable version.

func isLLVMObjdump(output string) bool

matchSymbol function #

matchSymbol checks if a symbol is to be selected by checking its name to the regexp and optionally its address. It returns the name(s) to be used for the matched symbol, or nil if no match

func matchSymbol(names []string, start uint64, end uint64, r *regexp.Regexp, address uint64) []string

newAddr2Liner function #

newAddr2Liner starts the given addr2liner command reporting information about the given executable file. If file is a shared library, base should be the address at which it was mapped in the program under consideration.

func newAddr2Liner(cmd string, file string, base uint64) (*addr2Liner, error)

newAddr2LinerNM function #

newAddr2LinerNM starts the given nm command reporting information about the given executable file. If file is a shared library, base should be the address at which it was mapped in the program under consideration.

func newAddr2LinerNM(cmd string, file string, base uint64) (*addr2LinerNM, error)

newLLVMSymbolizer function #

newLLVMSymbolizer starts the given llvmSymbolizer command reporting information about the given executable file. If file is a shared library, base should be the address at which it was mapped in the program under consideration.

func newLLVMSymbolizer(cmd string, file string, base uint64, isData bool) (*llvmSymbolizer, error)

nextSymbol function #

nextSymbol parses the nm output to find the next symbol listed. Skips over any output it cannot recognize.

func nextSymbol(buf *bytes.Buffer) (uint64, string, error)

openELF method #

func (b *binrep) openELF(name string, start uint64, limit uint64, offset uint64, relocationSymbol string) (plugin.ObjFile, error)

openFatMachO method #

func (b *binrep) openFatMachO(name string, start uint64, limit uint64, offset uint64) (plugin.ObjFile, error)

openMachO method #

func (b *binrep) openMachO(name string, start uint64, limit uint64, offset uint64) (plugin.ObjFile, error)

openMachOCommon method #

func (b *binrep) openMachOCommon(name string, of *macho.File, start uint64, limit uint64, offset uint64) (plugin.ObjFile, error)

openPE method #

func (b *binrep) openPE(name string, start uint64, limit uint64, offset uint64) (plugin.ObjFile, error)

parseAddr2LinerNM function #

func parseAddr2LinerNM(base uint64, nm io.Reader) (*addr2LinerNM, error)

rawAddrInfo method #

func (d *addr2Liner) rawAddrInfo(addr uint64) ([]plugin.Frame, error)

readCodeFrames method #

readCodeFrames parses the llvm-symbolizer CODE output for a single address. It returns a populated plugin.Frame array.

func (d *llvmSymbolizer) readCodeFrames() ([]plugin.Frame, error)

readDataFrames method #

readDataFrames parses the llvm-symbolizer DATA output for a single address. It returns a populated plugin.Frame array with a single entry.

func (d *llvmSymbolizer) readDataFrames() ([]plugin.Frame, error)

readFrame method #

readFrame parses the addr2line output for a single address. It returns a populated plugin.Frame and whether it has reached the end of the data.

func (d *addr2Liner) readFrame() (plugin.Frame, bool)

readLine method #

func (a *llvmSymbolizerJob) readLine() (string, error)

readLine method #

func (a *addr2LinerJob) readLine() (string, error)

update method #

update modifies the rep for bu via the supplied function.

func (bu *Binutils) update(fn func(r *binrep))

write method #

func (a *llvmSymbolizerJob) write(s string) error

write method #

func (a *addr2LinerJob) write(s string) error

Generated with Arrow