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