(rpt *Report, addrs map[uint64]addrInfo, flat map[uint64]int64)
| 369 | } |
| 370 | |
| 371 | func (sp *sourcePrinter) expandAddresses(rpt *Report, addrs map[uint64]addrInfo, flat map[uint64]int64) { |
| 372 | // We found interesting addresses (ones with non-zero samples) above. |
| 373 | // Get covering address ranges and disassemble the ranges. |
| 374 | ranges, unprocessed := sp.splitIntoRanges(rpt.prof, addrs, flat) |
| 375 | sp.handleUnprocessed(addrs, unprocessed) |
| 376 | |
| 377 | // Trim ranges if there are too many. |
| 378 | const maxRanges = 25 |
| 379 | sort.Slice(ranges, func(i, j int) bool { |
| 380 | return ranges[i].score > ranges[j].score |
| 381 | }) |
| 382 | if len(ranges) > maxRanges { |
| 383 | ranges = ranges[:maxRanges] |
| 384 | } |
| 385 | |
| 386 | for _, r := range ranges { |
| 387 | objBegin, err := r.obj.ObjAddr(r.begin) |
| 388 | if err != nil { |
| 389 | fmt.Fprintf(os.Stderr, "Failed to compute objdump address for range start %x: %v\n", r.begin, err) |
| 390 | continue |
| 391 | } |
| 392 | objEnd, err := r.obj.ObjAddr(r.end) |
| 393 | if err != nil { |
| 394 | fmt.Fprintf(os.Stderr, "Failed to compute objdump address for range end %x: %v\n", r.end, err) |
| 395 | continue |
| 396 | } |
| 397 | base := r.begin - objBegin |
| 398 | insts, err := sp.objectTool.Disasm(r.mapping.File, objBegin, objEnd, rpt.options.IntelSyntax) |
| 399 | if err != nil { |
| 400 | // TODO(sanjay): Report that the covered addresses are missing. |
| 401 | continue |
| 402 | } |
| 403 | |
| 404 | var lastFrames []plugin.Frame |
| 405 | var lastAddr, maxAddr uint64 |
| 406 | for i, inst := range insts { |
| 407 | addr := inst.Addr + base |
| 408 | |
| 409 | // Guard against duplicate output from Disasm. |
| 410 | if addr <= maxAddr { |
| 411 | continue |
| 412 | } |
| 413 | maxAddr = addr |
| 414 | |
| 415 | length := 1 |
| 416 | if i+1 < len(insts) && insts[i+1].Addr > inst.Addr { |
| 417 | // Extend to next instruction. |
| 418 | length = int(insts[i+1].Addr - inst.Addr) |
| 419 | } |
| 420 | |
| 421 | // Get inlined-call-stack for address. |
| 422 | frames, err := r.obj.SourceLine(addr) |
| 423 | if err != nil { |
| 424 | // Construct a frame from disassembler output. |
| 425 | frames = []plugin.Frame{{Func: inst.Function, File: inst.File, Line: inst.Line}} |
| 426 | } |
| 427 | |
| 428 | x := instructionInfo{objAddr: inst.Addr, length: length, disasm: inst.Text} |
no test coverage detected