// locateBinaries searches for binary files listed in the profile and, if found, // updates the profile accordingly. func locateBinaries(p *profile.Profile, s *source, obj plugin.ObjTool, ui plugin.UI) { // Construct search path to examine searchPath := os.Getenv("PPROF_BINARY_PATH") if searchPath == "" { // Use $HOME/pprof/binaries as default directory for local symbolization binaries searchPath = filepath.Join(os.Getenv("HOME"), "pprof", "binaries") } mapping: for i, m := range p.Mapping { var baseName string // Replace executable filename/buildID with the overrides from source. // Assumes the executable is the first Mapping entry. if i == 0 { if s.ExecName != "" { m.File = s.ExecName } if s.BuildID != "" { m.BuildID = s.BuildID } } if m.File != "" { baseName = filepath.Base(m.File) } for _, path := range filepath.SplitList(searchPath) { var fileNames []string if m.BuildID != "" { fileNames = []string{filepath.Join(path, m.BuildID, baseName)} if matches, err := filepath.Glob(filepath.Join(path, m.BuildID, "*")); err == nil { fileNames = append(fileNames, matches...) } } if baseName != "" { fileNames = append(fileNames, filepath.Join(path, baseName)) } for _, name := range fileNames { if f, err := obj.Open(name, m.Start, m.Limit, m.Offset); 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 { m.File = name continue mapping } } } } } }
// symbolsFromBinaries examines the binaries listed on the profile // that have associated samples, and identifies symbols matching rx. func symbolsFromBinaries(prof *profile.Profile, g *graph.Graph, rx *regexp.Regexp, address *uint64, obj plugin.ObjTool) []*objSymbol { hasSamples := make(map[string]bool) // Only examine mappings that have samples that match the // regexp. This is an optimization to speed up pprof. for _, n := range g.Nodes { if name := n.Info.PrintableName(); rx.MatchString(name) && n.Info.Objfile != "" { hasSamples[n.Info.Objfile] = true } } // Walk all mappings looking for matching functions with samples. var objSyms []*objSymbol for _, m := range prof.Mapping { if !hasSamples[filepath.Base(m.File)] { if address == nil || !(m.Start <= *address && *address <= m.Limit) { continue } } f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset) if err != nil { fmt.Printf("%v\n", err) continue } // Find symbols in this binary matching the user regexp. var addr uint64 if address != nil { addr = *address } msyms, err := f.Symbols(rx, addr) base := f.Base() f.Close() if err != nil { continue } for _, ms := range msyms { objSyms = append(objSyms, &objSymbol{ sym: ms, base: base, }, ) } } return objSyms }
// newMapping creates a mappingTable for a profile. func newMapping(prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, force bool) (*mappingTable, error) { mt := &mappingTable{ prof: prof, segments: make(map[*profile.Mapping]plugin.ObjFile), } // Identify used mappings mappings := make(map[*profile.Mapping]bool) for _, l := range prof.Location { mappings[l.Mapping] = true } for _, m := range prof.Mapping { if !mappings[m] { continue } // Do not attempt to re-symbolize a mapping that has already been symbolized. if !force && (m.HasFunctions || m.HasFilenames || m.HasLineNumbers) { continue } // Skip well-known system mappings name := filepath.Base(m.File) if name == "" || name == "[vdso]" || strings.HasPrefix(name, "linux-vdso") { continue } f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset) if err != nil { ui.PrintErr("Local symbolization failed for ", name, ": ", err) continue } if fid := f.BuildID(); m.BuildID != "" && fid != "" && fid != m.BuildID { ui.PrintErr("Local symbolization failed for ", name, ": build ID mismatch") f.Close() continue } mt.segments[m] = f } return mt, nil }
// newMapping creates a mappingTable for a profile. func newMapping(prof *profile.Profile, obj plugin.ObjTool, ui plugin.UI, force bool) (*mappingTable, error) { mt := &mappingTable{ prof: prof, segments: make(map[*profile.Mapping]plugin.ObjFile), } // Identify used mappings mappings := make(map[*profile.Mapping]bool) for _, l := range prof.Location { mappings[l.Mapping] = true } missingBinaries := false for midx, m := range prof.Mapping { if !mappings[m] { continue } // Do not attempt to re-symbolize a mapping that has already been symbolized. if !force && (m.HasFunctions || m.HasFilenames || m.HasLineNumbers) { continue } if m.File == "" { if midx == 0 { ui.PrintErr("Main binary filename not available.\n" + "Try passing the path to the main binary before the profile.") continue } missingBinaries = true continue } // Skip well-known system mappings name := filepath.Base(m.File) if name == "[vdso]" || strings.HasPrefix(name, "linux-vdso") { continue } // Skip mappings pointing to a source URL if m.BuildID == "" { if u, err := url.Parse(m.File); err == nil && u.IsAbs() { continue } } f, err := obj.Open(m.File, m.Start, m.Limit, m.Offset) if err != nil { ui.PrintErr("Local symbolization failed for ", name, ": ", err) continue } if fid := f.BuildID(); m.BuildID != "" && fid != "" && fid != m.BuildID { ui.PrintErr("Local symbolization failed for ", name, ": build ID mismatch") f.Close() continue } mt.segments[m] = f } if missingBinaries { ui.PrintErr("Some binary filenames not available. Symbolization may be incomplete.") } return mt, nil }