diff options
author | Yabin Cui <yabinc@google.com> | 2015-08-20 15:04:39 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2015-08-21 11:42:23 -0700 |
commit | c84856093e8bf4350d30fc521dc0f1c800c5270b (patch) | |
tree | 202c91d997d583c7f503cfec8d300f6c11d837a5 | |
parent | b84ee6cd81da6a0929035c589f1c0450e8d10902 (diff) | |
download | extras-c84856093e8bf4350d30fc521dc0f1c800c5270b.tar.gz |
Simpleperf: refactor dso.
Having DsoEntry and DsoFactory confuses me which part code should belong to.
This change merges the two into class Dso and makes things clear.
It is also a preparation for performance optimization in Dso.
Bug: 23387541
Change-Id: I41e773406a7f1582a11a18859df252ce8ea3acfa
-rw-r--r-- | simpleperf/cmd_record.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_report.cpp | 25 | ||||
-rw-r--r-- | simpleperf/dso.cpp | 223 | ||||
-rw-r--r-- | simpleperf/dso.h | 75 | ||||
-rw-r--r-- | simpleperf/environment.cpp | 7 | ||||
-rw-r--r-- | simpleperf/sample_tree.cpp | 10 | ||||
-rw-r--r-- | simpleperf/sample_tree.h | 6 | ||||
-rw-r--r-- | simpleperf/sample_tree_test.cpp | 6 | ||||
-rw-r--r-- | simpleperf/thread_tree.cpp | 31 | ||||
-rw-r--r-- | simpleperf/thread_tree.h | 36 |
10 files changed, 223 insertions, 200 deletions
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 5b7bec24..bed957b2 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -600,9 +600,9 @@ bool RecordCommand::GetHitFiles(std::set<std::string>* kernel_modules, const ThreadEntry* thread = thread_tree.FindThreadOrNew(r.tid_data.pid, r.tid_data.tid); const MapEntry* map = thread_tree.FindMap(thread, r.ip_data.ip, in_kernel); if (in_kernel) { - kernel_modules->insert(map->dso->path); + kernel_modules->insert(map->dso->Path()); } else { - user_files->insert(map->dso->path); + user_files->insert(map->dso->Path()); } } } diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp index 5d08993c..9c2f6062 100644 --- a/simpleperf/cmd_report.cpp +++ b/simpleperf/cmd_report.cpp @@ -165,11 +165,11 @@ class DsoItem : public Displayable, public Comparable { } int Compare(const SampleEntry& sample1, const SampleEntry& sample2) const override { - return strcmp(sample1.map->dso->path.c_str(), sample2.map->dso->path.c_str()); + return strcmp(sample1.map->dso->Path().c_str(), sample2.map->dso->Path().c_str()); } std::string Show(const SampleEntry& sample) const override { - return sample.map->dso->path; + return sample.map->dso->Path(); } }; @@ -194,12 +194,12 @@ class DsoFromItem : public Displayable, public Comparable { } int Compare(const SampleEntry& sample1, const SampleEntry& sample2) const override { - return strcmp(sample1.branch_from.map->dso->path.c_str(), - sample2.branch_from.map->dso->path.c_str()); + return strcmp(sample1.branch_from.map->dso->Path().c_str(), + sample2.branch_from.map->dso->Path().c_str()); } std::string Show(const SampleEntry& sample) const override { - return sample.branch_from.map->dso->path; + return sample.branch_from.map->dso->Path(); } }; @@ -424,12 +424,12 @@ bool ReportCommand::ParseOptions(const std::vector<std::string>& args) { } } - DsoFactory::GetInstance()->SetDemangle(demangle); - if (!DsoFactory::GetInstance()->SetSymFsDir(symfs_dir)) { + Dso::SetDemangle(demangle); + if (!Dso::SetSymFsDir(symfs_dir)) { return false; } if (!vmlinux.empty()) { - DsoFactory::GetInstance()->SetVmlinux(vmlinux); + Dso::SetVmlinux(vmlinux); } if (!accumulate_callchain_) { @@ -590,7 +590,7 @@ bool ReportCommand::ReadFeaturesFromRecordFile() { for (auto& r : records) { build_ids.push_back(std::make_pair(r.filename, r.build_id)); } - DsoFactory::GetInstance()->SetBuildIds(build_ids); + Dso::SetBuildIds(build_ids); std::string arch = record_file_reader_->ReadFeatureString(PerfFileFormat::FEAT_ARCH); if (!arch.empty()) { @@ -695,10 +695,11 @@ static void PrintCallGraphEntry(size_t depth, std::string prefix, double percentage = 100.0 * (node->period + node->children_period) / parent_period; percentage_s = android::base::StringPrintf("--%.2lf%%-- ", percentage); } - printf("%s%s%s\n", prefix.c_str(), percentage_s.c_str(), node->chain[0]->symbol->name.c_str()); + printf("%s%s%s\n", prefix.c_str(), percentage_s.c_str(), + node->chain[0]->symbol->GetDemangledName().c_str()); prefix.append(percentage_s.size(), ' '); for (size_t i = 1; i < node->chain.size(); ++i) { - printf("%s%s\n", prefix.c_str(), node->chain[i]->symbol->name.c_str()); + printf("%s%s\n", prefix.c_str(), node->chain[i]->symbol->GetDemangledName().c_str()); } for (size_t i = 0; i < node->children.size(); ++i) { @@ -710,7 +711,7 @@ static void PrintCallGraphEntry(size_t depth, std::string prefix, void ReportCommand::PrintCallGraph(const SampleEntry& sample) { std::string prefix = " "; printf("%s|\n", prefix.c_str()); - printf("%s-- %s\n", prefix.c_str(), sample.symbol->name.c_str()); + printf("%s-- %s\n", prefix.c_str(), sample.symbol->GetDemangledName().c_str()); prefix.append(3, ' '); for (size_t i = 0; i < sample.callchain.children.size(); ++i) { PrintCallGraphEntry(1, prefix, sample.callchain.children[i], sample.callchain.children_period, diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp index 55963c2a..0ac44640 100644 --- a/simpleperf/dso.cpp +++ b/simpleperf/dso.cpp @@ -17,61 +17,64 @@ #include "dso.h" #include <stdlib.h> + +#include <limits> + #include <base/logging.h> + #include "environment.h" #include "read_elf.h" #include "utils.h" -const std::string& SymbolEntry::GetDemangledName() const { +const std::string& Symbol::GetDemangledName() const { if (demangled_name_.empty()) { - demangled_name_ = DsoFactory::GetInstance()->Demangle(name); + demangled_name_ = Dso::Demangle(name); } return demangled_name_; } -bool SymbolComparator::operator()(const std::unique_ptr<SymbolEntry>& symbol1, - const std::unique_ptr<SymbolEntry>& symbol2) { +bool SymbolComparator::operator()(const std::unique_ptr<Symbol>& symbol1, + const std::unique_ptr<Symbol>& symbol2) { return symbol1->addr < symbol2->addr; } -DsoEntry::DsoEntry(DsoType type, const std::string& path) - : type(type), path(path), is_loaded(false) { +bool Dso::demangle_ = true; +std::string Dso::symfs_dir_; +std::string Dso::vmlinux_; +std::unordered_map<std::string, BuildId> Dso::build_id_map_; + +void Dso::SetDemangle(bool demangle) { + demangle_ = demangle; } -const SymbolEntry* DsoEntry::FindSymbol(uint64_t offset_in_dso) { - if (!is_loaded) { - DsoFactory::GetInstance()->LoadDso(this); - is_loaded = true; - } - std::unique_ptr<SymbolEntry> symbol(new SymbolEntry{ - "", // name - offset_in_dso, // addr - 0, // len - }); +extern "C" char* __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status); - auto it = symbols.upper_bound(symbol); - if (it != symbols.begin()) { - --it; - if ((*it)->addr <= offset_in_dso && (*it)->addr + (*it)->len > offset_in_dso) { - return (*it).get(); +std::string Dso::Demangle(const std::string& name) { + if (!demangle_) { + return name; + } + int status; + bool is_linker_symbol = (name.find(linker_prefix) == 0); + const char* mangled_str = name.c_str(); + if (is_linker_symbol) { + mangled_str += linker_prefix.size(); + } + std::string result = name; + char* demangled_name = __cxa_demangle(mangled_str, nullptr, nullptr, &status); + if (status == 0) { + if (is_linker_symbol) { + result = std::string("[linker]") + demangled_name; + } else { + result = demangled_name; } + free(demangled_name); + } else if (is_linker_symbol) { + result = std::string("[linker]") + mangled_str; } - return nullptr; -} - -DsoFactory* DsoFactory::GetInstance() { - static DsoFactory dso_factory; - return &dso_factory; -} - -DsoFactory::DsoFactory() : demangle_(true) { -} - -void DsoFactory::SetDemangle(bool demangle) { - demangle_ = demangle; + return result; } -bool DsoFactory::SetSymFsDir(const std::string& symfs_dir) { +bool Dso::SetSymFsDir(const std::string& symfs_dir) { std::string dirname = symfs_dir; if (!dirname.empty()) { if (dirname.back() != '/') { @@ -89,11 +92,11 @@ bool DsoFactory::SetSymFsDir(const std::string& symfs_dir) { return true; } -void DsoFactory::SetVmlinux(const std::string& vmlinux) { +void Dso::SetVmlinux(const std::string& vmlinux) { vmlinux_ = vmlinux; } -void DsoFactory::SetBuildIds(const std::vector<std::pair<std::string, BuildId>>& build_ids) { +void Dso::SetBuildIds(const std::vector<std::pair<std::string, BuildId>>& build_ids) { std::unordered_map<std::string, BuildId> map; for (auto& pair : build_ids) { LOG(DEBUG) << "build_id_map: " << pair.first << ", " << pair.second.ToString(); @@ -102,91 +105,90 @@ void DsoFactory::SetBuildIds(const std::vector<std::pair<std::string, BuildId>>& build_id_map_ = std::move(map); } -std::unique_ptr<DsoEntry> DsoFactory::CreateDso(DsoType dso_type, const std::string& dso_path) { +BuildId Dso::GetExpectedBuildId(const std::string& filename) { + auto it = build_id_map_.find(filename); + if (it != build_id_map_.end()) { + return it->second; + } + return BuildId(); +} + +std::unique_ptr<Dso> Dso::CreateDso(DsoType dso_type, const std::string& dso_path) { std::string path = dso_path; if (dso_type == DSO_KERNEL) { path = "[kernel.kallsyms]"; } - return std::unique_ptr<DsoEntry>(new DsoEntry(dso_type, path)); + return std::unique_ptr<Dso>(new Dso(dso_type, path)); } -extern "C" char* __cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status); +Dso::Dso(DsoType type, const std::string& path) : type_(type), path_(path), is_loaded_(false) { +} -std::string DsoFactory::Demangle(const std::string& name) { - if (!demangle_) { - return name; - } - int status; - bool is_linker_symbol = (name.find(linker_prefix) == 0); - const char* mangled_str = name.c_str(); - if (is_linker_symbol) { - mangled_str += linker_prefix.size(); +const Symbol* Dso::FindSymbol(uint64_t offset_in_dso) { + if (!is_loaded_) { + is_loaded_ = true; + if (!Load()) { + LOG(DEBUG) << "failed to load dso: " << path_; + return nullptr; + } } - std::string result = name; - char* demangled_name = __cxa_demangle(mangled_str, nullptr, nullptr, &status); - if (status == 0) { - if (is_linker_symbol) { - result = std::string("[linker]") + demangled_name; - } else { - result = demangled_name; + std::unique_ptr<Symbol> symbol(new Symbol{ + "", // name + offset_in_dso, // addr + 0, // len + }); + + auto it = symbols_.upper_bound(symbol); + if (it != symbols_.begin()) { + --it; + if ((*it)->addr <= offset_in_dso && (*it)->addr + (*it)->len > offset_in_dso) { + return (*it).get(); } - free(demangled_name); - } else if (is_linker_symbol) { - result = std::string("[linker]") + mangled_str; } - return result; + return nullptr; } -bool DsoFactory::LoadDso(DsoEntry* dso) { - switch (dso->type) { +bool Dso::Load() { + bool result = false; + switch (type_) { case DSO_KERNEL: - return LoadKernel(dso); + result = LoadKernel(); + break; case DSO_KERNEL_MODULE: - return LoadKernelModule(dso); + result = LoadKernelModule(); + break; case DSO_ELF_FILE: - return LoadElfFile(dso); - default: - return false; + result = LoadElfFile(); + break; + } + if (result) { + FixupSymbolLength(); } + return result; } static bool IsKernelFunctionSymbol(const KernelSymbol& symbol) { return (symbol.type == 'T' || symbol.type == 't' || symbol.type == 'W' || symbol.type == 'w'); } -static bool KernelSymbolCallback(const KernelSymbol& kernel_symbol, DsoEntry* dso) { +bool Dso::KernelSymbolCallback(const KernelSymbol& kernel_symbol, Dso* dso) { if (IsKernelFunctionSymbol(kernel_symbol)) { - dso->symbols.insert( - std::unique_ptr<SymbolEntry>(new SymbolEntry(kernel_symbol.name, kernel_symbol.addr, 0))); + dso->InsertSymbol(Symbol(kernel_symbol.name, kernel_symbol.addr, 0)); } return false; } -static void VmlinuxSymbolCallback(const ElfFileSymbol& elf_symbol, DsoEntry* dso) { +void Dso::VmlinuxSymbolCallback(const ElfFileSymbol& elf_symbol, Dso* dso) { if (elf_symbol.is_func) { - dso->symbols.insert(std::unique_ptr<SymbolEntry>( - new SymbolEntry(elf_symbol.name, elf_symbol.vaddr, elf_symbol.len))); - } -} - -static void FixupSymbolLength(DsoEntry* dso) { - SymbolEntry* prev_symbol = nullptr; - for (auto& symbol : dso->symbols) { - if (prev_symbol != nullptr && prev_symbol->len == 0) { - prev_symbol->len = symbol->addr - prev_symbol->addr; - } - prev_symbol = symbol.get(); - } - if (prev_symbol != nullptr && prev_symbol->len == 0) { - prev_symbol->len = ULLONG_MAX - prev_symbol->addr; + dso->InsertSymbol(Symbol(elf_symbol.name, elf_symbol.vaddr, elf_symbol.len)); } } -bool DsoFactory::LoadKernel(DsoEntry* dso) { +bool Dso::LoadKernel() { BuildId build_id = GetExpectedBuildId(DEFAULT_KERNEL_FILENAME_FOR_BUILD_ID); if (!vmlinux_.empty()) { ParseSymbolsFromElfFile(vmlinux_, build_id, - std::bind(VmlinuxSymbolCallback, std::placeholders::_1, dso)); + std::bind(VmlinuxSymbolCallback, std::placeholders::_1, this)); } else { if (!build_id.IsEmpty()) { BuildId real_build_id; @@ -199,17 +201,15 @@ bool DsoFactory::LoadKernel(DsoEntry* dso) { } } ProcessKernelSymbols("/proc/kallsyms", - std::bind(&KernelSymbolCallback, std::placeholders::_1, dso)); + std::bind(&KernelSymbolCallback, std::placeholders::_1, this)); } - FixupSymbolLength(dso); return true; } -static void ParseSymbolCallback(const ElfFileSymbol& elf_symbol, DsoEntry* dso, +void Dso::ElfFileSymbolCallback(const ElfFileSymbol& elf_symbol, Dso* dso, bool (*filter)(const ElfFileSymbol&)) { if (filter(elf_symbol)) { - dso->symbols.insert(std::unique_ptr<SymbolEntry>( - new SymbolEntry(elf_symbol.name, elf_symbol.start_in_file, elf_symbol.len))); + dso->InsertSymbol(Symbol(elf_symbol.name, elf_symbol.start_in_file, elf_symbol.len)); } } @@ -218,12 +218,11 @@ static bool SymbolFilterForKernelModule(const ElfFileSymbol& elf_symbol) { return (elf_symbol.is_func && elf_symbol.is_in_text_section); } -bool DsoFactory::LoadKernelModule(DsoEntry* dso) { - BuildId build_id = GetExpectedBuildId(dso->path); +bool Dso::LoadKernelModule() { + BuildId build_id = GetExpectedBuildId(path_); ParseSymbolsFromElfFile( - symfs_dir_ + dso->path, build_id, - std::bind(ParseSymbolCallback, std::placeholders::_1, dso, SymbolFilterForKernelModule)); - FixupSymbolLength(dso); + symfs_dir_ + path_, build_id, + std::bind(ElfFileSymbolCallback, std::placeholders::_1, this, SymbolFilterForKernelModule)); return true; } @@ -231,19 +230,27 @@ static bool SymbolFilterForDso(const ElfFileSymbol& elf_symbol) { return elf_symbol.is_func || (elf_symbol.is_label && elf_symbol.is_in_text_section); } -bool DsoFactory::LoadElfFile(DsoEntry* dso) { - BuildId build_id = GetExpectedBuildId(dso->path); +bool Dso::LoadElfFile() { + BuildId build_id = GetExpectedBuildId(path_); ParseSymbolsFromElfFile( - symfs_dir_ + dso->path, build_id, - std::bind(ParseSymbolCallback, std::placeholders::_1, dso, SymbolFilterForDso)); - FixupSymbolLength(dso); + symfs_dir_ + path_, build_id, + std::bind(ElfFileSymbolCallback, std::placeholders::_1, this, SymbolFilterForDso)); return true; } -BuildId DsoFactory::GetExpectedBuildId(const std::string& filename) { - auto it = build_id_map_.find(filename); - if (it != build_id_map_.end()) { - return it->second; +void Dso::InsertSymbol(const Symbol& symbol) { + symbols_.insert(std::unique_ptr<Symbol>(new Symbol(symbol))); +} + +void Dso::FixupSymbolLength() { + Symbol* prev_symbol = nullptr; + for (auto& symbol : symbols_) { + if (prev_symbol != nullptr && prev_symbol->len == 0) { + prev_symbol->len = symbol->addr - prev_symbol->addr; + } + prev_symbol = symbol.get(); + } + if (prev_symbol != nullptr && prev_symbol->len == 0) { + prev_symbol->len = std::numeric_limits<unsigned long long>::max() - prev_symbol->addr; } - return BuildId(); } diff --git a/simpleperf/dso.h b/simpleperf/dso.h index 5e44a994..148a47c8 100644 --- a/simpleperf/dso.h +++ b/simpleperf/dso.h @@ -25,13 +25,12 @@ #include "build_id.h" -struct SymbolEntry { +struct Symbol { std::string name; uint64_t addr; uint64_t len; - SymbolEntry(const std::string& name, uint64_t addr, uint64_t len) - : name(name), addr(addr), len(len) { + Symbol(const std::string& name, uint64_t addr, uint64_t len) : name(name), addr(addr), len(len) { } const std::string& GetDemangledName() const; @@ -41,8 +40,7 @@ struct SymbolEntry { }; struct SymbolComparator { - bool operator()(const std::unique_ptr<SymbolEntry>& symbol1, - const std::unique_ptr<SymbolEntry>& symbol2); + bool operator()(const std::unique_ptr<Symbol>& symbol1, const std::unique_ptr<Symbol>& symbol2); }; enum DsoType { @@ -51,42 +49,49 @@ enum DsoType { DSO_ELF_FILE, }; -struct DsoEntry { - DsoType type; - std::string path; - std::set<std::unique_ptr<SymbolEntry>, SymbolComparator> symbols; +struct KernelSymbol; +struct ElfFileSymbol; - DsoEntry(DsoType type, const std::string& path); - const SymbolEntry* FindSymbol(uint64_t offset_in_dso); - - private: - bool is_loaded; -}; - -class DsoFactory { +struct Dso { public: - static DsoFactory* GetInstance(); + static void SetDemangle(bool demangle); + static std::string Demangle(const std::string& name); + static bool SetSymFsDir(const std::string& symfs_dir); + static void SetVmlinux(const std::string& vmlinux); + static void SetBuildIds(const std::vector<std::pair<std::string, BuildId>>& build_ids); + + static std::unique_ptr<Dso> CreateDso(DsoType dso_type, const std::string& dso_path = ""); - void SetDemangle(bool demangle); - bool SetSymFsDir(const std::string& symfs_dir); - void SetVmlinux(const std::string& vmlinux); - void SetBuildIds(const std::vector<std::pair<std::string, BuildId>>& build_ids); + const std::string& Path() const { + return path_; + } - std::unique_ptr<DsoEntry> CreateDso(DsoType dso_type, const std::string& dso_path = ""); - std::string Demangle(const std::string& name); - bool LoadDso(DsoEntry* dso); + const Symbol* FindSymbol(uint64_t offset_in_dso); private: - DsoFactory(); - bool LoadKernel(DsoEntry* dso); - bool LoadKernelModule(DsoEntry* dso); - bool LoadElfFile(DsoEntry* dso); - BuildId GetExpectedBuildId(const std::string& filename); - - bool demangle_; - std::string symfs_dir_; - std::string vmlinux_; - std::unordered_map<std::string, BuildId> build_id_map_; + static BuildId GetExpectedBuildId(const std::string& filename); + static bool KernelSymbolCallback(const KernelSymbol& kernel_symbol, Dso* dso); + static void VmlinuxSymbolCallback(const ElfFileSymbol& elf_symbol, Dso* dso); + static void ElfFileSymbolCallback(const ElfFileSymbol& elf_symbol, Dso* dso, + bool (*filter)(const ElfFileSymbol&)); + + static bool demangle_; + static std::string symfs_dir_; + static std::string vmlinux_; + static std::unordered_map<std::string, BuildId> build_id_map_; + + Dso(DsoType type, const std::string& path); + bool Load(); + bool LoadKernel(); + bool LoadKernelModule(); + bool LoadElfFile(); + void InsertSymbol(const Symbol& symbol); + void FixupSymbolLength(); + + const DsoType type_; + const std::string path_; + std::set<std::unique_ptr<Symbol>, SymbolComparator> symbols_; + bool is_loaded_; }; #endif // SIMPLE_PERF_DSO_H_ diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp index 4d63530d..4e3c212e 100644 --- a/simpleperf/environment.cpp +++ b/simpleperf/environment.cpp @@ -19,6 +19,8 @@ #include <inttypes.h> #include <stdio.h> #include <stdlib.h> + +#include <limits> #include <unordered_map> #include <vector> @@ -218,7 +220,7 @@ bool GetKernelAndModuleMmaps(KernelMmap* kernel_mmap, std::vector<ModuleMmap>* m kernel_mmap->name = DEFAULT_KERNEL_MMAP_NAME; *module_mmaps = GetModulesInUse(); if (module_mmaps->size() == 0) { - kernel_mmap->len = ULLONG_MAX - kernel_mmap->start_addr; + kernel_mmap->len = std::numeric_limits<unsigned long long>::max() - kernel_mmap->start_addr; } else { std::sort( module_mmaps->begin(), module_mmaps->end(), @@ -238,7 +240,8 @@ bool GetKernelAndModuleMmaps(KernelMmap* kernel_mmap, std::vector<ModuleMmap>* m (*module_mmaps)[i + 1].start_addr - (*module_mmaps)[i].start_addr - 1; } } - module_mmaps->back().len = ULLONG_MAX - module_mmaps->back().start_addr; + module_mmaps->back().len = + std::numeric_limits<unsigned long long>::max() - module_mmaps->back().start_addr; } return true; } diff --git a/simpleperf/sample_tree.cpp b/simpleperf/sample_tree.cpp index 29bffdac..a55fd64e 100644 --- a/simpleperf/sample_tree.cpp +++ b/simpleperf/sample_tree.cpp @@ -34,7 +34,7 @@ SampleEntry* SampleTree::AddSample(int pid, int tid, uint64_t ip, uint64_t time, bool in_kernel) { const ThreadEntry* thread = thread_tree_->FindThreadOrNew(pid, tid); const MapEntry* map = thread_tree_->FindMap(thread, ip, in_kernel); - const SymbolEntry* symbol = thread_tree_->FindSymbol(map, ip); + const Symbol* symbol = thread_tree_->FindSymbol(map, ip); SampleEntry value(ip, time, period, 0, 1, thread, map, symbol); @@ -51,12 +51,12 @@ void SampleTree::AddBranchSample(int pid, int tid, uint64_t from_ip, uint64_t to if (from_map == thread_tree_->UnknownMap()) { from_map = thread_tree_->FindMap(thread, from_ip, true); } - const SymbolEntry* from_symbol = thread_tree_->FindSymbol(from_map, from_ip); + const Symbol* from_symbol = thread_tree_->FindSymbol(from_map, from_ip); const MapEntry* to_map = thread_tree_->FindMap(thread, to_ip, false); if (to_map == thread_tree_->UnknownMap()) { to_map = thread_tree_->FindMap(thread, to_ip, true); } - const SymbolEntry* to_symbol = thread_tree_->FindSymbol(to_map, to_ip); + const Symbol* to_symbol = thread_tree_->FindSymbol(to_map, to_ip); SampleEntry value(to_ip, time, period, 0, 1, thread, to_map, to_symbol); value.branch_from.ip = from_ip; @@ -75,7 +75,7 @@ SampleEntry* SampleTree::AddCallChainSample(int pid, int tid, uint64_t ip, uint6 const std::vector<SampleEntry*>& callchain) { const ThreadEntry* thread = thread_tree_->FindThreadOrNew(pid, tid); const MapEntry* map = thread_tree_->FindMap(thread, ip, in_kernel); - const SymbolEntry* symbol = thread_tree_->FindSymbol(map, ip); + const Symbol* symbol = thread_tree_->FindSymbol(map, ip); SampleEntry value(ip, time, 0, period, 0, thread, map, symbol); @@ -111,7 +111,7 @@ bool SampleTree::IsFilteredOut(const SampleEntry& value) { if (!comm_filter_.empty() && comm_filter_.find(value.thread_comm) == comm_filter_.end()) { return true; } - if (!dso_filter_.empty() && dso_filter_.find(value.map->dso->path) == dso_filter_.end()) { + if (!dso_filter_.empty() && dso_filter_.find(value.map->dso->Path()) == dso_filter_.end()) { return true; } return false; diff --git a/simpleperf/sample_tree.h b/simpleperf/sample_tree.h index 5227af20..6eb73722 100644 --- a/simpleperf/sample_tree.h +++ b/simpleperf/sample_tree.h @@ -31,7 +31,7 @@ struct BranchFromEntry { uint64_t ip; const MapEntry* map; - const SymbolEntry* symbol; + const Symbol* symbol; uint64_t flags; BranchFromEntry() : ip(0), map(nullptr), symbol(nullptr), flags(0) { @@ -47,13 +47,13 @@ struct SampleEntry { const ThreadEntry* thread; const char* thread_comm; // It refers to the thread comm when the sample happens. const MapEntry* map; - const SymbolEntry* symbol; + const Symbol* symbol; BranchFromEntry branch_from; CallChainRoot callchain; // A callchain tree representing all callchains in the sample records. SampleEntry(uint64_t ip, uint64_t time, uint64_t period, uint64_t accumulated_period, uint64_t sample_count, const ThreadEntry* thread, const MapEntry* map, - const SymbolEntry* symbol) + const Symbol* symbol) : ip(ip), time(time), period(period), diff --git a/simpleperf/sample_tree_test.cpp b/simpleperf/sample_tree_test.cpp index cb590832..8e14a8b8 100644 --- a/simpleperf/sample_tree_test.cpp +++ b/simpleperf/sample_tree_test.cpp @@ -35,7 +35,7 @@ static void SampleMatchExpectation(const SampleEntry& sample, const ExpectedSamp ASSERT_EQ(expected.tid, sample.thread->tid); ASSERT_STREQ(expected.comm, sample.thread_comm); ASSERT_TRUE(sample.map != nullptr); - ASSERT_EQ(expected.dso_name, sample.map->dso->path); + ASSERT_EQ(expected.dso_name, sample.map->dso->Path()); ASSERT_EQ(expected.map_start_addr, sample.map->start_addr); ASSERT_EQ(expected.sample_count, sample.sample_count); *has_error = false; @@ -60,8 +60,8 @@ static int CompareSampleFunction(const SampleEntry& sample1, const SampleEntry& if (strcmp(sample1.thread_comm, sample2.thread_comm) != 0) { return strcmp(sample1.thread_comm, sample2.thread_comm); } - if (sample1.map->dso->path != sample2.map->dso->path) { - return sample1.map->dso->path > sample2.map->dso->path ? 1 : -1; + if (sample1.map->dso->Path() != sample2.map->dso->Path()) { + return sample1.map->dso->Path() > sample2.map->dso->Path() ? 1 : -1; } if (sample1.map->start_addr != sample2.map->start_addr) { return sample1.map->start_addr - sample2.map->start_addr; diff --git a/simpleperf/thread_tree.cpp b/simpleperf/thread_tree.cpp index 9407733a..27b8583d 100644 --- a/simpleperf/thread_tree.cpp +++ b/simpleperf/thread_tree.cpp @@ -16,7 +16,10 @@ #include "thread_tree.h" +#include <limits> + #include <base/logging.h> + #include "environment.h" #include "perf_event.h" #include "record.h" @@ -91,7 +94,7 @@ void ThreadTree::AddKernelMap(uint64_t start_addr, uint64_t len, uint64_t pgoff, if (len == 0) { return; } - DsoEntry* dso = FindKernelDsoOrNew(filename); + Dso* dso = FindKernelDsoOrNew(filename); MapEntry* map = new MapEntry{ start_addr, len, pgoff, time, dso, }; @@ -101,16 +104,16 @@ void ThreadTree::AddKernelMap(uint64_t start_addr, uint64_t len, uint64_t pgoff, CHECK(pair.second); } -DsoEntry* ThreadTree::FindKernelDsoOrNew(const std::string& filename) { +Dso* ThreadTree::FindKernelDsoOrNew(const std::string& filename) { if (filename == DEFAULT_KERNEL_MMAP_NAME) { if (kernel_dso_ == nullptr) { - kernel_dso_ = DsoFactory::GetInstance()->CreateDso(DSO_KERNEL); + kernel_dso_ = Dso::CreateDso(DSO_KERNEL); } return kernel_dso_.get(); } auto it = module_dso_tree_.find(filename); if (it == module_dso_tree_.end()) { - module_dso_tree_[filename] = DsoFactory::GetInstance()->CreateDso(DSO_KERNEL_MODULE, filename); + module_dso_tree_[filename] = Dso::CreateDso(DSO_KERNEL_MODULE, filename); it = module_dso_tree_.find(filename); } return it->second.get(); @@ -119,7 +122,7 @@ DsoEntry* ThreadTree::FindKernelDsoOrNew(const std::string& filename) { void ThreadTree::AddThreadMap(int pid, int tid, uint64_t start_addr, uint64_t len, uint64_t pgoff, uint64_t time, const std::string& filename) { ThreadEntry* thread = FindThreadOrNew(pid, tid); - DsoEntry* dso = FindUserDsoOrNew(filename); + Dso* dso = FindUserDsoOrNew(filename); MapEntry* map = new MapEntry{ start_addr, len, pgoff, time, dso, }; @@ -129,10 +132,10 @@ void ThreadTree::AddThreadMap(int pid, int tid, uint64_t start_addr, uint64_t le CHECK(pair.second); } -DsoEntry* ThreadTree::FindUserDsoOrNew(const std::string& filename) { +Dso* ThreadTree::FindUserDsoOrNew(const std::string& filename) { auto it = user_dso_tree_.find(filename); if (it == user_dso_tree_.end()) { - user_dso_tree_[filename] = DsoFactory::GetInstance()->CreateDso(DSO_ELF_FILE, filename); + user_dso_tree_[filename] = Dso::CreateDso(DSO_ELF_FILE, filename); it = user_dso_tree_.find(filename); } return it->second.get(); @@ -145,11 +148,11 @@ static bool IsAddrInMap(uint64_t addr, const MapEntry* map) { static MapEntry* FindMapByAddr(const std::set<MapEntry*, MapComparator>& maps, uint64_t addr) { // Construct a map_entry which is strictly after the searched map_entry, based on MapComparator. MapEntry find_map = { - addr, // start_addr - ULLONG_MAX, // len - 0, // pgoff - ULLONG_MAX, // time - nullptr, // dso + addr, // start_addr + std::numeric_limits<unsigned long long>::max(), // len + 0, // pgoff + std::numeric_limits<unsigned long long>::max(), // time + nullptr, // dso }; auto it = maps.upper_bound(&find_map); if (it != maps.begin() && IsAddrInMap(addr, *--it)) { @@ -168,14 +171,14 @@ const MapEntry* ThreadTree::FindMap(const ThreadEntry* thread, uint64_t ip, bool return result != nullptr ? result : &unknown_map_; } -const SymbolEntry* ThreadTree::FindSymbol(const MapEntry* map, uint64_t ip) { +const Symbol* ThreadTree::FindSymbol(const MapEntry* map, uint64_t ip) { uint64_t offset_in_file; if (map->dso == kernel_dso_.get()) { offset_in_file = ip; } else { offset_in_file = ip - map->start_addr + map->pgoff; } - const SymbolEntry* symbol = map->dso->FindSymbol(offset_in_file); + const Symbol* symbol = map->dso->FindSymbol(offset_in_file); if (symbol == nullptr) { symbol = &unknown_symbol_; } diff --git a/simpleperf/thread_tree.h b/simpleperf/thread_tree.h index c0ec3ea4..7abfdfc3 100644 --- a/simpleperf/thread_tree.h +++ b/simpleperf/thread_tree.h @@ -17,9 +17,12 @@ #ifndef SIMPLE_PERF_THREAD_TREE_H_ #define SIMPLE_PERF_THREAD_TREE_H_ -#include <limits.h> #include <stdint.h> + +#include <limits> +#include <memory> #include <set> + #include "dso.h" struct MapEntry { @@ -27,7 +30,7 @@ struct MapEntry { uint64_t len; uint64_t pgoff; uint64_t time; // Map creation time. - DsoEntry* dso; + Dso* dso; }; struct MapComparator { @@ -43,13 +46,14 @@ struct ThreadEntry { class ThreadTree { public: - ThreadTree() : unknown_dso_(DSO_ELF_FILE, "unknown"), unknown_symbol_("unknown", 0, ULLONG_MAX) { + ThreadTree() : unknown_symbol_("unknown", 0, std::numeric_limits<unsigned long long>::max()) { + unknown_dso_ = Dso::CreateDso(DSO_ELF_FILE, "unknown"); unknown_map_ = MapEntry{ - 0, // start_addr - ULLONG_MAX, // len - 0, // pgoff - 0, // time - &unknown_dso_, // dso + 0, // start_addr + std::numeric_limits<unsigned long long>::max(), // len + 0, // pgoff + 0, // time + unknown_dso_.get(), // dso }; } @@ -61,14 +65,14 @@ class ThreadTree { void AddThreadMap(int pid, int tid, uint64_t start_addr, uint64_t len, uint64_t pgoff, uint64_t time, const std::string& filename); const MapEntry* FindMap(const ThreadEntry* thread, uint64_t ip, bool in_kernel); - const SymbolEntry* FindSymbol(const MapEntry* map, uint64_t ip); + const Symbol* FindSymbol(const MapEntry* map, uint64_t ip); const MapEntry* UnknownMap() const { return &unknown_map_; } private: - DsoEntry* FindKernelDsoOrNew(const std::string& filename); - DsoEntry* FindUserDsoOrNew(const std::string& filename); + Dso* FindKernelDsoOrNew(const std::string& filename); + Dso* FindUserDsoOrNew(const std::string& filename); std::unordered_map<int, std::unique_ptr<ThreadEntry>> thread_tree_; std::vector<std::unique_ptr<std::string>> thread_comm_storage_; @@ -77,11 +81,11 @@ class ThreadTree { std::vector<std::unique_ptr<MapEntry>> map_storage_; MapEntry unknown_map_; - std::unique_ptr<DsoEntry> kernel_dso_; - std::unordered_map<std::string, std::unique_ptr<DsoEntry>> module_dso_tree_; - std::unordered_map<std::string, std::unique_ptr<DsoEntry>> user_dso_tree_; - DsoEntry unknown_dso_; - SymbolEntry unknown_symbol_; + std::unique_ptr<Dso> kernel_dso_; + std::unordered_map<std::string, std::unique_ptr<Dso>> module_dso_tree_; + std::unordered_map<std::string, std::unique_ptr<Dso>> user_dso_tree_; + std::unique_ptr<Dso> unknown_dso_; + Symbol unknown_symbol_; }; struct Record; |