simpleperf: show dso[+vaddr_in_file] for unknown symbols.
It gives more information than just unknown symbols.
Add --no-show-ip option to disable this additional detail.
Bug: 29772268
Change-Id: Ie8067f95b5fdc65806044e229ee12095367d115a
Test: run simpleperf_unit_test.
diff --git a/simpleperf/cmd_report.cpp b/simpleperf/cmd_report.cpp
index 464c57f..cbdd14b 100644
--- a/simpleperf/cmd_report.cpp
+++ b/simpleperf/cmd_report.cpp
@@ -280,6 +280,7 @@
"-i <file> Specify path of record file, default is perf.data.\n"
"-n Print the sample count for each item.\n"
"--no-demangle Don't demangle symbol names.\n"
+"--no-show-ip Don't show vaddr in file for unknown symbols.\n"
"-o report_file_name Set report file name, default is stdout.\n"
"--pids pid1,pid2,... Report only for selected pids.\n"
"--sort key1,key2,... Select keys used to sort and print the report. The\n"
@@ -379,6 +380,7 @@
bool ReportCommand::ParseOptions(const std::vector<std::string>& args) {
bool demangle = true;
+ bool show_ip_for_unknown_symbol = true;
std::string symfs_dir;
std::string vmlinux;
bool print_sample_count = false;
@@ -428,6 +430,8 @@
} else if (args[i] == "--no-demangle") {
demangle = false;
+ } else if (args[i] == "--no-show-ip") {
+ show_ip_for_unknown_symbol = false;
} else if (args[i] == "-o") {
if (!NextArgumentOrError(args, &i)) {
return false;
@@ -488,6 +492,10 @@
Dso::SetVmlinux(vmlinux);
}
+ if (show_ip_for_unknown_symbol) {
+ thread_tree_.ShowIpForUnknownSymbol();
+ }
+
SampleDisplayer<SampleEntry, SampleTree> displayer;
SampleComparator<SampleEntry> comparator;
diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp
index 1281137..d6231bf 100644
--- a/simpleperf/cmd_report_test.cpp
+++ b/simpleperf/cmd_report_test.cpp
@@ -340,6 +340,15 @@
testing::ExitedWithCode(0), "build id.*mismatch");
}
+TEST_F(ReportCommandTest, no_show_ip_option) {
+ Report(PERF_DATA);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(content.find("unknown"), std::string::npos);
+ Report(PERF_DATA, {"--no-show-ip"});
+ ASSERT_TRUE(success);
+ ASSERT_NE(content.find("unknown"), std::string::npos);
+}
+
#if defined(__linux__)
static std::unique_ptr<Command> RecordCmd() {
diff --git a/simpleperf/dso.cpp b/simpleperf/dso.cpp
index c10779a..f31d4c4 100644
--- a/simpleperf/dso.cpp
+++ b/simpleperf/dso.cpp
@@ -154,6 +154,12 @@
debug_file_path_ = path_in_symfs;
}
}
+ size_t pos = path.find_last_of("/\\");
+ if (pos != std::string::npos) {
+ file_name_ = path.substr(pos + 1);
+ } else {
+ file_name_ = path;
+ }
dso_count_++;
}
diff --git a/simpleperf/dso.h b/simpleperf/dso.h
index a352570..c381e6d 100644
--- a/simpleperf/dso.h
+++ b/simpleperf/dso.h
@@ -86,6 +86,8 @@
const std::string& Path() const { return path_; }
// Return the path containing symbol table and debug information.
const std::string& GetDebugFilePath() const { return debug_file_path_; }
+ // Return the file name without directory info.
+ const std::string& FileName() const { return file_name_; }
bool HasDumped() const { return has_dumped_; }
@@ -122,6 +124,8 @@
// path of the shared library having symbol table and debug information
// It is the same as path_, or has the same build id as path_.
std::string debug_file_path_;
+ // File name of the shared library, got by removing directories in path_.
+ std::string file_name_;
uint64_t min_vaddr_;
std::set<Symbol, SymbolComparator> symbols_;
bool is_loaded_;
diff --git a/simpleperf/thread_tree.cpp b/simpleperf/thread_tree.cpp
index f3291e5..fafefa0 100644
--- a/simpleperf/thread_tree.cpp
+++ b/simpleperf/thread_tree.cpp
@@ -16,9 +16,12 @@
#include "thread_tree.h"
+#include <inttypes.h>
+
#include <limits>
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include "environment.h"
#include "perf_event.h"
@@ -207,21 +210,31 @@
const Symbol* ThreadTree::FindSymbol(const MapEntry* map, uint64_t ip,
uint64_t* pvaddr_in_file) {
uint64_t vaddr_in_file;
- if (map->dso == kernel_dso_.get()) {
+ Dso* dso = map->dso;
+ if (dso == kernel_dso_.get()) {
vaddr_in_file = ip;
} else {
vaddr_in_file = ip - map->start_addr + map->dso->MinVirtualAddress();
}
- const Symbol* symbol = map->dso->FindSymbol(vaddr_in_file);
- if (symbol == nullptr && map->in_kernel && map->dso != kernel_dso_.get()) {
+ const Symbol* symbol = dso->FindSymbol(vaddr_in_file);
+ if (symbol == nullptr && map->in_kernel && dso != kernel_dso_.get()) {
// It is in a kernel module, but we can't find the kernel module file, or
// the kernel module file contains no symbol. Try finding the symbol in
// /proc/kallsyms.
vaddr_in_file = ip;
- symbol = kernel_dso_->FindSymbol(vaddr_in_file);
+ dso = kernel_dso_.get();
+ symbol = dso->FindSymbol(vaddr_in_file);
}
if (symbol == nullptr) {
- symbol = &unknown_symbol_;
+ if (show_ip_for_unknown_symbol_) {
+ std::string name = android::base::StringPrintf(
+ "%s[+%" PRIx64 "]", dso->FileName().c_str(), vaddr_in_file);
+ dso->InsertSymbol(Symbol(name, vaddr_in_file, 1));
+ symbol = dso->FindSymbol(vaddr_in_file);
+ CHECK(symbol != nullptr);
+ } else {
+ symbol = &unknown_symbol_;
+ }
}
if (pvaddr_in_file != nullptr) {
*pvaddr_in_file = vaddr_in_file;
diff --git a/simpleperf/thread_tree.h b/simpleperf/thread_tree.h
index ae73cc7..a8d3fa0 100644
--- a/simpleperf/thread_tree.h
+++ b/simpleperf/thread_tree.h
@@ -68,7 +68,8 @@
class ThreadTree {
public:
ThreadTree()
- : unknown_symbol_("unknown", 0,
+ : show_ip_for_unknown_symbol_(false),
+ unknown_symbol_("unknown", 0,
std::numeric_limits<unsigned long long>::max()) {
unknown_dso_ = Dso::CreateDso(DSO_ELF_FILE, "unknown");
unknown_map_ = MapEntry(0, std::numeric_limits<unsigned long long>::max(),
@@ -92,6 +93,7 @@
const Symbol* FindKernelSymbol(uint64_t ip);
const Symbol* UnknownSymbol() const { return &unknown_symbol_; }
+ void ShowIpForUnknownSymbol() { show_ip_for_unknown_symbol_ = true; }
// Clear thread and map information, but keep loaded dso information. It saves
// the time to reload dso information.
void ClearThreadAndMap();
@@ -117,6 +119,7 @@
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_;
+ bool show_ip_for_unknown_symbol_;
Symbol unknown_symbol_;
std::unordered_map<uint64_t, Dso*> dso_id_to_dso_map_;
};