// 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 nodes, src string, obj plugin.ObjTool) map[int]nodes { assembly := make(map[int]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 { g, err := newGraph(rpt) if err != nil { return err } o := rpt.options prof := rpt.prof // 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.ns, 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 := sumNodes(sns) // 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 }