OSDN Git Service

Simpleperf: load symbols from dso file only when necessary.
authorYabin Cui <yabinc@google.com>
Tue, 21 Jul 2015 18:24:48 +0000 (11:24 -0700)
committerYabin Cui <yabinc@google.com>
Tue, 21 Jul 2015 18:24:48 +0000 (11:24 -0700)
Bug: 22630113
Change-Id: I12bb24ec02ba3ddb94bcb2a26ae2d6e7b445ed4d

simpleperf/dso.cpp
simpleperf/dso.h
simpleperf/sample_tree.cpp
simpleperf/sample_tree.h

index ec8fbaa..2b63641 100644 (file)
@@ -27,7 +27,15 @@ bool SymbolComparator::operator()(const std::unique_ptr<SymbolEntry>& symbol1,
   return symbol1->addr < symbol2->addr;
 }
 
+DsoEntry::DsoEntry(DsoType type, const std::string& path)
+    : type(type), path(path), is_loaded(false) {
+}
+
 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
@@ -87,6 +95,27 @@ 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) {
+  std::string path = dso_path;
+  if (dso_type == DSO_KERNEL) {
+    path = "[kernel.kallsyms]";
+  }
+  return std::unique_ptr<DsoEntry>(new DsoEntry(dso_type, path));
+}
+
+bool DsoFactory::LoadDso(DsoEntry* dso) {
+  switch (dso->type) {
+    case DSO_KERNEL:
+      return LoadKernel(dso);
+    case DSO_KERNEL_MODULE:
+      return LoadKernelModule(dso);
+    case DSO_ELF_FILE:
+      return LoadElfFile(dso);
+    default:
+      return false;
+  }
+}
+
 static bool IsKernelFunctionSymbol(const KernelSymbol& symbol) {
   return (symbol.type == 'T' || symbol.type == 't' || symbol.type == 'W' || symbol.type == 'w');
 }
@@ -127,13 +156,11 @@ static void FixupSymbolLength(DsoEntry* dso) {
   }
 }
 
-std::unique_ptr<DsoEntry> DsoFactory::LoadKernel() {
-  std::unique_ptr<DsoEntry> dso(new DsoEntry);
-  dso->path = "[kernel.kallsyms]";
+bool DsoFactory::LoadKernel(DsoEntry* dso) {
   BuildId build_id = GetExpectedBuildId(DEFAULT_KERNEL_FILENAME_FOR_BUILD_ID);
   if (!vmlinux_.empty()) {
     ParseSymbolsFromElfFile(vmlinux_, build_id,
-                            std::bind(VmlinuxSymbolCallback, std::placeholders::_1, dso.get()));
+                            std::bind(VmlinuxSymbolCallback, std::placeholders::_1, dso));
   } else {
     BuildId real_build_id;
     GetKernelBuildId(&real_build_id);
@@ -142,10 +169,10 @@ std::unique_ptr<DsoEntry> DsoFactory::LoadKernel() {
                << build_id.ToString() << ", real " << real_build_id.ToString();
     if (match) {
       ProcessKernelSymbols("/proc/kallsyms",
-                           std::bind(&KernelSymbolCallback, std::placeholders::_1, dso.get()));
+                           std::bind(&KernelSymbolCallback, std::placeholders::_1, dso));
     }
   }
-  FixupSymbolLength(dso.get());
+  FixupSymbolLength(dso);
   return dso;
 }
 
@@ -166,14 +193,12 @@ static bool SymbolFilterForKernelModule(const ElfFileSymbol& elf_symbol) {
   return (elf_symbol.is_func && elf_symbol.is_in_text_section);
 }
 
-std::unique_ptr<DsoEntry> DsoFactory::LoadKernelModule(const std::string& dso_path) {
-  std::unique_ptr<DsoEntry> dso(new DsoEntry);
-  dso->path = dso_path;
-  BuildId build_id = GetExpectedBuildId(dso_path);
-  ParseSymbolsFromElfFile(symfs_dir_ + dso_path, build_id,
-                          std::bind(ParseSymbolCallback, std::placeholders::_1, dso.get(),
-                                    SymbolFilterForKernelModule));
-  FixupSymbolLength(dso.get());
+bool DsoFactory::LoadKernelModule(DsoEntry* dso) {
+  BuildId build_id = GetExpectedBuildId(dso->path);
+  ParseSymbolsFromElfFile(
+      symfs_dir_ + dso->path, build_id,
+      std::bind(ParseSymbolCallback, std::placeholders::_1, dso, SymbolFilterForKernelModule));
+  FixupSymbolLength(dso);
   return dso;
 }
 
@@ -204,19 +229,17 @@ static void DemangleInPlace(std::string* name) {
   }
 }
 
-std::unique_ptr<DsoEntry> DsoFactory::LoadDso(const std::string& dso_path) {
-  std::unique_ptr<DsoEntry> dso(new DsoEntry);
-  dso->path = dso_path;
-  BuildId build_id = GetExpectedBuildId(dso_path);
+bool DsoFactory::LoadElfFile(DsoEntry* dso) {
+  BuildId build_id = GetExpectedBuildId(dso->path);
   ParseSymbolsFromElfFile(
-      symfs_dir_ + dso_path, build_id,
-      std::bind(ParseSymbolCallback, std::placeholders::_1, dso.get(), SymbolFilterForDso));
+      symfs_dir_ + dso->path, build_id,
+      std::bind(ParseSymbolCallback, std::placeholders::_1, dso, SymbolFilterForDso));
   if (demangle_) {
     for (auto& symbol : dso->symbols) {
       DemangleInPlace(&symbol->name);
     }
   }
-  FixupSymbolLength(dso.get());
+  FixupSymbolLength(dso);
   return dso;
 }
 
index ba105c1..8b83000 100644 (file)
@@ -36,11 +36,22 @@ struct SymbolComparator {
                   const std::unique_ptr<SymbolEntry>& symbol2);
 };
 
+enum DsoType {
+  DSO_KERNEL,
+  DSO_KERNEL_MODULE,
+  DSO_ELF_FILE,
+};
+
 struct DsoEntry {
+  DsoType type;
   std::string path;
   std::set<std::unique_ptr<SymbolEntry>, SymbolComparator> symbols;
 
+  DsoEntry(DsoType type, const std::string& path);
   const SymbolEntry* FindSymbol(uint64_t offset_in_dso);
+
+ private:
+  bool is_loaded;
 };
 
 class DsoFactory {
@@ -50,12 +61,14 @@ class DsoFactory {
   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);
-  std::unique_ptr<DsoEntry> LoadKernel();
-  std::unique_ptr<DsoEntry> LoadKernelModule(const std::string& dso_path);
-  std::unique_ptr<DsoEntry> LoadDso(const std::string& dso_path);
+  std::unique_ptr<DsoEntry> CreateDso(DsoType dso_type, const std::string& dso_path = "");
+  bool LoadDso(DsoEntry* dso);
 
  private:
   DsoFactory();
+  bool LoadKernel(DsoEntry* dso);
+  bool LoadKernelModule(DsoEntry* dso);
+  bool LoadElfFile(DsoEntry* dso);
   BuildId GetExpectedBuildId(const std::string& filename);
 
   bool demangle_;
index ce09246..6d0b403 100644 (file)
@@ -88,13 +88,13 @@ void SampleTree::AddKernelMap(uint64_t start_addr, uint64_t len, uint64_t pgoff,
 DsoEntry* SampleTree::FindKernelDsoOrNew(const std::string& filename) {
   if (filename == DEFAULT_KERNEL_MMAP_NAME) {
     if (kernel_dso_ == nullptr) {
-      kernel_dso_ = DsoFactory::GetInstance()->LoadKernel();
+      kernel_dso_ = DsoFactory::GetInstance()->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()->LoadKernelModule(filename);
+    module_dso_tree_[filename] = DsoFactory::GetInstance()->CreateDso(DSO_KERNEL_MODULE, filename);
     it = module_dso_tree_.find(filename);
   }
   return it->second.get();
@@ -127,7 +127,7 @@ ThreadEntry* SampleTree::FindThreadOrNew(int pid, int tid) {
 DsoEntry* SampleTree::FindUserDsoOrNew(const std::string& filename) {
   auto it = user_dso_tree_.find(filename);
   if (it == user_dso_tree_.end()) {
-    user_dso_tree_[filename] = DsoFactory::GetInstance()->LoadDso(filename);
+    user_dso_tree_[filename] = DsoFactory::GetInstance()->CreateDso(DSO_ELF_FILE, filename);
     it = user_dso_tree_.find(filename);
   }
   return it->second.get();
index 2e97ceb..4e51aca 100644 (file)
@@ -93,7 +93,8 @@ typedef std::function<int(const SampleEntry&, const SampleEntry&)> compare_sampl
 class SampleTree {
  public:
   SampleTree(compare_sample_func_t sample_compare_function)
-      : sample_comparator_(sample_compare_function),
+      : unknown_dso_(DSO_ELF_FILE, "unknown"),
+        sample_comparator_(sample_compare_function),
         sample_tree_(sample_comparator_),
         sorted_sample_comparator_(sample_compare_function),
         sorted_sample_tree_(sorted_sample_comparator_),
@@ -106,7 +107,6 @@ class SampleTree {
         0,              // time
         &unknown_dso_,  // dso
     };
-    unknown_dso_.path = "unknown";
     unknown_symbol_ = SymbolEntry{
         "unknown",   // name
         0,           // addr