• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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 #define HILOG_TAG "Symbols"
17 
18 #include "symbols_file.h"
19 
20 #include <algorithm>
21 #include <chrono>
22 #include <cxxabi.h>
23 #include <fcntl.h>
24 #include <fstream>
25 
26 #if is_mingw
27 #include <memoryapi.h>
28 #else
29 #include <sys/mman.h>
30 #include <sys/stat.h>
31 #endif
32 
33 #include <cstdlib>
34 #include <unistd.h>
35 #include "common.h"
36 #include "dfx_ark.h"
37 #include "dfx_extractor_utils.h"
38 #include "dfx_symbols.h"
39 #include "dwarf_encoding.h"
40 #include "elf_factory.h"
41 #include "utilities.h"
42 
43 using namespace OHOS::HiviewDFX;
44 using namespace std::chrono;
45 
46 namespace OHOS {
47 namespace Developtools {
48 namespace NativeDaemon {
49 bool SymbolsFile::onRecording_ = true;
GetBuildId() const50 const std::string SymbolsFile::GetBuildId() const
51 {
52     return buildId_;
53 }
54 
UpdateBuildIdIfMatch(std::string buildId)55 bool SymbolsFile::UpdateBuildIdIfMatch(std::string buildId)
56 {
57     /*
58         here we have two case
59         1 buildId_ is empty
60             a) always return match
61         2 buildId_ is not empty
62             a) really check if the same one
63     */
64 
65     if (buildId_.empty()) {
66         // we have new empty build
67         if (buildId.empty()) {
68             // both empty , no build id provided
69             HLOGD("build id is empty.");
70             return true;
71         } else {
72             buildId_ = buildId;
73             HLOGD("new buildId %s", buildId_.c_str());
74             return true;
75         }
76     } else {
77         // we already have a build id
78         // so this is not the first time load symbol
79         // we need check if it match
80         HLOGV("expected buildid: %s vs %s", buildId_.c_str(), buildId.c_str());
81 
82         if (buildId_ != buildId) {
83             HLOGW("id not match");
84             return false;
85         } else {
86             HLOGD("id match");
87             return true;
88         }
89     }
90 }
91 
SearchReadableFile(const std::vector<std::string> & searchPaths,const std::string & filePath) const92 std::string SymbolsFile::SearchReadableFile(const std::vector<std::string> &searchPaths,
93                                             const std::string &filePath) const
94 {
95     UNWIND_CHECK_TRUE(!filePath.empty(), filePath, "nothing to found");
96     for (auto searchPath : searchPaths) {
97         if (searchPath.back() != PATH_SEPARATOR) {
98             searchPath += PATH_SEPARATOR;
99         }
100         std::string PossibleFilePath = searchPath + filePath;
101         if (CheckPathReadable(PossibleFilePath)) {
102             return PossibleFilePath;
103         }
104         HLOGW("have not found '%s' in search paths %s", filePath.c_str(), searchPath.c_str());
105     }
106     return EMPTY_STRING;
107 }
108 
FindSymbolFile(const std::vector<std::string> & symbolsFileSearchPaths,std::string symboleFilePath) const109 const std::string SymbolsFile::FindSymbolFile(
110     const std::vector<std::string> &symbolsFileSearchPaths, std::string symboleFilePath) const
111 {
112     /*
113         this function do 2 things:
114         find by name:
115             1 find dso path
116             2 find search path
117                 a) search path + dso path
118                 b) search path + dso name
119 
120         show we should return filePath_ as default ?
121     */
122     if (symboleFilePath.empty()) {
123         symboleFilePath = filePath_;
124         HLOGD("use default filename: %s ", symboleFilePath.c_str());
125     }
126     symboleFilePath = PlatformPathConvert(symboleFilePath);
127     std::string foundPath;
128     // search fisrt if we have path
129     if (symbolsFileSearchPaths.size() != 0) {
130         foundPath = SearchReadableFile(symbolsFileSearchPaths, symboleFilePath);
131         if (foundPath.empty()) {
132             HLOGV("try base name for: %s split with %s", symboleFilePath.c_str(),
133                   PATH_SEPARATOR_STR.c_str());
134             auto pathSplit = StringSplit(symboleFilePath, PATH_SEPARATOR_STR);
135             if (pathSplit.size() > 1) {
136                 HLOGV("base name is: %s ", pathSplit.back().c_str());
137                 // found it again with base name , split it and get last name
138                 foundPath = SearchReadableFile(symbolsFileSearchPaths, pathSplit.back());
139             }
140         }
141     }
142     auto pathSplit = StringSplit(symboleFilePath, "!");
143     if (pathSplit.size() > 1) {
144         HLOGV("base name is: %s ", pathSplit.back().c_str());
145         if (StringEndsWith(pathSplit[0], ".hap")) {
146             foundPath = pathSplit[0];
147         }
148     }
149     // only access the patch in onRecording_
150     // in report mode we don't load any thing in runtime path
151     if (foundPath.empty() and onRecording_) {
152         // try access direct at last
153         if (CheckPathReadable(symboleFilePath)) {
154             // found direct folder
155             HLOGD("find %s in current work dir", symboleFilePath.c_str());
156             return symboleFilePath;
157         }
158     }
159     return foundPath;
160 }
161 
162 class ElfFileSymbols : public SymbolsFile {
163 public:
ElfFileSymbols(const std::string & symbolFilePath,const SymbolsFileType symbolsFileType=SYMBOL_ELF_FILE)164     explicit ElfFileSymbols(const std::string &symbolFilePath,
165                             const SymbolsFileType symbolsFileType = SYMBOL_ELF_FILE)
166         : SymbolsFile(symbolsFileType, symbolFilePath)
167     {
168     }
169 
~ElfFileSymbols()170     virtual ~ElfFileSymbols()
171     {
172     }
173 
LoadSymbols(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)174     bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
175     {
176         symbolsLoaded_ = true;
177         std::string findPath = FindSymbolFile(symbolsFileSearchPaths_, symbolFilePath);
178         UNWIND_CHECK_TRUE(!findPath.empty(), false, "elf found failed (belong to %s)", filePath_.c_str());
179         if (LoadElfSymbols(map, findPath)) {
180             return true;
181         } else {
182             HLOGW("elf open failed with '%s'", findPath.c_str());
183             return false;
184         }
185         return false;
186     }
187 
GetElfFile()188     std::shared_ptr<DfxElf> GetElfFile() override
189     {
190         return elfFile_;
191     }
192 
193 protected:
LoadDebugInfo(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)194     bool LoadDebugInfo(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
195     {
196         if (debugInfoLoaded_) {
197             return true;
198         } else {
199             debugInfoLoaded_ = true;
200         }
201         std::string elfPath = FindSymbolFile(symbolsFileSearchPaths_, symbolFilePath);
202         UNWIND_CHECK_TRUE(!elfPath.empty(), false, "elf found failed (belong to %s)", filePath_.c_str());
203         if (elfFile_ == nullptr) {
204             if (StringEndsWith(elfPath, ".hap") && StringStartsWith(elfPath, "/proc")) {
205                 CompressHapElfFactory elfFactory(elfPath, map->prevMap);
206                 elfFile_ = elfFactory.Create();
207                 map->offset -= map->prevMap->offset;
208                 map->elf = elfFile_;
209             } else {
210                 RegularElfFactory elfFactory(elfPath);
211                 elfFile_ = elfFactory.Create();
212             }
213         }
214 
215         if (elfFile_ == nullptr) {
216             HLOGE("Failed to create elf file for %s.", elfPath.c_str());
217             return false;
218         }
219 
220         if (!elfFile_->IsValid()) {
221             HLOGE("parse elf file failed.");
222             return false;
223         }
224 
225         HLOGD("loaded elf %s", elfPath.c_str());
226         // update path for so in hap
227         if (StringEndsWith(elfPath, ".hap")) {
228             filePath_ = elfPath + "!" + elfFile_->GetElfName();
229             HLOGD("update path for so in hap %s.", filePath_.c_str());
230             map->name = filePath_;
231             map->elf = elfFile_;
232             map->prevMap->name = filePath_;
233             map->prevMap->elf = elfFile_;
234         }
235         textExecVaddr_ = elfFile_->GetStartVaddr();
236         textExecVaddrFileOffset_ = elfFile_->GetStartOffset();
237         HLOGD("textExecVaddr_ 0x%016" PRIx64 " file offset 0x%016" PRIx64 "", textExecVaddr_,
238               textExecVaddrFileOffset_);
239 
240 #ifndef __arm__
241         ShdrInfo shinfo;
242         if (elfFile_->GetSectionInfo(shinfo, ".eh_frame_hdr")) {
243             LoadEhFrameHDR(elfFile_->GetMmapPtr() + shinfo.offset, shinfo.size, shinfo.offset);
244         }
245 #endif
246         return true;
247     }
248 
249 private:
250     bool ehFrameHDRValid_ {false};
251     uint64_t ehFrameHDRElfOffset_ {0};
252     uint64_t ehFrameHDRFdeCount_ {0};
253     uint64_t ehFrameHDRFdeTableItemSize_ {0};
254     uint64_t ehFrameHDRFdeTableElfOffset_ {0};
255     std::shared_ptr<DfxElf> elfFile_;
GetSectionInfo(const std::string & name,uint64_t & sectionVaddr,uint64_t & sectionSize,uint64_t & sectionFileOffset) const256     bool GetSectionInfo(const std::string &name, uint64_t &sectionVaddr, uint64_t &sectionSize,
257                         uint64_t &sectionFileOffset) const override
258     {
259         struct ShdrInfo shdrInfo;
260         if (elfFile_ != nullptr && elfFile_->GetSectionInfo(shdrInfo, name)) {
261             sectionVaddr = shdrInfo.addr;
262             sectionSize = shdrInfo.size;
263             sectionFileOffset = shdrInfo.offset;
264             HLOGM("Get Section '%s' %" PRIx64 " - %" PRIx64 "", name.c_str(), sectionVaddr, sectionSize);
265             return true;
266         } else {
267             HLOGW("Section '%s' not found", name.c_str());
268             return false;
269         }
270     }
271 
272 #ifndef __arm__
GetHDRSectionInfo(uint64_t & ehFrameHdrElfOffset,uint64_t & fdeTableElfOffset,uint64_t & fdeTableSize)273     bool GetHDRSectionInfo(uint64_t &ehFrameHdrElfOffset, uint64_t &fdeTableElfOffset,
274                            uint64_t &fdeTableSize) override
275     {
276         ShdrInfo shinfo;
277         if (elfFile_ == nullptr || !elfFile_->GetSectionInfo(shinfo, ".eh_frame_hdr")) {
278             return false;
279         }
280 
281         ehFrameHDRElfOffset_ = shinfo.offset;
282         if (ehFrameHDRValid_) {
283             ehFrameHdrElfOffset = ehFrameHDRElfOffset_;
284             fdeTableElfOffset = ehFrameHDRFdeTableElfOffset_;
285             fdeTableSize = ehFrameHDRFdeCount_;
286             return true;
287         } else {
288             HLOGW("!ehFrameHDRValid_");
289             return false;
290         }
291         if (!LoadEhFrameHDR(elfFile_->GetMmapPtr() + shinfo.offset, elfFile_->GetMmapSize(), shinfo.offset)) {
292             HLOGW("Failed to load eh_frame_hdr");
293             return false;
294         }
295 
296         ehFrameHdrElfOffset = ehFrameHDRElfOffset_;
297         fdeTableElfOffset = ehFrameHDRFdeTableElfOffset_;
298         fdeTableSize = ehFrameHDRFdeCount_;
299         return true;
300     }
301 #endif
302 
DumpEhFrameHDR() const303     void DumpEhFrameHDR() const
304     {
305         HLOGD("  ehFrameHDRElfOffset_:          0x%" PRIx64 "", ehFrameHDRElfOffset_);
306         HLOGD("  ehFrameHDRFdeCount_:           0x%" PRIx64 "", ehFrameHDRFdeCount_);
307         HLOGD("  ehFrameHDRFdeTableElfOffset_:  0x%" PRIx64 "", ehFrameHDRFdeTableElfOffset_);
308         HLOGD("  ehFrameHDRFdeTableItemSize_:   0x%" PRIx64 "", ehFrameHDRFdeTableItemSize_);
309     }
310 
LoadEhFrameHDR(const unsigned char * buffer,size_t bufferSize,uint64_t shdrOffset)311     bool LoadEhFrameHDR(const unsigned char *buffer, size_t bufferSize, uint64_t shdrOffset)
312     {
313         eh_frame_hdr *ehFrameHdr = (eh_frame_hdr *)buffer;
314         if (ehFrameHdr == nullptr) {
315             HLOGD("LoadEhFrameHDR error: ehFrameHdr is null!");
316             return false;
317         }
318         const uint8_t *dataPtr = ehFrameHdr->encode_data;
319         DwarfEncoding dwEhFramePtr(ehFrameHdr->eh_frame_ptr_enc, dataPtr);
320         DwarfEncoding dwFdeCount(ehFrameHdr->fde_count_enc, dataPtr);
321         DwarfEncoding dwTable(ehFrameHdr->table_enc, dataPtr);
322         DwarfEncoding dwTableValue(ehFrameHdr->table_enc, dataPtr);
323 
324         HLOGD("eh_frame_hdr:");
325         HexDump(buffer, BITS_OF_FOUR_BYTE, bufferSize);
326         unsigned char version = ehFrameHdr->version;
327         HLOGD("  version:             %02x:%s", version, (version == 1) ? "valid" : "invalid");
328         HLOGD("  eh_frame_ptr_enc:    %s", dwEhFramePtr.ToString().c_str());
329         HLOGD("  fde_count_enc:       %s", dwFdeCount.ToString().c_str());
330         HLOGD("  table_enc:           %s", dwTable.ToString().c_str());
331         HLOGD("  table_value_enc:     %s", dwTableValue.ToString().c_str());
332         HLOGD("  table_item_size:     %zd", dwTable.GetSize() + dwTableValue.GetSize());
333         HLOGD("  table_offset_in_hdr: %zu", dwTable.GetData() - buffer);
334 
335         if (version != 1) {
336             HLOGD("eh_frame_hdr version is invalid");
337             return false;
338         }
339         ehFrameHDRValid_ = true;
340         ehFrameHDRElfOffset_ = shdrOffset;
341         ehFrameHDRFdeCount_ = dwFdeCount.GetAppliedValue();
342         ehFrameHDRFdeTableElfOffset_ = dwTable.GetData() - buffer + shdrOffset;
343         ehFrameHDRFdeTableItemSize_ = dwTable.GetSize() + dwTableValue.GetSize();
344         DumpEhFrameHDR();
345 
346         if (!dwFdeCount.IsOmit() && dwFdeCount.GetValue() > 0) {
347             return true;
348         } else {
349             HLOGW("fde table not found.\n");
350         }
351         return false;
352     }
353 
UpdateSymbols(std::vector<DfxSymbol> & symbolsTable,const std::string & elfPath)354     void UpdateSymbols(std::vector<DfxSymbol> &symbolsTable, const std::string &elfPath)
355     {
356         symbols_.clear();
357         HLOGD("%zu symbols loadded from symbolsTable.", symbolsTable.size());
358 
359         symbols_.swap(symbolsTable);
360 
361         AdjustSymbols();
362         HLOGD("%zu symbols loadded from elf '%s'.", symbols_.size(), elfPath.c_str());
363         for (auto& symbol: symbols_) {
364             HLOGD("symbol %s", symbol.ToDebugString().c_str());
365         }
366         if (buildId_.empty()) {
367             HLOGD("buildId not found from elf '%s'.", elfPath.c_str());
368             // dont failed. some time the lib have not got the build id
369             // buildId not found from elf '/system/bin/ld-musl-arm.so.1'.
370         }
371     }
372 
LoadElfSymbols(std::shared_ptr<DfxMap> map,std::string elfPath)373     bool LoadElfSymbols(std::shared_ptr<DfxMap> map, std::string elfPath)
374     {
375 #ifdef HIPERF_DEBUG_TIME
376         const auto startTime = steady_clock::now();
377 #endif
378         if (elfFile_ == nullptr) {
379             if (StringEndsWith(elfPath, ".hap") && StringStartsWith(elfPath, "/proc") && map != nullptr) {
380                 CompressHapElfFactory elfFactory(elfPath, map->prevMap);
381                 elfFile_ = elfFactory.Create();
382                 map->offset -= map->prevMap->offset;
383                 map->elf = elfFile_;
384                 HLOGD("loaded map %s", elfPath.c_str());
385             } else {
386                 RegularElfFactory elfFactory(elfPath);
387                 elfFile_ = elfFactory.Create();
388                 HLOGD("loaded elf %s", elfPath.c_str());
389             }
390         }
391 
392         if (elfFile_ == nullptr || !elfFile_->IsValid()) {
393             HLOGD("parser elf file failed.");
394             return false;
395         }
396         textExecVaddr_ = elfFile_->GetStartVaddr();
397         textExecVaddrFileOffset_ = elfFile_->GetStartOffset();
398         HLOGD("textExecVaddr_ 0x%016" PRIx64 " file offset 0x%016" PRIx64 "", textExecVaddr_,
399               textExecVaddrFileOffset_);
400 
401         // we prepare two table here
402         // only one we will push in to symbols_
403         // or both drop if build id is not same
404         std::string buildIdFound = elfFile_->GetBuildId();
405         std::vector<DfxSymbol> symbolsTable;
406 
407         // use elfFile_ to get symbolsTable
408         DfxSymbols::ParseSymbols(symbolsTable, elfFile_, elfPath);
409         DfxSymbols::AddSymbolsByPlt(symbolsTable, elfFile_, elfPath);
410 
411         if (UpdateBuildIdIfMatch(buildIdFound)) {
412             UpdateSymbols(symbolsTable, elfPath);
413         } else {
414             HLOGW("symbols will not update for '%s' because buildId is not match.",
415                   elfPath.c_str());
416             // this mean failed . we dont goon for this.
417             return false;
418         }
419 
420 #ifdef HIPERF_DEBUG_TIME
421         auto usedTime = duration_cast<microseconds>(steady_clock::now() - startTime);
422         if (usedTime.count() != 0) {
423             HLOGV("cost %0.3f ms to load symbols '%s'",
424                   usedTime.count() / static_cast<double>(milliseconds::duration::period::den),
425                   elfPath.c_str());
426         }
427 #endif
428         return true;
429     }
430 
GetVaddrInSymbols(uint64_t ip,uint64_t mapStart,uint64_t mapPageOffset) const431     uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart,
432                                uint64_t mapPageOffset) const override
433     {
434         /*
435             00200000-002c5000 r--p 00000000 08:02 46400311
436             002c5000-00490000 r-xp 000c5000 08:02 4640031
437 
438             [14] .text             PROGBITS         00000000002c5000  000c5000
439 
440             if ip is 0x46e6ab
441             1. find the map range is 002c5000-00490000
442             2. ip - map start(002c5000) = map section offset
443             3. map section offset + map page offset(000c5000) = elf file offset
444             4. elf file offset - exec file offset(000c5000)
445                 = ip offset (ip always in exec file offset)
446             5. ip offset + exec begin vaddr(2c5000) = virtual ip in elf
447         */
448         uint64_t vaddr = ip - mapStart + mapPageOffset - textExecVaddrFileOffset_ + textExecVaddr_;
449         HLOGM(" ip :0x%016" PRIx64 " -> elf offset :0x%016" PRIx64 " -> vaddr :0x%016" PRIx64 " ",
450               ip, ip - mapStart + mapPageOffset, vaddr);
451         HLOGM("(minExecAddrFileOffset_ is 0x%" PRIx64 " textExecVaddr_ is 0x%" PRIx64 ")",
452               textExecVaddrFileOffset_, textExecVaddr_);
453         return vaddr;
454     }
455 };
456 
457 class KernelSymbols : public ElfFileSymbols {
458 public:
KernelSymbols(const std::string & symbolFilePath)459     explicit KernelSymbols(const std::string &symbolFilePath)
460         : ElfFileSymbols(symbolFilePath, SYMBOL_KERNEL_FILE)
461     {
462     }
463 
464     static constexpr const int KSYM_MIN_TOKENS = 3;
465     static constexpr const int KSYM_DEFAULT_LINE = 35000;
466     static constexpr const int KSYM_DEFAULT_SIZE = 1024 * 1024 * 1; // 1MB
467 
ParseKallsymsLine()468     bool ParseKallsymsLine()
469     {
470         size_t lines = 0;
471         std::string kallsym;
472         if (!ReadFileToString("/proc/kallsyms", kallsym, KSYM_DEFAULT_SIZE)) {
473             HLOGW("/proc/kallsyms load failed.");
474             return false;
475         }
476         // reduce the mem alloc
477         symbols_.reserve(KSYM_DEFAULT_LINE);
478 
479         char *lineBegin = kallsym.data();
480         char *dataEnd = lineBegin + kallsym.size();
481         while (lineBegin < dataEnd) {
482             char *lineEnd = strchr(lineBegin, '\n');
483             if (lineEnd != nullptr) {
484                 *lineEnd = '\0';
485             }
486             size_t lineSize = (lineEnd != nullptr) ? (lineEnd - lineBegin) : (dataEnd - lineBegin);
487 
488             lines++;
489             uint64_t addr = 0;
490             char type = '\0';
491 
492             char nameRaw[lineSize];
493             char moduleRaw[lineSize];
494             int ret = sscanf_s(lineBegin, "%" PRIx64 " %c %s%s", &addr, &type, sizeof(type),
495                                nameRaw, sizeof(nameRaw), moduleRaw, sizeof(moduleRaw));
496 
497             lineBegin = lineEnd + 1;
498             if (ret >= KSYM_MIN_TOKENS) {
499                 if (ret == KSYM_MIN_TOKENS) {
500                     moduleRaw[0] = '\0';
501                 }
502                 HLOGM(" 0x%016" PRIx64 " %c '%s' '%s'", addr, type, nameRaw, moduleRaw);
503             } else {
504                 HLOGW("unknow line %d: '%s'", ret, lineBegin);
505                 continue;
506             }
507             std::string name = nameRaw;
508             std::string module = moduleRaw;
509 
510             /*
511             T
512             The symbol is in the text (code) section.
513 
514             W
515             The symbol is a weak symbol that has not been specifically
516             tagged as a weak object symbol. When a weak defined symbol is
517             linked with a normal defined symbol, the normal defined symbol
518             is used with no error. When a weak undefined symbol is linked
519             and the symbol is not defined, the value of the weak symbol
520             becomes zero with no error.
521             */
522             if (addr != 0 && strchr("TtWw", type)) {
523                 // we only need text symbols
524                 symbols_.emplace_back(addr, name, module.empty() ? filePath_ : module);
525             }
526         }
527         HLOGD("%zu line processed(%zu symbols)", lines, symbols_.size());
528         return true;
529     }
530 
531     const std::string KPTR_RESTRICT = "/proc/sys/kernel/kptr_restrict";
532 
LoadKernelSyms()533     bool LoadKernelSyms()
534     {
535         if (COMMON::IsUserMode()) {
536             HLOGE("only root mode can access kernel symbols");
537             return false;
538         }
539         HLOGD("try read /proc/kallsyms");
540         if (access("/proc/kallsyms", R_OK) != 0) {
541             printf("No vmlinux path is given, and kallsyms cannot be opened\n");
542             return false;
543         }
544 
545         if (ReadFileToString(KPTR_RESTRICT).front() != '0') {
546             printf("/proc/sys/kernel/kptr_restrict is NOT 0, will try set it to 0.\n");
547             if (!WriteStringToFile(KPTR_RESTRICT, "0")) {
548                 printf("/proc/sys/kernel/kptr_restrict write failed and we cant not change it.\n");
549             }
550         }
551 
552         // getline end
553         if (!ParseKallsymsLine()) {
554             return false;
555         }
556 
557         if (symbols_.empty()) {
558             printf("The symbol table addresses in /proc/kallsyms are all 0.\n"
559                    "Please check the value of /proc/sys/kernel/kptr_restrict, it "
560                    "should be 0.\n"
561                    "Or provide a separate vmlinux path.\n");
562 
563             if (buildId_.size() != 0) {
564                 // but we got the buildid , so we make a dummpy symbols
565                 HLOGD("kallsyms not found. but we have the buildid");
566                 return true;
567             } else {
568                 // we got nothing
569                 return false;
570             }
571         } else {
572             AdjustSymbols();
573             HLOGV("%zu symbols_ loadded from kallsyms.\n", symbols_.size());
574             return true;
575         }
576     }
LoadSymbols(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)577     bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
578     {
579         symbolsLoaded_ = true;
580         HLOGV("KernelSymbols try read '%s' search paths size %zu, inDeviceRecord %d",
581               symbolFilePath.c_str(), symbolsFileSearchPaths_.size(), onRecording_);
582 
583         if (onRecording_) {
584             // try read
585             HLOGD("try read /sys/kernel/notes");
586             std::string notes = ReadFileToString("/sys/kernel/notes");
587             if (notes.empty()) {
588                 printf("notes cannot be opened, unable get buildid\n");
589                 return false;
590             } else {
591                 HLOGD("kernel notes size: %zu", notes.size());
592                 buildId_ = DfxElf::GetBuildId((uint64_t)notes.data(), (uint64_t)notes.size());
593             }
594 
595             const auto startTime = std::chrono::steady_clock::now();
596             if (!LoadKernelSyms()) {
597                 printf("parse kalsyms failed.\n");
598                 return false;
599             } else {
600                 const auto thisTime = std::chrono::steady_clock::now();
601                 const auto usedTimeMsTick =
602                     std::chrono::duration_cast<std::chrono::milliseconds>(thisTime - startTime);
603                 HLOGV("Load kernel symbols (total %" PRId64 " ms)\n", (int64_t)usedTimeMsTick.count());
604                 // load complete
605                 return true;
606             }
607         } // no search path
608 
609         // try vmlinux
610         return ElfFileSymbols::LoadSymbols(nullptr, KERNEL_ELF_NAME);
611     }
GetVaddrInSymbols(uint64_t ip,uint64_t mapStart,uint64_t) const612     uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t) const override
613     {
614         // ip is vaddr in /proc/kallsyms
615         return ip;
616     }
~KernelSymbols()617     ~KernelSymbols() override {}
618 };
619 
620 class KernelModuleSymbols : public ElfFileSymbols {
621 public:
KernelModuleSymbols(const std::string & symbolFilePath)622     explicit KernelModuleSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath)
623     {
624         HLOGV("create %s", symbolFilePath.c_str());
625         symbolFileType_ = SYMBOL_KERNEL_MODULE_FILE;
626         module_ = symbolFilePath;
627     }
~KernelModuleSymbols()628     ~KernelModuleSymbols() override {};
629 
LoadSymbols(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)630     bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
631     {
632         symbolsLoaded_ = true;
633         if (module_ == filePath_ and onRecording_) {
634             // file name sitll not convert to ko file path
635             // this is in record mode
636             HLOGV("find ko name %s", module_.c_str());
637             for (const std::string &path : kernelModulePaths) {
638                 if (access(path.c_str(), R_OK) == 0) {
639                     std::string koPath = path + module_ + KERNEL_MODULES_EXT_NAME;
640                     HLOGV("found ko in %s", koPath.c_str());
641                     if (access(koPath.c_str(), R_OK) == 0) {
642                         // create symbol
643                         filePath_ = koPath;
644                         break; // find next ko
645                     }
646                 }
647             }
648             LoadBuildId();
649         } else {
650             HLOGV("we have file path, load with %s", filePath_.c_str());
651             return ElfFileSymbols::LoadSymbols(nullptr, filePath_);
652         }
653         return false;
654     }
GetVaddrInSymbols(uint64_t ip,uint64_t mapStart,uint64_t) const655     uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t) const override
656     {
657         return ip - mapStart;
658     }
659 
660 private:
LoadBuildId()661     bool LoadBuildId()
662     {
663         std::string sysFile = "/sys/module/" + module_ + "/notes/.note.gnu.build-id";
664         std::string buildIdRaw = ReadFileToString(sysFile);
665         if (!buildIdRaw.empty()) {
666             buildId_ = DfxElf::GetBuildId((uint64_t)buildIdRaw.data(), (uint64_t)buildIdRaw.size());
667             HLOGD("kerne module %s(%s) build id %s", module_.c_str(), filePath_.c_str(),
668                   buildId_.c_str());
669             return buildId_.empty() ? false : true;
670         }
671         return false;
672     }
673 
674     const std::vector<std::string> kernelModulePaths = {"/vendor/modules/"};
675     std::string module_ = "";
676 };
677 
678 class JavaFileSymbols : public ElfFileSymbols {
679 public:
JavaFileSymbols(const std::string & symbolFilePath)680     explicit JavaFileSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath)
681     {
682         symbolFileType_ = SYMBOL_KERNEL_FILE;
683     }
LoadSymbols(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)684     bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
685     {
686         symbolsLoaded_ = true;
687         return false;
688     }
~JavaFileSymbols()689     ~JavaFileSymbols() override {}
690 
GetVaddrInSymbols(uint64_t ip,uint64_t mapStart,uint64_t mapPageOffset) const691     uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart,
692                                        uint64_t mapPageOffset) const override
693     {
694         // this is different with elf
695         // elf use  ip - mapStart + mapPageOffset - minExecAddrFileOffset_ + textExecVaddr_
696         return ip - mapStart + mapPageOffset;
697     }
698 };
699 
700 class JSFileSymbols : public ElfFileSymbols {
701 public:
JSFileSymbols(const std::string & symbolFilePath)702     explicit JSFileSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath)
703     {
704         symbolFileType_ = SYMBOL_KERNEL_FILE;
705     }
LoadSymbols(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)706     bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
707     {
708         symbolsLoaded_ = true;
709         return false;
710     }
~JSFileSymbols()711     ~JSFileSymbols() override {}
712 };
713 
714 class HapFileSymbols : public ElfFileSymbols {
715 private:
716 #if defined(is_ohos) && is_ohos
717     std::unique_ptr<DfxExtractor> dfxExtractor_;
718     bool hapExtracted_ = false;
719 #endif
720     std::unique_ptr<uint8_t[]> abcDataPtr_ = nullptr;
721     [[maybe_unused]] uintptr_t loadOffSet_ = 0;
722     [[maybe_unused]] size_t abcDataSize_ = 0;
723     [[maybe_unused]] uintptr_t arkExtractorptr_ = 0;
724     bool isHapAbc_ = false;
725     pid_t pid_ = 0;
726 public:
HapFileSymbols(const std::string & symbolFilePath,pid_t pid)727     explicit HapFileSymbols(const std::string &symbolFilePath, pid_t pid)
728         : ElfFileSymbols(symbolFilePath, SYMBOL_HAP_FILE)
729     {
730         pid_ = pid;
731     }
732 
~HapFileSymbols()733     ~HapFileSymbols() override
734     {
735 #if defined(is_ohos) && is_ohos
736         if (arkExtractorptr_ != 0) {
737             DfxArk::Instance().ArkDestoryJsSymbolExtractor(arkExtractorptr_);
738             arkExtractorptr_ = 0;
739         }
740 #endif
741     }
742     // abc is the ark bytecode
IsHapAbc()743     bool IsHapAbc()
744     {
745 #if defined(is_ohos) && is_ohos
746         if (hapExtracted_) {
747             return isHapAbc_;
748         }
749         hapExtracted_ = true;
750         HLOGD("the symbol file is %s.", filePath_.c_str());
751         if (StringEndsWith(filePath_, ".hap") && map_->IsMapExec()) {
752             HLOGD("map is exec not abc file , the symbol file is:%s", map_->name.c_str());
753             return false;
754         }
755         if (StringEndsWith(filePath_, ".hap") || StringEndsWith(filePath_, ".hsp")
756             || StringEndsWith(filePath_, ".hqf")) {
757             dfxExtractor_ = std::make_unique<DfxExtractor>(filePath_);
758             if (dfxExtractor_ == nullptr) {
759                 HLOGD("DfxExtractor create failed.");
760                 return false;
761             }
762             // extract the bytecode information of the ark in the hap package
763             if (!dfxExtractor_->GetHapAbcInfo(loadOffSet_, abcDataPtr_, abcDataSize_)) {
764                 HLOGD("failed to call GetHapAbcInfo, the symbol file is:%s", filePath_.c_str());
765                 return false;
766             }
767             HLOGD("loadOffSet %u", (uint32_t)loadOffSet_);
768             if (abcDataPtr_ != nullptr) {
769                 isHapAbc_ = true;
770                 HLOGD("input abcDataPtr : %s, isAbc: %d", abcDataPtr_.get(), isHapAbc_);
771             }
772         } else {
773             if (map_ == nullptr) {
774                 return false;
775             }
776             loadOffSet_ = map_->offset;
777             abcDataSize_ = map_->end - map_->begin;
778             abcDataPtr_ = std::make_unique<uint8_t[]>(abcDataSize_);
779             auto size = DfxMemory::ReadProcMemByPid(pid_, map_->begin, abcDataPtr_.get(), map_->end - map_->begin);
780             if (size != abcDataSize_) {
781                 HLOGD("return size is small abcDataPtr : %s, isAbc: %d", abcDataPtr_.get(), isHapAbc_);
782                 return false;
783             }
784             isHapAbc_ = true;
785             HLOGD("symbol file name %s loadOffSet %u abcDataSize_ %u abcDataPtr_ %s",
786                   filePath_.c_str(), (uint32_t)loadOffSet_, (uint32_t)abcDataSize_, abcDataPtr_.get());
787         }
788         auto ret = DfxArk::Instance().ArkCreateJsSymbolExtractor(&arkExtractorptr_);
789         if (ret < 0) {
790             arkExtractorptr_ = 0;
791             HLOGE("failed to call ArkCreateJsSymbolExtractor, the symbol file is:%s", filePath_.c_str());
792         }
793 #endif
794         return isHapAbc_;
795     }
796 
IsAbc()797     bool IsAbc() override
798     {
799         return isHapAbc_ == true;
800     }
801 
SetBoolValue(bool value)802     void SetBoolValue(bool value) override
803     {
804         isHapAbc_ = value;
805     }
806 
LoadDebugInfo(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)807     bool LoadDebugInfo(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
808     {
809         HLOGD("map ptr:%p, map name:%s", map.get(), map->name.c_str());
810         if (debugInfoLoaded_) {
811             return true;
812         }
813         if (!onRecording_) {
814             return true;
815         }
816 
817         if (!IsHapAbc()) {
818             ElfFileSymbols::LoadDebugInfo(map, "");
819         }
820         debugInfoLoaded_ = true;
821         debugInfoLoadResult_ = true;
822         return true;
823     }
824 
LoadSymbols(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)825     bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
826     {
827         HLOGD("map ptr:%p, map name:%s", map.get(), map->name.c_str());
828         if (symbolsLoaded_ || !onRecording_) {
829             return true;
830         }
831         symbolsLoaded_ = true;
832         if (!IsHapAbc()) {
833             ElfFileSymbols::LoadSymbols(map, "");
834         }
835         return true;
836     }
837 
GetSymbolWithPcAndMap(uint64_t ip,std::shared_ptr<DfxMap> map)838     DfxSymbol GetSymbolWithPcAndMap(uint64_t ip, std::shared_ptr<DfxMap> map) override
839     {
840         // get cache
841         auto iter = symbolsMap_.find(ip);
842         if (iter != symbolsMap_.end()) {
843             return iter->second;
844         }
845         if (map == nullptr) {
846             return DfxSymbol(ip, "");
847         }
848         HLOGD("map ptr:%p, map name:%s", map.get(), map->name.c_str());
849 
850 #if defined(is_ohos) && is_ohos
851         if (IsAbc()) {
852             JsFunction jsFunc;
853             std::string module = map->name;
854             HLOGD("map->name module:%s", module.c_str());
855             // symbolization based on ark bytecode
856             auto ret = DfxArk::Instance().ParseArkFrameInfo(static_cast<uintptr_t>(ip),
857                                                             static_cast<uintptr_t>(map->begin),
858                                                             loadOffSet_, abcDataPtr_.get(), abcDataSize_,
859                                                             arkExtractorptr_, &jsFunc);
860             if (ret == -1) {
861                 HLOGD("failed to call ParseArkFrameInfo, the symbol file is : %s", map->name.c_str());
862                 return DfxSymbol(ip, "");
863             }
864             this->symbolsMap_.insert(std::make_pair(ip,
865                                                     DfxSymbol(ip,
866                                                     jsFunc.codeBegin,
867                                                     jsFunc.functionName,
868                                                     jsFunc.ToString(),
869                                                     map->name)));
870 
871             DfxSymbol &foundSymbol = symbolsMap_[ip];
872             if (!foundSymbol.matched_) {
873                 foundSymbol.matched_ = true;
874                 matchedSymbols_.push_back(&(symbolsMap_[ip]));
875             }
876 
877             HLOGD("ip : 0x%" PRIx64 " the symbol file is : %s, function is %s demangle_ : %s", ip,
878                   symbolsMap_[ip].module_.data(), jsFunc.functionName, matchedSymbols_.back()->demangle_.data());
879             return symbolsMap_[ip];
880         }
881 #endif
882         DfxSymbol symbol(ip, "");
883         return symbol;
884     }
885 };
886 
887 class UnknowFileSymbols : public SymbolsFile {
888 public:
UnknowFileSymbols(const std::string & symbolFilePath)889     explicit UnknowFileSymbols(const std::string &symbolFilePath)
890         : SymbolsFile(SYMBOL_UNKNOW_FILE, symbolFilePath)
891     {
892     }
LoadSymbols(std::shared_ptr<DfxMap> map,const std::string & symbolFilePath)893     bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override
894     {
895         symbolsLoaded_ = true;
896         return false;
897     }
~UnknowFileSymbols()898     ~UnknowFileSymbols() override {}
899 };
900 
~SymbolsFile()901 SymbolsFile::~SymbolsFile() {}
902 
CreateSymbolsFile(SymbolsFileType symbolType,const std::string symbolFilePath,pid_t pid)903 std::unique_ptr<SymbolsFile> SymbolsFile::CreateSymbolsFile(SymbolsFileType symbolType,
904                                                             const std::string symbolFilePath, pid_t pid)
905 {
906     switch (symbolType) {
907         case SYMBOL_KERNEL_FILE:
908             return std::make_unique<KernelSymbols>(symbolFilePath.empty() ? KERNEL_MMAP_NAME
909                                                                           : symbolFilePath);
910         case SYMBOL_KERNEL_MODULE_FILE:
911             return std::make_unique<KernelModuleSymbols>(symbolFilePath);
912         case SYMBOL_ELF_FILE:
913             return std::make_unique<ElfFileSymbols>(symbolFilePath);
914         case SYMBOL_JAVA_FILE:
915             return std::make_unique<JavaFileSymbols>(symbolFilePath);
916         case SYMBOL_JS_FILE:
917             return std::make_unique<JSFileSymbols>(symbolFilePath);
918         case SYMBOL_HAP_FILE:
919             return std::make_unique<HapFileSymbols>(symbolFilePath, pid);
920         default:
921             return std::make_unique<SymbolsFile>(SYMBOL_UNKNOW_FILE, symbolFilePath);
922     }
923 }
924 
CreateSymbolsFile(const std::string & symbolFilePath,pid_t pid)925 std::unique_ptr<SymbolsFile> SymbolsFile::CreateSymbolsFile(const std::string &symbolFilePath, pid_t pid)
926 {
927     // we need check file name here
928     if (symbolFilePath == KERNEL_MMAP_NAME) {
929         return SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE, symbolFilePath);
930     } else if (StringEndsWith(symbolFilePath, KERNEL_MODULES_EXT_NAME)) {
931         return SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_MODULE_FILE, symbolFilePath);
932     } else if (IsArkJsFile(symbolFilePath)) {
933         return SymbolsFile::CreateSymbolsFile(SYMBOL_HAP_FILE, symbolFilePath, pid);
934     } else {
935         // default is elf
936         return SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, symbolFilePath);
937     }
938 }
939 
AdjustSymbols()940 void SymbolsFile::AdjustSymbols()
941 {
942     if (symbols_.size() <= 1u) {
943         return;
944     }
945 
946     // order
947     sort(symbols_.begin(), symbols_.end(), [](const DfxSymbol& a, const DfxSymbol& b) {
948         return a.funcVaddr_ < b.funcVaddr_;
949     });
950     HLOGV("sort completed");
951 
952     size_t fullSize = symbols_.size();
953     size_t erased = 0;
954 
955     // Check for duplicate vaddr
956     auto last = std::unique(symbols_.begin(), symbols_.end(), [](const DfxSymbol &a, const DfxSymbol &b) {
957         return (a.funcVaddr_ == b.funcVaddr_);
958     });
959     symbols_.erase(last, symbols_.end());
960     erased = fullSize - symbols_.size();
961     HLOGV("uniqued completed");
962     auto it = symbols_.begin();
963     while (it != symbols_.end()) {
964         it->index_ = it - symbols_.begin();
965         it++;
966     }
967     HLOGV("indexed completed");
968 
969     HLOG_ASSERT(symbols_.size() != 0);
970 
971     if (textExecVaddrRange_ == maxVaddr) {
972         textExecVaddrRange_ = symbols_.back().funcVaddr_ - symbols_.front().funcVaddr_;
973     }
974 
975     HLOGDDD("%zu symbols after adjust (%zu erased) 0x%016" PRIx64 " - 0x%016" PRIx64
976             " @0x%016" PRIx64 " ",
977             symbols_.size(), erased, symbols_.front().funcVaddr_, symbols_.back().funcVaddr_,
978             textExecVaddrFileOffset_);
979 }
980 
SortMatchedSymbols()981 void SymbolsFile::SortMatchedSymbols()
982 {
983     if (matchedSymbols_.size() <= 1u) {
984         return;
985     }
986     sort(matchedSymbols_.begin(), matchedSymbols_.end(), [](const DfxSymbol* a, const DfxSymbol* b) {
987         return a->funcVaddr_ < b->funcVaddr_;
988     });
989 }
990 
GetSymbols()991 const std::vector<DfxSymbol> &SymbolsFile::GetSymbols()
992 {
993     return symbols_;
994 }
995 
GetMatchedSymbols()996 const std::vector<DfxSymbol *> &SymbolsFile::GetMatchedSymbols()
997 {
998     return matchedSymbols_;
999 }
1000 
GetSymbolWithVaddr(uint64_t vaddrInFile)1001 const DfxSymbol SymbolsFile::GetSymbolWithVaddr(uint64_t vaddrInFile)
1002 {
1003 #ifdef HIPERF_DEBUG_TIME
1004     const auto startTime = steady_clock::now();
1005 #endif
1006     DfxSymbol symbol;
1007     // it should be already order from small to large
1008     auto found =
1009         std::upper_bound(symbols_.begin(), symbols_.end(), vaddrInFile, DfxSymbol::ValueLessThen);
1010     /*
1011     if data is { 1, 2, 4, 5, 5, 6 };
1012     upper_bound for each val :
1013         0 < 1 at index 0
1014         1 < 2 at index 1
1015         2 < 4 at index 2
1016         3 < 4 at index 2
1017         4 < 5 at index 3
1018         5 < 6 at index 5
1019         6 < not found
1020     if key symbol vaddr is { 1, 2, 4, 5, 5, 6 };
1021      check ip vaddr for each val :
1022        ip   sym
1023         0   not found
1024         1   1
1025         1   1
1026         2   2
1027         3   3
1028         4   4
1029         5   5
1030         6   6
1031         7   7
1032     */
1033     if (found != symbols_.begin()) {
1034         found = std::prev(found);
1035         if (found->Contain(vaddrInFile)) {
1036             if (!found->matched_) {
1037                 found->matched_ = true;
1038                 matchedSymbols_.push_back(&(*found));
1039             }
1040             symbol = *found; // copy
1041             HLOGV("found '%s' for vaddr 0x%016" PRIx64 "", symbol.ToString().c_str(), vaddrInFile);
1042         }
1043     }
1044 
1045     if (!symbol.IsValid()) {
1046         HLOGV("NOT found vaddr 0x%" PRIx64 " in symbole file %s(%zu)", vaddrInFile,
1047               filePath_.c_str(), symbols_.size());
1048     }
1049     symbol.SetIpVAddress(vaddrInFile);
1050 
1051 #ifdef HIPERF_DEBUG_TIME
1052     auto usedTime = duration_cast<milliseconds>(steady_clock::now() - startTime);
1053     if (usedTime > 1ms) {
1054         HLOGW("cost %" PRId64 "ms to search ", usedTime.count());
1055     }
1056 #endif
1057     return symbol;
1058 }
1059 
CheckPathReadable(const std::string & path) const1060 bool SymbolsFile::CheckPathReadable(const std::string &path) const
1061 {
1062     if (access(path.c_str(), R_OK) == 0) {
1063         return true;
1064     } else {
1065         HLOGM("'%s' is unable read", path.c_str());
1066         return false;
1067     }
1068 }
1069 
setSymbolsFilePath(const std::vector<std::string> & symbolsSearchPaths)1070 bool SymbolsFile::setSymbolsFilePath(const std::vector<std::string> &symbolsSearchPaths)
1071 {
1072     symbolsFileSearchPaths_.clear();
1073     for (auto &symbolsSearchPath : symbolsSearchPaths) {
1074         if (CheckPathReadable(symbolsSearchPath)) {
1075             symbolsFileSearchPaths_.emplace_back(symbolsSearchPath);
1076             HLOGV("'%s' is add to symbolsSearchPath", symbolsSearchPath.c_str());
1077         }
1078     }
1079     return (symbolsFileSearchPaths_.size() > 0);
1080 }
1081 
LoadSymbolsFromSaved(const SymbolFileStruct & symbolFileStruct)1082 std::unique_ptr<SymbolsFile> SymbolsFile::LoadSymbolsFromSaved(
1083     const SymbolFileStruct &symbolFileStruct)
1084 {
1085     auto symbolsFile = CreateSymbolsFile(symbolFileStruct.filePath_);
1086     symbolsFile->filePath_ = symbolFileStruct.filePath_;
1087     symbolsFile->symbolFileType_ = (SymbolsFileType)symbolFileStruct.symbolType_;
1088     symbolsFile->textExecVaddr_ = symbolFileStruct.textExecVaddr_;
1089     symbolsFile->textExecVaddrFileOffset_ = symbolFileStruct.textExecVaddrFileOffset_;
1090     symbolsFile->buildId_ = symbolFileStruct.buildId_;
1091     for (auto &symbolStruct : symbolFileStruct.symbolStructs_) {
1092         symbolsFile->symbols_.emplace_back(symbolStruct.vaddr_, symbolStruct.len_,
1093                                            symbolStruct.symbolName_, symbolFileStruct.filePath_);
1094     }
1095     symbolsFile->AdjustSymbols(); // reorder
1096     HLOGV("load %zu symbol from SymbolFileStruct for file '%s'", symbolsFile->symbols_.size(),
1097           symbolsFile->filePath_.c_str());
1098     return symbolsFile;
1099 }
1100 
SetBoolValue(bool value)1101 void SymbolsFile::SetBoolValue(bool value)
1102 {
1103 }
1104 
ExportSymbolToFileFormat(SymbolFileStruct & symbolFileStruct)1105 void SymbolsFile::ExportSymbolToFileFormat(SymbolFileStruct &symbolFileStruct)
1106 {
1107     symbolFileStruct.filePath_ = filePath_;
1108     symbolFileStruct.symbolType_ = symbolFileType_;
1109     symbolFileStruct.textExecVaddr_ = textExecVaddr_;
1110     symbolFileStruct.textExecVaddrFileOffset_ = textExecVaddrFileOffset_;
1111     symbolFileStruct.buildId_ = buildId_;
1112 
1113     SortMatchedSymbols();
1114     auto symbols = GetMatchedSymbols();
1115     symbolFileStruct.symbolStructs_.reserve(symbols.size());
1116     for (auto symbol : symbols) {
1117         auto &symbolStruct = symbolFileStruct.symbolStructs_.emplace_back();
1118         symbolStruct.vaddr_ = symbol->funcVaddr_;
1119         symbolStruct.len_ = symbol->size_;
1120         symbolStruct.symbolName_ = symbol->GetName();
1121     }
1122 
1123     HLOGV("export %zu symbol to SymbolFileStruct from %s", symbolFileStruct.symbolStructs_.size(),
1124           filePath_.c_str());
1125 }
1126 
GetVaddrInSymbols(uint64_t ip,uint64_t,uint64_t) const1127 uint64_t SymbolsFile::GetVaddrInSymbols(uint64_t ip, uint64_t, uint64_t) const
1128 {
1129     // no convert
1130     return ip;
1131 }
1132 } // namespace NativeDaemon
1133 } // namespace Developtools
1134 } // namespace OHOS
1135