Home | History | Annotate | Download | only in plugin
      1 // Copyright 2014 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Package plugin defines the plugin implementations that the main pprof driver requires.
      6 package plugin
      7 
      8 import (
      9 	"bufio"
     10 	"fmt"
     11 	"os"
     12 	"regexp"
     13 	"strings"
     14 	"time"
     15 
     16 	"cmd/pprof/internal/profile"
     17 )
     18 
     19 // A FlagSet creates and parses command-line flags.
     20 // It is similar to the standard flag.FlagSet.
     21 type FlagSet interface {
     22 	// Bool, Int, Float64, and String define new flags,
     23 	// like the functions of the same name in package flag.
     24 	Bool(name string, def bool, usage string) *bool
     25 	Int(name string, def int, usage string) *int
     26 	Float64(name string, def float64, usage string) *float64
     27 	String(name string, def string, usage string) *string
     28 
     29 	// ExtraUsage returns any additional text that should be
     30 	// printed after the standard usage message.
     31 	// The typical use of ExtraUsage is to show any custom flags
     32 	// defined by the specific pprof plugins being used.
     33 	ExtraUsage() string
     34 
     35 	// Parse initializes the flags with their values for this run
     36 	// and returns the non-flag command line arguments.
     37 	// If an unknown flag is encountered or there are no arguments,
     38 	// Parse should call usage and return nil.
     39 	Parse(usage func()) []string
     40 }
     41 
     42 // An ObjTool inspects shared libraries and executable files.
     43 type ObjTool interface {
     44 	// Open opens the named object file.
     45 	// If the object is a shared library, start is the address where
     46 	// it is mapped into memory in the address space being inspected.
     47 	Open(file string, start uint64) (ObjFile, error)
     48 
     49 	// Demangle translates a batch of symbol names from mangled
     50 	// form to human-readable form.
     51 	Demangle(names []string) (map[string]string, error)
     52 
     53 	// Disasm disassembles the named object file, starting at
     54 	// the start address and stopping at (before) the end address.
     55 	Disasm(file string, start, end uint64) ([]Inst, error)
     56 
     57 	// SetConfig configures the tool.
     58 	// The implementation defines the meaning of the string
     59 	// and can ignore it entirely.
     60 	SetConfig(config string)
     61 }
     62 
     63 // NoObjTool returns a trivial implementation of the ObjTool interface.
     64 // Open returns an error indicating that the requested file does not exist.
     65 // Demangle returns an empty map and a nil error.
     66 // Disasm returns an error.
     67 // SetConfig is a no-op.
     68 func NoObjTool() ObjTool {
     69 	return noObjTool{}
     70 }
     71 
     72 type noObjTool struct{}
     73 
     74 func (noObjTool) Open(file string, start uint64) (ObjFile, error) {
     75 	return nil, &os.PathError{Op: "open", Path: file, Err: os.ErrNotExist}
     76 }
     77 
     78 func (noObjTool) Demangle(name []string) (map[string]string, error) {
     79 	return make(map[string]string), nil
     80 }
     81 
     82 func (noObjTool) Disasm(file string, start, end uint64) ([]Inst, error) {
     83 	return nil, fmt.Errorf("disassembly not supported")
     84 }
     85 
     86 func (noObjTool) SetConfig(config string) {
     87 }
     88 
     89 // An ObjFile is a single object file: a shared library or executable.
     90 type ObjFile interface {
     91 	// Name returns the underlyinf file name, if available
     92 	Name() string
     93 
     94 	// Base returns the base address to use when looking up symbols in the file.
     95 	Base() uint64
     96 
     97 	// BuildID returns the GNU build ID of the file, or an empty string.
     98 	BuildID() string
     99 
    100 	// SourceLine reports the source line information for a given
    101 	// address in the file. Due to inlining, the source line information
    102 	// is in general a list of positions representing a call stack,
    103 	// with the leaf function first.
    104 	SourceLine(addr uint64) ([]Frame, error)
    105 
    106 	// Symbols returns a list of symbols in the object file.
    107 	// If r is not nil, Symbols restricts the list to symbols
    108 	// with names matching the regular expression.
    109 	// If addr is not zero, Symbols restricts the list to symbols
    110 	// containing that address.
    111 	Symbols(r *regexp.Regexp, addr uint64) ([]*Sym, error)
    112 
    113 	// Close closes the file, releasing associated resources.
    114 	Close() error
    115 }
    116 
    117 // A Frame describes a single line in a source file.
    118 type Frame struct {
    119 	Func string // name of function
    120 	File string // source file name
    121 	Line int    // line in file
    122 }
    123 
    124 // A Sym describes a single symbol in an object file.
    125 type Sym struct {
    126 	Name  []string // names of symbol (many if symbol was dedup'ed)
    127 	File  string   // object file containing symbol
    128 	Start uint64   // start virtual address
    129 	End   uint64   // virtual address of last byte in sym (Start+size-1)
    130 }
    131 
    132 // An Inst is a single instruction in an assembly listing.
    133 type Inst struct {
    134 	Addr uint64 // virtual address of instruction
    135 	Text string // instruction text
    136 	File string // source file
    137 	Line int    // source line
    138 }
    139 
    140 // A UI manages user interactions.
    141 type UI interface {
    142 	// Read returns a line of text (a command) read from the user.
    143 	ReadLine() (string, error)
    144 
    145 	// Print shows a message to the user.
    146 	// It formats the text as fmt.Print would and adds a final \n if not already present.
    147 	// For line-based UI, Print writes to standard error.
    148 	// (Standard output is reserved for report data.)
    149 	Print(...interface{})
    150 
    151 	// PrintErr shows an error message to the user.
    152 	// It formats the text as fmt.Print would and adds a final \n if not already present.
    153 	// For line-based UI, PrintErr writes to standard error.
    154 	PrintErr(...interface{})
    155 
    156 	// IsTerminal returns whether the UI is known to be tied to an
    157 	// interactive terminal (as opposed to being redirected to a file).
    158 	IsTerminal() bool
    159 
    160 	// SetAutoComplete instructs the UI to call complete(cmd) to obtain
    161 	// the auto-completion of cmd, if the UI supports auto-completion at all.
    162 	SetAutoComplete(complete func(string) string)
    163 }
    164 
    165 // StandardUI returns a UI that reads from standard input,
    166 // prints messages to standard output,
    167 // prints errors to standard error, and doesn't use auto-completion.
    168 func StandardUI() UI {
    169 	return &stdUI{r: bufio.NewReader(os.Stdin)}
    170 }
    171 
    172 type stdUI struct {
    173 	r *bufio.Reader
    174 }
    175 
    176 func (ui *stdUI) ReadLine() (string, error) {
    177 	os.Stdout.WriteString("(pprof) ")
    178 	return ui.r.ReadString('\n')
    179 }
    180 
    181 func (ui *stdUI) Print(args ...interface{}) {
    182 	ui.fprint(os.Stderr, args)
    183 }
    184 
    185 func (ui *stdUI) PrintErr(args ...interface{}) {
    186 	ui.fprint(os.Stderr, args)
    187 }
    188 
    189 func (ui *stdUI) IsTerminal() bool {
    190 	return false
    191 }
    192 
    193 func (ui *stdUI) SetAutoComplete(func(string) string) {
    194 }
    195 
    196 func (ui *stdUI) fprint(f *os.File, args []interface{}) {
    197 	text := fmt.Sprint(args...)
    198 	if !strings.HasSuffix(text, "\n") {
    199 		text += "\n"
    200 	}
    201 	f.WriteString(text)
    202 }
    203 
    204 // A Fetcher reads and returns the profile named by src.
    205 // It gives up after the given timeout, unless src contains a timeout override
    206 // (as defined by the implementation).
    207 // It can print messages to ui.
    208 type Fetcher func(src string, timeout time.Duration, ui UI) (*profile.Profile, error)
    209 
    210 // A Symbolizer annotates a profile with symbol information.
    211 // The profile was fetch from src.
    212 // The meaning of mode is defined by the implementation.
    213 type Symbolizer func(mode, src string, prof *profile.Profile, obj ObjTool, ui UI) error
    214