void ReportCommand::ProcessSampleRecord(const SampleRecord& r) { if (use_branch_address_ && (r.sample_type & PERF_SAMPLE_BRANCH_STACK)) { for (auto& item : r.branch_stack_data.stack) { if (item.from != 0 && item.to != 0) { sample_tree_->AddBranchSample(r.tid_data.pid, r.tid_data.tid, item.from, item.to, item.flags, r.time_data.time, r.period_data.period); } } } else { bool in_kernel = (r.header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_KERNEL; SampleEntry* sample = sample_tree_->AddSample(r.tid_data.pid, r.tid_data.tid, r.ip_data.ip, r.time_data.time, r.period_data.period, in_kernel); CHECK(sample != nullptr); if (accumulate_callchain_ && (r.sample_type & PERF_SAMPLE_CALLCHAIN) != 0) { std::vector<SampleEntry*> callchain; callchain.push_back(sample); const std::vector<uint64_t>& ips = r.callchain_data.ips; bool first_ip = true; for (auto& ip : ips) { if (ip >= PERF_CONTEXT_MAX) { switch (ip) { case PERF_CONTEXT_KERNEL: in_kernel = true; break; case PERF_CONTEXT_USER: in_kernel = false; break; default: LOG(ERROR) << "Unexpected perf_context in callchain: " << ip; } } else { if (first_ip) { // Remove duplication with sampled ip. if (ip == r.ip_data.ip) { continue; } first_ip = false; } SampleEntry* sample = sample_tree_->AddCallChainSample(r.tid_data.pid, r.tid_data.tid, ip, r.time_data.time, r.period_data.period, in_kernel, callchain); callchain.push_back(sample); } } if (print_callgraph_) { std::set<SampleEntry*> added_set; while (callchain.size() >= 2) { SampleEntry* sample = callchain[0]; callchain.erase(callchain.begin()); // Add only once for recursive calls on callchain. if (added_set.find(sample) != added_set.end()) { continue; } added_set.insert(sample); sample_tree_->InsertCallChainForSample(sample, callchain, r.period_data.period); } } } } }