// assemblyPerSourceLine disassembles the binary containing a symbol // and classifies the assembly instructions according to its // corresponding source line, annotating them with a set of samples. func assemblyPerSourceLine(objSyms []*objSymbol, rs graph.Nodes, src string, obj plugin.ObjTool) map[int]graph.Nodes { assembly := make(map[int]graph.Nodes) // Identify symbol to use for this collection of samples. o := findMatchingSymbol(objSyms, rs) if o == nil { return assembly } // Extract assembly for matched symbol insns, err := obj.Disasm(o.sym.File, o.sym.Start, o.sym.End) if err != nil { return assembly } srcBase := filepath.Base(src) anodes := annotateAssembly(insns, rs, o.base) var lineno = 0 for _, an := range anodes { if filepath.Base(an.Info.File) == srcBase { lineno = an.Info.Lineno } if lineno != 0 { assembly[lineno] = append(assembly[lineno], an) } } return assembly }
// printAssembly prints an annotated assembly listing. func printAssembly(w io.Writer, rpt *Report, obj plugin.ObjTool) error { o := rpt.options prof := rpt.prof g := rpt.newGraph(nil) // If the regexp source can be parsed as an address, also match // functions that land on that address. var address *uint64 if hex, err := strconv.ParseUint(o.Symbol.String(), 0, 64); err == nil { address = &hex } fmt.Fprintln(w, "Total:", rpt.formatValue(rpt.total)) symbols := symbolsFromBinaries(prof, g, o.Symbol, address, obj) symNodes := nodesPerSymbol(g.Nodes, symbols) // Sort function names for printing. var syms objSymbols for s := range symNodes { syms = append(syms, s) } sort.Sort(syms) // Correlate the symbols from the binary with the profile samples. for _, s := range syms { sns := symNodes[s] // Gather samples for this symbol. flatSum, cumSum := sns.Sum() // Get the function assembly. insns, err := obj.Disasm(s.sym.File, s.sym.Start, s.sym.End) if err != nil { return err } ns := annotateAssembly(insns, sns, s.base) fmt.Fprintf(w, "ROUTINE ======================== %s\n", s.sym.Name[0]) for _, name := range s.sym.Name[1:] { fmt.Fprintf(w, " AKA ======================== %s\n", name) } fmt.Fprintf(w, "%10s %10s (flat, cum) %s of Total\n", rpt.formatValue(flatSum), rpt.formatValue(cumSum), percentage(cumSum, rpt.total)) for _, n := range ns { fmt.Fprintf(w, "%10s %10s %10x: %s\n", valueOrDot(n.Flat, rpt), valueOrDot(n.Cum, rpt), n.Info.Address, n.Info.Name) } } return nil }