• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <base/mem_map.h>
26 #include <build_id.h>
27 #include <read_dex_file.h>
28 #include <read_elf.h>
29 #include <vdex_file.h>
30 
31 namespace perfprofd {
32 
33 namespace {
34 
35 struct SimpleperfSymbolizer : public Symbolizer {
36   // For simplicity, we assume non-overlapping symbols.
37   struct Symbol {
Symbolperfprofd::__anon2a2b97bd0111::SimpleperfSymbolizer::Symbol38     Symbol(std::string_view n, uint64_t l) : name(n), length(l) {}
39 
40     std::string name;
41     uint64_t length;
42   };
43   using SymbolMap = std::map<uint64_t, Symbol>;
44 
Decodeperfprofd::__anon2a2b97bd0111::SimpleperfSymbolizer45   std::string Decode(const std::string& dso, uint64_t address) override {
46     auto it = dsos.find(dso);
47     if (it == dsos.end()) {
48       LoadDso(dso);
49       it = dsos.find(dso);
50       DCHECK(it != dsos.end());
51     }
52 
53     const SymbolMap& map = it->second;
54     if (map.empty()) {
55       return "";
56     }
57     auto upper_bound = map.upper_bound(address);
58     if (upper_bound == map.begin()) {
59       // Nope, not in the map.
60       return "";
61     }
62 
63     upper_bound--;
64     if (upper_bound->first + upper_bound->second.length > address) {
65       // This element covers the given address, return its name.
66       return upper_bound->second.name;
67     }
68 
69     return "";
70   }
71 
LoadDsoperfprofd::__anon2a2b97bd0111::SimpleperfSymbolizer72   void LoadDso(const std::string& dso) {
73     // See whether it's an ELF file.
74     {
75       SymbolMap elf_data;
76       auto callback = [&elf_data](const ElfFileSymbol& sym) {
77         if (sym.is_func) {
78           if (sym.len == 0) {
79             LOG(ERROR) << "Symbol size is zero for " << sym.name;
80           }
81           elf_data.emplace(sym.vaddr, Symbol(sym.name, sym.len));
82         }
83       };
84       ElfStatus status = ParseSymbolsFromElfFile(dso, BuildId(), callback);
85       if (status == ElfStatus::NO_ERROR) {
86         dsos.emplace(dso, std::move(elf_data));
87         return;
88       }
89     }
90 
91     // See whether it's a vdex file.
92     {
93       ::art::MemMap::Init();
94 
95       using VdexFile = ::art::VdexFile;
96       std::string error_msg;
97       std::unique_ptr<VdexFile> vdex = VdexFile::Open(dso,
98                                                       /* writable= */ false,
99                                                       /* low_4gb= */ false,
100                                                       /* unquicken= */ false,
101                                                       &error_msg);
102       if (vdex != nullptr) {
103         const uint8_t* cur = nullptr;
104         std::vector<uint64_t> dex_file_offsets;
105         const uint8_t* base = vdex->Begin();
106         for (;;) {
107           cur = vdex->GetNextDexFileData(cur);
108           if (cur == nullptr) {
109             break;
110           }
111           dex_file_offsets.push_back(cur - base);
112         }
113 
114         if (!dex_file_offsets.empty()) {
115           std::vector<DexFileSymbol> symbols;
116           if (ReadSymbolsFromDexFile(dso, dex_file_offsets, &symbols)) {
117             SymbolMap vdex_data;
118             for (const DexFileSymbol& symbol : symbols) {
119               vdex_data.emplace(symbol.offset, Symbol(symbol.name, symbol.len));
120             }
121             dsos.emplace(dso, std::move(vdex_data));
122             LOG(INFO) << "Found " << symbols.size() << " dex symbols in " << dso;
123             return;
124           } else {
125             LOG(WARNING) << "Could not read symbols from dex files in " << dso;
126           }
127         } else {
128           LOG(WARNING) << "Could not find dex files for vdex " << dso;
129           dsos.emplace(dso, SymbolMap());
130         }
131       } else {
132         LOG(WARNING) << dso << " is not a vdex: " << error_msg;
133       }
134     }
135 
136     // TODO: See whether it's a dex file.
137 
138     // OK, give up.
139     LOG(WARNING) << "Could not symbolize " << dso;
140     dsos.emplace(dso, SymbolMap());
141   }
142 
GetMinExecutableVAddrperfprofd::__anon2a2b97bd0111::SimpleperfSymbolizer143   bool GetMinExecutableVAddr(const std::string& dso, uint64_t* addr) override {
144     uint64_t file_offset_of_min_vaddr;
145     ElfStatus status = ReadMinExecutableVirtualAddressFromElfFile(dso, BuildId(), addr,
146                                                                   &file_offset_of_min_vaddr);
147     if (status != ElfStatus::NO_ERROR) {
148       return true;
149     }
150 
151     {
152       ::art::MemMap::Init();
153 
154       using VdexFile = ::art::VdexFile;
155       std::string error_msg;
156       std::unique_ptr<VdexFile> vdex = VdexFile::Open(dso,
157                                                       /* writable= */ false,
158                                                       /* low_4gb= */ false,
159                                                       /* unquicken= */ false,
160                                                       &error_msg);
161       if (vdex != nullptr) {
162         *addr = 0u;
163         return true;
164       }
165     }
166 
167     return false;
168   }
169 
170   std::unordered_map<std::string, SymbolMap> dsos;
171 };
172 
173 }  // namespace
174 
CreateELFSymbolizer()175 std::unique_ptr<Symbolizer> CreateELFSymbolizer() {
176   return std::unique_ptr<Symbolizer>(new SimpleperfSymbolizer());
177 }
178 
179 }  // namespace perfprofd
180