thread_tree.cpp revision 003b245939bae5e86ed53b3c6b333637dbc571b4
10596faeddefbf198de137d5e893708495ab1584cFredrik Roubert/* 264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert * Copyright (C) 2015 The Android Open Source Project 385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Licensed under the Apache License, Version 2.0 (the "License"); 58de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert * you may not use this file except in compliance with the License. 685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * You may obtain a copy of the License at 785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * http://www.apache.org/licenses/LICENSE-2.0 985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * 1085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * Unless required by applicable law or agreed to in writing, software 1185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * distributed under the License is distributed on an "AS IS" BASIS, 1285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * See the License for the specific language governing permissions and 1485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * limitations under the License. 150b3ec0516c035ea443fdc334025048597c740be1Markus Scherer */ 160b3ec0516c035ea443fdc334025048597c740be1Markus Scherer 1785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "thread_tree.h" 18b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 19b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include <inttypes.h> 200b3ec0516c035ea443fdc334025048597c740be1Markus Scherer 210b3ec0516c035ea443fdc334025048597c740be1Markus Scherer#include <limits> 2285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 2385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include <android-base/logging.h> 2485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include <android-base/stringprintf.h> 2585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 2685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "perf_event.h" 270596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include "record.h" 2859d709d503bab6e2b61931737e662dd293b40578ccornelius 2985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Honamespace simpleperf { 3085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 31ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertbool MapComparator::operator()(const MapEntry* map1, 3285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho const MapEntry* map2) const { 3359d709d503bab6e2b61931737e662dd293b40578ccornelius if (map1->start_addr != map2->start_addr) { 3459d709d503bab6e2b61931737e662dd293b40578ccornelius return map1->start_addr < map2->start_addr; 3585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 3685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho // Compare map->len instead of map->get_end_addr() here. Because we set map's 3759d709d503bab6e2b61931737e662dd293b40578ccornelius // len to std::numeric_limits<uint64_t>::max() in FindMapByAddr(), which makes 3859d709d503bab6e2b61931737e662dd293b40578ccornelius // map->get_end_addr() overflow. 39c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert if (map1->len != map2->len) { 408de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert return map1->len < map2->len; 41c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 4259d709d503bab6e2b61931737e662dd293b40578ccornelius if (map1->time != map2->time) { 4359d709d503bab6e2b61931737e662dd293b40578ccornelius return map1->time < map2->time; 4459d709d503bab6e2b61931737e662dd293b40578ccornelius } 4559d709d503bab6e2b61931737e662dd293b40578ccornelius return false; 4659d709d503bab6e2b61931737e662dd293b40578ccornelius} 4759d709d503bab6e2b61931737e662dd293b40578ccornelius 4859d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid ThreadTree::AddThread(int pid, int tid, const std::string& comm) { 4959d709d503bab6e2b61931737e662dd293b40578ccornelius auto it = thread_tree_.find(tid); 5059d709d503bab6e2b61931737e662dd293b40578ccornelius if (it == thread_tree_.end()) { 5159d709d503bab6e2b61931737e662dd293b40578ccornelius ThreadEntry* thread = new ThreadEntry{ 5259d709d503bab6e2b61931737e662dd293b40578ccornelius pid, tid, 5359d709d503bab6e2b61931737e662dd293b40578ccornelius "unknown", // comm 5459d709d503bab6e2b61931737e662dd293b40578ccornelius std::set<MapEntry*, MapComparator>(), // maps 5559d709d503bab6e2b61931737e662dd293b40578ccornelius }; 5659d709d503bab6e2b61931737e662dd293b40578ccornelius auto pair = thread_tree_.insert( 5759d709d503bab6e2b61931737e662dd293b40578ccornelius std::make_pair(tid, std::unique_ptr<ThreadEntry>(thread))); 5859d709d503bab6e2b61931737e662dd293b40578ccornelius CHECK(pair.second); 5959d709d503bab6e2b61931737e662dd293b40578ccornelius it = pair.first; 6059d709d503bab6e2b61931737e662dd293b40578ccornelius } 6159d709d503bab6e2b61931737e662dd293b40578ccornelius if (comm != it->second->comm) { 6259d709d503bab6e2b61931737e662dd293b40578ccornelius thread_comm_storage_.push_back( 6359d709d503bab6e2b61931737e662dd293b40578ccornelius std::unique_ptr<std::string>(new std::string(comm))); 6459d709d503bab6e2b61931737e662dd293b40578ccornelius it->second->comm = thread_comm_storage_.back()->c_str(); 6559d709d503bab6e2b61931737e662dd293b40578ccornelius } 6659d709d503bab6e2b61931737e662dd293b40578ccornelius} 6759d709d503bab6e2b61931737e662dd293b40578ccornelius 6859d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid ThreadTree::ForkThread(int pid, int tid, int ppid, int ptid) { 6959d709d503bab6e2b61931737e662dd293b40578ccornelius ThreadEntry* parent = FindThreadOrNew(ppid, ptid); 7059d709d503bab6e2b61931737e662dd293b40578ccornelius ThreadEntry* child = FindThreadOrNew(pid, tid); 7159d709d503bab6e2b61931737e662dd293b40578ccornelius child->comm = parent->comm; 7259d709d503bab6e2b61931737e662dd293b40578ccornelius child->maps = parent->maps; 7359d709d503bab6e2b61931737e662dd293b40578ccornelius} 7459d709d503bab6e2b61931737e662dd293b40578ccornelius 7559d709d503bab6e2b61931737e662dd293b40578ccorneliusThreadEntry* ThreadTree::FindThreadOrNew(int pid, int tid) { 7659d709d503bab6e2b61931737e662dd293b40578ccornelius auto it = thread_tree_.find(tid); 7759d709d503bab6e2b61931737e662dd293b40578ccornelius if (it == thread_tree_.end()) { 7859d709d503bab6e2b61931737e662dd293b40578ccornelius AddThread(pid, tid, "unknown"); 7959d709d503bab6e2b61931737e662dd293b40578ccornelius it = thread_tree_.find(tid); 8059d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 8159d709d503bab6e2b61931737e662dd293b40578ccornelius if (pid != it->second.get()->pid) { 8259d709d503bab6e2b61931737e662dd293b40578ccornelius // TODO: b/22185053. 8359d709d503bab6e2b61931737e662dd293b40578ccornelius LOG(DEBUG) << "unexpected (pid, tid) pair: expected (" 8459d709d503bab6e2b61931737e662dd293b40578ccornelius << it->second.get()->pid << ", " << tid << "), actual (" << pid 8559d709d503bab6e2b61931737e662dd293b40578ccornelius << ", " << tid << ")"; 8659d709d503bab6e2b61931737e662dd293b40578ccornelius } 8759d709d503bab6e2b61931737e662dd293b40578ccornelius } 8859d709d503bab6e2b61931737e662dd293b40578ccornelius return it->second.get(); 8959d709d503bab6e2b61931737e662dd293b40578ccornelius} 9059d709d503bab6e2b61931737e662dd293b40578ccornelius 9159d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid ThreadTree::AddKernelMap(uint64_t start_addr, uint64_t len, uint64_t pgoff, 9259d709d503bab6e2b61931737e662dd293b40578ccornelius uint64_t time, const std::string& filename) { 9359d709d503bab6e2b61931737e662dd293b40578ccornelius // kernel map len can be 0 when record command is not run in supervisor mode. 9459d709d503bab6e2b61931737e662dd293b40578ccornelius if (len == 0) { 9559d709d503bab6e2b61931737e662dd293b40578ccornelius return; 9659d709d503bab6e2b61931737e662dd293b40578ccornelius } 9759d709d503bab6e2b61931737e662dd293b40578ccornelius Dso* dso = FindKernelDsoOrNew(filename); 9859d709d503bab6e2b61931737e662dd293b40578ccornelius MapEntry* map = 9959d709d503bab6e2b61931737e662dd293b40578ccornelius AllocateMap(MapEntry(start_addr, len, pgoff, time, dso, true)); 10059d709d503bab6e2b61931737e662dd293b40578ccornelius FixOverlappedMap(&kernel_map_tree_, map); 10159d709d503bab6e2b61931737e662dd293b40578ccornelius auto pair = kernel_map_tree_.insert(map); 10259d709d503bab6e2b61931737e662dd293b40578ccornelius CHECK(pair.second); 10359d709d503bab6e2b61931737e662dd293b40578ccornelius} 10459d709d503bab6e2b61931737e662dd293b40578ccornelius 10559d709d503bab6e2b61931737e662dd293b40578ccorneliusDso* ThreadTree::FindKernelDsoOrNew(const std::string& filename) { 10659d709d503bab6e2b61931737e662dd293b40578ccornelius if (filename == DEFAULT_KERNEL_MMAP_NAME) { 10759d709d503bab6e2b61931737e662dd293b40578ccornelius return kernel_dso_.get(); 10859d709d503bab6e2b61931737e662dd293b40578ccornelius } 10985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho auto it = module_dso_tree_.find(filename); 11085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if (it == module_dso_tree_.end()) { 11185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho module_dso_tree_[filename] = Dso::CreateDso(DSO_KERNEL_MODULE, filename); 11285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho it = module_dso_tree_.find(filename); 11385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 11485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho return it->second.get(); 11559d709d503bab6e2b61931737e662dd293b40578ccornelius} 11685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 11759d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid ThreadTree::AddThreadMap(int pid, int tid, uint64_t start_addr, 11859d709d503bab6e2b61931737e662dd293b40578ccornelius uint64_t len, uint64_t pgoff, uint64_t time, 11985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho const std::string& filename) { 12085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho ThreadEntry* thread = FindThreadOrNew(pid, tid); 12185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Dso* dso = FindUserDsoOrNew(filename); 12259d709d503bab6e2b61931737e662dd293b40578ccornelius MapEntry* map = 12359d709d503bab6e2b61931737e662dd293b40578ccornelius AllocateMap(MapEntry(start_addr, len, pgoff, time, dso, false)); 12459d709d503bab6e2b61931737e662dd293b40578ccornelius FixOverlappedMap(&thread->maps, map); 12559d709d503bab6e2b61931737e662dd293b40578ccornelius auto pair = thread->maps.insert(map); 12659d709d503bab6e2b61931737e662dd293b40578ccornelius CHECK(pair.second); 12759d709d503bab6e2b61931737e662dd293b40578ccornelius} 12885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho 12985bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoDso* ThreadTree::FindUserDsoOrNew(const std::string& filename) { 13059d709d503bab6e2b61931737e662dd293b40578ccornelius auto it = user_dso_tree_.find(filename); 13159d709d503bab6e2b61931737e662dd293b40578ccornelius if (it == user_dso_tree_.end()) { 13259d709d503bab6e2b61931737e662dd293b40578ccornelius user_dso_tree_[filename] = Dso::CreateDso(DSO_ELF_FILE, filename); 13359d709d503bab6e2b61931737e662dd293b40578ccornelius it = user_dso_tree_.find(filename); 13459d709d503bab6e2b61931737e662dd293b40578ccornelius } 13559d709d503bab6e2b61931737e662dd293b40578ccornelius return it->second.get(); 13659d709d503bab6e2b61931737e662dd293b40578ccornelius} 13759d709d503bab6e2b61931737e662dd293b40578ccornelius 13859d709d503bab6e2b61931737e662dd293b40578ccorneliusMapEntry* ThreadTree::AllocateMap(const MapEntry& value) { 13959d709d503bab6e2b61931737e662dd293b40578ccornelius MapEntry* map = new MapEntry(value); 14085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho map_storage_.push_back(std::unique_ptr<MapEntry>(map)); 14159d709d503bab6e2b61931737e662dd293b40578ccornelius return map; 14285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho} 14359d709d503bab6e2b61931737e662dd293b40578ccornelius 14459d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid ThreadTree::FixOverlappedMap(std::set<MapEntry*, MapComparator>* map_set, 14559d709d503bab6e2b61931737e662dd293b40578ccornelius const MapEntry* map) { 14659d709d503bab6e2b61931737e662dd293b40578ccornelius for (auto it = map_set->begin(); it != map_set->end();) { 14759d709d503bab6e2b61931737e662dd293b40578ccornelius if ((*it)->start_addr >= map->get_end_addr()) { 14859d709d503bab6e2b61931737e662dd293b40578ccornelius // No more overlapped maps. 14959d709d503bab6e2b61931737e662dd293b40578ccornelius break; 15059d709d503bab6e2b61931737e662dd293b40578ccornelius } 15185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho if ((*it)->get_end_addr() <= map->start_addr) { 15259d709d503bab6e2b61931737e662dd293b40578ccornelius ++it; 15359d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 15459d709d503bab6e2b61931737e662dd293b40578ccornelius MapEntry* old = *it; 15559d709d503bab6e2b61931737e662dd293b40578ccornelius if (old->start_addr < map->start_addr) { 15659d709d503bab6e2b61931737e662dd293b40578ccornelius MapEntry* before = AllocateMap( 15759d709d503bab6e2b61931737e662dd293b40578ccornelius MapEntry(old->start_addr, map->start_addr - old->start_addr, 15859d709d503bab6e2b61931737e662dd293b40578ccornelius old->pgoff, old->time, old->dso, old->in_kernel)); 15959d709d503bab6e2b61931737e662dd293b40578ccornelius map_set->insert(before); 16059d709d503bab6e2b61931737e662dd293b40578ccornelius } 16159d709d503bab6e2b61931737e662dd293b40578ccornelius if (old->get_end_addr() > map->get_end_addr()) { 16259d709d503bab6e2b61931737e662dd293b40578ccornelius MapEntry* after = AllocateMap(MapEntry( 16359d709d503bab6e2b61931737e662dd293b40578ccornelius map->get_end_addr(), old->get_end_addr() - map->get_end_addr(), 16459d709d503bab6e2b61931737e662dd293b40578ccornelius map->get_end_addr() - old->start_addr + old->pgoff, old->time, 16559d709d503bab6e2b61931737e662dd293b40578ccornelius old->dso, old->in_kernel)); 16659d709d503bab6e2b61931737e662dd293b40578ccornelius map_set->insert(after); 16759d709d503bab6e2b61931737e662dd293b40578ccornelius } 16859d709d503bab6e2b61931737e662dd293b40578ccornelius 16959d709d503bab6e2b61931737e662dd293b40578ccornelius it = map_set->erase(it); 17059d709d503bab6e2b61931737e662dd293b40578ccornelius } 17159d709d503bab6e2b61931737e662dd293b40578ccornelius } 17259d709d503bab6e2b61931737e662dd293b40578ccornelius} 17359d709d503bab6e2b61931737e662dd293b40578ccornelius 17459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic bool IsAddrInMap(uint64_t addr, const MapEntry* map) { 17559d709d503bab6e2b61931737e662dd293b40578ccornelius return (addr >= map->start_addr && addr < map->get_end_addr()); 17659d709d503bab6e2b61931737e662dd293b40578ccornelius} 17759d709d503bab6e2b61931737e662dd293b40578ccornelius 17859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic MapEntry* FindMapByAddr(const std::set<MapEntry*, MapComparator>& maps, 17959d709d503bab6e2b61931737e662dd293b40578ccornelius uint64_t addr) { 18059d709d503bab6e2b61931737e662dd293b40578ccornelius // Construct a map_entry which is strictly after the searched map_entry, based 181ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert // on MapComparator. 182ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert MapEntry find_map(addr, std::numeric_limits<uint64_t>::max(), 0, 183ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert std::numeric_limits<uint64_t>::max(), nullptr, false); 184ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert auto it = maps.upper_bound(&find_map); 185ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert if (it != maps.begin() && IsAddrInMap(addr, *--it)) { 186ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert return *it; 187ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 188ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert return nullptr; 189ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert} 190ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert 191ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertconst MapEntry* ThreadTree::FindMap(const ThreadEntry* thread, uint64_t ip, 192ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert bool in_kernel) { 193ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert MapEntry* result = nullptr; 194ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert if (!in_kernel) { 195ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert result = FindMapByAddr(thread->maps, ip); 196ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } else { 197ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert result = FindMapByAddr(kernel_map_tree_, ip); 198ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 199ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert return result != nullptr ? result : &unknown_map_; 200ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert} 201ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert 202ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertconst MapEntry* ThreadTree::FindMap(const ThreadEntry* thread, uint64_t ip) { 203ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert MapEntry* result = FindMapByAddr(thread->maps, ip); 204ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert if (result != nullptr) { 205ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert return result; 206ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 207ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert result = FindMapByAddr(kernel_map_tree_, ip); 208ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert return result != nullptr ? result : &unknown_map_; 209ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert} 210ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert 211ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertconst Symbol* ThreadTree::FindSymbol(const MapEntry* map, uint64_t ip, 212ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert uint64_t* pvaddr_in_file) { 213ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert uint64_t vaddr_in_file; 214ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert Dso* dso = map->dso; 215ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert if (dso == kernel_dso_.get()) { 216ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert vaddr_in_file = ip; 217ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } else { 218ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert vaddr_in_file = ip - map->start_addr + map->dso->MinVirtualAddress(); 219ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 220ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert const Symbol* symbol = dso->FindSymbol(vaddr_in_file); 221ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert if (symbol == nullptr && map->in_kernel && dso != kernel_dso_.get()) { 222ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert // It is in a kernel module, but we can't find the kernel module file, or 223ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert // the kernel module file contains no symbol. Try finding the symbol in 224ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert // /proc/kallsyms. 225ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert vaddr_in_file = ip; 226ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert dso = kernel_dso_.get(); 227ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert symbol = dso->FindSymbol(vaddr_in_file); 228ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 229ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert if (symbol == nullptr) { 230ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert if (show_ip_for_unknown_symbol_) { 231ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert std::string name = android::base::StringPrintf( 232ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert "%s%s[+%" PRIx64 "]", (show_mark_for_unknown_symbol_ ? "*" : ""), 233ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert dso->FileName().c_str(), vaddr_in_file); 234ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert dso->InsertSymbol(Symbol(name, vaddr_in_file, 1)); 235ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert symbol = dso->FindSymbol(vaddr_in_file); 236ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert CHECK(symbol != nullptr); 237ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } else { 238ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert symbol = &unknown_symbol_; 239ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 240ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 241ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert if (pvaddr_in_file != nullptr) { 242ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert *pvaddr_in_file = vaddr_in_file; 243ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 244ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert return symbol; 245ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert} 246ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert 247ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertconst Symbol* ThreadTree::FindKernelSymbol(uint64_t ip) { 248ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert const MapEntry* map = FindMap(nullptr, ip, true); 24959d709d503bab6e2b61931737e662dd293b40578ccornelius return FindSymbol(map, ip, nullptr); 25059d709d503bab6e2b61931737e662dd293b40578ccornelius} 25159d709d503bab6e2b61931737e662dd293b40578ccornelius 25259d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid ThreadTree::ClearThreadAndMap() { 25359d709d503bab6e2b61931737e662dd293b40578ccornelius thread_tree_.clear(); 25459d709d503bab6e2b61931737e662dd293b40578ccornelius thread_comm_storage_.clear(); 25559d709d503bab6e2b61931737e662dd293b40578ccornelius kernel_map_tree_.clear(); 256ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert map_storage_.clear(); 25759d709d503bab6e2b61931737e662dd293b40578ccornelius} 25859d709d503bab6e2b61931737e662dd293b40578ccornelius 25959d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid ThreadTree::Update(const Record& record) { 26059d709d503bab6e2b61931737e662dd293b40578ccornelius if (record.type() == PERF_RECORD_MMAP) { 26159d709d503bab6e2b61931737e662dd293b40578ccornelius const MmapRecord& r = *static_cast<const MmapRecord*>(&record); 26259d709d503bab6e2b61931737e662dd293b40578ccornelius if (r.InKernel()) { 26359d709d503bab6e2b61931737e662dd293b40578ccornelius AddKernelMap(r.data->addr, r.data->len, r.data->pgoff, 26459d709d503bab6e2b61931737e662dd293b40578ccornelius r.sample_id.time_data.time, r.filename); 26559d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 266c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert AddThreadMap(r.data->pid, r.data->tid, r.data->addr, r.data->len, 26759d709d503bab6e2b61931737e662dd293b40578ccornelius r.data->pgoff, r.sample_id.time_data.time, r.filename); 268ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } 26959d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (record.type() == PERF_RECORD_MMAP2) { 27059d709d503bab6e2b61931737e662dd293b40578ccornelius const Mmap2Record& r = *static_cast<const Mmap2Record*>(&record); 27159d709d503bab6e2b61931737e662dd293b40578ccornelius if (r.InKernel()) { 272ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert AddKernelMap(r.data->addr, r.data->len, r.data->pgoff, 273ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert r.sample_id.time_data.time, r.filename); 274ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } else { 275ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert std::string filename = (r.filename == DEFAULT_EXECNAME_FOR_THREAD_MMAP) 276ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert ? "[unknown]" 277ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert : r.filename; 27859d709d503bab6e2b61931737e662dd293b40578ccornelius AddThreadMap(r.data->pid, r.data->tid, r.data->addr, r.data->len, 27959d709d503bab6e2b61931737e662dd293b40578ccornelius r.data->pgoff, r.sample_id.time_data.time, filename); 28059d709d503bab6e2b61931737e662dd293b40578ccornelius } 28159d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (record.type() == PERF_RECORD_COMM) { 28259d709d503bab6e2b61931737e662dd293b40578ccornelius const CommRecord& r = *static_cast<const CommRecord*>(&record); 28359d709d503bab6e2b61931737e662dd293b40578ccornelius AddThread(r.data->pid, r.data->tid, r.comm); 28459d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (record.type() == PERF_RECORD_FORK) { 28559d709d503bab6e2b61931737e662dd293b40578ccornelius const ForkRecord& r = *static_cast<const ForkRecord*>(&record); 28659d709d503bab6e2b61931737e662dd293b40578ccornelius ForkThread(r.data->pid, r.data->tid, r.data->ppid, r.data->ptid); 28759d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (record.type() == SIMPLE_PERF_RECORD_KERNEL_SYMBOL) { 28859d709d503bab6e2b61931737e662dd293b40578ccornelius const auto& r = *static_cast<const KernelSymbolRecord*>(&record); 28959d709d503bab6e2b61931737e662dd293b40578ccornelius Dso::SetKallsyms(std::move(r.kallsyms)); 29059d709d503bab6e2b61931737e662dd293b40578ccornelius } else if (record.type() == SIMPLE_PERF_RECORD_DSO) { 29159d709d503bab6e2b61931737e662dd293b40578ccornelius auto& r = *static_cast<const DsoRecord*>(&record); 29259d709d503bab6e2b61931737e662dd293b40578ccornelius Dso* dso = nullptr; 29359d709d503bab6e2b61931737e662dd293b40578ccornelius if (r.dso_type == DSO_KERNEL || r.dso_type == DSO_KERNEL_MODULE) { 29459d709d503bab6e2b61931737e662dd293b40578ccornelius dso = FindKernelDsoOrNew(r.dso_name); 295ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert } else { 296ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert dso = FindUserDsoOrNew(r.dso_name); 29785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 29885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho dso->SetMinVirtualAddress(r.min_vaddr); 29985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho dso_id_to_dso_map_[r.dso_id] = dso; 30085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } else if (record.type() == SIMPLE_PERF_RECORD_SYMBOL) { 30185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho auto& r = *static_cast<const SymbolRecord*>(&record); 30285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho Dso* dso = dso_id_to_dso_map_[r.dso_id]; 30385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho CHECK(dso != nullptr); 30485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho dso->InsertSymbol(Symbol(r.name, r.addr, r.len)); 30585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho } 30659d709d503bab6e2b61931737e662dd293b40578ccornelius} 30759d709d503bab6e2b61931737e662dd293b40578ccornelius 30859d709d503bab6e2b61931737e662dd293b40578ccornelius} // namespace simpleperf 30959d709d503bab6e2b61931737e662dd293b40578ccornelius