summaryrefslogtreecommitdiff
path: root/simpleperf/thread_tree.cpp
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2016-06-29 12:18:11 -0700
committerYabin Cui <yabinc@google.com>2016-06-29 13:32:57 -0700
commit9970a2344333f2c19d9126cfec4f833f50ff2f22 (patch)
tree49fb22bf07f936b96ef63a5ffae87e3c9336eb52 /simpleperf/thread_tree.cpp
parentd937202a3b23e6908c2109d5a96da237ee9cbba8 (diff)
downloadextras-9970a2344333f2c19d9126cfec4f833f50ff2f22.tar.gz
Simpleperf: add vaddr_in_file sort key in report command.
Currently report command can't report more details than function name. After adding vaddr_in_file sort key, it can report the place of the instruction being sampled. vaddr_in_file is the instruction's virtual address in elf file, which matches output generated by objdump. Bug: 29826956 Test: run simpleperf_unit_test. Change-Id: Ifad4dfb7c60014a03c01ffbfd0b972858f1a4884
Diffstat (limited to 'simpleperf/thread_tree.cpp')
-rw-r--r--simpleperf/thread_tree.cpp87
1 files changed, 52 insertions, 35 deletions
diff --git a/simpleperf/thread_tree.cpp b/simpleperf/thread_tree.cpp
index 8e4e9e9d..d81e8f48 100644
--- a/simpleperf/thread_tree.cpp
+++ b/simpleperf/thread_tree.cpp
@@ -26,12 +26,13 @@
namespace simpleperf {
-bool MapComparator::operator()(const MapEntry* map1, const MapEntry* map2) const {
+bool MapComparator::operator()(const MapEntry* map1,
+ const MapEntry* map2) const {
if (map1->start_addr != map2->start_addr) {
return map1->start_addr < map2->start_addr;
}
- // Compare map->len instead of map->get_end_addr() here. Because we set map's len
- // to std::numeric_limits<uint64_t>::max() in FindMapByAddr(), which makes
+ // Compare map->len instead of map->get_end_addr() here. Because we set map's
+ // len to std::numeric_limits<uint64_t>::max() in FindMapByAddr(), which makes
// map->get_end_addr() overflow.
if (map1->len != map2->len) {
return map1->len < map2->len;
@@ -50,11 +51,13 @@ void ThreadTree::AddThread(int pid, int tid, const std::string& comm) {
"unknown", // comm
std::set<MapEntry*, MapComparator>(), // maps
};
- auto pair = thread_tree_.insert(std::make_pair(tid, std::unique_ptr<ThreadEntry>(thread)));
+ auto pair = thread_tree_.insert(
+ std::make_pair(tid, std::unique_ptr<ThreadEntry>(thread)));
CHECK(pair.second);
it = pair.first;
}
- thread_comm_storage_.push_back(std::unique_ptr<std::string>(new std::string(comm)));
+ thread_comm_storage_.push_back(
+ std::unique_ptr<std::string>(new std::string(comm)));
it->second->comm = thread_comm_storage_.back()->c_str();
}
@@ -73,21 +76,23 @@ ThreadEntry* ThreadTree::FindThreadOrNew(int pid, int tid) {
} else {
if (pid != it->second.get()->pid) {
// TODO: b/22185053.
- LOG(DEBUG) << "unexpected (pid, tid) pair: expected (" << it->second.get()->pid << ", " << tid
- << "), actual (" << pid << ", " << tid << ")";
+ LOG(DEBUG) << "unexpected (pid, tid) pair: expected ("
+ << it->second.get()->pid << ", " << tid << "), actual (" << pid
+ << ", " << tid << ")";
}
}
return it->second.get();
}
-void ThreadTree::AddKernelMap(uint64_t start_addr, uint64_t len, uint64_t pgoff, uint64_t time,
- const std::string& filename) {
+void ThreadTree::AddKernelMap(uint64_t start_addr, uint64_t len, uint64_t pgoff,
+ uint64_t time, const std::string& filename) {
// kernel map len can be 0 when record command is not run in supervisor mode.
if (len == 0) {
return;
}
Dso* dso = FindKernelDsoOrNew(filename);
- MapEntry* map = AllocateMap(MapEntry(start_addr, len, pgoff, time, dso, true));
+ MapEntry* map =
+ AllocateMap(MapEntry(start_addr, len, pgoff, time, dso, true));
FixOverlappedMap(&kernel_map_tree_, map);
auto pair = kernel_map_tree_.insert(map);
CHECK(pair.second);
@@ -105,11 +110,13 @@ Dso* ThreadTree::FindKernelDsoOrNew(const std::string& filename) {
return it->second.get();
}
-void ThreadTree::AddThreadMap(int pid, int tid, uint64_t start_addr, uint64_t len, uint64_t pgoff,
- uint64_t time, 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);
Dso* dso = FindUserDsoOrNew(filename);
- MapEntry* map = AllocateMap(MapEntry(start_addr, len, pgoff, time, dso, false));
+ MapEntry* map =
+ AllocateMap(MapEntry(start_addr, len, pgoff, time, dso, false));
FixOverlappedMap(&thread->maps, map);
auto pair = thread->maps.insert(map);
CHECK(pair.second);
@@ -130,7 +137,8 @@ MapEntry* ThreadTree::AllocateMap(const MapEntry& value) {
return map;
}
-void ThreadTree::FixOverlappedMap(std::set<MapEntry*, MapComparator>* map_set, const MapEntry* map) {
+void ThreadTree::FixOverlappedMap(std::set<MapEntry*, MapComparator>* map_set,
+ const MapEntry* map) {
for (auto it = map_set->begin(); it != map_set->end();) {
if ((*it)->start_addr >= map->get_end_addr()) {
// No more overlapped maps.
@@ -141,14 +149,16 @@ void ThreadTree::FixOverlappedMap(std::set<MapEntry*, MapComparator>* map_set, c
} else {
MapEntry* old = *it;
if (old->start_addr < map->start_addr) {
- MapEntry* before = AllocateMap(MapEntry(old->start_addr, map->start_addr - old->start_addr,
- old->pgoff, old->time, old->dso, old->in_kernel));
+ MapEntry* before = AllocateMap(
+ MapEntry(old->start_addr, map->start_addr - old->start_addr,
+ old->pgoff, old->time, old->dso, old->in_kernel));
map_set->insert(before);
}
if (old->get_end_addr() > map->get_end_addr()) {
- MapEntry* after = AllocateMap(
- MapEntry(map->get_end_addr(), old->get_end_addr() - map->get_end_addr(),
- map->get_end_addr() - old->start_addr + old->pgoff, old->time, old->dso, old->in_kernel));
+ MapEntry* after = AllocateMap(MapEntry(
+ map->get_end_addr(), old->get_end_addr() - map->get_end_addr(),
+ map->get_end_addr() - old->start_addr + old->pgoff, old->time,
+ old->dso, old->in_kernel));
map_set->insert(after);
}
@@ -161,8 +171,10 @@ static bool IsAddrInMap(uint64_t addr, const MapEntry* map) {
return (addr >= map->start_addr && addr < map->get_end_addr());
}
-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.
+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, std::numeric_limits<uint64_t>::max(), 0,
std::numeric_limits<uint64_t>::max(), nullptr, false);
auto it = maps.upper_bound(&find_map);
@@ -172,7 +184,8 @@ static MapEntry* FindMapByAddr(const std::set<MapEntry*, MapComparator>& maps, u
return nullptr;
}
-const MapEntry* ThreadTree::FindMap(const ThreadEntry* thread, uint64_t ip, bool in_kernel) {
+const MapEntry* ThreadTree::FindMap(const ThreadEntry* thread, uint64_t ip,
+ bool in_kernel) {
MapEntry* result = nullptr;
if (!in_kernel) {
result = FindMapByAddr(thread->maps, ip);
@@ -191,7 +204,8 @@ const MapEntry* ThreadTree::FindMap(const ThreadEntry* thread, uint64_t ip) {
return result != nullptr ? result : &unknown_map_;
}
-const Symbol* ThreadTree::FindSymbol(const MapEntry* map, uint64_t ip) {
+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()) {
vaddr_in_file = ip;
@@ -209,12 +223,15 @@ const Symbol* ThreadTree::FindSymbol(const MapEntry* map, uint64_t ip) {
if (symbol == nullptr) {
symbol = &unknown_symbol_;
}
+ if (pvaddr_in_file != nullptr) {
+ *pvaddr_in_file = vaddr_in_file;
+ }
return symbol;
}
const Symbol* ThreadTree::FindKernelSymbol(uint64_t ip) {
const MapEntry* map = FindMap(nullptr, ip, true);
- return FindSymbol(map, ip);
+ return FindSymbol(map, ip, nullptr);
}
void ThreadTree::ClearThreadAndMap() {
@@ -228,22 +245,23 @@ void ThreadTree::Update(const Record& record) {
if (record.type() == PERF_RECORD_MMAP) {
const MmapRecord& r = *static_cast<const MmapRecord*>(&record);
if (r.InKernel()) {
- AddKernelMap(r.data.addr, r.data.len, r.data.pgoff, r.sample_id.time_data.time,
- r.filename);
+ AddKernelMap(r.data.addr, r.data.len, r.data.pgoff,
+ r.sample_id.time_data.time, r.filename);
} else {
- AddThreadMap(r.data.pid, r.data.tid, r.data.addr, r.data.len, r.data.pgoff,
- r.sample_id.time_data.time, r.filename);
+ AddThreadMap(r.data.pid, r.data.tid, r.data.addr, r.data.len,
+ r.data.pgoff, r.sample_id.time_data.time, r.filename);
}
} else if (record.type() == PERF_RECORD_MMAP2) {
const Mmap2Record& r = *static_cast<const Mmap2Record*>(&record);
if (r.InKernel()) {
- AddKernelMap(r.data.addr, r.data.len, r.data.pgoff, r.sample_id.time_data.time,
- r.filename);
+ AddKernelMap(r.data.addr, r.data.len, r.data.pgoff,
+ r.sample_id.time_data.time, r.filename);
} else {
- std::string filename =
- (r.filename == DEFAULT_EXECNAME_FOR_THREAD_MMAP) ? "[unknown]" : r.filename;
- AddThreadMap(r.data.pid, r.data.tid, r.data.addr, r.data.len, r.data.pgoff,
- r.sample_id.time_data.time, filename);
+ std::string filename = (r.filename == DEFAULT_EXECNAME_FOR_THREAD_MMAP)
+ ? "[unknown]"
+ : r.filename;
+ AddThreadMap(r.data.pid, r.data.tid, r.data.addr, r.data.len,
+ r.data.pgoff, r.sample_id.time_data.time, filename);
}
} else if (record.type() == PERF_RECORD_COMM) {
const CommRecord& r = *static_cast<const CommRecord*>(&record);
@@ -272,4 +290,3 @@ void ThreadTree::Update(const Record& record) {
}
} // namespace simpleperf
-