|  | // Copyright 2014 Google Inc. All Rights Reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | // Package driver provides an external entry point to the pprof driver. | 
|  | package driver | 
|  |  | 
|  | import ( | 
|  | "io" | 
|  | "net/http" | 
|  | "regexp" | 
|  | "time" | 
|  |  | 
|  | internaldriver "github.com/google/pprof/internal/driver" | 
|  | "github.com/google/pprof/internal/plugin" | 
|  | "github.com/google/pprof/profile" | 
|  | ) | 
|  |  | 
|  | // PProf acquires a profile, and symbolizes it using a profile | 
|  | // manager. Then it generates a report formatted according to the | 
|  | // options selected through the flags package. | 
|  | func PProf(o *Options) error { | 
|  | return internaldriver.PProf(o.internalOptions()) | 
|  | } | 
|  |  | 
|  | func (o *Options) internalOptions() *plugin.Options { | 
|  | var obj plugin.ObjTool | 
|  | if o.Obj != nil { | 
|  | obj = &internalObjTool{o.Obj} | 
|  | } | 
|  | var sym plugin.Symbolizer | 
|  | if o.Sym != nil { | 
|  | sym = &internalSymbolizer{o.Sym} | 
|  | } | 
|  | var httpServer func(args *plugin.HTTPServerArgs) error | 
|  | if o.HTTPServer != nil { | 
|  | httpServer = func(args *plugin.HTTPServerArgs) error { | 
|  | return o.HTTPServer(((*HTTPServerArgs)(args))) | 
|  | } | 
|  | } | 
|  | return &plugin.Options{ | 
|  | Writer:        o.Writer, | 
|  | Flagset:       o.Flagset, | 
|  | Fetch:         o.Fetch, | 
|  | Sym:           sym, | 
|  | Obj:           obj, | 
|  | UI:            o.UI, | 
|  | HTTPServer:    httpServer, | 
|  | HTTPTransport: o.HTTPTransport, | 
|  | } | 
|  | } | 
|  |  | 
|  | // HTTPServerArgs contains arguments needed by an HTTP server that | 
|  | // is exporting a pprof web interface. | 
|  | type HTTPServerArgs plugin.HTTPServerArgs | 
|  |  | 
|  | // Options groups all the optional plugins into pprof. | 
|  | type Options struct { | 
|  | Writer        Writer | 
|  | Flagset       FlagSet | 
|  | Fetch         Fetcher | 
|  | Sym           Symbolizer | 
|  | Obj           ObjTool | 
|  | UI            UI | 
|  | HTTPServer    func(*HTTPServerArgs) error | 
|  | HTTPTransport http.RoundTripper | 
|  | } | 
|  |  | 
|  | // Writer provides a mechanism to write data under a certain name, | 
|  | // typically a filename. | 
|  | type Writer interface { | 
|  | Open(name string) (io.WriteCloser, error) | 
|  | } | 
|  |  | 
|  | // A FlagSet creates and parses command-line flags. | 
|  | // It is similar to the standard flag.FlagSet. | 
|  | type FlagSet interface { | 
|  | // Bool, Int, Float64, and String define new flags, | 
|  | // like the functions of the same name in package flag. | 
|  | Bool(name string, def bool, usage string) *bool | 
|  | Int(name string, def int, usage string) *int | 
|  | Float64(name string, def float64, usage string) *float64 | 
|  | String(name string, def string, usage string) *string | 
|  |  | 
|  | // StringList is similar to String but allows multiple values for a | 
|  | // single flag | 
|  | StringList(name string, def string, usage string) *[]*string | 
|  |  | 
|  | // ExtraUsage returns any additional text that should be printed after the | 
|  | // standard usage message. The extra usage message returned includes all text | 
|  | // added with AddExtraUsage(). | 
|  | // The typical use of ExtraUsage is to show any custom flags defined by the | 
|  | // specific pprof plugins being used. | 
|  | ExtraUsage() string | 
|  |  | 
|  | // AddExtraUsage appends additional text to the end of the extra usage message. | 
|  | AddExtraUsage(eu string) | 
|  |  | 
|  | // Parse initializes the flags with their values for this run | 
|  | // and returns the non-flag command line arguments. | 
|  | // If an unknown flag is encountered or there are no arguments, | 
|  | // Parse should call usage and return nil. | 
|  | Parse(usage func()) []string | 
|  | } | 
|  |  | 
|  | // A Fetcher reads and returns the profile named by src, using | 
|  | // the specified duration and timeout. It returns the fetched | 
|  | // profile and a string indicating a URL from where the profile | 
|  | // was fetched, which may be different than src. | 
|  | type Fetcher interface { | 
|  | Fetch(src string, duration, timeout time.Duration) (*profile.Profile, string, error) | 
|  | } | 
|  |  | 
|  | // A Symbolizer introduces symbol information into a profile. | 
|  | type Symbolizer interface { | 
|  | Symbolize(mode string, srcs MappingSources, prof *profile.Profile) error | 
|  | } | 
|  |  | 
|  | // MappingSources map each profile.Mapping to the source of the profile. | 
|  | // The key is either Mapping.File or Mapping.BuildId. | 
|  | type MappingSources map[string][]struct { | 
|  | Source string // URL of the source the mapping was collected from | 
|  | Start  uint64 // delta applied to addresses from this source (to represent Merge adjustments) | 
|  | } | 
|  |  | 
|  | // An ObjTool inspects shared libraries and executable files. | 
|  | type ObjTool interface { | 
|  | // Open opens the named object file. If the object is a shared | 
|  | // library, start/limit/offset are the addresses where it is mapped | 
|  | // into memory in the address space being inspected. | 
|  | Open(file string, start, limit, offset uint64) (ObjFile, error) | 
|  |  | 
|  | // Disasm disassembles the named object file, starting at | 
|  | // the start address and stopping at (before) the end address. | 
|  | Disasm(file string, start, end uint64, intelSyntax bool) ([]Inst, error) | 
|  | } | 
|  |  | 
|  | // An Inst is a single instruction in an assembly listing. | 
|  | type Inst struct { | 
|  | Addr     uint64 // virtual address of instruction | 
|  | Text     string // instruction text | 
|  | Function string // function name | 
|  | File     string // source file | 
|  | Line     int    // source line | 
|  | } | 
|  |  | 
|  | // An ObjFile is a single object file: a shared library or executable. | 
|  | type ObjFile interface { | 
|  | // Name returns the underlying file name, if available. | 
|  | Name() string | 
|  |  | 
|  | // Base returns the base address to use when looking up symbols in the file. | 
|  | Base() uint64 | 
|  |  | 
|  | // BuildID returns the GNU build ID of the file, or an empty string. | 
|  | BuildID() string | 
|  |  | 
|  | // SourceLine reports the source line information for a given | 
|  | // address in the file. Due to inlining, the source line information | 
|  | // is in general a list of positions representing a call stack, | 
|  | // with the leaf function first. | 
|  | SourceLine(addr uint64) ([]Frame, error) | 
|  |  | 
|  | // Symbols returns a list of symbols in the object file. | 
|  | // If r is not nil, Symbols restricts the list to symbols | 
|  | // with names matching the regular expression. | 
|  | // If addr is not zero, Symbols restricts the list to symbols | 
|  | // containing that address. | 
|  | Symbols(r *regexp.Regexp, addr uint64) ([]*Sym, error) | 
|  |  | 
|  | // Close closes the file, releasing associated resources. | 
|  | Close() error | 
|  | } | 
|  |  | 
|  | // A Frame describes a single line in a source file. | 
|  | type Frame struct { | 
|  | Func string // name of function | 
|  | File string // source file name | 
|  | Line int    // line in file | 
|  | } | 
|  |  | 
|  | // A Sym describes a single symbol in an object file. | 
|  | type Sym struct { | 
|  | Name  []string // names of symbol (many if symbol was dedup'ed) | 
|  | File  string   // object file containing symbol | 
|  | Start uint64   // start virtual address | 
|  | End   uint64   // virtual address of last byte in sym (Start+size-1) | 
|  | } | 
|  |  | 
|  | // A UI manages user interactions. | 
|  | type UI interface { | 
|  | // Read returns a line of text (a command) read from the user. | 
|  | // prompt is printed before reading the command. | 
|  | ReadLine(prompt string) (string, error) | 
|  |  | 
|  | // Print shows a message to the user. | 
|  | // It formats the text as fmt.Print would and adds a final \n if not already present. | 
|  | // For line-based UI, Print writes to standard error. | 
|  | // (Standard output is reserved for report data.) | 
|  | Print(...interface{}) | 
|  |  | 
|  | // PrintErr shows an error message to the user. | 
|  | // It formats the text as fmt.Print would and adds a final \n if not already present. | 
|  | // For line-based UI, PrintErr writes to standard error. | 
|  | PrintErr(...interface{}) | 
|  |  | 
|  | // IsTerminal returns whether the UI is known to be tied to an | 
|  | // interactive terminal (as opposed to being redirected to a file). | 
|  | IsTerminal() bool | 
|  |  | 
|  | // WantBrowser indicates whether browser should be opened with the -http option. | 
|  | WantBrowser() bool | 
|  |  | 
|  | // SetAutoComplete instructs the UI to call complete(cmd) to obtain | 
|  | // the auto-completion of cmd, if the UI supports auto-completion at all. | 
|  | SetAutoComplete(complete func(string) string) | 
|  | } | 
|  |  | 
|  | // internalObjTool is a wrapper to map from the pprof external | 
|  | // interface to the internal interface. | 
|  | type internalObjTool struct { | 
|  | ObjTool | 
|  | } | 
|  |  | 
|  | func (o *internalObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) { | 
|  | f, err := o.ObjTool.Open(file, start, limit, offset) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | return &internalObjFile{f}, err | 
|  | } | 
|  |  | 
|  | type internalObjFile struct { | 
|  | ObjFile | 
|  | } | 
|  |  | 
|  | func (f *internalObjFile) SourceLine(frame uint64) ([]plugin.Frame, error) { | 
|  | frames, err := f.ObjFile.SourceLine(frame) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | var pluginFrames []plugin.Frame | 
|  | for _, f := range frames { | 
|  | pluginFrames = append(pluginFrames, plugin.Frame(f)) | 
|  | } | 
|  | return pluginFrames, nil | 
|  | } | 
|  |  | 
|  | func (f *internalObjFile) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) { | 
|  | syms, err := f.ObjFile.Symbols(r, addr) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | var pluginSyms []*plugin.Sym | 
|  | for _, s := range syms { | 
|  | ps := plugin.Sym(*s) | 
|  | pluginSyms = append(pluginSyms, &ps) | 
|  | } | 
|  | return pluginSyms, nil | 
|  | } | 
|  |  | 
|  | func (o *internalObjTool) Disasm(file string, start, end uint64, intelSyntax bool) ([]plugin.Inst, error) { | 
|  | insts, err := o.ObjTool.Disasm(file, start, end, intelSyntax) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | var pluginInst []plugin.Inst | 
|  | for _, inst := range insts { | 
|  | pluginInst = append(pluginInst, plugin.Inst(inst)) | 
|  | } | 
|  | return pluginInst, nil | 
|  | } | 
|  |  | 
|  | // internalSymbolizer is a wrapper to map from the pprof external | 
|  | // interface to the internal interface. | 
|  | type internalSymbolizer struct { | 
|  | Symbolizer | 
|  | } | 
|  |  | 
|  | func (s *internalSymbolizer) Symbolize(mode string, srcs plugin.MappingSources, prof *profile.Profile) error { | 
|  | isrcs := MappingSources{} | 
|  | for m, s := range srcs { | 
|  | isrcs[m] = s | 
|  | } | 
|  | return s.Symbolizer.Symbolize(mode, isrcs, prof) | 
|  | } |