You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

304 lines
9.9 KiB

  1. // Copyright 2014 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package driver provides an external entry point to the pprof driver.
  15. package driver
  16. import (
  17. "io"
  18. "net/http"
  19. "regexp"
  20. "time"
  21. internaldriver "github.com/google/pprof/internal/driver"
  22. "github.com/google/pprof/internal/plugin"
  23. "github.com/google/pprof/profile"
  24. )
  25. // PProf acquires a profile, and symbolizes it using a profile
  26. // manager. Then it generates a report formatted according to the
  27. // options selected through the flags package.
  28. func PProf(o *Options) error {
  29. return internaldriver.PProf(o.internalOptions())
  30. }
  31. func (o *Options) internalOptions() *plugin.Options {
  32. var obj plugin.ObjTool
  33. if o.Obj != nil {
  34. obj = &internalObjTool{o.Obj}
  35. }
  36. var sym plugin.Symbolizer
  37. if o.Sym != nil {
  38. sym = &internalSymbolizer{o.Sym}
  39. }
  40. var httpServer func(args *plugin.HTTPServerArgs) error
  41. if o.HTTPServer != nil {
  42. httpServer = func(args *plugin.HTTPServerArgs) error {
  43. return o.HTTPServer(((*HTTPServerArgs)(args)))
  44. }
  45. }
  46. return &plugin.Options{
  47. Writer: o.Writer,
  48. Flagset: o.Flagset,
  49. Fetch: o.Fetch,
  50. Sym: sym,
  51. Obj: obj,
  52. UI: o.UI,
  53. HTTPServer: httpServer,
  54. HTTPTransport: o.HTTPTransport,
  55. }
  56. }
  57. // HTTPServerArgs contains arguments needed by an HTTP server that
  58. // is exporting a pprof web interface.
  59. type HTTPServerArgs plugin.HTTPServerArgs
  60. // Options groups all the optional plugins into pprof.
  61. type Options struct {
  62. Writer Writer
  63. Flagset FlagSet
  64. Fetch Fetcher
  65. Sym Symbolizer
  66. Obj ObjTool
  67. UI UI
  68. HTTPServer func(*HTTPServerArgs) error
  69. HTTPTransport http.RoundTripper
  70. }
  71. // Writer provides a mechanism to write data under a certain name,
  72. // typically a filename.
  73. type Writer interface {
  74. Open(name string) (io.WriteCloser, error)
  75. }
  76. // A FlagSet creates and parses command-line flags.
  77. // It is similar to the standard flag.FlagSet.
  78. type FlagSet interface {
  79. // Bool, Int, Float64, and String define new flags,
  80. // like the functions of the same name in package flag.
  81. Bool(name string, def bool, usage string) *bool
  82. Int(name string, def int, usage string) *int
  83. Float64(name string, def float64, usage string) *float64
  84. String(name string, def string, usage string) *string
  85. // BoolVar, IntVar, Float64Var, and StringVar define new flags referencing
  86. // a given pointer, like the functions of the same name in package flag.
  87. BoolVar(pointer *bool, name string, def bool, usage string)
  88. IntVar(pointer *int, name string, def int, usage string)
  89. Float64Var(pointer *float64, name string, def float64, usage string)
  90. StringVar(pointer *string, name string, def string, usage string)
  91. // StringList is similar to String but allows multiple values for a
  92. // single flag
  93. StringList(name string, def string, usage string) *[]*string
  94. // ExtraUsage returns any additional text that should be printed after the
  95. // standard usage message. The extra usage message returned includes all text
  96. // added with AddExtraUsage().
  97. // The typical use of ExtraUsage is to show any custom flags defined by the
  98. // specific pprof plugins being used.
  99. ExtraUsage() string
  100. // AddExtraUsage appends additional text to the end of the extra usage message.
  101. AddExtraUsage(eu string)
  102. // Parse initializes the flags with their values for this run
  103. // and returns the non-flag command line arguments.
  104. // If an unknown flag is encountered or there are no arguments,
  105. // Parse should call usage and return nil.
  106. Parse(usage func()) []string
  107. }
  108. // A Fetcher reads and returns the profile named by src, using
  109. // the specified duration and timeout. It returns the fetched
  110. // profile and a string indicating a URL from where the profile
  111. // was fetched, which may be different than src.
  112. type Fetcher interface {
  113. Fetch(src string, duration, timeout time.Duration) (*profile.Profile, string, error)
  114. }
  115. // A Symbolizer introduces symbol information into a profile.
  116. type Symbolizer interface {
  117. Symbolize(mode string, srcs MappingSources, prof *profile.Profile) error
  118. }
  119. // MappingSources map each profile.Mapping to the source of the profile.
  120. // The key is either Mapping.File or Mapping.BuildId.
  121. type MappingSources map[string][]struct {
  122. Source string // URL of the source the mapping was collected from
  123. Start uint64 // delta applied to addresses from this source (to represent Merge adjustments)
  124. }
  125. // An ObjTool inspects shared libraries and executable files.
  126. type ObjTool interface {
  127. // Open opens the named object file. If the object is a shared
  128. // library, start/limit/offset are the addresses where it is mapped
  129. // into memory in the address space being inspected.
  130. Open(file string, start, limit, offset uint64) (ObjFile, error)
  131. // Disasm disassembles the named object file, starting at
  132. // the start address and stopping at (before) the end address.
  133. Disasm(file string, start, end uint64) ([]Inst, error)
  134. }
  135. // An Inst is a single instruction in an assembly listing.
  136. type Inst struct {
  137. Addr uint64 // virtual address of instruction
  138. Text string // instruction text
  139. Function string // function name
  140. File string // source file
  141. Line int // source line
  142. }
  143. // An ObjFile is a single object file: a shared library or executable.
  144. type ObjFile interface {
  145. // Name returns the underlying file name, if available.
  146. Name() string
  147. // Base returns the base address to use when looking up symbols in the file.
  148. Base() uint64
  149. // BuildID returns the GNU build ID of the file, or an empty string.
  150. BuildID() string
  151. // SourceLine reports the source line information for a given
  152. // address in the file. Due to inlining, the source line information
  153. // is in general a list of positions representing a call stack,
  154. // with the leaf function first.
  155. SourceLine(addr uint64) ([]Frame, error)
  156. // Symbols returns a list of symbols in the object file.
  157. // If r is not nil, Symbols restricts the list to symbols
  158. // with names matching the regular expression.
  159. // If addr is not zero, Symbols restricts the list to symbols
  160. // containing that address.
  161. Symbols(r *regexp.Regexp, addr uint64) ([]*Sym, error)
  162. // Close closes the file, releasing associated resources.
  163. Close() error
  164. }
  165. // A Frame describes a single line in a source file.
  166. type Frame struct {
  167. Func string // name of function
  168. File string // source file name
  169. Line int // line in file
  170. }
  171. // A Sym describes a single symbol in an object file.
  172. type Sym struct {
  173. Name []string // names of symbol (many if symbol was dedup'ed)
  174. File string // object file containing symbol
  175. Start uint64 // start virtual address
  176. End uint64 // virtual address of last byte in sym (Start+size-1)
  177. }
  178. // A UI manages user interactions.
  179. type UI interface {
  180. // Read returns a line of text (a command) read from the user.
  181. // prompt is printed before reading the command.
  182. ReadLine(prompt string) (string, error)
  183. // Print shows a message to the user.
  184. // It formats the text as fmt.Print would and adds a final \n if not already present.
  185. // For line-based UI, Print writes to standard error.
  186. // (Standard output is reserved for report data.)
  187. Print(...interface{})
  188. // PrintErr shows an error message to the user.
  189. // It formats the text as fmt.Print would and adds a final \n if not already present.
  190. // For line-based UI, PrintErr writes to standard error.
  191. PrintErr(...interface{})
  192. // IsTerminal returns whether the UI is known to be tied to an
  193. // interactive terminal (as opposed to being redirected to a file).
  194. IsTerminal() bool
  195. // WantBrowser indicates whether browser should be opened with the -http option.
  196. WantBrowser() bool
  197. // SetAutoComplete instructs the UI to call complete(cmd) to obtain
  198. // the auto-completion of cmd, if the UI supports auto-completion at all.
  199. SetAutoComplete(complete func(string) string)
  200. }
  201. // internalObjTool is a wrapper to map from the pprof external
  202. // interface to the internal interface.
  203. type internalObjTool struct {
  204. ObjTool
  205. }
  206. func (o *internalObjTool) Open(file string, start, limit, offset uint64) (plugin.ObjFile, error) {
  207. f, err := o.ObjTool.Open(file, start, limit, offset)
  208. if err != nil {
  209. return nil, err
  210. }
  211. return &internalObjFile{f}, err
  212. }
  213. type internalObjFile struct {
  214. ObjFile
  215. }
  216. func (f *internalObjFile) SourceLine(frame uint64) ([]plugin.Frame, error) {
  217. frames, err := f.ObjFile.SourceLine(frame)
  218. if err != nil {
  219. return nil, err
  220. }
  221. var pluginFrames []plugin.Frame
  222. for _, f := range frames {
  223. pluginFrames = append(pluginFrames, plugin.Frame(f))
  224. }
  225. return pluginFrames, nil
  226. }
  227. func (f *internalObjFile) Symbols(r *regexp.Regexp, addr uint64) ([]*plugin.Sym, error) {
  228. syms, err := f.ObjFile.Symbols(r, addr)
  229. if err != nil {
  230. return nil, err
  231. }
  232. var pluginSyms []*plugin.Sym
  233. for _, s := range syms {
  234. ps := plugin.Sym(*s)
  235. pluginSyms = append(pluginSyms, &ps)
  236. }
  237. return pluginSyms, nil
  238. }
  239. func (o *internalObjTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
  240. insts, err := o.ObjTool.Disasm(file, start, end)
  241. if err != nil {
  242. return nil, err
  243. }
  244. var pluginInst []plugin.Inst
  245. for _, inst := range insts {
  246. pluginInst = append(pluginInst, plugin.Inst(inst))
  247. }
  248. return pluginInst, nil
  249. }
  250. // internalSymbolizer is a wrapper to map from the pprof external
  251. // interface to the internal interface.
  252. type internalSymbolizer struct {
  253. Symbolizer
  254. }
  255. func (s *internalSymbolizer) Symbolize(mode string, srcs plugin.MappingSources, prof *profile.Profile) error {
  256. isrcs := MappingSources{}
  257. for m, s := range srcs {
  258. isrcs[m] = s
  259. }
  260. return s.Symbolizer.Symbolize(mode, isrcs, prof)
  261. }