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