OSDN Git Service

3f7ea4d1b69b0ca3fc1035e1febde4c943fa44d6
[android-x86/system-extras.git] / perfprofd / symbolizer.cc
1 /*
2  *
3  * Copyright 2018, The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include "symbolizer.h"
19
20 #include <map>
21 #include <memory>
22 #include <unordered_map>
23
24 #include <android-base/logging.h>
25
26 #include "build_id.h"
27 #include "read_elf.h"
28
29 namespace perfprofd {
30
31 namespace {
32
33 struct SimpleperfSymbolizer : public Symbolizer {
34   // For simplicity, we assume non-overlapping symbols.
35   struct Symbol {
36     std::string name;
37     uint64_t length;
38   };
39   using SymbolMap = std::map<uint64_t, Symbol>;
40
41   std::string Decode(const std::string& dso, uint64_t address) override {
42     auto it = dsos.find(dso);
43     if (it == dsos.end()) {
44       LoadDso(dso);
45       it = dsos.find(dso);
46       DCHECK(it != dsos.end());
47     }
48
49     const SymbolMap& map = it->second;
50     if (map.empty()) {
51       return "";
52     }
53     auto upper_bound = map.upper_bound(address);
54     if (upper_bound == map.begin()) {
55       // Nope, not in the map.
56       return "";
57     }
58
59     upper_bound--;
60     if (upper_bound->first + upper_bound->second.length > address) {
61       // This element covers the given address, return its name.
62       return upper_bound->second.name;
63     }
64
65     return "";
66   }
67
68   void LoadDso(const std::string& dso) {
69     SymbolMap data;
70     auto callback = [&data](const ElfFileSymbol& sym) {
71       Symbol symbol;
72       symbol.name = sym.name;
73       symbol.length = sym.len;
74       data.emplace(sym.vaddr, std::move(symbol));
75     };
76     ElfStatus status = ParseSymbolsFromElfFile(dso, BuildId(), callback);
77     if (status != ElfStatus::NO_ERROR) {
78       LOG(WARNING) << "Could not parse dso " << dso << ": " << status;
79     }
80     dsos.emplace(dso, std::move(data));
81   }
82
83   std::unordered_map<std::string, SymbolMap> dsos;
84 };
85
86 }  // namespace
87
88 std::unique_ptr<Symbolizer> CreateELFSymbolizer() {
89   return std::unique_ptr<Symbolizer>(new SimpleperfSymbolizer());
90 }
91
92 }  // namespace perfprofd
93