Simpleperf: load symbols from dso file only when necessary.
Bug: 22630113
Change-Id: I12bb24ec02ba3ddb94bcb2a26ae2d6e7b445ed4d
diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp
index ec8fbaa..2b63641 100644
--- a/simpleperf/dso.cpp
+++ b/simpleperf/dso.cpp
@@ -27,7 +27,15 @@
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 @@
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 @@
}
}
-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 @@
<< 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 @@
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 @@
}
}
-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;
}
diff --git a/simpleperf/dso.h b/simpleperf/dso.h
index ba105c1..8b83000 100644
--- a/simpleperf/dso.h
+++ b/simpleperf/dso.h
@@ -36,11 +36,22 @@
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 @@
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_;
diff --git a/simpleperf/sample_tree.cpp b/simpleperf/sample_tree.cpp
index ce09246..6d0b403 100644
--- a/simpleperf/sample_tree.cpp
+++ b/simpleperf/sample_tree.cpp
@@ -88,13 +88,13 @@
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 @@
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();
diff --git a/simpleperf/sample_tree.h b/simpleperf/sample_tree.h
index 2e97ceb..4e51aca 100644
--- a/simpleperf/sample_tree.h
+++ b/simpleperf/sample_tree.h
@@ -93,7 +93,8 @@
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 @@
0, // time
&unknown_dso_, // dso
};
- unknown_dso_.path = "unknown";
unknown_symbol_ = SymbolEntry{
"unknown", // name
0, // addr