summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2023-11-22 15:51:32 -0800
committerYabin Cui <yabinc@google.com>2023-12-04 19:34:33 -0800
commit82d48057901353b9d6be37c3c3e6079e370c5076 (patch)
treefa97cc710bfcc3673253ff42996c243bc907141c
parent4320c32a6abea547013313facc2640c496e1e341 (diff)
downloadextras-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.bp5
-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.cpp4
-rw-r--r--simpleperf/ETMDecoder.h6
-rw-r--r--simpleperf/branch_list.proto67
-rw-r--r--simpleperf/cmd_dumprecord.cpp6
-rw-r--r--simpleperf/cmd_inject.cpp158
-rw-r--r--simpleperf/cmd_record.cpp6
-rw-r--r--simpleperf/etm_branch_list.proto66
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;
-}