1 /* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef HIPERF_SYMBOLS_H 17 #define HIPERF_SYMBOLS_H 18 19 #include <cinttypes> 20 #include <iomanip> 21 #include <sstream> 22 #include <string> 23 24 #include "dfx_elf.h" 25 #include "dfx_symbol.h" 26 #include "perf_file_format.h" 27 #include "utilities.h" 28 29 #define HIPERF_ELF_READ_USE_MMAP 30 31 namespace OHOS { 32 namespace Developtools { 33 namespace HiPerf { 34 using namespace OHOS::HiviewDFX; 35 36 constexpr const char KERNEL_MMAP_NAME[] = "[kernel.kallsyms]"; 37 constexpr const char KERNEL_MODULES_EXT_NAME[] = ".ko"; 38 constexpr const char KERNEL_ELF_NAME[] = "vmlinux"; 39 constexpr const char MMAP_VDSO_NAME[] = "[vdso]"; 40 constexpr const char MMAP_ANONYMOUS_NAME[] = "[anon]"; 41 constexpr const char MMAP_ANONYMOUS_OHOS_NAME[] = "//anon"; 42 43 const std::string NOTE_GNU_BUILD_ID = ".note.gnu.build-id"; 44 const std::string EH_FRAME_HR = ".eh_frame_hdr"; 45 const std::string EH_FRAME = ".eh_frame"; 46 const std::string ARM_EXIDX = ".ARM.exidx"; 47 const std::string SYMTAB = ".symtab"; 48 const std::string DYNSYM = ".dynsym"; 49 const std::string GNU_DEBUGDATA = ".gnu_debugdata"; 50 const std::string PLT = ".plt"; 51 const std::string LINKER_PREFIX = "__dl_"; 52 const std::string LINKER_PREFIX_NAME = "[linker]"; 53 54 const int MAX_SYMBOLS_TYPE_NAME_LEN = 10; 55 56 const pid_t SYSMGR_PID = 2; 57 const std::string SYSMGR_NAME = "sysmgr"; 58 const std::string SYSMGR_FILE_NAME = "sysmgr.elf"; 59 const std::string DEVHOST_FILE_NAME = "devhost.elf"; 60 const std::string DEVHOST_LINUX_FILE_NAME = "/lib/libdh-linux.so"; 61 const std::string DEVHOST_LINUX_PREFIX = "/liblinux/"; 62 63 class FileSymbol { 64 [[maybe_unused]] uint64_t vaddr_ = 0; 65 [[maybe_unused]] uint64_t len_ = 0; 66 std::string name_ = ""; 67 std::string demangle_ = ""; // demangle string FileSymbol(uint64_t vaddr,uint64_t len,const char * name,const char * demangle)68 FileSymbol(uint64_t vaddr, uint64_t len, const char *name, const char *demangle) 69 : vaddr_(vaddr), len_(len), name_(name), demangle_(demangle) 70 { 71 } 72 }; 73 74 enum SymbolsFileType { 75 SYMBOL_KERNEL_FILE, 76 SYMBOL_KERNEL_MODULE_FILE, 77 SYMBOL_KERNEL_THREAD_FILE, 78 // .hap!elf, normal elf. 79 SYMBOL_ELF_FILE, 80 SYMBOL_JAVA_FILE, 81 SYMBOL_JS_FILE, 82 SYMBOL_HAP_FILE, 83 SYMBOL_UNKNOW_FILE, 84 }; 85 86 class SymbolsFile { 87 public: 88 SymbolsFileType symbolFileType_; 89 std::string filePath_ = ""; 90 int32_t id_ = -1; // used to report protobuf file 91 92 // [14] .text PROGBITS 00000000002c5000 000c5000 93 // min exec addr , general it point to .text 94 // we make a default value for min compare 95 static const uint64_t maxVaddr = std::numeric_limits<uint64_t>::max(); 96 97 uint64_t textExecVaddr_ = maxVaddr; 98 uint64_t textExecVaddrFileOffset_ = 0; 99 uint64_t textExecVaddrRange_ = maxVaddr; 100 std::shared_ptr<DfxMap> map_ = nullptr; 101 SymbolsFile(SymbolsFileType symbolType,const std::string path)102 SymbolsFile(SymbolsFileType symbolType, const std::string path) 103 : symbolFileType_(symbolType), filePath_(path) {}; 104 virtual ~SymbolsFile(); 105 GetElfFile()106 virtual std::shared_ptr<DfxElf> GetElfFile() 107 { 108 return nullptr; 109 } 110 111 // create the symbols file object 112 static std::unique_ptr<SymbolsFile> CreateSymbolsFile( 113 SymbolsFileType = SYMBOL_UNKNOW_FILE, const std::string symbolFilePath = EMPTY_STRING, pid_t pid = 0); 114 static std::unique_ptr<SymbolsFile> CreateSymbolsFile(const std::string &symbolFilePath, pid_t pid = 0); 115 116 // set symbols path setSymbolsFilePath(const std::string & symbolsSearchPath)117 bool setSymbolsFilePath(const std::string &symbolsSearchPath) 118 { 119 std::vector<std::string> symbolsSearchPaths = {symbolsSearchPath}; 120 return setSymbolsFilePath(symbolsSearchPaths); 121 }; 122 bool setSymbolsFilePath(const std::vector<std::string> &); IsAbc()123 virtual bool IsAbc() 124 { 125 return false; 126 } 127 128 virtual void SetBoolValue(bool value); 129 // load symbol from file 130 virtual bool LoadSymbols([[maybe_unused]] std::shared_ptr<DfxMap> map = nullptr, 131 [[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING) 132 { 133 HLOGV("virtual dummy function called"); 134 symbolsLoaded_ = true; 135 return false; 136 }; 137 // load debug info for unwind 138 virtual bool LoadDebugInfo(std::shared_ptr<DfxMap> map = nullptr, 139 [[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING) 140 { 141 HLOGV("virtual dummy function called"); 142 debugInfoLoaded_ = true; 143 return false; 144 }; 145 GetPtLoads()146 virtual const std::unordered_map<uint64_t, ElfLoadInfo> GetPtLoads() 147 { 148 std::unordered_map<uint64_t, ElfLoadInfo> loadInfoMap; 149 return loadInfoMap; 150 } 151 152 // get the build if from symbols 153 const std::string GetBuildId() const; 154 EnableMiniDebugInfo()155 virtual void EnableMiniDebugInfo() {} 156 // get the symbols vector 157 const std::vector<DfxSymbol> &GetSymbols(); 158 const std::vector<DfxSymbol *> &GetMatchedSymbols(); 159 160 // get vaddr(in symbol) from ip(real addr , after mmap reloc) 161 virtual uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t mapOffset) const; 162 163 // get symbols from vaddr 164 const DfxSymbol GetSymbolWithVaddr(uint64_t vaddrInFile); 165 166 // get the section info , like .ARM.exidx GetSectionInfo(const std::string & name,uint64_t & sectionVaddr,uint64_t & sectionSize,uint64_t & sectionFileOffset)167 virtual bool GetSectionInfo([[maybe_unused]] const std::string &name, 168 [[maybe_unused]] uint64_t §ionVaddr, 169 [[maybe_unused]] uint64_t §ionSize, 170 [[maybe_unused]] uint64_t §ionFileOffset) const 171 { 172 HLOGV("virtual dummy function called"); 173 return false; 174 } 175 #ifndef __arm__ 176 // get hdr info for unwind , need provide the fde table location and entry count GetHDRSectionInfo(uint64_t & ehFrameHdrElfOffset,uint64_t & fdeTableElfOffset,uint64_t & fdeTableSize)177 virtual bool GetHDRSectionInfo([[maybe_unused]] uint64_t &ehFrameHdrElfOffset, 178 [[maybe_unused]] uint64_t &fdeTableElfOffset, 179 [[maybe_unused]] uint64_t &fdeTableSize) 180 { 181 HLOGV("virtual dummy function called"); 182 return false; 183 } 184 #endif 185 // load from symbols from the perf.data format 186 static std::unique_ptr<SymbolsFile> LoadSymbolsFromSaved(const SymbolFileStruct &); 187 // save the symbols to perf.data format 188 void ExportSymbolToFileFormat(SymbolFileStruct &symbolFileStruct); 189 SymbolsLoaded()190 bool SymbolsLoaded() 191 { 192 return symbolsLoaded_; 193 } 194 195 void AddSymbol(DfxSymbol symbol); 196 197 // this means we are in recording 198 // will try read some elf in runtime path 199 static bool onRecording_; 200 static bool needParseJsFunc_; 201 std::vector<DfxSymbol> symbols_ {}; 202 std::vector<DfxSymbol *> matchedSymbols_ {}; 203 std::map<uint64_t, DfxSymbol> symbolsMap_; GetSymbolWithPcAndMap(uint64_t pc,std::shared_ptr<DfxMap> map)204 virtual DfxSymbol GetSymbolWithPcAndMap(uint64_t pc, std::shared_ptr<DfxMap> map) 205 { 206 return DfxSymbol(); 207 } 208 209 // set map info SetMapsInfo(std::shared_ptr<DfxMap> map)210 void SetMapsInfo(std::shared_ptr<DfxMap> map) 211 { 212 map_ = map; 213 } 214 215 protected: 216 bool symbolsLoaded_ = false; 217 bool symbolsLoadResult_ = false; 218 bool debugInfoLoaded_ = false; 219 bool debugInfoLoadResult_ = false; 220 const std::string FindSymbolFile(const std::vector<std::string> &, 221 std::string symboleFilePath = EMPTY_STRING) const; 222 223 std::string SearchReadableFile(const std::vector<std::string> &searchPaths, 224 const std::string &filePath) const; 225 bool UpdateBuildIdIfMatch(std::string buildId); 226 std::string buildId_ = ""; 227 std::vector<std::string> symbolsFileSearchPaths_; 228 229 std::vector<FileSymbol> fileSymbols_ {}; 230 std::mutex mutex_; 231 232 void AdjustSymbols(); 233 void SortMatchedSymbols(); 234 bool CheckPathReadable(const std::string &path) const; 235 236 FRIEND_TEST(SymbolsFileTest, FindSymbolFile); 237 FRIEND_TEST(SymbolsFileTest, UpdateBuildIdIfMatch); 238 FRIEND_TEST(SymbolsFileTest, exportSymbolToFileFormat); 239 FRIEND_TEST(SymbolsFileTest, exportSymbolToFileFormatMatched); 240 friend class VirtualRuntimeTest; 241 FRIEND_TEST(ReportJsonFileTest, ProcessSymbolsFiles); 242 FRIEND_TEST(ReportProtobufFileTest, ProcessSymbolsFiles); 243 friend class ReportProtobufFileTest; 244 }; 245 } // namespace HiPerf 246 } // namespace Developtools 247 } // namespace OHOS 248 #endif // HIPERF_SYMBOLS_H 249