• 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_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 &sectionVaddr,
169                                 [[maybe_unused]] uint64_t &sectionSize,
170                                 [[maybe_unused]] uint64_t &sectionFileOffset) 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