• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_CJ_FILE,
84     SYMBOL_V8_FILE,
85     SYMBOL_UNKNOW_FILE,
86 };
87 
88 class SymbolsFile {
89 public:
90     SymbolsFileType symbolFileType_;
91     std::string filePath_ = "";
92     int32_t id_ = -1; // used to report protobuf file
93 
94     // [14] .text             PROGBITS         00000000002c5000  000c5000
95     // min exec addr , general it point to .text
96     // we make a default value for min compare
97     static const uint64_t maxVaddr = std::numeric_limits<uint64_t>::max();
98 
99     uint64_t textExecVaddr_ = maxVaddr;
100     uint64_t textExecVaddrFileOffset_ = 0;
101     uint64_t textExecVaddrRange_ = maxVaddr;
102     std::shared_ptr<DfxMap> map_ = nullptr;
103 
SymbolsFile(SymbolsFileType symbolType,const std::string path)104     SymbolsFile(SymbolsFileType symbolType, const std::string path)
105         : symbolFileType_(symbolType), filePath_(path) {};
106     virtual ~SymbolsFile();
107 
GetElfFile()108     virtual std::shared_ptr<DfxElf> GetElfFile()
109     {
110         return nullptr;
111     }
112 
113     // create the symbols file object
114     static std::unique_ptr<SymbolsFile> CreateSymbolsFile(
115         SymbolsFileType = SYMBOL_UNKNOW_FILE, const std::string symbolFilePath = EMPTY_STRING, pid_t pid = 0);
116     static std::unique_ptr<SymbolsFile> CreateSymbolsFile(const std::string &symbolFilePath, pid_t pid = 0);
117 
118     // set symbols path
setSymbolsFilePath(const std::string & symbolsSearchPath)119     bool setSymbolsFilePath(const std::string &symbolsSearchPath)
120     {
121         std::vector<std::string> symbolsSearchPaths = {symbolsSearchPath};
122         return setSymbolsFilePath(symbolsSearchPaths);
123     };
124     bool setSymbolsFilePath(const std::vector<std::string> &);
IsAbc()125     virtual bool IsAbc()
126     {
127         return false;
128     }
IsV8()129     virtual bool IsV8()
130     {
131         return false;
132     }
133 
134     virtual void SetBoolValue(bool value);
135     // load symbol from file
136     virtual bool LoadSymbols([[maybe_unused]] std::shared_ptr<DfxMap> map = nullptr,
137                              [[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING)
138     {
139         HLOGV("virtual dummy function called");
140         symbolsLoaded_ = true;
141         return false;
142     };
143     // load debug info for unwind
144     virtual bool LoadDebugInfo(std::shared_ptr<DfxMap> map = nullptr,
145                                [[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING)
146     {
147         HLOGV("virtual dummy function called");
148         debugInfoLoaded_ = true;
149         return false;
150     };
151 
GetPtLoads()152     virtual const std::unordered_map<uint64_t, ElfLoadInfo> GetPtLoads()
153     {
154         std::unordered_map<uint64_t, ElfLoadInfo> loadInfoMap;
155         return loadInfoMap;
156     }
157 
158     // get the build if from symbols
159     const std::string GetBuildId() const;
160 
EnableMiniDebugInfo()161     virtual void EnableMiniDebugInfo() {}
162     // get the symbols vector
163     const std::vector<DfxSymbol> &GetSymbols();
164     const std::vector<DfxSymbol *> &GetMatchedSymbols();
165 
166     // get vaddr(in symbol) from ip(real addr , after mmap reloc)
167     virtual uint64_t GetVaddrInSymbols(const uint64_t ip, const uint64_t mapStart, const uint64_t mapOffset) const;
168 
169     // get symbols from vaddr
170     const DfxSymbol GetSymbolWithVaddr(uint64_t vaddrInFile);
171 
172     // get the section info , like .ARM.exidx
GetSectionInfo(const std::string & name,uint64_t & sectionVaddr,uint64_t & sectionSize,uint64_t & sectionFileOffset)173     virtual bool GetSectionInfo([[maybe_unused]] const std::string &name,
174                                 [[maybe_unused]] uint64_t &sectionVaddr,
175                                 [[maybe_unused]] uint64_t &sectionSize,
176                                 [[maybe_unused]] uint64_t &sectionFileOffset) const
177     {
178         HLOGV("virtual dummy function called");
179         return false;
180     }
181 #ifndef __arm__
182     // get hdr info for unwind , need provide the fde table location and entry count
GetHDRSectionInfo(uint64_t & ehFrameHdrElfOffset,uint64_t & fdeTableElfOffset,uint64_t & fdeTableSize)183     virtual bool GetHDRSectionInfo([[maybe_unused]] uint64_t &ehFrameHdrElfOffset,
184                                    [[maybe_unused]] uint64_t &fdeTableElfOffset,
185                                    [[maybe_unused]] uint64_t &fdeTableSize)
186     {
187         HLOGV("virtual dummy function called");
188         return false;
189     }
190 #endif
191     // load from symbols from the perf.data format
192     static std::unique_ptr<SymbolsFile> LoadSymbolsFromSaved(const SymbolFileStruct &);
193     // save the symbols to perf.data format
194     void ExportSymbolToFileFormat(SymbolFileStruct &symbolFileStruct);
195 
SymbolsLoaded()196     bool SymbolsLoaded()
197     {
198         return symbolsLoaded_;
199     }
200 
201     void AddSymbol(DfxSymbol symbol);
202 
203     // this means we are in recording
204     // will try read some elf in runtime path
205     static bool onRecording_;
206     static bool needParseJsFunc_;
207     std::vector<DfxSymbol> symbols_ {};
208     std::vector<DfxSymbol *> matchedSymbols_ {};
209     std::map<uint64_t, DfxSymbol> symbolsMap_;
210     static uint32_t offsetNum_;
GetSymbolWithPcAndMap(const uint64_t pc,std::shared_ptr<DfxMap> map)211     virtual DfxSymbol GetSymbolWithPcAndMap(const uint64_t pc, std::shared_ptr<DfxMap> map)
212     {
213         return DfxSymbol();
214     }
215 
216     // set map info
SetMapsInfo(std::shared_ptr<DfxMap> map)217     void SetMapsInfo(std::shared_ptr<DfxMap> map)
218     {
219         map_ = map;
220     }
221 
222 protected:
223     bool symbolsLoaded_ = false;
224     bool symbolsLoadResult_ = false;
225     bool debugInfoLoaded_ = false;
226     bool debugInfoLoadResult_ = false;
227     const std::string FindSymbolFile(const std::vector<std::string> &,
228                                      std::string symboleFilePath = EMPTY_STRING) const;
229 
230     std::string SearchReadableFile(const std::vector<std::string> &searchPaths,
231                                    const std::string &filePath) const;
232     bool UpdateBuildIdIfMatch(const std::string &buildId);
233     std::string buildId_ = "";
234     std::vector<std::string> symbolsFileSearchPaths_;
235 
236     std::vector<FileSymbol> fileSymbols_ {};
237     std::mutex mutex_;
238 
239     void AdjustSymbols();
240     void SortMatchedSymbols();
241     bool CheckPathReadable(const std::string &path) const;
242 };
243 } // namespace HiPerf
244 } // namespace Developtools
245 } // namespace OHOS
246 #endif // HIPERF_SYMBOLS_H
247