diff options
author | Yabin Cui <yabinc@google.com> | 2023-11-22 15:51:32 -0800 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2023-12-04 19:34:33 -0800 |
commit | 82d48057901353b9d6be37c3c3e6079e370c5076 (patch) | |
tree | fa97cc710bfcc3673253ff42996c243bc907141c | |
parent | 4320c32a6abea547013313facc2640c496e1e341 (diff) | |
download | extras-82d48057901353b9d6be37c3c3e6079e370c5076.tar.gz |
simpleperf: Prepare for adding code handling LBR profiles
1. Rename etm_branch_list.proto to branch_list.proto.
2. Rename ETMBranchListFile to BranchListFile.
3. Add ETM prefix in ETM specific names.
4. Also remove duplicate BinaryFilter.
Bug: 293953824
Test: run simpleperf_unit_test
Change-Id: I914c46b717a62f47f0b721082d1417d93486746a
-rw-r--r-- | simpleperf/Android.bp | 5 | ||||
-rw-r--r-- | simpleperf/BranchListFile.cpp (renamed from simpleperf/ETMBranchListFile.cpp) | 64 | ||||
-rw-r--r-- | simpleperf/BranchListFile.h (renamed from simpleperf/ETMBranchListFile.h) | 82 | ||||
-rw-r--r-- | simpleperf/BranchListFile_test.cpp (renamed from simpleperf/ETMBranchListFile_test.cpp) | 8 | ||||
-rw-r--r-- | simpleperf/ETMDecoder.cpp | 4 | ||||
-rw-r--r-- | simpleperf/ETMDecoder.h | 6 | ||||
-rw-r--r-- | simpleperf/branch_list.proto | 67 | ||||
-rw-r--r-- | simpleperf/cmd_dumprecord.cpp | 6 | ||||
-rw-r--r-- | simpleperf/cmd_inject.cpp | 158 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 6 | ||||
-rw-r--r-- | simpleperf/etm_branch_list.proto | 66 |
11 files changed, 225 insertions, 247 deletions
diff --git a/simpleperf/Android.bp b/simpleperf/Android.bp index f1cbb1ea..bf33df45 100644 --- a/simpleperf/Android.bp +++ b/simpleperf/Android.bp @@ -220,8 +220,8 @@ cc_defaults { "cmd_report_sample.proto", "command.cpp", "dso.cpp", - "etm_branch_list.proto", - "ETMBranchListFile.cpp", + "branch_list.proto", + "BranchListFile.cpp", "event_attr.cpp", "event_type.cpp", "kallsyms.cpp", @@ -561,6 +561,7 @@ cc_defaults { "cmd_report_test.cpp", ], srcs: [ + "BranchListFile_test.cpp", "cmd_inject_test.cpp", "cmd_kmem_test.cpp", "cmd_merge_test.cpp", diff --git a/simpleperf/ETMBranchListFile.cpp b/simpleperf/BranchListFile.cpp index c92cf8cc..e8f6b22c 100644 --- a/simpleperf/ETMBranchListFile.cpp +++ b/simpleperf/BranchListFile.cpp @@ -14,16 +14,16 @@ * limitations under the License. */ -#include "ETMBranchListFile.h" +#include "BranchListFile.h" #include "ETMDecoder.h" -#include "system/extras/simpleperf/etm_branch_list.pb.h" +#include "system/extras/simpleperf/branch_list.pb.h" namespace simpleperf { static constexpr const char* ETM_BRANCH_LIST_PROTO_MAGIC = "simpleperf:EtmBranchList"; -std::string BranchToProtoString(const std::vector<bool>& branch) { +std::string ETMBranchToProtoString(const std::vector<bool>& branch) { size_t bytes = (branch.size() + 7) / 8; std::string res(bytes, '\0'); for (size_t i = 0; i < branch.size(); i++) { @@ -34,7 +34,7 @@ std::string BranchToProtoString(const std::vector<bool>& branch) { return res; } -std::vector<bool> ProtoStringToBranch(const std::string& s, size_t bit_size) { +std::vector<bool> ProtoStringToETMBranch(const std::string& s, size_t bit_size) { std::vector<bool> branch(bit_size, false); for (size_t i = 0; i < bit_size; i++) { if (s[i >> 3] & (1 << (i & 7))) { @@ -44,28 +44,28 @@ std::vector<bool> ProtoStringToBranch(const std::string& s, size_t bit_size) { return branch; } -static std::optional<proto::ETMBranchList_Binary::BinaryType> ToProtoBinaryType(DsoType dso_type) { +static std::optional<proto::ETMBinary::BinaryType> ToProtoBinaryType(DsoType dso_type) { switch (dso_type) { case DSO_ELF_FILE: - return proto::ETMBranchList_Binary::ELF_FILE; + return proto::ETMBinary::ELF_FILE; case DSO_KERNEL: - return proto::ETMBranchList_Binary::KERNEL; + return proto::ETMBinary::KERNEL; case DSO_KERNEL_MODULE: - return proto::ETMBranchList_Binary::KERNEL_MODULE; + return proto::ETMBinary::KERNEL_MODULE; default: LOG(ERROR) << "unexpected dso type " << dso_type; return std::nullopt; } } -bool BranchListBinaryMapToString(const BranchListBinaryMap& binary_map, std::string& s) { - proto::ETMBranchList branch_list_proto; +bool ETMBinaryMapToString(const ETMBinaryMap& binary_map, std::string& s) { + proto::BranchList branch_list_proto; branch_list_proto.set_magic(ETM_BRANCH_LIST_PROTO_MAGIC); std::vector<char> branch_buf; for (const auto& p : binary_map) { const BinaryKey& key = p.first; - const BranchListBinaryInfo& binary = p.second; - auto binary_proto = branch_list_proto.add_binaries(); + const ETMBinary& binary = p.second; + auto binary_proto = branch_list_proto.add_etm_data(); binary_proto->set_path(key.path); if (!key.build_id.IsEmpty()) { @@ -85,7 +85,7 @@ bool BranchListBinaryMapToString(const BranchListBinaryMap& binary_map, std::str const std::vector<bool>& branch = branch_p.first; auto branch_proto = addr_proto->add_branches(); - branch_proto->set_branch(BranchToProtoString(branch)); + branch_proto->set_branch(ETMBranchToProtoString(branch)); branch_proto->set_branch_size(branch.size()); branch_proto->set_count(branch_p.second); } @@ -102,13 +102,13 @@ bool BranchListBinaryMapToString(const BranchListBinaryMap& binary_map, std::str return true; } -static std::optional<DsoType> ToDsoType(proto::ETMBranchList_Binary::BinaryType binary_type) { +static std::optional<DsoType> ToDsoType(proto::ETMBinary::BinaryType binary_type) { switch (binary_type) { - case proto::ETMBranchList_Binary::ELF_FILE: + case proto::ETMBinary::ELF_FILE: return DSO_ELF_FILE; - case proto::ETMBranchList_Binary::KERNEL: + case proto::ETMBinary::KERNEL: return DSO_KERNEL; - case proto::ETMBranchList_Binary::KERNEL_MODULE: + case proto::ETMBinary::KERNEL_MODULE: return DSO_KERNEL_MODULE; default: LOG(ERROR) << "unexpected binary type " << binary_type; @@ -116,46 +116,46 @@ static std::optional<DsoType> ToDsoType(proto::ETMBranchList_Binary::BinaryType } } -static UnorderedBranchMap BuildUnorderedBranchMap(const proto::ETMBranchList_Binary& binary_proto) { - UnorderedBranchMap branch_map; +static UnorderedETMBranchMap BuildUnorderedETMBranchMap(const proto::ETMBinary& binary_proto) { + UnorderedETMBranchMap branch_map; for (size_t i = 0; i < binary_proto.addrs_size(); i++) { const auto& addr_proto = binary_proto.addrs(i); auto& b_map = branch_map[addr_proto.addr()]; for (size_t j = 0; j < addr_proto.branches_size(); j++) { const auto& branch_proto = addr_proto.branches(j); std::vector<bool> branch = - ProtoStringToBranch(branch_proto.branch(), branch_proto.branch_size()); + ProtoStringToETMBranch(branch_proto.branch(), branch_proto.branch_size()); b_map[branch] = branch_proto.count(); } } return branch_map; } -bool StringToBranchListBinaryMap(const std::string& s, BranchListBinaryMap& binary_map) { - proto::ETMBranchList branch_list_proto; +bool StringToETMBinaryMap(const std::string& s, ETMBinaryMap& binary_map) { + proto::BranchList branch_list_proto; if (!branch_list_proto.ParseFromString(s)) { PLOG(ERROR) << "failed to read ETMBranchList msg"; return false; } if (branch_list_proto.magic() != ETM_BRANCH_LIST_PROTO_MAGIC) { - PLOG(ERROR) << "not in format etm_branch_list.proto"; + PLOG(ERROR) << "not in etm branch list format in branch_list.proto"; return false; } - for (size_t i = 0; i < branch_list_proto.binaries_size(); i++) { - const auto& binary_proto = branch_list_proto.binaries(i); + for (size_t i = 0; i < branch_list_proto.etm_data_size(); i++) { + const auto& binary_proto = branch_list_proto.etm_data(i); BinaryKey key(binary_proto.path(), BuildId(binary_proto.build_id())); if (binary_proto.has_kernel_info()) { key.kernel_start_addr = binary_proto.kernel_info().kernel_start_addr(); } - BranchListBinaryInfo& binary = binary_map[key]; + ETMBinary& binary = binary_map[key]; auto dso_type = ToDsoType(binary_proto.type()); if (!dso_type) { LOG(ERROR) << "invalid binary type " << binary_proto.type(); return false; } binary.dso_type = dso_type.value(); - binary.branch_map = BuildUnorderedBranchMap(binary_proto); + binary.branch_map = BuildUnorderedETMBranchMap(binary_proto); } return true; } @@ -231,7 +231,7 @@ class ETMBranchListGeneratorImpl : public ETMBranchListGenerator { } bool ProcessRecord(const Record& r, bool& consumed) override; - BranchListBinaryMap GetBranchListBinaryMap() override; + ETMBinaryMap GetETMBinaryMap() override; private: struct AuxRecordData { @@ -257,7 +257,7 @@ class ETMBranchListGeneratorImpl : public ETMBranchListGenerator { BinaryFilter binary_filter_; std::map<uint32_t, PerCpuData> cpu_map_; std::unique_ptr<ETMDecoder> etm_decoder_; - std::unordered_map<Dso*, BranchListBinaryInfo> branch_list_binary_map_; + std::unordered_map<Dso*, ETMBinary> branch_list_binary_map_; }; bool ETMBranchListGeneratorImpl::ProcessRecord(const Record& r, bool& consumed) { @@ -353,11 +353,11 @@ void ETMBranchListGeneratorImpl::ProcessBranchList(const ETMBranchList& branch_l ++branch_map[branch_list.addr][branch_list.branch]; } -BranchListBinaryMap ETMBranchListGeneratorImpl::GetBranchListBinaryMap() { - BranchListBinaryMap binary_map; +ETMBinaryMap ETMBranchListGeneratorImpl::GetETMBinaryMap() { + ETMBinaryMap binary_map; for (auto& p : branch_list_binary_map_) { Dso* dso = p.first; - BranchListBinaryInfo& binary = p.second; + ETMBinary& binary = p.second; binary.dso_type = dso->type(); BuildId build_id; GetBuildId(*dso, build_id); diff --git a/simpleperf/ETMBranchListFile.h b/simpleperf/BranchListFile.h index fd595c56..3ed13003 100644 --- a/simpleperf/ETMBranchListFile.h +++ b/simpleperf/BranchListFile.h @@ -27,7 +27,7 @@ namespace simpleperf { // But this isn't sufficient when merging binary info from multiple input files. Because // binaries for the same path may be changed between generating input files. So after processing // each input file, we create BinaryKeys to identify binaries, which consider path, build_id and -// kernel_start_addr (for vmlinux). kernel_start_addr affects how addresses in BranchListBinaryInfo +// kernel_start_addr (for vmlinux). kernel_start_addr affects how addresses in ETMBinary // are interpreted for vmlinux. struct BinaryKey { std::string path; @@ -63,14 +63,42 @@ struct BinaryKeyHash { } }; -using UnorderedBranchMap = +class BinaryFilter { + public: + BinaryFilter(const RegEx* binary_name_regex) : binary_name_regex_(binary_name_regex) {} + + void SetRegex(const RegEx* binary_name_regex) { + binary_name_regex_ = binary_name_regex; + dso_filter_cache_.clear(); + } + + bool Filter(Dso* dso) { + auto lookup = dso_filter_cache_.find(dso); + if (lookup != dso_filter_cache_.end()) { + return lookup->second; + } + bool match = Filter(dso->Path()); + dso_filter_cache_.insert({dso, match}); + return match; + } + + bool Filter(const std::string& path) { + return binary_name_regex_ == nullptr || binary_name_regex_->Search(path); + } + + private: + const RegEx* binary_name_regex_; + std::unordered_map<Dso*, bool> dso_filter_cache_; +}; + +using UnorderedETMBranchMap = std::unordered_map<uint64_t, std::unordered_map<std::vector<bool>, uint64_t>>; -struct BranchListBinaryInfo { +struct ETMBinary { DsoType dso_type; - UnorderedBranchMap branch_map; + UnorderedETMBranchMap branch_map; - void Merge(const BranchListBinaryInfo& other) { + void Merge(const ETMBinary& other) { for (auto& other_p : other.branch_map) { auto it = branch_map.find(other_p.first); if (it == branch_map.end()) { @@ -89,8 +117,8 @@ struct BranchListBinaryInfo { } } - BranchMap GetOrderedBranchMap() const { - BranchMap result; + ETMBranchMap GetOrderedBranchMap() const { + ETMBranchMap result; for (const auto& p : branch_map) { uint64_t addr = p.first; const auto& b_map = p.second; @@ -100,38 +128,10 @@ struct BranchListBinaryInfo { } }; -using BranchListBinaryMap = std::unordered_map<BinaryKey, BranchListBinaryInfo, BinaryKeyHash>; +using ETMBinaryMap = std::unordered_map<BinaryKey, ETMBinary, BinaryKeyHash>; -bool BranchListBinaryMapToString(const BranchListBinaryMap& binary_map, std::string& s); -bool StringToBranchListBinaryMap(const std::string& s, BranchListBinaryMap& binary_map); - -class BinaryFilter { - public: - BinaryFilter(const RegEx* binary_name_regex) : binary_name_regex_(binary_name_regex) {} - - void SetRegex(const RegEx* binary_name_regex) { - binary_name_regex_ = binary_name_regex; - dso_filter_cache_.clear(); - } - - bool Filter(Dso* dso) { - auto lookup = dso_filter_cache_.find(dso); - if (lookup != dso_filter_cache_.end()) { - return lookup->second; - } - bool match = Filter(dso->Path()); - dso_filter_cache_.insert({dso, match}); - return match; - } - - bool Filter(const std::string& path) { - return binary_name_regex_ == nullptr || binary_name_regex_->Search(path); - } - - private: - const RegEx* binary_name_regex_; - std::unordered_map<Dso*, bool> dso_filter_cache_; -}; +bool ETMBinaryMapToString(const ETMBinaryMap& binary_map, std::string& s); +bool StringToETMBinaryMap(const std::string& s, ETMBinaryMap& binary_map); // Convert ETM data into branch lists while recording. class ETMBranchListGenerator { @@ -142,11 +142,11 @@ class ETMBranchListGenerator { virtual void SetExcludePid(pid_t pid) = 0; virtual void SetBinaryFilter(const RegEx* binary_name_regex) = 0; virtual bool ProcessRecord(const Record& r, bool& consumed) = 0; - virtual BranchListBinaryMap GetBranchListBinaryMap() = 0; + virtual ETMBinaryMap GetETMBinaryMap() = 0; }; // for testing -std::string BranchToProtoString(const std::vector<bool>& branch); -std::vector<bool> ProtoStringToBranch(const std::string& s, size_t bit_size); +std::string ETMBranchToProtoString(const std::vector<bool>& branch); +std::vector<bool> ProtoStringToETMBranch(const std::string& s, size_t bit_size); } // namespace simpleperf diff --git a/simpleperf/ETMBranchListFile_test.cpp b/simpleperf/BranchListFile_test.cpp index 227c68b3..759b0218 100644 --- a/simpleperf/ETMBranchListFile_test.cpp +++ b/simpleperf/BranchListFile_test.cpp @@ -16,20 +16,20 @@ #include <gtest/gtest.h> -#include "ETMBranchListFile.h" +#include "BranchListFile.h" using namespace simpleperf; -TEST(ETMBranchListFile, branch_to_proto_string) { +TEST(BranchListFile, etm_branch_to_proto_string) { std::vector<bool> branch; for (size_t i = 0; i < 100; i++) { branch.push_back(i % 2 == 0); - std::string s = BranchToProtoString(branch); + std::string s = ETMBranchToProtoString(branch); for (size_t j = 0; j <= i; j++) { bool b = s[j >> 3] & (1 << (j & 7)); ASSERT_EQ(b, branch[j]); } - std::vector<bool> branch2 = ProtoStringToBranch(s, branch.size()); + std::vector<bool> branch2 = ProtoStringToETMBranch(s, branch.size()); ASSERT_EQ(branch, branch2); } } diff --git a/simpleperf/ETMDecoder.cpp b/simpleperf/ETMDecoder.cpp index 9cf43851..822cc6cd 100644 --- a/simpleperf/ETMDecoder.cpp +++ b/simpleperf/ETMDecoder.cpp @@ -930,8 +930,8 @@ class BranchDecoder { InstructionDecoder instruction_decoder_; }; -android::base::expected<void, std::string> ConvertBranchMapToInstrRanges( - Dso* dso, const BranchMap& branch_map, const ETMDecoder::InstrRangeCallbackFn& callback) { +android::base::expected<void, std::string> ConvertETMBranchMapToInstrRanges( + Dso* dso, const ETMBranchMap& branch_map, const ETMDecoder::InstrRangeCallbackFn& callback) { ETMInstrRange instr_range; instr_range.dso = dso; diff --git a/simpleperf/ETMDecoder.h b/simpleperf/ETMDecoder.h index e8ae7f7d..cb5c8dc8 100644 --- a/simpleperf/ETMDecoder.h +++ b/simpleperf/ETMDecoder.h @@ -90,9 +90,9 @@ class ETMDecoder { // Map from addrs to a map of (branch_list, count). // Use maps instead of unordered_maps. Because it helps locality by decoding instructions for sorted // addresses. -using BranchMap = std::map<uint64_t, std::map<std::vector<bool>, uint64_t>>; +using ETMBranchMap = std::map<uint64_t, std::map<std::vector<bool>, uint64_t>>; -android::base::expected<void, std::string> ConvertBranchMapToInstrRanges( - Dso* dso, const BranchMap& branch_map, const ETMDecoder::InstrRangeCallbackFn& callback); +android::base::expected<void, std::string> ConvertETMBranchMapToInstrRanges( + Dso* dso, const ETMBranchMap& branch_map, const ETMDecoder::InstrRangeCallbackFn& callback); } // namespace simpleperf
\ No newline at end of file diff --git a/simpleperf/branch_list.proto b/simpleperf/branch_list.proto new file mode 100644 index 00000000..29247933 --- /dev/null +++ b/simpleperf/branch_list.proto @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// The branch list file format is generated by the inject command. It contains +// a single BranchList message. + +syntax = "proto3"; + +package simpleperf.proto; + +message BranchList { + // Used to identify format in generated proto files. + // Should always be "simpleperf:EtmBranchList". + string magic = 1; + repeated ETMBinary etm_data = 2; +} + +message ETMBinary { + string path = 1; + string build_id = 2; + + message Address { + // vaddr in binary, instr addr before the first branch + uint64 addr = 1; + + message Branch { + // Each bit represents a branch: 0 for not branch, 1 for branch. + // Bit 0 comes first, bit 7 comes last. + bytes branch = 1; + uint32 branch_size = 2; + uint64 count = 3; + } + + repeated Branch branches = 2; + } + + repeated Address addrs = 3; + + enum BinaryType { + ELF_FILE = 0; + KERNEL = 1; + KERNEL_MODULE = 2; + } + BinaryType type = 4; + + message KernelBinaryInfo { + // kernel_start_addr is used to convert kernel ip address to vaddr in vmlinux. + // If it is zero, the Address in KERNEL binary has been converted to vaddr. Otherwise, + // the Address in KERNEL binary is still ip address, and need to be converted later. + uint64 kernel_start_addr = 1; + } + + KernelBinaryInfo kernel_info = 5; +} diff --git a/simpleperf/cmd_dumprecord.cpp b/simpleperf/cmd_dumprecord.cpp index 0bbbb10b..013af562 100644 --- a/simpleperf/cmd_dumprecord.cpp +++ b/simpleperf/cmd_dumprecord.cpp @@ -26,7 +26,7 @@ #include <android-base/stringprintf.h> #include <android-base/strings.h> -#include "ETMBranchListFile.h" +#include "BranchListFile.h" #include "ETMDecoder.h" #include "command.h" #include "dso.h" @@ -550,8 +550,8 @@ bool DumpRecordCommand::DumpFeatureSection() { if (!record_file_reader_->ReadFeatureSection(FEAT_ETM_BRANCH_LIST, &data)) { return false; } - BranchListBinaryMap binary_map; - if (!StringToBranchListBinaryMap(data, binary_map)) { + ETMBinaryMap binary_map; + if (!StringToETMBinaryMap(data, binary_map)) { return false; } PrintIndented(1, "etm_branch_list:\n"); diff --git a/simpleperf/cmd_inject.cpp b/simpleperf/cmd_inject.cpp index d3f66cd7..712f6ee0 100644 --- a/simpleperf/cmd_inject.cpp +++ b/simpleperf/cmd_inject.cpp @@ -25,12 +25,12 @@ #include <android-base/parseint.h> #include <android-base/strings.h> -#include "ETMBranchListFile.h" +#include "BranchListFile.h" #include "ETMDecoder.h" #include "RegEx.h" #include "command.h" #include "record_file.h" -#include "system/extras/simpleperf/etm_branch_list.pb.h" +#include "system/extras/simpleperf/branch_list.pb.h" #include "thread_tree.h" #include "utils.h" @@ -87,7 +87,7 @@ struct AutoFDOBinaryInfo { }; using AutoFDOBinaryCallback = std::function<void(const BinaryKey&, AutoFDOBinaryInfo&)>; -using BranchListBinaryCallback = std::function<void(const BinaryKey&, BranchListBinaryInfo&)>; +using ETMBinaryCallback = std::function<void(const BinaryKey&, ETMBinary&)>; class ETMThreadTreeWithFilter : public ETMThreadTree { public: @@ -110,29 +110,6 @@ class ETMThreadTreeWithFilter : public ETMThreadTree { std::optional<pid_t> exclude_pid_; }; -class BinaryFilter { - public: - BinaryFilter(const RegEx* binary_name_regex) : binary_name_regex_(binary_name_regex) {} - - bool Filter(Dso* dso) { - auto lookup = dso_filter_cache_.find(dso); - if (lookup != dso_filter_cache_.end()) { - return lookup->second; - } - bool match = Filter(dso->Path()); - dso_filter_cache_.insert({dso, match}); - return match; - } - - bool Filter(const std::string& path) { - return binary_name_regex_ == nullptr || binary_name_regex_->Search(path); - } - - private: - const RegEx* binary_name_regex_; - std::unordered_map<Dso*, bool> dso_filter_cache_; -}; - static uint64_t GetFirstLoadSegmentVaddr(Dso* dso) { ElfStatus status; if (auto elf = ElfFile::Open(dso->GetDebugFilePath(), &status); elf) { @@ -145,19 +122,19 @@ static uint64_t GetFirstLoadSegmentVaddr(Dso* dso) { return 0; } -// Read perf.data, and generate AutoFDOBinaryInfo or BranchListBinaryInfo. +// Read perf.data, and generate AutoFDOBinaryInfo or ETMBinary. // To avoid resetting data, it only processes one input file per instance. -class PerfDataReader { +class ETMPerfDataReader { public: - PerfDataReader(const std::string& filename, bool exclude_perf, ETMDumpOption etm_dump_option, - const RegEx* binary_name_regex) + ETMPerfDataReader(const std::string& filename, bool exclude_perf, ETMDumpOption etm_dump_option, + const RegEx* binary_name_regex) : filename_(filename), exclude_perf_(exclude_perf), etm_dump_option_(etm_dump_option), binary_filter_(binary_name_regex) {} void SetCallback(const AutoFDOBinaryCallback& callback) { autofdo_callback_ = callback; } - void SetCallback(const BranchListBinaryCallback& callback) { branch_list_callback_ = callback; } + void SetCallback(const ETMBinaryCallback& callback) { etm_binary_callback_ = callback; } bool Read() { record_file_reader_ = RecordFileReader::CreateInstance(filename_); @@ -192,8 +169,8 @@ class PerfDataReader { } if (autofdo_callback_) { ProcessAutoFDOBinaryInfo(); - } else if (branch_list_callback_) { - ProcessBranchListBinaryInfo(); + } else if (etm_binary_callback_) { + ProcessETMBinary(); } return true; } @@ -207,20 +184,20 @@ class PerfDataReader { LOG(ERROR) << "convert to autofdo format isn't support on perf.data with etm branch list"; return false; } - CHECK(branch_list_callback_); + CHECK(etm_binary_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)) { + ETMBinaryMap binary_map; + if (!StringToETMBinaryMap(s, binary_map)) { return false; } for (auto& [key, binary] : binary_map) { if (!binary_filter_.Filter(key.path)) { continue; } - branch_list_callback_(key, binary); + etm_binary_callback_(key, binary); } return true; } @@ -236,9 +213,9 @@ class PerfDataReader { if (autofdo_callback_) { etm_decoder_->RegisterCallback( [this](const ETMInstrRange& range) { ProcessInstrRange(range); }); - } else if (branch_list_callback_) { + } else if (etm_binary_callback_) { etm_decoder_->RegisterCallback( - [this](const ETMBranchList& branch) { ProcessBranchList(branch); }); + [this](const ETMBranchList& branch) { ProcessETMBranchList(branch); }); } } else if (r->type() == PERF_RECORD_AUX) { AuxRecord* aux = static_cast<AuxRecord*>(r); @@ -277,12 +254,12 @@ class PerfDataReader { autofdo_binary_map_[instr_range.dso].AddInstrRange(instr_range); } - void ProcessBranchList(const ETMBranchList& branch_list) { + void ProcessETMBranchList(const ETMBranchList& branch_list) { if (!binary_filter_.Filter(branch_list.dso)) { return; } - auto& branch_map = branch_list_binary_map_[branch_list.dso].branch_map; + auto& branch_map = etm_binary_map_[branch_list.dso].branch_map; ++branch_map[branch_list.addr][branch_list.branch]; } @@ -295,10 +272,10 @@ class PerfDataReader { } } - void ProcessBranchListBinaryInfo() { - for (auto& p : branch_list_binary_map_) { + void ProcessETMBinary() { + for (auto& p : etm_binary_map_) { Dso* dso = p.first; - BranchListBinaryInfo& binary = p.second; + ETMBinary& binary = p.second; binary.dso_type = dso->type(); BinaryKey key(dso, 0); if (binary.dso_type == DSO_KERNEL) { @@ -313,7 +290,7 @@ class PerfDataReader { key.kernel_start_addr = kernel_map_start_addr_; } } - branch_list_callback_(key, binary); + etm_binary_callback_(key, binary); } } @@ -322,7 +299,7 @@ class PerfDataReader { ETMDumpOption etm_dump_option_; BinaryFilter binary_filter_; AutoFDOBinaryCallback autofdo_callback_; - BranchListBinaryCallback branch_list_callback_; + ETMBinaryCallback etm_binary_callback_; std::vector<uint8_t> aux_data_buffer_; std::unique_ptr<ETMDecoder> etm_decoder_; @@ -332,16 +309,16 @@ class PerfDataReader { // Store results for AutoFDO. std::unordered_map<Dso*, AutoFDOBinaryInfo> autofdo_binary_map_; // Store results for BranchList. - std::unordered_map<Dso*, BranchListBinaryInfo> branch_list_binary_map_; + std::unordered_map<Dso*, ETMBinary> etm_binary_map_; }; -// Read a protobuf file specified by etm_branch_list.proto, and generate BranchListBinaryInfo. -class BranchListReader { +// Read a protobuf file specified by etm_branch_list.proto, and generate ETMBinary. +class ETMBranchListReader { public: - BranchListReader(const std::string& filename, const RegEx* binary_name_regex) + ETMBranchListReader(const std::string& filename, const RegEx* binary_name_regex) : filename_(filename), binary_filter_(binary_name_regex) {} - void SetCallback(const BranchListBinaryCallback& callback) { callback_ = callback; } + void SetCallback(const ETMBinaryCallback& callback) { callback_ = callback; } bool Read() { std::string s; @@ -349,8 +326,8 @@ class BranchListReader { PLOG(ERROR) << "failed to read " << filename_; return false; } - BranchListBinaryMap binary_map; - if (!StringToBranchListBinaryMap(s, binary_map)) { + ETMBinaryMap binary_map; + if (!StringToETMBinaryMap(s, binary_map)) { PLOG(ERROR) << "file is in wrong format: " << filename_; return false; } @@ -366,13 +343,13 @@ class BranchListReader { private: const std::string filename_; BinaryFilter binary_filter_; - BranchListBinaryCallback callback_; + ETMBinaryCallback callback_; }; -// Convert BranchListBinaryInfo into AutoFDOBinaryInfo. -class BranchListToAutoFDOConverter { +// Convert ETMBinary into AutoFDOBinaryInfo. +class ETMBranchListToAutoFDOConverter { public: - std::unique_ptr<AutoFDOBinaryInfo> Convert(const BinaryKey& key, BranchListBinaryInfo& binary) { + std::unique_ptr<AutoFDOBinaryInfo> Convert(const BinaryKey& key, ETMBinary& binary) { BuildId build_id = key.build_id; std::unique_ptr<Dso> dso = Dso::CreateDsoWithBuildId(binary.dso_type, key.path, build_id); if (!dso || !CheckBuildId(dso.get(), key.build_id)) { @@ -390,8 +367,8 @@ class BranchListToAutoFDOConverter { autofdo_binary->AddInstrRange(range); }; - auto result = - ConvertBranchMapToInstrRanges(dso.get(), binary.GetOrderedBranchMap(), process_instr_range); + auto result = ConvertETMBranchMapToInstrRanges(dso.get(), binary.GetOrderedBranchMap(), + process_instr_range); if (!result.ok()) { LOG(WARNING) << "failed to build instr ranges for binary " << dso->Path() << ": " << result.error(); @@ -410,15 +387,14 @@ class BranchListToAutoFDOConverter { build_id == expected_build_id; } - void ModifyBranchMapForKernel(Dso* dso, uint64_t kernel_start_addr, - BranchListBinaryInfo& binary) { + void ModifyBranchMapForKernel(Dso* dso, uint64_t kernel_start_addr, ETMBinary& binary) { if (kernel_start_addr == 0) { // vmlinux has been provided when generating branch lists. Addresses in branch lists are // already vaddrs in vmlinux. return; } // Addresses are still kernel ip addrs in memory. Need to convert them to vaddrs in vmlinux. - UnorderedBranchMap new_branch_map; + UnorderedETMBranchMap new_branch_map; for (auto& p : binary.branch_map) { uint64_t vaddr_in_file = dso->IpToVaddrInFile(p.first, kernel_start_addr, 0); new_branch_map[vaddr_in_file] = std::move(p.second); @@ -511,9 +487,9 @@ class AutoFDOWriter { std::unordered_map<BinaryKey, AutoFDOBinaryInfo, BinaryKeyHash> binary_map_; }; -// Merge BranchListBinaryInfo. -struct BranchListMerger { - void AddBranchListBinary(const BinaryKey& key, BranchListBinaryInfo& binary) { +// Merge ETMBinary. +struct ETMBranchListMerger { + void AddETMBinary(const BinaryKey& key, ETMBinary& binary) { auto it = binary_map.find(key); if (it == binary_map.end()) { binary_map[key] = std::move(binary); @@ -522,13 +498,13 @@ struct BranchListMerger { } } - BranchListBinaryMap binary_map; + ETMBinaryMap binary_map; }; // Write branch lists to a protobuf file specified by etm_branch_list.proto. -class BranchListWriter { +class ETMBranchListWriter { public: - bool Write(const std::string& output_filename, const BranchListBinaryMap& binary_map) { + bool Write(const std::string& output_filename, const ETMBinaryMap& binary_map) { // Don't produce empty output file. if (binary_map.empty()) { LOG(INFO) << "Skip empty output file."; @@ -536,8 +512,8 @@ class BranchListWriter { return true; } std::string s; - if (!BranchListBinaryMapToString(binary_map, s)) { - LOG(ERROR) << "invalid BranchListBinaryMap"; + if (!ETMBinaryMapToString(binary_map, s)) { + LOG(ERROR) << "invalid ETMBinaryMap"; return false; } if (!android::base::WriteStringToFile(s, output_filename)) { @@ -690,8 +666,8 @@ class InjectCommand : public Command { autofdo_writer.AddAutoFDOBinary(key, binary); }; for (const auto& input_filename : input_filenames_) { - PerfDataReader reader(input_filename, exclude_perf_, etm_dump_option_, - binary_name_regex_.get()); + ETMPerfDataReader reader(input_filename, exclude_perf_, etm_dump_option_, + binary_name_regex_.get()); reader.SetCallback(callback); if (!reader.Read()) { return false; @@ -701,42 +677,42 @@ class InjectCommand : public Command { } bool ConvertPerfDataToBranchList() { - BranchListMerger branch_list_merger; - auto callback = [&](const BinaryKey& key, BranchListBinaryInfo& binary) { - branch_list_merger.AddBranchListBinary(key, binary); + ETMBranchListMerger branch_list_merger; + auto callback = [&](const BinaryKey& key, ETMBinary& binary) { + branch_list_merger.AddETMBinary(key, binary); }; for (const auto& input_filename : input_filenames_) { - PerfDataReader reader(input_filename, exclude_perf_, etm_dump_option_, - binary_name_regex_.get()); + ETMPerfDataReader reader(input_filename, exclude_perf_, etm_dump_option_, + binary_name_regex_.get()); reader.SetCallback(callback); if (!reader.Read()) { return false; } } - BranchListWriter branch_list_writer; + ETMBranchListWriter branch_list_writer; return branch_list_writer.Write(output_filename_, branch_list_merger.binary_map); } bool ConvertBranchListToAutoFDO() { // Step1 : Merge branch lists from all input files. - BranchListMerger branch_list_merger; - auto callback = [&](const BinaryKey& key, BranchListBinaryInfo& binary) { - branch_list_merger.AddBranchListBinary(key, binary); + ETMBranchListMerger branch_list_merger; + auto callback = [&](const BinaryKey& key, ETMBinary& binary) { + branch_list_merger.AddETMBinary(key, binary); }; for (const auto& input_filename : input_filenames_) { - BranchListReader reader(input_filename, binary_name_regex_.get()); + ETMBranchListReader reader(input_filename, binary_name_regex_.get()); reader.SetCallback(callback); if (!reader.Read()) { return false; } } - // Step2: Convert BranchListBinaryInfo to AutoFDOBinaryInfo. + // Step2: Convert ETMBinary to AutoFDOBinaryInfo. AutoFDOWriter autofdo_writer; - BranchListToAutoFDOConverter converter; + ETMBranchListToAutoFDOConverter converter; for (auto& p : branch_list_merger.binary_map) { const BinaryKey& key = p.first; - BranchListBinaryInfo& binary = p.second; + ETMBinary& binary = p.second; std::unique_ptr<AutoFDOBinaryInfo> autofdo_binary = converter.Convert(key, binary); if (autofdo_binary) { // Create new BinaryKey with kernel_start_addr = 0. Because AutoFDO output doesn't care @@ -751,19 +727,19 @@ class InjectCommand : public Command { bool ConvertBranchListToBranchList() { // Step1 : Merge branch lists from all input files. - BranchListMerger branch_list_merger; - auto callback = [&](const BinaryKey& key, BranchListBinaryInfo& binary) { - branch_list_merger.AddBranchListBinary(key, binary); + ETMBranchListMerger branch_list_merger; + auto callback = [&](const BinaryKey& key, ETMBinary& binary) { + branch_list_merger.AddETMBinary(key, binary); }; for (const auto& input_filename : input_filenames_) { - BranchListReader reader(input_filename, binary_name_regex_.get()); + ETMBranchListReader reader(input_filename, binary_name_regex_.get()); reader.SetCallback(callback); if (!reader.Read()) { return false; } } - // Step2: Write BranchListBinaryInfo. - BranchListWriter branch_list_writer; + // Step2: Write ETMBinary. + ETMBranchListWriter branch_list_writer; return branch_list_writer.Write(output_filename_, branch_list_merger.binary_map); } diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index ad1133ce..da1a31bf 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -47,8 +47,8 @@ #endif #include <unwindstack/Error.h> +#include "BranchListFile.h" #include "CallChainJoiner.h" -#include "ETMBranchListFile.h" #include "ETMRecorder.h" #include "IOEventLoop.h" #include "JITDebugReader.h" @@ -2214,9 +2214,9 @@ void RecordCommand::CollectHitFileInfo(const SampleRecord& r, std::unordered_set } bool RecordCommand::DumpETMBranchListFeature() { - BranchListBinaryMap binary_map = etm_branch_list_generator_->GetBranchListBinaryMap(); + ETMBinaryMap binary_map = etm_branch_list_generator_->GetETMBinaryMap(); std::string s; - if (!BranchListBinaryMapToString(binary_map, s)) { + if (!ETMBinaryMapToString(binary_map, s)) { return false; } return record_file_writer_->WriteFeature(PerfFileFormat::FEAT_ETM_BRANCH_LIST, s.data(), diff --git a/simpleperf/etm_branch_list.proto b/simpleperf/etm_branch_list.proto deleted file mode 100644 index c66b0d5e..00000000 --- a/simpleperf/etm_branch_list.proto +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto3"; - -package simpleperf.proto; - -message ETMBranchList { - - message Binary { - string path = 1; - string build_id = 2; - - message Address { - // vaddr in binary, instr addr before the first branch - uint64 addr = 1; - - message Branch { - // Each bit represents a branch: 0 for not branch, 1 for branch. - // Bit 0 comes first, bit 7 comes last. - bytes branch = 1; - uint32 branch_size = 2; - uint64 count = 3; - } - - repeated Branch branches = 2; - } - - repeated Address addrs = 3; - - enum BinaryType { - ELF_FILE = 0; - KERNEL = 1; - KERNEL_MODULE = 2; - } - BinaryType type = 4; - - message KernelBinaryInfo { - // kernel_start_addr is used to convert kernel ip address to vaddr in vmlinux. - // If it is zero, the Address in KERNEL binary has been converted to vaddr. Otherwise, - // the Address in KERNEL binary is still ip address, and need to be converted later. - uint64 kernel_start_addr = 1; - } - - KernelBinaryInfo kernel_info = 5; - - } - - // Used to identify format in generated proto files. - // Should always be "simpleperf:EtmBranchList". - string magic = 1; - repeated Binary binaries = 2; -} |