summaryrefslogtreecommitdiff
path: root/simpleperf/thread_tree.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'simpleperf/thread_tree.cpp')
-rw-r--r--simpleperf/thread_tree.cpp83
1 files changed, 46 insertions, 37 deletions
diff --git a/simpleperf/thread_tree.cpp b/simpleperf/thread_tree.cpp
index 27b8583d..a45992c9 100644
--- a/simpleperf/thread_tree.cpp
+++ b/simpleperf/thread_tree.cpp
@@ -28,8 +28,8 @@ bool MapComparator::operator()(const MapEntry* map1, const MapEntry* map2) const
if (map1->start_addr != map2->start_addr) {
return map1->start_addr < map2->start_addr;
}
- if (map1->len != map2->len) {
- return map1->len < map2->len;
+ if (map1->get_end_addr() != map2->get_end_addr()) {
+ return map1->get_end_addr() < map2->get_end_addr();
}
if (map1->time != map2->time) {
return map1->time < map2->time;
@@ -75,19 +75,6 @@ ThreadEntry* ThreadTree::FindThreadOrNew(int pid, int tid) {
return it->second.get();
}
-static void RemoveOverlappedMap(std::set<MapEntry*, MapComparator>* map_set, const MapEntry* map) {
- for (auto it = map_set->begin(); it != map_set->end();) {
- if ((*it)->start_addr >= map->start_addr + map->len) {
- break;
- }
- if ((*it)->start_addr + (*it)->len <= map->start_addr) {
- ++it;
- } else {
- it = map_set->erase(it);
- }
- }
-}
-
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.
@@ -95,11 +82,8 @@ void ThreadTree::AddKernelMap(uint64_t start_addr, uint64_t len, uint64_t pgoff,
return;
}
Dso* dso = FindKernelDsoOrNew(filename);
- MapEntry* map = new MapEntry{
- start_addr, len, pgoff, time, dso,
- };
- map_storage_.push_back(std::unique_ptr<MapEntry>(map));
- RemoveOverlappedMap(&kernel_map_tree_, map);
+ MapEntry* map = AllocateMap(MapEntry(start_addr, len, pgoff, time, dso));
+ FixOverlappedMap(&kernel_map_tree_, map);
auto pair = kernel_map_tree_.insert(map);
CHECK(pair.second);
}
@@ -123,11 +107,8 @@ void ThreadTree::AddThreadMap(int pid, int tid, uint64_t start_addr, uint64_t le
uint64_t time, const std::string& filename) {
ThreadEntry* thread = FindThreadOrNew(pid, tid);
Dso* dso = FindUserDsoOrNew(filename);
- MapEntry* map = new MapEntry{
- start_addr, len, pgoff, time, dso,
- };
- map_storage_.push_back(std::unique_ptr<MapEntry>(map));
- RemoveOverlappedMap(&thread->maps, map);
+ MapEntry* map = AllocateMap(MapEntry(start_addr, len, pgoff, time, dso));
+ FixOverlappedMap(&thread->maps, map);
auto pair = thread->maps.insert(map);
CHECK(pair.second);
}
@@ -141,19 +122,47 @@ Dso* ThreadTree::FindUserDsoOrNew(const std::string& filename) {
return it->second.get();
}
+MapEntry* ThreadTree::AllocateMap(const MapEntry& value) {
+ MapEntry* map = new MapEntry(value);
+ map_storage_.push_back(std::unique_ptr<MapEntry>(map));
+ return 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.
+ break;
+ }
+ if ((*it)->get_end_addr() <= map->start_addr) {
+ ++it;
+ } 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));
+ 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));
+ map_set->insert(after);
+ }
+
+ it = map_set->erase(it);
+ }
+ }
+}
+
static bool IsAddrInMap(uint64_t addr, const MapEntry* map) {
- return (addr >= map->start_addr && addr < map->start_addr + map->len);
+ 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.
- MapEntry find_map = {
- addr, // start_addr
- std::numeric_limits<unsigned long long>::max(), // len
- 0, // pgoff
- std::numeric_limits<unsigned long long>::max(), // time
- nullptr, // dso
- };
+ MapEntry find_map(addr, std::numeric_limits<uint64_t>::max(), 0,
+ std::numeric_limits<uint64_t>::max(), nullptr);
auto it = maps.upper_bound(&find_map);
if (it != maps.begin() && IsAddrInMap(addr, *--it)) {
return *it;
@@ -172,13 +181,13 @@ const MapEntry* ThreadTree::FindMap(const ThreadEntry* thread, uint64_t ip, bool
}
const Symbol* ThreadTree::FindSymbol(const MapEntry* map, uint64_t ip) {
- uint64_t offset_in_file;
+ uint64_t vaddr_in_file;
if (map->dso == kernel_dso_.get()) {
- offset_in_file = ip;
+ vaddr_in_file = ip;
} else {
- offset_in_file = ip - map->start_addr + map->pgoff;
+ vaddr_in_file = ip - map->start_addr + map->dso->MinVirtualAddress();
}
- const Symbol* symbol = map->dso->FindSymbol(offset_in_file);
+ const Symbol* symbol = map->dso->FindSymbol(vaddr_in_file);
if (symbol == nullptr) {
symbol = &unknown_symbol_;
}