OSDN Git Service

Simpleperf: refactor dso.
authorYabin Cui <yabinc@google.com>
Thu, 20 Aug 2015 22:04:39 +0000 (15:04 -0700)
committerYabin Cui <yabinc@google.com>
Fri, 21 Aug 2015 18:42:23 +0000 (11:42 -0700)
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

simpleperf/cmd_record.cpp
simpleperf/cmd_report.cpp
simpleperf/dso.cpp
simpleperf/dso.h
simpleperf/environment.cpp
simpleperf/sample_tree.cpp
simpleperf/sample_tree.h
simpleperf/sample_tree_test.cpp
simpleperf/thread_tree.cpp
simpleperf/thread_tree.h

index 5b7bec2..bed957b 100644 (file)
@@ -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());
       }
     }
   }
index 5d08993..9c2f606 100644 (file)
@@ -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,
index 55963c2..0ac4464 100644 (file)
 #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();
 }
index 5e44a99..148a47c 100644 (file)
 
 #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_
index 4d63530..4e3c212 100644 (file)
@@ -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;
 }
index 29bffda..a55fd64 100644 (file)
@@ -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;
index 5227af2..6eb7372 100644 (file)
@@ -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),
index cb59083..8e14a8b 100644 (file)
@@ -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;
index 9407733..27b8583 100644 (file)
 
 #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_;
   }
index c0ec3ea..7abfdfc 100644 (file)
 #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;