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 bool GetMinExecutableVAddr(const std::string& dso, uint64_t* addr) override { 84 ElfStatus status = ReadMinExecutableVirtualAddressFromElfFile(dso, BuildId(), addr); 85 return status == ElfStatus::NO_ERROR; 86 } 87 88 std::unordered_map<std::string, SymbolMap> dsos; 89 }; 90 91 } // namespace 92 93 std::unique_ptr<Symbolizer> CreateELFSymbolizer() { 94 return std::unique_ptr<Symbolizer>(new SimpleperfSymbolizer()); 95 } 96 97 } // namespace perfprofd 98 99