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 §ionVaddr, uint64_t §ionSize,
253 uint64_t §ionFileOffset) 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