diff options
| author | Heschi Kreinick <heschi@google.com> | 2022-03-16 18:17:58 -0400 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2022-03-18 18:48:36 +0000 |
| commit | 7e5804cb7014bf3154542a3d2afc68c3a61b7452 (patch) | |
| tree | 7de804293b5c1d7057bff7924cce0bf5648e464b /src/cmd/vendor/github.com/google/pprof/internal | |
| parent | 9f252a0462bd8c279beec56d1538e8a6c26c44c5 (diff) | |
| download | go-7e5804cb7014bf3154542a3d2afc68c3a61b7452.tar.xz | |
cmd: update vendored pprof
go get github.com/google/pprof@latest
go mod vendor
Plus a tiny change to the pprof command to match an upstream interface
change.
Updates #36905.
Change-Id: I4c7bbe8c317a6eeb217fce971b208f96ab0727fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/393370
Trust: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
Auto-Submit: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/cmd/vendor/github.com/google/pprof/internal')
10 files changed, 48 insertions, 44 deletions
diff --git a/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go b/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go index e920eeb2fa..efa9167af7 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/binutils/binutils.go @@ -284,7 +284,7 @@ func (bu *Binutils) Disasm(file string, start, end uint64, intelSyntax bool) ([] } // Open satisfies the plugin.ObjTool interface. -func (bu *Binutils) Open(name string, start, limit, offset uint64) (plugin.ObjFile, error) { +func (bu *Binutils) Open(name string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) { b := bu.get() // Make sure file is a supported executable. @@ -316,7 +316,7 @@ func (bu *Binutils) Open(name string, start, limit, offset uint64) (plugin.ObjFi // Match against supported file types. if elfMagic == elf.ELFMAG { - f, err := b.openELF(name, start, limit, offset) + f, err := b.openELF(name, start, limit, offset, relocationSymbol) if err != nil { return nil, fmt.Errorf("error reading ELF file %s: %v", name, err) } @@ -425,7 +425,7 @@ func (b *binrep) openMachO(name string, start, limit, offset uint64) (plugin.Obj return b.openMachOCommon(name, of, start, limit, offset) } -func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFile, error) { +func (b *binrep) openELF(name string, start, limit, offset uint64, relocationSymbol string) (plugin.ObjFile, error) { ef, err := elfOpen(name) if err != nil { return nil, fmt.Errorf("error parsing %s: %v", name, err) @@ -440,8 +440,8 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi } var ( - stextOffset *uint64 - pageAligned = func(addr uint64) bool { return addr%4096 == 0 } + kernelOffset *uint64 + pageAligned = func(addr uint64) bool { return addr%4096 == 0 } ) if strings.Contains(name, "vmlinux") || !pageAligned(start) || !pageAligned(limit) || !pageAligned(offset) { // Reading all Symbols is expensive, and we only rarely need it so @@ -455,10 +455,18 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi if err != nil && err != elf.ErrNoSymbols { return nil, err } + + // The kernel relocation symbol (the mapping start address) can be either + // _text or _stext. When profiles are generated by `perf`, which one was used is + // distinguished by the mapping name for the kernel image: + // '[kernel.kallsyms]_text' or '[kernel.kallsyms]_stext', respectively. If we haven't + // been able to parse it from the mapping, we default to _stext. + if relocationSymbol == "" { + relocationSymbol = "_stext" + } for _, s := range symbols { - if s.Name == "_stext" { - // The kernel may use _stext as the mapping start address. - stextOffset = &s.Value + if s.Name == relocationSymbol { + kernelOffset = &s.Value break } } @@ -469,7 +477,7 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi // value until we have a sample address for this mapping, so that we can // correctly identify the associated program segment that is needed to compute // the base. - if _, err := elfexec.GetBase(&ef.FileHeader, elfexec.FindTextProgHeader(ef), stextOffset, start, limit, offset); err != nil { + if _, err := elfexec.GetBase(&ef.FileHeader, elfexec.FindTextProgHeader(ef), kernelOffset, start, limit, offset); err != nil { return nil, fmt.Errorf("could not identify base for %s: %v", name, err) } @@ -478,14 +486,14 @@ func (b *binrep) openELF(name string, start, limit, offset uint64) (plugin.ObjFi b: b, name: name, buildID: buildID, - m: &elfMapping{start: start, limit: limit, offset: offset, stextOffset: stextOffset}, + m: &elfMapping{start: start, limit: limit, offset: offset, kernelOffset: kernelOffset}, }}, nil } return &fileAddr2Line{file: file{ b: b, name: name, buildID: buildID, - m: &elfMapping{start: start, limit: limit, offset: offset, stextOffset: stextOffset}, + m: &elfMapping{start: start, limit: limit, offset: offset, kernelOffset: kernelOffset}, }}, nil } @@ -521,8 +529,8 @@ func (b *binrep) openPE(name string, start, limit, offset uint64) (plugin.ObjFil type elfMapping struct { // Runtime mapping parameters. start, limit, offset uint64 - // Offset of _stext symbol. Only defined for kernel images, nil otherwise. - stextOffset *uint64 + // Offset of kernel relocation symbol. Only defined for kernel images, nil otherwise. + kernelOffset *uint64 } // findProgramHeader returns the program segment that matches the current @@ -535,7 +543,7 @@ func (m *elfMapping) findProgramHeader(ef *elf.File, addr uint64) (*elf.ProgHead // it's a kernel / .ko module mapping, because with quipper address remapping // enabled, the address would be in the lower half of the address space. - if m.stextOffset != nil || m.start >= m.limit || m.limit >= (uint64(1)<<63) { + if m.kernelOffset != nil || m.start >= m.limit || m.limit >= (uint64(1)<<63) { // For the kernel, find the program segment that includes the .text section. return elfexec.FindTextProgHeader(ef), nil } @@ -601,7 +609,7 @@ func (f *file) computeBase(addr uint64) error { return fmt.Errorf("failed to find program header for file %q, ELF mapping %#v, address %x: %v", f.name, *f.m, addr, err) } - base, err := elfexec.GetBase(&ef.FileHeader, ph, f.m.stextOffset, f.m.start, f.m.limit, f.m.offset) + base, err := elfexec.GetBase(&ef.FileHeader, ph, f.m.kernelOffset, f.m.start, f.m.limit, f.m.offset) if err != nil { return err } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go index 492400c5f3..237cc33233 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/cli.go @@ -98,7 +98,7 @@ func parseFlags(o *plugin.Options) (*source, []string, error) { // Recognize first argument as an executable or buildid override. if len(args) > 1 { arg0 := args[0] - if file, err := o.Obj.Open(arg0, 0, ^uint64(0), 0); err == nil { + if file, err := o.Obj.Open(arg0, 0, ^uint64(0), 0, ""); err == nil { file.Close() execName = arg0 args = args[1:] diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go index b8a69e87fc..0b361651bc 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/fetch.go @@ -420,12 +420,14 @@ mapping: fileNames = append(fileNames, filepath.Join(path, m.File)) } for _, name := range fileNames { - if f, err := obj.Open(name, m.Start, m.Limit, m.Offset); err == nil { + if f, err := obj.Open(name, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol); err == nil { defer f.Close() fileBuildID := f.BuildID() if m.BuildID != "" && m.BuildID != fileBuildID { ui.PrintErr("Ignoring local file " + name + ": build-id mismatch (" + m.BuildID + " != " + fileBuildID + ")") } else { + // Explicitly do not update KernelRelocationSymbol -- + // the new local file name is most likely missing it. m.File = name continue mapping } @@ -449,6 +451,8 @@ mapping: if execName, buildID := s.ExecName, s.BuildID; execName != "" || buildID != "" { m := p.Mapping[0] if execName != "" { + // Explicitly do not update KernelRelocationSymbol -- + // the source override is most likely missing it. m.File = execName } if buildID != "" { diff --git a/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go b/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go index b9c73271b8..63df668321 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/driver/webhtml.go @@ -17,13 +17,11 @@ package driver import ( "html/template" - "github.com/google/pprof/third_party/d3" "github.com/google/pprof/third_party/d3flamegraph" ) // addTemplates adds a set of template definitions to templates. func addTemplates(templates *template.Template) { - template.Must(templates.Parse(`{{define "d3script"}}` + d3.JSSource + `{{end}}`)) template.Must(templates.Parse(`{{define "d3flamegraphscript"}}` + d3flamegraph.JSSource + `{{end}}`)) template.Must(templates.Parse(`{{define "d3flamegraphcss"}}` + d3flamegraph.CSSSource + `{{end}}`)) template.Must(templates.Parse(` @@ -1329,40 +1327,29 @@ function viewer(baseUrl, nodes) { </div> {{template "script" .}} <script>viewer(new URL(window.location.href), {{.Nodes}});</script> - <script>{{template "d3script" .}}</script> <script>{{template "d3flamegraphscript" .}}</script> <script> var data = {{.FlameGraph}}; var width = document.getElementById('chart').clientWidth; - var flameGraph = d3.flamegraph() + var flameGraph = flamegraph() .width(width) .cellHeight(18) .minFrameSize(1) .transitionDuration(750) - .transitionEase(d3.easeCubic) .inverted(true) .sort(true) .title('') .tooltip(false) - .details(document.getElementById('flamegraphdetails')); + .setDetailsElement(document.getElementById('flamegraphdetails')); // <full name> (percentage, value) flameGraph.label((d) => d.data.f + ' (' + d.data.p + ', ' + d.data.l + ')'); - (function(flameGraph) { - var oldColorMapper = flameGraph.color(); - function colorMapper(d) { - // Hack to force default color mapper to use 'warm' color scheme by not passing libtype - const { data, highlight } = d; - return oldColorMapper({ data: { n: data.n }, highlight }); - } - - flameGraph.color(colorMapper); - }(flameGraph)); + flameGraph.setColorHue('warm'); - d3.select('#chart') + select('#chart') .datum(data) .call(flameGraph); diff --git a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go index 6447092d3d..718481b078 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/elfexec/elfexec.go @@ -165,9 +165,9 @@ func GetBuildID(binary io.ReaderAt) ([]byte, error) { return nil, nil } -// kernelBase caluclates the base for kernel mappings, which usually require +// kernelBase calculates the base for kernel mappings, which usually require // special handling. For kernel mappings, tools (like perf) use the address of -// the kernel relocation symbol (_text or _stext) as the mmap start. Additionaly, +// the kernel relocation symbol (_text or _stext) as the mmap start. Additionally, // for obfuscation, ChromeOS profiles have the kernel image remapped to the 0-th page. func kernelBase(loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, bool) { const ( @@ -217,7 +217,7 @@ func kernelBase(loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, // GetBase determines the base address to subtract from virtual // address to get symbol table address. For an executable, the base // is 0. Otherwise, it's a shared library, and the base is the -// address where the mapping starts. The kernel needs special hanldling. +// address where the mapping starts. The kernel needs special handling. func GetBase(fh *elf.FileHeader, loadSegment *elf.ProgHeader, stextOffset *uint64, start, limit, offset uint64) (uint64, error) { if start == 0 && offset == 0 && (limit == ^uint64(0) || limit == 0) { diff --git a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go index 8008675248..9ff4c95adb 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/graph/dotgraph.go @@ -126,7 +126,7 @@ func (b *builder) addLegend() { return } title := labels[0] - fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, title) + fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, escapeForDot(title)) fmt.Fprintf(b, ` label="%s\l"`, strings.Join(escapeAllForDot(labels), `\l`)) if b.config.LegendURL != "" { fmt.Fprintf(b, ` URL="%s" target="_blank"`, b.config.LegendURL) @@ -485,7 +485,7 @@ func escapeAllForDot(in []string) []string { // escapeForDot escapes double quotes and backslashes, and replaces Graphviz's // "center" character (\n) with a left-justified character. -// See https://graphviz.org/doc/info/attrs.html#k:escString for more info. +// See https://graphviz.org/docs/attr-types/escString/ for more info. func escapeForDot(str string) string { return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(str, `\`, `\\`), `"`, `\"`), "\n", `\l`) } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go b/src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go index a57a0b20a9..98eb1dd817 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/plugin/plugin.go @@ -109,8 +109,10 @@ type MappingSources map[string][]struct { 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) + // into memory in the address space being inspected. If the object + // is a linux kernel, relocationSymbol is the name of the symbol + // corresponding to the start address. + Open(file string, start, limit, offset uint64, relocationSymbol string) (ObjFile, error) // Disasm disassembles the named object file, starting at // the start address and stopping at (before) the end address. diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/report.go b/src/cmd/vendor/github.com/google/pprof/internal/report/report.go index e2fb00314c..36ddf2e934 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/report.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/report.go @@ -526,7 +526,7 @@ func symbolsFromBinaries(prof *profile.Profile, g *graph.Graph, rx *regexp.Regex } } - f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset) + f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol) if err != nil { fmt.Printf("%v\n", err) continue diff --git a/src/cmd/vendor/github.com/google/pprof/internal/report/source.go b/src/cmd/vendor/github.com/google/pprof/internal/report/source.go index 33d04c591d..d8b4395265 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/report/source.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/report/source.go @@ -744,7 +744,7 @@ func (sp *sourcePrinter) objectFile(m *profile.Mapping) plugin.ObjFile { if object, ok := sp.objects[m.File]; ok { return object // May be nil if we detected an error earlier. } - object, err := sp.objectTool.Open(m.File, m.Start, m.Limit, m.Offset) + object, err := sp.objectTool.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol) if err != nil { object = nil } diff --git a/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go b/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go index d741e7ad7f..cbb0ed4d1b 100644 --- a/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go +++ b/src/cmd/vendor/github.com/google/pprof/internal/symbolizer/symbolizer.go @@ -325,7 +325,10 @@ func newMapping(prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, force b } name := filepath.Base(m.File) - f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset) + if m.BuildID != "" { + name += fmt.Sprintf(" (build ID %s)", m.BuildID) + } + f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset, m.KernelRelocationSymbol) if err != nil { ui.PrintErr("Local symbolization failed for ", name, ": ", err) missingBinaries = true |
