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