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