From adbb6341047d414fe1f7c373f7d4a246de13471b Mon Sep 17 00:00:00 2001 From: Yabin Cui Date: Mon, 1 May 2023 15:48:12 -0700 Subject: simpleperf: Store etm branch list in the recording file Store etm branch list in a new feature section. Also supports pasing it in the inject and dump commands. Bug: 279094308 Test: run simpleperf_unit_test (cherry picked from https://android-review.googlesource.com/q/commit:6601cb4ec033b0ed03de8b9f55cffbc9619c50d3) Merged-In: I9a7ea67955b2f139b1f9dab773da75674e5cbc36 Change-Id: I9a7ea67955b2f139b1f9dab773da75674e5cbc36 --- simpleperf/cmd_dumprecord.cpp | 30 ++++++++++++++++++++++++++++++ simpleperf/cmd_inject.cpp | 29 +++++++++++++++++++++++++++++ simpleperf/cmd_record.cpp | 17 +++++++++++++++++ simpleperf/record_file_format.h | 4 ++++ simpleperf/record_file_reader.cpp | 1 + 5 files changed, 81 insertions(+) diff --git a/simpleperf/cmd_dumprecord.cpp b/simpleperf/cmd_dumprecord.cpp index 4738eef6..0b8df15a 100644 --- a/simpleperf/cmd_dumprecord.cpp +++ b/simpleperf/cmd_dumprecord.cpp @@ -26,6 +26,7 @@ #include #include +#include "ETMBranchListFile.h" #include "ETMDecoder.h" #include "command.h" #include "dso.h" @@ -540,6 +541,35 @@ bool DumpRecordCommand::DumpFeatureSection() { PrintIndented(2, "size: %" PRIu64 "\n", file.size); } } + } else if (feature == FEAT_ETM_BRANCH_LIST) { + std::string data; + if (!record_file_reader_->ReadFeatureSection(FEAT_ETM_BRANCH_LIST, &data)) { + return false; + } + BranchListBinaryMap binary_map; + if (!StringToBranchListBinaryMap(data, binary_map)) { + return false; + } + PrintIndented(1, "etm_branch_list:\n"); + for (const auto& [key, binary] : binary_map) { + PrintIndented(2, "path: %s\n", key.path.c_str()); + PrintIndented(2, "build_id: %s\n", key.build_id.ToString().c_str()); + PrintIndented(2, "binary_type: %s\n", DsoTypeToString(binary.dso_type)); + if (binary.dso_type == DSO_KERNEL) { + PrintIndented(2, "kernel_start_addr: 0x%" PRIx64 "\n", key.kernel_start_addr); + } + for (const auto& [addr, branches] : binary.GetOrderedBranchMap()) { + PrintIndented(3, "addr: 0x%" PRIx64 "\n", addr); + for (const auto& [branch, count] : branches) { + std::string s = "0b"; + for (auto it = branch.rbegin(); it != branch.rend(); ++it) { + s.push_back(*it ? '1' : '0'); + } + PrintIndented(3, "branch: %s\n", s.c_str()); + PrintIndented(3, "count: %" PRIu64 "\n", count); + } + } + } } } return true; diff --git a/simpleperf/cmd_inject.cpp b/simpleperf/cmd_inject.cpp index f83805ac..d3f66cd7 100644 --- a/simpleperf/cmd_inject.cpp +++ b/simpleperf/cmd_inject.cpp @@ -164,6 +164,9 @@ class PerfDataReader { if (!record_file_reader_) { return false; } + if (record_file_reader_->HasFeature(PerfFileFormat::FEAT_ETM_BRANCH_LIST)) { + return ProcessETMBranchListFeature(); + } if (exclude_perf_) { const auto& info_map = record_file_reader_->GetMetaInfoFeature(); if (auto it = info_map.find("recording_process"); it == info_map.end()) { @@ -196,6 +199,32 @@ class PerfDataReader { } private: + bool ProcessETMBranchListFeature() { + if (exclude_perf_) { + LOG(WARNING) << "--exclude-perf has no effect on perf.data with etm branch list"; + } + if (autofdo_callback_) { + LOG(ERROR) << "convert to autofdo format isn't support on perf.data with etm branch list"; + return false; + } + CHECK(branch_list_callback_); + std::string s; + if (!record_file_reader_->ReadFeatureSection(PerfFileFormat::FEAT_ETM_BRANCH_LIST, &s)) { + return false; + } + BranchListBinaryMap binary_map; + if (!StringToBranchListBinaryMap(s, binary_map)) { + return false; + } + for (auto& [key, binary] : binary_map) { + if (!binary_filter_.Filter(key.path)) { + continue; + } + branch_list_callback_(key, binary); + } + return true; + } + bool ProcessRecord(Record* r) { thread_tree_.GetThreadTree().Update(*r); if (r->type() == PERF_RECORD_AUXTRACE_INFO) { diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 4ef2b7ff..21b5e50d 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -409,6 +409,7 @@ RECORD_FILTER_OPTION_HELP_MSG_FOR_RECORDING bool DumpMetaInfoFeature(bool kernel_symbols_available); bool DumpDebugUnwindFeature(const std::unordered_set& dso_set); void CollectHitFileInfo(const SampleRecord& r, std::unordered_set* dso_set); + bool DumpETMBranchListFeature(); std::unique_ptr sample_speed_; bool system_wide_collection_; @@ -1996,6 +1997,9 @@ bool RecordCommand::DumpAdditionalFeatures(const std::vector& args) if (keep_failed_unwinding_debug_info_) { feature_count += 2; } + if (etm_branch_list_generator_) { + feature_count++; + } if (!record_file_writer_->BeginWriteFeatures(feature_count)) { return false; } @@ -2038,6 +2042,9 @@ bool RecordCommand::DumpAdditionalFeatures(const std::vector& args) if (keep_failed_unwinding_debug_info_ && !DumpDebugUnwindFeature(debug_unwinding_files)) { return false; } + if (etm_branch_list_generator_ && !DumpETMBranchListFeature()) { + return false; + } if (!record_file_writer_->EndWriteFeatures()) { return false; @@ -2177,6 +2184,16 @@ void RecordCommand::CollectHitFileInfo(const SampleRecord& r, std::unordered_set } } +bool RecordCommand::DumpETMBranchListFeature() { + BranchListBinaryMap binary_map = etm_branch_list_generator_->GetBranchListBinaryMap(); + std::string s; + if (!BranchListBinaryMapToString(binary_map, s)) { + return false; + } + return record_file_writer_->WriteFeature(PerfFileFormat::FEAT_ETM_BRANCH_LIST, s.data(), + s.size()); +} + } // namespace static bool ConsumeStr(const char*& p, const char* s) { diff --git a/simpleperf/record_file_format.h b/simpleperf/record_file_format.h index 53c6719b..0b36f351 100644 --- a/simpleperf/record_file_format.h +++ b/simpleperf/record_file_format.h @@ -82,6 +82,9 @@ file2 feature section (used to replace file feature section): uint32_t file_msg2_size; FileFeature file_msg2; ... + +etm_branch_list feature section: + ETMBranchList etm_branch_list; // from etm_branch_list.proto */ namespace simpleperf { @@ -116,6 +119,7 @@ enum { FEAT_DEBUG_UNWIND, FEAT_DEBUG_UNWIND_FILE, FEAT_FILE2, + FEAT_ETM_BRANCH_LIST, FEAT_MAX_NUM = 256, }; diff --git a/simpleperf/record_file_reader.cpp b/simpleperf/record_file_reader.cpp index 8f54e65d..1b1bab7e 100644 --- a/simpleperf/record_file_reader.cpp +++ b/simpleperf/record_file_reader.cpp @@ -60,6 +60,7 @@ static const std::map feature_name_map = { {FEAT_DEBUG_UNWIND, "debug_unwind"}, {FEAT_DEBUG_UNWIND_FILE, "debug_unwind_file"}, {FEAT_FILE2, "file2"}, + {FEAT_ETM_BRANCH_LIST, "etm_branch_list"}, }; std::string GetFeatureName(int feature_id) { -- cgit v1.2.3