148f512ceSopenharmony_ci/* 248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 448f512ceSopenharmony_ci * you may not use this file except in compliance with the License. 548f512ceSopenharmony_ci * You may obtain a copy of the License at 648f512ceSopenharmony_ci * 748f512ceSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 848f512ceSopenharmony_ci * 948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and 1348f512ceSopenharmony_ci * limitations under the License. 1448f512ceSopenharmony_ci */ 1548f512ceSopenharmony_ci 1648f512ceSopenharmony_ci#define HILOG_TAG "Symbols" 1748f512ceSopenharmony_ci 1848f512ceSopenharmony_ci#include "symbols_file.h" 1948f512ceSopenharmony_ci 2048f512ceSopenharmony_ci#include <algorithm> 2148f512ceSopenharmony_ci#include <chrono> 2248f512ceSopenharmony_ci#include <cxxabi.h> 2348f512ceSopenharmony_ci#include <cstdlib> 2448f512ceSopenharmony_ci#include <fcntl.h> 2548f512ceSopenharmony_ci#include <fstream> 2648f512ceSopenharmony_ci#include <string_view> 2748f512ceSopenharmony_ci#include <type_traits> 2848f512ceSopenharmony_ci 2948f512ceSopenharmony_ci#if defined(is_mingw) && is_mingw 3048f512ceSopenharmony_ci#include <memoryapi.h> 3148f512ceSopenharmony_ci#else 3248f512ceSopenharmony_ci#include <sys/mman.h> 3348f512ceSopenharmony_ci#include <sys/stat.h> 3448f512ceSopenharmony_ci#endif 3548f512ceSopenharmony_ci#include <unistd.h> 3648f512ceSopenharmony_ci 3748f512ceSopenharmony_ci#include "dfx_ark.h" 3848f512ceSopenharmony_ci#include "dfx_extractor_utils.h" 3948f512ceSopenharmony_ci#include "dfx_symbols.h" 4048f512ceSopenharmony_ci#include "dwarf_encoding.h" 4148f512ceSopenharmony_ci#include "hiperf_hilog.h" 4248f512ceSopenharmony_ci#include "unwinder_config.h" 4348f512ceSopenharmony_ci#include "utilities.h" 4448f512ceSopenharmony_ci 4548f512ceSopenharmony_ciusing namespace OHOS::HiviewDFX; 4648f512ceSopenharmony_ciusing namespace std::chrono; 4748f512ceSopenharmony_ci 4848f512ceSopenharmony_cinamespace OHOS { 4948f512ceSopenharmony_cinamespace Developtools { 5048f512ceSopenharmony_cinamespace HiPerf { 5148f512ceSopenharmony_cibool SymbolsFile::onRecording_ = true; 5248f512ceSopenharmony_cibool SymbolsFile::needParseJsFunc_ = false; 5348f512ceSopenharmony_ci 5448f512ceSopenharmony_ciconst std::string SymbolsFile::GetBuildId() const 5548f512ceSopenharmony_ci{ 5648f512ceSopenharmony_ci return buildId_; 5748f512ceSopenharmony_ci} 5848f512ceSopenharmony_ci 5948f512ceSopenharmony_cibool SymbolsFile::UpdateBuildIdIfMatch(std::string buildId) 6048f512ceSopenharmony_ci{ 6148f512ceSopenharmony_ci /* 6248f512ceSopenharmony_ci here we have two case 6348f512ceSopenharmony_ci 1 buildId_ is empty 6448f512ceSopenharmony_ci a) always return match 6548f512ceSopenharmony_ci 2 buildId_ is not empty 6648f512ceSopenharmony_ci a) really check if the same one 6748f512ceSopenharmony_ci */ 6848f512ceSopenharmony_ci 6948f512ceSopenharmony_ci if (buildId_.empty()) { 7048f512ceSopenharmony_ci // we have new empty build 7148f512ceSopenharmony_ci if (buildId.empty()) { 7248f512ceSopenharmony_ci // both empty , no build id provided 7348f512ceSopenharmony_ci HLOGD("build id is empty."); 7448f512ceSopenharmony_ci return true; 7548f512ceSopenharmony_ci } else { 7648f512ceSopenharmony_ci buildId_ = buildId; 7748f512ceSopenharmony_ci HLOGD("new buildId %s", buildId_.c_str()); 7848f512ceSopenharmony_ci return true; 7948f512ceSopenharmony_ci } 8048f512ceSopenharmony_ci } else { 8148f512ceSopenharmony_ci // we already have a build id 8248f512ceSopenharmony_ci // so this is not the first time load symbol 8348f512ceSopenharmony_ci // we need check if it match 8448f512ceSopenharmony_ci HLOGV("expected buildid: %s vs %s", buildId_.c_str(), buildId.c_str()); 8548f512ceSopenharmony_ci 8648f512ceSopenharmony_ci if (buildId_ != buildId) { 8748f512ceSopenharmony_ci HLOGW("id not match"); 8848f512ceSopenharmony_ci return false; 8948f512ceSopenharmony_ci } else { 9048f512ceSopenharmony_ci HLOGD("id match"); 9148f512ceSopenharmony_ci return true; 9248f512ceSopenharmony_ci } 9348f512ceSopenharmony_ci } 9448f512ceSopenharmony_ci} 9548f512ceSopenharmony_ci 9648f512ceSopenharmony_cistd::string SymbolsFile::SearchReadableFile(const std::vector<std::string> &searchPaths, 9748f512ceSopenharmony_ci const std::string &filePath) const 9848f512ceSopenharmony_ci{ 9948f512ceSopenharmony_ci if (filePath.empty()) { 10048f512ceSopenharmony_ci HLOGW("nothing to found"); 10148f512ceSopenharmony_ci return filePath; 10248f512ceSopenharmony_ci } 10348f512ceSopenharmony_ci for (auto searchPath : searchPaths) { 10448f512ceSopenharmony_ci if (searchPath.back() != PATH_SEPARATOR) { 10548f512ceSopenharmony_ci searchPath += PATH_SEPARATOR; 10648f512ceSopenharmony_ci } 10748f512ceSopenharmony_ci std::string PossibleFilePath = searchPath + filePath; 10848f512ceSopenharmony_ci if (CheckPathReadable(PossibleFilePath)) { 10948f512ceSopenharmony_ci return PossibleFilePath; 11048f512ceSopenharmony_ci } 11148f512ceSopenharmony_ci HLOGW("have not found '%s' in search paths %s", filePath.c_str(), searchPath.c_str()); 11248f512ceSopenharmony_ci } 11348f512ceSopenharmony_ci return EMPTY_STRING; 11448f512ceSopenharmony_ci} 11548f512ceSopenharmony_ci 11648f512ceSopenharmony_ciconst std::string SymbolsFile::FindSymbolFile( 11748f512ceSopenharmony_ci const std::vector<std::string> &symbolsFileSearchPaths, std::string symboleFilePath) const 11848f512ceSopenharmony_ci{ 11948f512ceSopenharmony_ci /* 12048f512ceSopenharmony_ci this function do 2 things: 12148f512ceSopenharmony_ci find by name: 12248f512ceSopenharmony_ci 1 find dso path 12348f512ceSopenharmony_ci 2 find search path 12448f512ceSopenharmony_ci a) search path + dso path 12548f512ceSopenharmony_ci b) search path + dso name 12648f512ceSopenharmony_ci 12748f512ceSopenharmony_ci show we should return filePath_ as default ? 12848f512ceSopenharmony_ci */ 12948f512ceSopenharmony_ci if (symboleFilePath.empty()) { 13048f512ceSopenharmony_ci symboleFilePath = filePath_; 13148f512ceSopenharmony_ci HLOGD("use default filename: %s ", symboleFilePath.c_str()); 13248f512ceSopenharmony_ci } 13348f512ceSopenharmony_ci symboleFilePath = PlatformPathConvert(symboleFilePath); 13448f512ceSopenharmony_ci std::string foundPath; 13548f512ceSopenharmony_ci // search first if we have path 13648f512ceSopenharmony_ci if (symbolsFileSearchPaths.size() != 0) { 13748f512ceSopenharmony_ci foundPath = SearchReadableFile(symbolsFileSearchPaths, symboleFilePath); 13848f512ceSopenharmony_ci if (foundPath.empty()) { 13948f512ceSopenharmony_ci HLOGV("try base name for: %s split with %s", symboleFilePath.c_str(), 14048f512ceSopenharmony_ci PATH_SEPARATOR_STR.c_str()); 14148f512ceSopenharmony_ci auto pathSplit = StringSplit(symboleFilePath, PATH_SEPARATOR_STR); 14248f512ceSopenharmony_ci if (pathSplit.size() > 1) { 14348f512ceSopenharmony_ci HLOGV("base name is: %s ", pathSplit.back().c_str()); 14448f512ceSopenharmony_ci // found it again with base name , split it and get last name 14548f512ceSopenharmony_ci foundPath = SearchReadableFile(symbolsFileSearchPaths, pathSplit.back()); 14648f512ceSopenharmony_ci } 14748f512ceSopenharmony_ci } 14848f512ceSopenharmony_ci } 14948f512ceSopenharmony_ci 15048f512ceSopenharmony_ci // only access the patch in onRecording_ 15148f512ceSopenharmony_ci // in report mode we don't load any thing in runtime path 15248f512ceSopenharmony_ci if (foundPath.empty() and onRecording_) { 15348f512ceSopenharmony_ci // try access direct at last 15448f512ceSopenharmony_ci if (CheckPathReadable(symboleFilePath)) { 15548f512ceSopenharmony_ci // found direct folder 15648f512ceSopenharmony_ci HLOGD("find %s in current work dir", symboleFilePath.c_str()); 15748f512ceSopenharmony_ci return symboleFilePath; 15848f512ceSopenharmony_ci } 15948f512ceSopenharmony_ci } 16048f512ceSopenharmony_ci return foundPath; 16148f512ceSopenharmony_ci} 16248f512ceSopenharmony_ci 16348f512ceSopenharmony_ciclass ElfFileSymbols : public SymbolsFile { 16448f512ceSopenharmony_cipublic: 16548f512ceSopenharmony_ci explicit ElfFileSymbols(const std::string &symbolFilePath, 16648f512ceSopenharmony_ci const SymbolsFileType symbolsFileType = SYMBOL_ELF_FILE) 16748f512ceSopenharmony_ci : SymbolsFile(symbolsFileType, symbolFilePath) 16848f512ceSopenharmony_ci { 16948f512ceSopenharmony_ci } 17048f512ceSopenharmony_ci 17148f512ceSopenharmony_ci virtual ~ElfFileSymbols() 17248f512ceSopenharmony_ci { 17348f512ceSopenharmony_ci } 17448f512ceSopenharmony_ci 17548f512ceSopenharmony_ci DfxSymbol GetSymbolWithPcAndMap(uint64_t pc, std::shared_ptr<DfxMap> map) override 17648f512ceSopenharmony_ci { 17748f512ceSopenharmony_ci const DfxSymbol symbol; 17848f512ceSopenharmony_ci return symbol; 17948f512ceSopenharmony_ci } 18048f512ceSopenharmony_ci 18148f512ceSopenharmony_ci bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 18248f512ceSopenharmony_ci { 18348f512ceSopenharmony_ci symbolsLoaded_ = true; 18448f512ceSopenharmony_ci std::string findPath = FindSymbolFile(symbolsFileSearchPaths_, symbolFilePath); 18548f512ceSopenharmony_ci if (findPath.empty() && elfFile_ == nullptr) { // elf not compressed in hap has been initialized before 18648f512ceSopenharmony_ci HLOGW("elf found failed (belong to %s)", filePath_.c_str()); 18748f512ceSopenharmony_ci return false; 18848f512ceSopenharmony_ci } 18948f512ceSopenharmony_ci if (LoadElfSymbols(map, findPath)) { 19048f512ceSopenharmony_ci return true; 19148f512ceSopenharmony_ci } else { 19248f512ceSopenharmony_ci HLOGW("elf open failed with '%s'", findPath.c_str()); 19348f512ceSopenharmony_ci return false; 19448f512ceSopenharmony_ci } 19548f512ceSopenharmony_ci return false; 19648f512ceSopenharmony_ci } 19748f512ceSopenharmony_ci 19848f512ceSopenharmony_ci void EnableMiniDebugInfo() override 19948f512ceSopenharmony_ci { 20048f512ceSopenharmony_ci UnwinderConfig::SetEnableMiniDebugInfo(true); 20148f512ceSopenharmony_ci } 20248f512ceSopenharmony_ci 20348f512ceSopenharmony_ci std::shared_ptr<DfxElf> GetElfFile() override 20448f512ceSopenharmony_ci { 20548f512ceSopenharmony_ci return elfFile_; 20648f512ceSopenharmony_ci } 20748f512ceSopenharmony_ci 20848f512ceSopenharmony_ci const std::unordered_map<uint64_t, ElfLoadInfo> GetPtLoads() override 20948f512ceSopenharmony_ci { 21048f512ceSopenharmony_ci CHECK_TRUE(elfFile_ == nullptr, info_, 0, ""); 21148f512ceSopenharmony_ci return elfFile_->GetPtLoads(); 21248f512ceSopenharmony_ci } 21348f512ceSopenharmony_ci 21448f512ceSopenharmony_ciprotected: 21548f512ceSopenharmony_ci bool LoadDebugInfo(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 21648f512ceSopenharmony_ci { 21748f512ceSopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 21848f512ceSopenharmony_ci if (debugInfoLoadResult_) { 21948f512ceSopenharmony_ci return true; // it must have been loaded 22048f512ceSopenharmony_ci } else if (debugInfoLoaded_) { 22148f512ceSopenharmony_ci return debugInfoLoadResult_; // return the result of loaded 22248f512ceSopenharmony_ci } else { 22348f512ceSopenharmony_ci debugInfoLoaded_ = true; 22448f512ceSopenharmony_ci } 22548f512ceSopenharmony_ci std::string elfPath = FindSymbolFile(symbolsFileSearchPaths_, symbolFilePath); 22648f512ceSopenharmony_ci if (elfPath.empty()) { 22748f512ceSopenharmony_ci HLOGW("elf found failed (belong to %s)", filePath_.c_str()); 22848f512ceSopenharmony_ci return false; 22948f512ceSopenharmony_ci } 23048f512ceSopenharmony_ci 23148f512ceSopenharmony_ci if (elfFile_ == nullptr) { 23248f512ceSopenharmony_ci if (StringEndsWith(elfPath, ".hap")) { 23348f512ceSopenharmony_ci CHECK_TRUE(map == nullptr, false, 1, "map should not be nullptr."); 23448f512ceSopenharmony_ci elfFile_ = DfxElf::CreateFromHap(elfPath, map->prevMap, map->offset); 23548f512ceSopenharmony_ci HLOGD("try create elf from hap"); 23648f512ceSopenharmony_ci } else { 23748f512ceSopenharmony_ci elfFile_ = std::make_shared<DfxElf>(elfPath); 23848f512ceSopenharmony_ci } 23948f512ceSopenharmony_ci } 24048f512ceSopenharmony_ci 24148f512ceSopenharmony_ci CHECK_TRUE(elfFile_ == nullptr, false, 1, "Failed to create elf file for %s.", elfPath.c_str()); 24248f512ceSopenharmony_ci 24348f512ceSopenharmony_ci CHECK_TRUE(!elfFile_->IsValid(), false, 1, "parser elf file failed."); 24448f512ceSopenharmony_ci 24548f512ceSopenharmony_ci HLOGD("loaded elf %s", elfPath.c_str()); 24648f512ceSopenharmony_ci // update path for so in hap 24748f512ceSopenharmony_ci if (StringEndsWith(elfPath, ".hap")) { 24848f512ceSopenharmony_ci filePath_ = elfPath + "!" + elfFile_->GetElfName(); 24948f512ceSopenharmony_ci HLOGD("update path for so in hap %s.", filePath_.c_str()); 25048f512ceSopenharmony_ci if (map == nullptr) { 25148f512ceSopenharmony_ci HLOGW("map should not be nullptr."); 25248f512ceSopenharmony_ci return false; 25348f512ceSopenharmony_ci } 25448f512ceSopenharmony_ci map->name = filePath_; 25548f512ceSopenharmony_ci map->elf = elfFile_; 25648f512ceSopenharmony_ci map->prevMap->name = filePath_; 25748f512ceSopenharmony_ci map->prevMap->elf = elfFile_; 25848f512ceSopenharmony_ci } 25948f512ceSopenharmony_ci 26048f512ceSopenharmony_ci textExecVaddr_ = elfFile_->GetStartVaddr(); 26148f512ceSopenharmony_ci textExecVaddrFileOffset_ = elfFile_->GetStartOffset(); 26248f512ceSopenharmony_ci 26348f512ceSopenharmony_ci HLOGD("textExecVaddr_ 0x%016" PRIx64 " file offset 0x%016" PRIx64 "", textExecVaddr_, 26448f512ceSopenharmony_ci textExecVaddrFileOffset_); 26548f512ceSopenharmony_ci 26648f512ceSopenharmony_ci#ifndef __arm__ 26748f512ceSopenharmony_ci ShdrInfo shinfo; 26848f512ceSopenharmony_ci if (elfFile_->GetSectionInfo(shinfo, ".eh_frame_hdr")) { 26948f512ceSopenharmony_ci auto mmapPtr = elfFile_->GetMmapPtr(); 27048f512ceSopenharmony_ci CHECK_TRUE(mmapPtr == nullptr, false, 1, "mmapPtr should not be nullptr."); 27148f512ceSopenharmony_ci LoadEhFrameHDR(mmapPtr + shinfo.offset, shinfo.size, shinfo.offset); 27248f512ceSopenharmony_ci } 27348f512ceSopenharmony_ci#endif 27448f512ceSopenharmony_ci 27548f512ceSopenharmony_ci HLOGD("LoadDebugInfo success!"); 27648f512ceSopenharmony_ci debugInfoLoadResult_ = true; 27748f512ceSopenharmony_ci return true; 27848f512ceSopenharmony_ci } 27948f512ceSopenharmony_ci 28048f512ceSopenharmony_ciprivate: 28148f512ceSopenharmony_ci bool EhFrameHDRValid_ {false}; 28248f512ceSopenharmony_ci uint64_t ehFrameHDRElfOffset_ {0}; 28348f512ceSopenharmony_ci uint64_t ehFrameHDRFdeCount_ {0}; 28448f512ceSopenharmony_ci uint64_t ehFrameHDRFdeTableItemSize_ {0}; 28548f512ceSopenharmony_ci uint64_t ehFrameHDRFdeTableElfOffset_ {0}; 28648f512ceSopenharmony_ci std::shared_ptr<DfxElf> elfFile_; 28748f512ceSopenharmony_ci std::unordered_map<uint64_t, ElfLoadInfo> info_; 28848f512ceSopenharmony_ci 28948f512ceSopenharmony_ci bool GetSectionInfo(const std::string &name, uint64_t §ionVaddr, uint64_t §ionSize, 29048f512ceSopenharmony_ci uint64_t §ionFileOffset) const override 29148f512ceSopenharmony_ci { 29248f512ceSopenharmony_ci struct ShdrInfo shdrInfo; 29348f512ceSopenharmony_ci if (elfFile_->GetSectionInfo(shdrInfo, name)) { 29448f512ceSopenharmony_ci sectionVaddr = shdrInfo.addr; 29548f512ceSopenharmony_ci sectionSize = shdrInfo.size; 29648f512ceSopenharmony_ci sectionFileOffset = shdrInfo.offset; 29748f512ceSopenharmony_ci HLOGM("Get Section '%s' %" PRIx64 " - %" PRIx64 "", name.c_str(), sectionVaddr, sectionSize); 29848f512ceSopenharmony_ci return true; 29948f512ceSopenharmony_ci } else { 30048f512ceSopenharmony_ci HLOGW("Section '%s' not found", name.c_str()); 30148f512ceSopenharmony_ci return false; 30248f512ceSopenharmony_ci } 30348f512ceSopenharmony_ci } 30448f512ceSopenharmony_ci 30548f512ceSopenharmony_ci#ifndef __arm__ 30648f512ceSopenharmony_ci bool GetHDRSectionInfo(uint64_t &ehFrameHdrElfOffset, uint64_t &fdeTableElfOffset, 30748f512ceSopenharmony_ci uint64_t &fdeTableSize) override 30848f512ceSopenharmony_ci { 30948f512ceSopenharmony_ci CHECK_TRUE(elfFile_ == nullptr, false, 0, ""); 31048f512ceSopenharmony_ci ShdrInfo shinfo; 31148f512ceSopenharmony_ci if (!elfFile_->GetSectionInfo(shinfo, ".eh_frame_hdr")) { 31248f512ceSopenharmony_ci return false; 31348f512ceSopenharmony_ci } 31448f512ceSopenharmony_ci 31548f512ceSopenharmony_ci ehFrameHDRElfOffset_ = shinfo.offset; 31648f512ceSopenharmony_ci if (EhFrameHDRValid_) { 31748f512ceSopenharmony_ci ehFrameHdrElfOffset = ehFrameHDRElfOffset_; 31848f512ceSopenharmony_ci fdeTableElfOffset = ehFrameHDRFdeTableElfOffset_; 31948f512ceSopenharmony_ci fdeTableSize = ehFrameHDRFdeCount_; 32048f512ceSopenharmony_ci return true; 32148f512ceSopenharmony_ci } 32248f512ceSopenharmony_ci auto mmapPtr = elfFile_->GetMmapPtr(); 32348f512ceSopenharmony_ci if (mmapPtr == nullptr) { 32448f512ceSopenharmony_ci HLOGE("mmapPtr should not be nullptr."); 32548f512ceSopenharmony_ci return false; 32648f512ceSopenharmony_ci } 32748f512ceSopenharmony_ci if (!LoadEhFrameHDR(mmapPtr + shinfo.offset, elfFile_->GetMmapSize(), shinfo.offset)) { 32848f512ceSopenharmony_ci HLOGW("Failed to load eh_frame_hdr"); 32948f512ceSopenharmony_ci return false; 33048f512ceSopenharmony_ci } 33148f512ceSopenharmony_ci 33248f512ceSopenharmony_ci ehFrameHdrElfOffset = ehFrameHDRElfOffset_; 33348f512ceSopenharmony_ci fdeTableElfOffset = ehFrameHDRFdeTableElfOffset_; 33448f512ceSopenharmony_ci fdeTableSize = ehFrameHDRFdeCount_; 33548f512ceSopenharmony_ci return true; 33648f512ceSopenharmony_ci } 33748f512ceSopenharmony_ci#endif 33848f512ceSopenharmony_ci 33948f512ceSopenharmony_ci void DumpEhFrameHDR() 34048f512ceSopenharmony_ci { 34148f512ceSopenharmony_ci HLOGD(" ehFrameHDRElfOffset_: 0x%" PRIx64 "", ehFrameHDRElfOffset_); 34248f512ceSopenharmony_ci HLOGD(" ehFrameHDRFdeCount_: 0x%" PRIx64 "", ehFrameHDRFdeCount_); 34348f512ceSopenharmony_ci HLOGD(" ehFrameHDRFdeTableElfOffset_: 0x%" PRIx64 "", ehFrameHDRFdeTableElfOffset_); 34448f512ceSopenharmony_ci HLOGD(" ehFrameHDRFdeTableItemSize_: 0x%" PRIx64 "", ehFrameHDRFdeTableItemSize_); 34548f512ceSopenharmony_ci } 34648f512ceSopenharmony_ci 34748f512ceSopenharmony_ci bool LoadEhFrameHDR(const unsigned char *buffer, size_t bufferSize, uint64_t shdrOffset) 34848f512ceSopenharmony_ci { 34948f512ceSopenharmony_ci const eh_frame_hdr *ehFrameHdr = reinterpret_cast<const eh_frame_hdr *>(buffer); 35048f512ceSopenharmony_ci CHECK_TRUE(ehFrameHdr == nullptr, false, 0, ""); 35148f512ceSopenharmony_ci const uint8_t *dataPtr = ehFrameHdr->encode_data; 35248f512ceSopenharmony_ci DwarfEncoding dwEhFramePtr(ehFrameHdr->eh_frame_ptr_enc, dataPtr); 35348f512ceSopenharmony_ci DwarfEncoding dwFdeCount(ehFrameHdr->fde_count_enc, dataPtr); 35448f512ceSopenharmony_ci DwarfEncoding dwTable(ehFrameHdr->table_enc, dataPtr); 35548f512ceSopenharmony_ci DwarfEncoding dwTableValue(ehFrameHdr->table_enc, dataPtr); 35648f512ceSopenharmony_ci 35748f512ceSopenharmony_ci HLOGD("eh_frame_hdr:"); 35848f512ceSopenharmony_ci HexDump(ehFrameHdr, BITS_OF_FOUR_BYTE, bufferSize); 35948f512ceSopenharmony_ci unsigned char version = ehFrameHdr->version; 36048f512ceSopenharmony_ci HLOGD(" version: %02x:%s", version, (version == 1) ? "valid" : "invalid"); 36148f512ceSopenharmony_ci HLOGD(" eh_frame_ptr_enc: %s", dwEhFramePtr.ToString().c_str()); 36248f512ceSopenharmony_ci HLOGD(" fde_count_enc: %s", dwFdeCount.ToString().c_str()); 36348f512ceSopenharmony_ci HLOGD(" table_enc: %s", dwTable.ToString().c_str()); 36448f512ceSopenharmony_ci HLOGD(" table_value_enc: %s", dwTableValue.ToString().c_str()); 36548f512ceSopenharmony_ci HLOGD(" table_item_size: %zd", dwTable.GetSize() + dwTableValue.GetSize()); 36648f512ceSopenharmony_ci HLOGD(" table_offset_in_hdr: %zu", dwTable.GetData() - buffer); 36748f512ceSopenharmony_ci 36848f512ceSopenharmony_ci CHECK_TRUE(version != 1, false, 1, "eh_frame_hdr version is invalid"); 36948f512ceSopenharmony_ci EhFrameHDRValid_ = true; 37048f512ceSopenharmony_ci ehFrameHDRElfOffset_ = shdrOffset; 37148f512ceSopenharmony_ci ehFrameHDRFdeCount_ = dwFdeCount.GetAppliedValue(); 37248f512ceSopenharmony_ci ehFrameHDRFdeTableElfOffset_ = dwTable.GetData() - buffer + shdrOffset; 37348f512ceSopenharmony_ci ehFrameHDRFdeTableItemSize_ = dwTable.GetSize() + dwTableValue.GetSize(); 37448f512ceSopenharmony_ci DumpEhFrameHDR(); 37548f512ceSopenharmony_ci 37648f512ceSopenharmony_ci if (!dwFdeCount.IsOmit() && dwFdeCount.GetValue() > 0) { 37748f512ceSopenharmony_ci return true; 37848f512ceSopenharmony_ci } else { 37948f512ceSopenharmony_ci HLOGW("fde table not found.\n"); 38048f512ceSopenharmony_ci } 38148f512ceSopenharmony_ci return false; 38248f512ceSopenharmony_ci } 38348f512ceSopenharmony_ci 38448f512ceSopenharmony_ci void UpdateSymbols(std::vector<DfxSymbol> &symbolsTable, const std::string &elfPath) 38548f512ceSopenharmony_ci { 38648f512ceSopenharmony_ci symbols_.clear(); 38748f512ceSopenharmony_ci HLOGD("%zu symbols loadded from symbolsTable.", symbolsTable.size()); 38848f512ceSopenharmony_ci 38948f512ceSopenharmony_ci symbols_.swap(symbolsTable); 39048f512ceSopenharmony_ci 39148f512ceSopenharmony_ci AdjustSymbols(); 39248f512ceSopenharmony_ci HLOGD("%zu symbols loadded from elf '%s'.", symbols_.size(), elfPath.c_str()); 39348f512ceSopenharmony_ci for (auto& symbol: symbols_) { 39448f512ceSopenharmony_ci HLOGD("symbol %s", symbol.ToDebugString().c_str()); 39548f512ceSopenharmony_ci } 39648f512ceSopenharmony_ci if (buildId_.empty()) { 39748f512ceSopenharmony_ci HLOGD("buildId not found from elf '%s'.", elfPath.c_str()); 39848f512ceSopenharmony_ci // don't failed. some time the lib have not got the build id 39948f512ceSopenharmony_ci // buildId not found from elf '/system/bin/ld-musl-arm.so.1'. 40048f512ceSopenharmony_ci } 40148f512ceSopenharmony_ci } 40248f512ceSopenharmony_ci 40348f512ceSopenharmony_ci void AddSymbols(std::vector<DfxSymbol>& symbolsTable, std::shared_ptr<DfxElf> elf, const std::string& filePath) 40448f512ceSopenharmony_ci { 40548f512ceSopenharmony_ci // use elfFile_ to get symbolsTable 40648f512ceSopenharmony_ci DfxSymbols::ParseSymbols(symbolsTable, elf, filePath); 40748f512ceSopenharmony_ci DfxSymbols::AddSymbolsByPlt(symbolsTable, elf, filePath); 40848f512ceSopenharmony_ci } 40948f512ceSopenharmony_ci 41048f512ceSopenharmony_ci bool LoadElfSymbols(std::shared_ptr<DfxMap> map, std::string elfPath) 41148f512ceSopenharmony_ci { 41248f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 41348f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 41448f512ceSopenharmony_ci#endif 41548f512ceSopenharmony_ci if (elfFile_ == nullptr) { 41648f512ceSopenharmony_ci if (StringEndsWith(elfPath, ".hap") && map != nullptr) { 41748f512ceSopenharmony_ci elfFile_ = DfxElf::CreateFromHap(elfPath, map->prevMap, map->offset); 41848f512ceSopenharmony_ci map->elf = elfFile_; 41948f512ceSopenharmony_ci } else { 42048f512ceSopenharmony_ci elfFile_ = std::make_shared<DfxElf>(elfPath); 42148f512ceSopenharmony_ci } 42248f512ceSopenharmony_ci } 42348f512ceSopenharmony_ci CHECK_TRUE(elfFile_ == nullptr, false, 1, "Failed to create elf file for %s.", elfPath.c_str()); 42448f512ceSopenharmony_ci HLOGD("loaded elf %s", elfPath.c_str()); 42548f512ceSopenharmony_ci if (!elfFile_->IsValid()) { 42648f512ceSopenharmony_ci HLOGD("parser elf file failed."); 42748f512ceSopenharmony_ci return false; 42848f512ceSopenharmony_ci } 42948f512ceSopenharmony_ci 43048f512ceSopenharmony_ci textExecVaddr_ = elfFile_->GetStartVaddr(); 43148f512ceSopenharmony_ci textExecVaddrFileOffset_ = elfFile_->GetStartOffset(); 43248f512ceSopenharmony_ci HLOGD("textExecVaddr_ 0x%016" PRIx64 " file offset 0x%016" PRIx64 "", textExecVaddr_, 43348f512ceSopenharmony_ci textExecVaddrFileOffset_); 43448f512ceSopenharmony_ci 43548f512ceSopenharmony_ci // we prepare two table here 43648f512ceSopenharmony_ci // only one we will push in to symbols_ 43748f512ceSopenharmony_ci // or both drop if build id is not same 43848f512ceSopenharmony_ci std::string buildIdFound = elfFile_->GetBuildId(); 43948f512ceSopenharmony_ci std::vector<DfxSymbol> symbolsTable; 44048f512ceSopenharmony_ci AddSymbols(symbolsTable, elfFile_, filePath_); 44148f512ceSopenharmony_ci if (UpdateBuildIdIfMatch(buildIdFound)) { 44248f512ceSopenharmony_ci UpdateSymbols(symbolsTable, elfPath); 44348f512ceSopenharmony_ci } else { 44448f512ceSopenharmony_ci HLOGW("symbols will not update for '%s' because buildId is not match.", 44548f512ceSopenharmony_ci elfPath.c_str()); 44648f512ceSopenharmony_ci // this mean failed . we don't goon for this. 44748f512ceSopenharmony_ci return false; 44848f512ceSopenharmony_ci } 44948f512ceSopenharmony_ci 45048f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 45148f512ceSopenharmony_ci auto usedTime = duration_cast<microseconds>(steady_clock::now() - startTime); 45248f512ceSopenharmony_ci if (usedTime.count() != 0) { 45348f512ceSopenharmony_ci HLOGV("cost %0.3f ms to load symbols '%s'", 45448f512ceSopenharmony_ci usedTime.count() / static_cast<double>(milliseconds::duration::period::den), 45548f512ceSopenharmony_ci elfPath.c_str()); 45648f512ceSopenharmony_ci } 45748f512ceSopenharmony_ci#endif 45848f512ceSopenharmony_ci return true; 45948f512ceSopenharmony_ci } 46048f512ceSopenharmony_ci 46148f512ceSopenharmony_ci uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, 46248f512ceSopenharmony_ci uint64_t mapPageOffset) const override 46348f512ceSopenharmony_ci { 46448f512ceSopenharmony_ci /* 46548f512ceSopenharmony_ci 00200000-002c5000 r--p 00000000 08:02 46400311 46648f512ceSopenharmony_ci 002c5000-00490000 r-xp 000c5000 08:02 4640031 46748f512ceSopenharmony_ci 46848f512ceSopenharmony_ci [14] .text PROGBITS 00000000002c5000 000c5000 46948f512ceSopenharmony_ci 47048f512ceSopenharmony_ci if ip is 0x46e6ab 47148f512ceSopenharmony_ci 1. find the map range is 002c5000-00490000 47248f512ceSopenharmony_ci 2. ip - map start(002c5000) = map section offset 47348f512ceSopenharmony_ci 3. map section offset + map page offset(000c5000) = elf file offset 47448f512ceSopenharmony_ci 4. elf file offset - exec file offset(000c5000) 47548f512ceSopenharmony_ci = ip offset (ip always in exec file offset) 47648f512ceSopenharmony_ci 5. ip offset + exec begin vaddr(2c5000) = virtual ip in elf 47748f512ceSopenharmony_ci */ 47848f512ceSopenharmony_ci uint64_t vaddr = ip - mapStart + mapPageOffset - textExecVaddrFileOffset_ + textExecVaddr_; 47948f512ceSopenharmony_ci HLOGM(" ip :0x%016" PRIx64 " -> elf offset :0x%016" PRIx64 " -> vaddr :0x%016" PRIx64 " ", 48048f512ceSopenharmony_ci ip, ip - mapStart + mapPageOffset, vaddr); 48148f512ceSopenharmony_ci HLOGM("(minExecAddrFileOffset_ is 0x%" PRIx64 " textExecVaddr_ is 0x%" PRIx64 ")", 48248f512ceSopenharmony_ci textExecVaddrFileOffset_, textExecVaddr_); 48348f512ceSopenharmony_ci return vaddr; 48448f512ceSopenharmony_ci } 48548f512ceSopenharmony_ci}; 48648f512ceSopenharmony_ci 48748f512ceSopenharmony_ciclass KernelSymbols : public ElfFileSymbols { 48848f512ceSopenharmony_cipublic: 48948f512ceSopenharmony_ci explicit KernelSymbols(const std::string &symbolFilePath) 49048f512ceSopenharmony_ci : ElfFileSymbols(symbolFilePath, SYMBOL_KERNEL_FILE) 49148f512ceSopenharmony_ci { 49248f512ceSopenharmony_ci } 49348f512ceSopenharmony_ci 49448f512ceSopenharmony_ci KernelSymbols(const std::string &symbolFilePath, 49548f512ceSopenharmony_ci const SymbolsFileType symbolsFileType) 49648f512ceSopenharmony_ci : ElfFileSymbols(symbolFilePath, symbolsFileType) 49748f512ceSopenharmony_ci { 49848f512ceSopenharmony_ci } 49948f512ceSopenharmony_ci 50048f512ceSopenharmony_ci static constexpr const int KSYM_MIN_TOKENS = 3; 50148f512ceSopenharmony_ci static constexpr const int KSYM_DEFAULT_LINE = 35000; 50248f512ceSopenharmony_ci static constexpr const int KSYM_DEFAULT_SIZE = 1024 * 1024 * 1; // 1MB 50348f512ceSopenharmony_ci 50448f512ceSopenharmony_ci bool ParseKallsymsLine(const std::string &kallsymsPath) 50548f512ceSopenharmony_ci { 50648f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 50748f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 50848f512ceSopenharmony_ci std::chrono::microseconds parseLineTime = std::chrono::microseconds::zero(); 50948f512ceSopenharmony_ci std::chrono::microseconds sscanfTime = std::chrono::microseconds::zero(); 51048f512ceSopenharmony_ci std::chrono::microseconds newTime = std::chrono::microseconds::zero(); 51148f512ceSopenharmony_ci std::chrono::microseconds readFileTime = std::chrono::microseconds::zero(); 51248f512ceSopenharmony_ci#endif 51348f512ceSopenharmony_ci size_t lines = 0; 51448f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 51548f512ceSopenharmony_ci const auto eachFileStartTime = steady_clock::now(); 51648f512ceSopenharmony_ci#endif 51748f512ceSopenharmony_ci std::string kallsym; 51848f512ceSopenharmony_ci CHECK_TRUE(!ReadFileToString(kallsymsPath, kallsym, KSYM_DEFAULT_SIZE) || kallsym.empty(), false, 1, 51948f512ceSopenharmony_ci "%s load failed.", kallsymsPath.c_str()); 52048f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 52148f512ceSopenharmony_ci // any way we finish the line scan 52248f512ceSopenharmony_ci readFileTime += duration_cast<milliseconds>(steady_clock::now() - eachFileStartTime); 52348f512ceSopenharmony_ci#endif 52448f512ceSopenharmony_ci // reduce the mem alloc 52548f512ceSopenharmony_ci symbols_.reserve(KSYM_DEFAULT_LINE); 52648f512ceSopenharmony_ci 52748f512ceSopenharmony_ci char *lineBegin = kallsym.data(); 52848f512ceSopenharmony_ci char *dataEnd = lineBegin + kallsym.size(); 52948f512ceSopenharmony_ci while (lineBegin < dataEnd) { 53048f512ceSopenharmony_ci char *lineEnd = strchr(lineBegin, '\n'); 53148f512ceSopenharmony_ci if (lineEnd != nullptr) { 53248f512ceSopenharmony_ci *lineEnd = '\0'; 53348f512ceSopenharmony_ci } else { 53448f512ceSopenharmony_ci lineEnd = dataEnd; 53548f512ceSopenharmony_ci } 53648f512ceSopenharmony_ci size_t lineSize = (lineEnd != nullptr) ? (lineEnd - lineBegin) : (dataEnd - lineBegin); 53748f512ceSopenharmony_ci 53848f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 53948f512ceSopenharmony_ci const auto eachLineStartTime = steady_clock::now(); 54048f512ceSopenharmony_ci#endif 54148f512ceSopenharmony_ci lines++; 54248f512ceSopenharmony_ci uint64_t addr = 0; 54348f512ceSopenharmony_ci char type = '\0'; 54448f512ceSopenharmony_ci 54548f512ceSopenharmony_ci char nameRaw[lineSize]; 54648f512ceSopenharmony_ci char moduleRaw[lineSize]; 54748f512ceSopenharmony_ci int ret = sscanf_s(lineBegin, "%" PRIx64 " %c %s%s", &addr, &type, sizeof(type), 54848f512ceSopenharmony_ci nameRaw, sizeof(nameRaw), moduleRaw, sizeof(moduleRaw)); 54948f512ceSopenharmony_ci 55048f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 55148f512ceSopenharmony_ci // any way we finish the line scan 55248f512ceSopenharmony_ci sscanfTime += duration_cast<milliseconds>(steady_clock::now() - eachLineStartTime); 55348f512ceSopenharmony_ci#endif 55448f512ceSopenharmony_ci if (ret >= KSYM_MIN_TOKENS) { 55548f512ceSopenharmony_ci if (ret == KSYM_MIN_TOKENS) { 55648f512ceSopenharmony_ci moduleRaw[0] = '\0'; 55748f512ceSopenharmony_ci } 55848f512ceSopenharmony_ci HLOGM(" 0x%016" PRIx64 " %c '%s' '%s'", addr, type, nameRaw, moduleRaw); 55948f512ceSopenharmony_ci } else { 56048f512ceSopenharmony_ci HLOGW("unknown line %d: '%s'", ret, lineBegin); 56148f512ceSopenharmony_ci lineBegin = lineEnd + 1; 56248f512ceSopenharmony_ci continue; 56348f512ceSopenharmony_ci } 56448f512ceSopenharmony_ci lineBegin = lineEnd + 1; 56548f512ceSopenharmony_ci std::string name = nameRaw; 56648f512ceSopenharmony_ci std::string module = moduleRaw; 56748f512ceSopenharmony_ci 56848f512ceSopenharmony_ci /* 56948f512ceSopenharmony_ci T 57048f512ceSopenharmony_ci The symbol is in the text (code) section. 57148f512ceSopenharmony_ci 57248f512ceSopenharmony_ci W 57348f512ceSopenharmony_ci The symbol is a weak symbol that has not been specifically 57448f512ceSopenharmony_ci tagged as a weak object symbol. When a weak defined symbol is 57548f512ceSopenharmony_ci linked with a normal defined symbol, the normal defined symbol 57648f512ceSopenharmony_ci is used with no error. When a weak undefined symbol is linked 57748f512ceSopenharmony_ci and the symbol is not defined, the value of the weak symbol 57848f512ceSopenharmony_ci becomes zero with no error. 57948f512ceSopenharmony_ci */ 58048f512ceSopenharmony_ci if (addr != 0 && strchr("TtWw", type)) { 58148f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 58248f512ceSopenharmony_ci const auto eachNewSymbolTime = steady_clock::now(); 58348f512ceSopenharmony_ci#endif 58448f512ceSopenharmony_ci // we only need text symbols 58548f512ceSopenharmony_ci symbols_.emplace_back(addr, name, module.empty() ? filePath_ : module); 58648f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 58748f512ceSopenharmony_ci newTime += duration_cast<milliseconds>(steady_clock::now() - eachNewSymbolTime); 58848f512ceSopenharmony_ci#endif 58948f512ceSopenharmony_ci } 59048f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 59148f512ceSopenharmony_ci parseLineTime += duration_cast<milliseconds>(steady_clock::now() - eachLineStartTime); 59248f512ceSopenharmony_ci#endif 59348f512ceSopenharmony_ci } 59448f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_SYMBOLS_TIME 59548f512ceSopenharmony_ci std::chrono::microseconds usedTime = 59648f512ceSopenharmony_ci duration_cast<milliseconds>(steady_clock::now() - startTime); 59748f512ceSopenharmony_ci printf("parse kernel symbols use : %0.3f ms\n", usedTime.count() / MS_DURATION); 59848f512ceSopenharmony_ci printf("parse line use : %0.3f ms\n", parseLineTime.count() / MS_DURATION); 59948f512ceSopenharmony_ci printf("sscanf line use : %0.3f ms\n", sscanfTime.count() / MS_DURATION); 60048f512ceSopenharmony_ci printf("new symbols use : %0.3f ms\n", newTime.count() / MS_DURATION); 60148f512ceSopenharmony_ci printf("read file use : %0.3f ms\n", readFileTime.count() / MS_DURATION); 60248f512ceSopenharmony_ci#endif 60348f512ceSopenharmony_ci HLOGD("load %s: %zu line processed(%zu symbols)", kallsymsPath.c_str(), lines, symbols_.size()); 60448f512ceSopenharmony_ci return true; 60548f512ceSopenharmony_ci } 60648f512ceSopenharmony_ci 60748f512ceSopenharmony_ci const std::string KPTR_RESTRICT = "/proc/sys/kernel/kptr_restrict"; 60848f512ceSopenharmony_ci 60948f512ceSopenharmony_ci bool LoadKernelSyms() 61048f512ceSopenharmony_ci { 61148f512ceSopenharmony_ci if (!IsRoot()) { 61248f512ceSopenharmony_ci return false; 61348f512ceSopenharmony_ci } 61448f512ceSopenharmony_ci HLOGD("try read /proc/kallsyms"); 61548f512ceSopenharmony_ci if (access("/proc/kallsyms", R_OK) != 0) { 61648f512ceSopenharmony_ci printf("No vmlinux path is given, and kallsyms cannot be opened\n"); 61748f512ceSopenharmony_ci return false; 61848f512ceSopenharmony_ci } 61948f512ceSopenharmony_ci bool hasChangeKptr = false; 62048f512ceSopenharmony_ci std::string oldKptrRestrict = ReadFileToString(KPTR_RESTRICT); 62148f512ceSopenharmony_ci if (oldKptrRestrict.front() != '0') { 62248f512ceSopenharmony_ci printf("/proc/sys/kernel/kptr_restrict is NOT 0, will try set it to 0.\n"); 62348f512ceSopenharmony_ci hasChangeKptr = WriteStringToFile(KPTR_RESTRICT, "0"); 62448f512ceSopenharmony_ci if (!hasChangeKptr) { 62548f512ceSopenharmony_ci printf("/proc/sys/kernel/kptr_restrict write failed and we can't not change it.\n"); 62648f512ceSopenharmony_ci } 62748f512ceSopenharmony_ci } 62848f512ceSopenharmony_ci 62948f512ceSopenharmony_ci // getline end 63048f512ceSopenharmony_ci CHECK_TRUE(!ParseKallsymsLine("/proc/kallsyms"), false, 0, ""); 63148f512ceSopenharmony_ci 63248f512ceSopenharmony_ci if (hasChangeKptr) { 63348f512ceSopenharmony_ci if (!WriteStringToFile(KPTR_RESTRICT, oldKptrRestrict)) { 63448f512ceSopenharmony_ci printf("recover /proc/sys/kernel/kptr_restrict fail.\n"); 63548f512ceSopenharmony_ci } 63648f512ceSopenharmony_ci } 63748f512ceSopenharmony_ci 63848f512ceSopenharmony_ci if (symbols_.empty()) { 63948f512ceSopenharmony_ci printf("The symbol table addresses in /proc/kallsyms are all 0.\n" 64048f512ceSopenharmony_ci "Please check the value of /proc/sys/kernel/kptr_restrict, it " 64148f512ceSopenharmony_ci "should be 0.\n" 64248f512ceSopenharmony_ci "Or provide a separate vmlinux path.\n"); 64348f512ceSopenharmony_ci 64448f512ceSopenharmony_ci if (buildId_.size() != 0) { 64548f512ceSopenharmony_ci // but we got the buildid , so we make a dummpy symbols 64648f512ceSopenharmony_ci HLOGD("kallsyms not found. but we have the buildid"); 64748f512ceSopenharmony_ci return true; 64848f512ceSopenharmony_ci } else { 64948f512ceSopenharmony_ci // we got nothing 65048f512ceSopenharmony_ci return false; 65148f512ceSopenharmony_ci } 65248f512ceSopenharmony_ci } else { 65348f512ceSopenharmony_ci AdjustSymbols(); 65448f512ceSopenharmony_ci HLOGV("%zu symbols_ loadded from kallsyms.\n", symbols_.size()); 65548f512ceSopenharmony_ci return true; 65648f512ceSopenharmony_ci } 65748f512ceSopenharmony_ci } 65848f512ceSopenharmony_ci bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 65948f512ceSopenharmony_ci { 66048f512ceSopenharmony_ci symbolsLoaded_ = true; 66148f512ceSopenharmony_ci HLOGV("KernelSymbols try read '%s' search paths size %zu, inDeviceRecord %d", 66248f512ceSopenharmony_ci symbolFilePath.c_str(), symbolsFileSearchPaths_.size(), onRecording_); 66348f512ceSopenharmony_ci 66448f512ceSopenharmony_ci if (onRecording_) { 66548f512ceSopenharmony_ci const auto startTime = std::chrono::steady_clock::now(); 66648f512ceSopenharmony_ci if (!LoadKernelSyms()) { 66748f512ceSopenharmony_ci if (IsRoot()) { 66848f512ceSopenharmony_ci printf("parse kalsyms failed.\n"); 66948f512ceSopenharmony_ci } 67048f512ceSopenharmony_ci return false; 67148f512ceSopenharmony_ci } else { 67248f512ceSopenharmony_ci const auto thisTime = std::chrono::steady_clock::now(); 67348f512ceSopenharmony_ci const auto usedTimeMsTick = 67448f512ceSopenharmony_ci std::chrono::duration_cast<std::chrono::milliseconds>(thisTime - startTime); 67548f512ceSopenharmony_ci HLOGV("Load kernel symbols (total %" PRId64 " ms)\n", (int64_t)usedTimeMsTick.count()); 67648f512ceSopenharmony_ci // load complete 67748f512ceSopenharmony_ci return true; 67848f512ceSopenharmony_ci } 67948f512ceSopenharmony_ci 68048f512ceSopenharmony_ci // try read 68148f512ceSopenharmony_ci HLOGD("try read /sys/kernel/notes"); 68248f512ceSopenharmony_ci std::string notes = ReadFileToString("/sys/kernel/notes"); 68348f512ceSopenharmony_ci if (notes.empty()) { 68448f512ceSopenharmony_ci printf("notes cannot be opened, unable get buildid\n"); 68548f512ceSopenharmony_ci return false; 68648f512ceSopenharmony_ci } else { 68748f512ceSopenharmony_ci HLOGD("kernel notes size: %zu", notes.size()); 68848f512ceSopenharmony_ci buildId_ = DfxElf::GetBuildId((uint64_t)notes.data(), (uint64_t)notes.size()); 68948f512ceSopenharmony_ci } 69048f512ceSopenharmony_ci } // no search path 69148f512ceSopenharmony_ci 69248f512ceSopenharmony_ci // try vmlinux 69348f512ceSopenharmony_ci return ElfFileSymbols::LoadSymbols(nullptr, KERNEL_ELF_NAME); 69448f512ceSopenharmony_ci } 69548f512ceSopenharmony_ci uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t) const override 69648f512ceSopenharmony_ci { 69748f512ceSopenharmony_ci // ip is vaddr in /proc/kallsyms 69848f512ceSopenharmony_ci return ip; 69948f512ceSopenharmony_ci } 70048f512ceSopenharmony_ci ~KernelSymbols() override {} 70148f512ceSopenharmony_ci}; 70248f512ceSopenharmony_ci 70348f512ceSopenharmony_ciclass KernelThreadSymbols : public KernelSymbols { 70448f512ceSopenharmony_cipublic: 70548f512ceSopenharmony_ci explicit KernelThreadSymbols(const std::string &symbolFilePath) 70648f512ceSopenharmony_ci : KernelSymbols(symbolFilePath, SYMBOL_KERNEL_THREAD_FILE) 70748f512ceSopenharmony_ci { 70848f512ceSopenharmony_ci } 70948f512ceSopenharmony_ci 71048f512ceSopenharmony_ci bool LoadKernelSyms() 71148f512ceSopenharmony_ci { 71248f512ceSopenharmony_ci if (!IsRoot()) { 71348f512ceSopenharmony_ci return false; 71448f512ceSopenharmony_ci } 71548f512ceSopenharmony_ci // find real proc path by filePath_ 71648f512ceSopenharmony_ci std::string procPath; 71748f512ceSopenharmony_ci if (filePath_ == SYSMGR_FILE_NAME) { 71848f512ceSopenharmony_ci procPath = StringPrintf("/proc/%u/uallsyms", SYSMGR_PID); 71948f512ceSopenharmony_ci } else if (filePath_ == DEVHOST_FILE_NAME) { 72048f512ceSopenharmony_ci procPath = "/proc/devhost/root/kallsyms"; 72148f512ceSopenharmony_ci } 72248f512ceSopenharmony_ci HLOGD("try read kernel thread symbol file %s in %s", filePath_.c_str(), procPath.c_str()); 72348f512ceSopenharmony_ci CHECK_TRUE(access(procPath.c_str(), R_OK) != 0, false, LOG_TYPE_PRINTF, 72448f512ceSopenharmony_ci "kernel thread symbol file %s cannot be opened\n", filePath_.c_str()); 72548f512ceSopenharmony_ci bool hasChangeKptr = false; 72648f512ceSopenharmony_ci std::string oldKptrRestrict = ReadFileToString(KPTR_RESTRICT); 72748f512ceSopenharmony_ci if (oldKptrRestrict.front() != '0') { 72848f512ceSopenharmony_ci printf("/proc/sys/kernel/kptr_restrict is NOT 0, will try set it to 0.\n"); 72948f512ceSopenharmony_ci hasChangeKptr = WriteStringToFile(KPTR_RESTRICT, "0"); 73048f512ceSopenharmony_ci if (!hasChangeKptr) { 73148f512ceSopenharmony_ci printf("/proc/sys/kernel/kptr_restrict write failed and we can't not change it.\n"); 73248f512ceSopenharmony_ci } 73348f512ceSopenharmony_ci } 73448f512ceSopenharmony_ci 73548f512ceSopenharmony_ci // getline end 73648f512ceSopenharmony_ci CHECK_TRUE(!ParseKallsymsLine(procPath), false, 0, ""); 73748f512ceSopenharmony_ci 73848f512ceSopenharmony_ci if (hasChangeKptr) { 73948f512ceSopenharmony_ci if (!WriteStringToFile(KPTR_RESTRICT, oldKptrRestrict)) { 74048f512ceSopenharmony_ci printf("recover /proc/sys/kernel/kptr_restrict fail.\n"); 74148f512ceSopenharmony_ci } 74248f512ceSopenharmony_ci } 74348f512ceSopenharmony_ci 74448f512ceSopenharmony_ci if (symbols_.empty()) { 74548f512ceSopenharmony_ci printf("The symbol table addresses in %s are all 0.\n" 74648f512ceSopenharmony_ci "Please check the value of /proc/sys/kernel/kptr_restrict, it " 74748f512ceSopenharmony_ci "should be 0.\n", filePath_.c_str()); 74848f512ceSopenharmony_ci return false; 74948f512ceSopenharmony_ci } else { 75048f512ceSopenharmony_ci AdjustSymbols(); 75148f512ceSopenharmony_ci HLOGV("%zu symbols_ loadded from %s.\n", symbols_.size(), procPath.c_str()); 75248f512ceSopenharmony_ci return true; 75348f512ceSopenharmony_ci } 75448f512ceSopenharmony_ci } 75548f512ceSopenharmony_ci 75648f512ceSopenharmony_ci bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 75748f512ceSopenharmony_ci { 75848f512ceSopenharmony_ci symbolsLoaded_ = true; 75948f512ceSopenharmony_ci HLOGV("KernelThreadSymbols try read '%s', inDeviceRecord %d", 76048f512ceSopenharmony_ci filePath_.c_str(), onRecording_); 76148f512ceSopenharmony_ci 76248f512ceSopenharmony_ci if (onRecording_) { 76348f512ceSopenharmony_ci const auto startTime = std::chrono::steady_clock::now(); 76448f512ceSopenharmony_ci if (!LoadKernelSyms()) { 76548f512ceSopenharmony_ci if (IsRoot()) { 76648f512ceSopenharmony_ci printf("parse %s failed.\n", filePath_.c_str()); 76748f512ceSopenharmony_ci } 76848f512ceSopenharmony_ci } else { 76948f512ceSopenharmony_ci const auto thisTime = std::chrono::steady_clock::now(); 77048f512ceSopenharmony_ci const auto usedTimeMsTick = 77148f512ceSopenharmony_ci std::chrono::duration_cast<std::chrono::milliseconds>(thisTime - startTime); 77248f512ceSopenharmony_ci HLOGV("Load kernel thread symbols (total %" PRId64 " ms)\n", (int64_t)usedTimeMsTick.count()); 77348f512ceSopenharmony_ci // load complete 77448f512ceSopenharmony_ci return true; 77548f512ceSopenharmony_ci } 77648f512ceSopenharmony_ci } // no search path 77748f512ceSopenharmony_ci 77848f512ceSopenharmony_ci // try elf 77948f512ceSopenharmony_ci return ElfFileSymbols::LoadSymbols(nullptr, filePath_); 78048f512ceSopenharmony_ci } 78148f512ceSopenharmony_ci ~KernelThreadSymbols() override {} 78248f512ceSopenharmony_ci}; 78348f512ceSopenharmony_ci 78448f512ceSopenharmony_ciclass KernelModuleSymbols : public ElfFileSymbols { 78548f512ceSopenharmony_cipublic: 78648f512ceSopenharmony_ci explicit KernelModuleSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath) 78748f512ceSopenharmony_ci { 78848f512ceSopenharmony_ci HLOGV("create %s", symbolFilePath.c_str()); 78948f512ceSopenharmony_ci symbolFileType_ = SYMBOL_KERNEL_MODULE_FILE; 79048f512ceSopenharmony_ci module_ = symbolFilePath; 79148f512ceSopenharmony_ci } 79248f512ceSopenharmony_ci ~KernelModuleSymbols() override {}; 79348f512ceSopenharmony_ci 79448f512ceSopenharmony_ci bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 79548f512ceSopenharmony_ci { 79648f512ceSopenharmony_ci symbolsLoaded_ = true; 79748f512ceSopenharmony_ci if (module_ == filePath_ and onRecording_) { 79848f512ceSopenharmony_ci // file name still not convert to ko file path 79948f512ceSopenharmony_ci // this is in record mode 80048f512ceSopenharmony_ci HLOGV("find ko name %s", module_.c_str()); 80148f512ceSopenharmony_ci for (const std::string &path : kernelModulePaths) { 80248f512ceSopenharmony_ci if (access(path.c_str(), R_OK) == 0) { 80348f512ceSopenharmony_ci std::string koPath = path + module_ + KERNEL_MODULES_EXT_NAME; 80448f512ceSopenharmony_ci HLOGV("found ko in %s", koPath.c_str()); 80548f512ceSopenharmony_ci if (access(koPath.c_str(), R_OK) == 0) { 80648f512ceSopenharmony_ci // create symbol 80748f512ceSopenharmony_ci filePath_ = koPath; 80848f512ceSopenharmony_ci break; // find next ko 80948f512ceSopenharmony_ci } 81048f512ceSopenharmony_ci } 81148f512ceSopenharmony_ci } 81248f512ceSopenharmony_ci LoadBuildId(); 81348f512ceSopenharmony_ci } else { 81448f512ceSopenharmony_ci HLOGV("we have file path, load with %s", filePath_.c_str()); 81548f512ceSopenharmony_ci return ElfFileSymbols::LoadSymbols(nullptr, filePath_); 81648f512ceSopenharmony_ci } 81748f512ceSopenharmony_ci return false; 81848f512ceSopenharmony_ci } 81948f512ceSopenharmony_ci uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t) const override 82048f512ceSopenharmony_ci { 82148f512ceSopenharmony_ci return ip - mapStart; 82248f512ceSopenharmony_ci } 82348f512ceSopenharmony_ci 82448f512ceSopenharmony_ciprivate: 82548f512ceSopenharmony_ci bool LoadBuildId() 82648f512ceSopenharmony_ci { 82748f512ceSopenharmony_ci std::string sysFile = "/sys/module/" + module_ + "/notes/.note.gnu.build-id"; 82848f512ceSopenharmony_ci std::string buildIdRaw = ReadFileToString(sysFile); 82948f512ceSopenharmony_ci if (!buildIdRaw.empty()) { 83048f512ceSopenharmony_ci buildId_ = DfxElf::GetBuildId((uint64_t)buildIdRaw.data(), (uint64_t)buildIdRaw.size()); 83148f512ceSopenharmony_ci HLOGD("kerne module %s(%s) build id %s", module_.c_str(), filePath_.c_str(), 83248f512ceSopenharmony_ci buildId_.c_str()); 83348f512ceSopenharmony_ci return buildId_.empty() ? false : true; 83448f512ceSopenharmony_ci } 83548f512ceSopenharmony_ci return false; 83648f512ceSopenharmony_ci } 83748f512ceSopenharmony_ci 83848f512ceSopenharmony_ci const std::vector<std::string> kernelModulePaths = {"/vendor/modules/"}; 83948f512ceSopenharmony_ci std::string module_ = ""; 84048f512ceSopenharmony_ci}; 84148f512ceSopenharmony_ci 84248f512ceSopenharmony_ciclass JavaFileSymbols : public ElfFileSymbols { 84348f512ceSopenharmony_cipublic: 84448f512ceSopenharmony_ci explicit JavaFileSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath) 84548f512ceSopenharmony_ci { 84648f512ceSopenharmony_ci symbolFileType_ = SYMBOL_KERNEL_FILE; 84748f512ceSopenharmony_ci } 84848f512ceSopenharmony_ci bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 84948f512ceSopenharmony_ci { 85048f512ceSopenharmony_ci symbolsLoaded_ = true; 85148f512ceSopenharmony_ci return false; 85248f512ceSopenharmony_ci } 85348f512ceSopenharmony_ci ~JavaFileSymbols() override {} 85448f512ceSopenharmony_ci 85548f512ceSopenharmony_ci uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, 85648f512ceSopenharmony_ci uint64_t mapPageOffset) const override 85748f512ceSopenharmony_ci { 85848f512ceSopenharmony_ci // this is different with elf 85948f512ceSopenharmony_ci // elf use ip - mapStart + mapPageOffset - minExecAddrFileOffset_ + textExecVaddr_ 86048f512ceSopenharmony_ci return ip - mapStart + mapPageOffset; 86148f512ceSopenharmony_ci } 86248f512ceSopenharmony_ci}; 86348f512ceSopenharmony_ci 86448f512ceSopenharmony_ciclass JSFileSymbols : public ElfFileSymbols { 86548f512ceSopenharmony_cipublic: 86648f512ceSopenharmony_ci explicit JSFileSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath) 86748f512ceSopenharmony_ci { 86848f512ceSopenharmony_ci symbolFileType_ = SYMBOL_KERNEL_FILE; 86948f512ceSopenharmony_ci } 87048f512ceSopenharmony_ci bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 87148f512ceSopenharmony_ci { 87248f512ceSopenharmony_ci symbolsLoaded_ = true; 87348f512ceSopenharmony_ci return false; 87448f512ceSopenharmony_ci } 87548f512ceSopenharmony_ci ~JSFileSymbols() override {} 87648f512ceSopenharmony_ci}; 87748f512ceSopenharmony_ci 87848f512ceSopenharmony_ciclass HapFileSymbols : public ElfFileSymbols { 87948f512ceSopenharmony_ciprivate: 88048f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos 88148f512ceSopenharmony_ci std::unique_ptr<DfxExtractor> dfxExtractor_; 88248f512ceSopenharmony_ci bool hapExtracted_ = false; 88348f512ceSopenharmony_ci#endif 88448f512ceSopenharmony_ci std::unique_ptr<uint8_t[]> abcDataPtr_ = nullptr; 88548f512ceSopenharmony_ci [[maybe_unused]] uintptr_t loadOffSet_ = 0; 88648f512ceSopenharmony_ci [[maybe_unused]] size_t abcDataSize_ = 0; 88748f512ceSopenharmony_ci [[maybe_unused]] uintptr_t arkExtractorptr_ = 0; 88848f512ceSopenharmony_ci bool isHapAbc_ = false; 88948f512ceSopenharmony_ci pid_t pid_ = 0; 89048f512ceSopenharmony_cipublic: 89148f512ceSopenharmony_ci explicit HapFileSymbols(const std::string &symbolFilePath, pid_t pid) 89248f512ceSopenharmony_ci : ElfFileSymbols(symbolFilePath, SYMBOL_HAP_FILE) 89348f512ceSopenharmony_ci { 89448f512ceSopenharmony_ci pid_ = pid; 89548f512ceSopenharmony_ci } 89648f512ceSopenharmony_ci 89748f512ceSopenharmony_ci bool IsHapAbc() 89848f512ceSopenharmony_ci { 89948f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos 90048f512ceSopenharmony_ci if (hapExtracted_) { 90148f512ceSopenharmony_ci return isHapAbc_; 90248f512ceSopenharmony_ci } 90348f512ceSopenharmony_ci hapExtracted_ = true; 90448f512ceSopenharmony_ci HLOGD("the symbol file is %s, pid is %d.", filePath_.c_str(), pid_); 90548f512ceSopenharmony_ci if (IsRoot()) { 90648f512ceSopenharmony_ci if (IsApplicationEncryped(pid_)) { 90748f512ceSopenharmony_ci HLOGD("no need to parse js symbols"); 90848f512ceSopenharmony_ci return false; 90948f512ceSopenharmony_ci } 91048f512ceSopenharmony_ci } 91148f512ceSopenharmony_ci 91248f512ceSopenharmony_ci CHECK_TRUE(StringEndsWith(filePath_, ".hap") && map_->IsMapExec(), false, 1, 91348f512ceSopenharmony_ci "map is exec not abc file , the symbol file is:%s", map_->name.c_str()); 91448f512ceSopenharmony_ci 91548f512ceSopenharmony_ci if (StringEndsWith(filePath_, ".hap") || StringEndsWith(filePath_, ".hsp") || 91648f512ceSopenharmony_ci StringEndsWith(filePath_, ".hqf")) { 91748f512ceSopenharmony_ci dfxExtractor_ = std::make_unique<DfxExtractor>(filePath_); 91848f512ceSopenharmony_ci CHECK_TRUE(!dfxExtractor_->GetHapAbcInfo(loadOffSet_, abcDataPtr_, abcDataSize_), false, 1, 91948f512ceSopenharmony_ci "failed to call GetHapAbcInfo, the symbol file is:%s", filePath_.c_str()); 92048f512ceSopenharmony_ci HLOGD("loadOffSet %u", (uint32_t)loadOffSet_); 92148f512ceSopenharmony_ci if (abcDataPtr_ != nullptr) { 92248f512ceSopenharmony_ci isHapAbc_ = true; 92348f512ceSopenharmony_ci HLOGD("symbol file : %s, isAbc: %d", filePath_.c_str(), isHapAbc_); 92448f512ceSopenharmony_ci } 92548f512ceSopenharmony_ci } else { 92648f512ceSopenharmony_ci loadOffSet_ = map_->offset; 92748f512ceSopenharmony_ci abcDataSize_ = map_->end - map_->begin; 92848f512ceSopenharmony_ci abcDataPtr_ = std::make_unique<uint8_t[]>(abcDataSize_); 92948f512ceSopenharmony_ci auto size = DfxMemory::ReadProcMemByPid(pid_, map_->begin, abcDataPtr_.get(), map_->end - map_->begin); 93048f512ceSopenharmony_ci if (size != abcDataSize_) { 93148f512ceSopenharmony_ci HLOGD("return size is small abcDataPtr : %s, isAbc: %d", abcDataPtr_.get(), isHapAbc_); 93248f512ceSopenharmony_ci return false; 93348f512ceSopenharmony_ci } 93448f512ceSopenharmony_ci isHapAbc_ = true; 93548f512ceSopenharmony_ci HLOGD("symbol file name %s loadOffSet %u abcDataSize_ %u", 93648f512ceSopenharmony_ci filePath_.c_str(), (uint32_t)loadOffSet_, (uint32_t)abcDataSize_); 93748f512ceSopenharmony_ci } 93848f512ceSopenharmony_ci auto ret = DfxArk::ArkCreateJsSymbolExtractor(&arkExtractorptr_); 93948f512ceSopenharmony_ci if (ret < 0) { 94048f512ceSopenharmony_ci arkExtractorptr_ = 0; 94148f512ceSopenharmony_ci HLOGE("failed to call ArkCreateJsSymbolExtractor, the symbol file is:%s", filePath_.c_str()); 94248f512ceSopenharmony_ci } 94348f512ceSopenharmony_ci#endif 94448f512ceSopenharmony_ci return isHapAbc_; 94548f512ceSopenharmony_ci } 94648f512ceSopenharmony_ci 94748f512ceSopenharmony_ci bool IsAbc() override 94848f512ceSopenharmony_ci { 94948f512ceSopenharmony_ci return isHapAbc_ == true; 95048f512ceSopenharmony_ci } 95148f512ceSopenharmony_ci 95248f512ceSopenharmony_ci void SetBoolValue(bool value) override 95348f512ceSopenharmony_ci { 95448f512ceSopenharmony_ci isHapAbc_ = value; 95548f512ceSopenharmony_ci } 95648f512ceSopenharmony_ci 95748f512ceSopenharmony_ci bool LoadDebugInfo(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 95848f512ceSopenharmony_ci { 95948f512ceSopenharmony_ci HLOGD("map ptr:%p, map name:%s", map.get(), map->name.c_str()); 96048f512ceSopenharmony_ci if (debugInfoLoaded_) { 96148f512ceSopenharmony_ci return true; 96248f512ceSopenharmony_ci } 96348f512ceSopenharmony_ci CHECK_TRUE(!onRecording_, true, 0, ""); 96448f512ceSopenharmony_ci 96548f512ceSopenharmony_ci if (!IsHapAbc()) { 96648f512ceSopenharmony_ci ElfFileSymbols::LoadDebugInfo(map, ""); 96748f512ceSopenharmony_ci } 96848f512ceSopenharmony_ci debugInfoLoaded_ = true; 96948f512ceSopenharmony_ci debugInfoLoadResult_ = true; 97048f512ceSopenharmony_ci return true; 97148f512ceSopenharmony_ci } 97248f512ceSopenharmony_ci 97348f512ceSopenharmony_ci bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 97448f512ceSopenharmony_ci { 97548f512ceSopenharmony_ci HLOGD("map ptr:%p, map name:%s", map.get(), map->name.c_str()); 97648f512ceSopenharmony_ci CHECK_TRUE(symbolsLoaded_ || !onRecording_, true, 0, ""); 97748f512ceSopenharmony_ci symbolsLoaded_ = true; 97848f512ceSopenharmony_ci if (!IsHapAbc()) { 97948f512ceSopenharmony_ci ElfFileSymbols::LoadSymbols(map, ""); 98048f512ceSopenharmony_ci } 98148f512ceSopenharmony_ci return true; 98248f512ceSopenharmony_ci } 98348f512ceSopenharmony_ci 98448f512ceSopenharmony_ci DfxSymbol GetSymbolWithPcAndMap(uint64_t ip, std::shared_ptr<DfxMap> map) override 98548f512ceSopenharmony_ci { 98648f512ceSopenharmony_ci // get cache 98748f512ceSopenharmony_ci auto iter = symbolsMap_.find(ip); 98848f512ceSopenharmony_ci if (iter != symbolsMap_.end()) { 98948f512ceSopenharmony_ci return iter->second; 99048f512ceSopenharmony_ci } 99148f512ceSopenharmony_ci if (map == nullptr) { 99248f512ceSopenharmony_ci return DfxSymbol(ip, ""); 99348f512ceSopenharmony_ci } 99448f512ceSopenharmony_ci HLOGD("map ptr:%p, map name:%s", map.get(), map->name.c_str()); 99548f512ceSopenharmony_ci 99648f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos 99748f512ceSopenharmony_ci if (IsAbc() && needParseJsFunc_) { 99848f512ceSopenharmony_ci JsFunction jsFunc; 99948f512ceSopenharmony_ci std::string module = map->name; 100048f512ceSopenharmony_ci HLOGD("map->name module:%s", module.c_str()); 100148f512ceSopenharmony_ci auto ret = DfxArk::ParseArkFrameInfo(static_cast<uintptr_t>(ip), static_cast<uintptr_t>(map->begin), 100248f512ceSopenharmony_ci loadOffSet_, abcDataPtr_.get(), abcDataSize_, 100348f512ceSopenharmony_ci arkExtractorptr_, &jsFunc); 100448f512ceSopenharmony_ci if (ret == -1) { 100548f512ceSopenharmony_ci HLOGD("failed to call ParseArkFrameInfo, the symbol file is : %s", map->name.c_str()); 100648f512ceSopenharmony_ci return DfxSymbol(ip, ""); 100748f512ceSopenharmony_ci } 100848f512ceSopenharmony_ci this->symbolsMap_.insert(std::make_pair(ip, 100948f512ceSopenharmony_ci DfxSymbol(ip, 101048f512ceSopenharmony_ci jsFunc.codeBegin, 101148f512ceSopenharmony_ci jsFunc.functionName, 101248f512ceSopenharmony_ci jsFunc.ToString(), 101348f512ceSopenharmony_ci map->name))); 101448f512ceSopenharmony_ci 101548f512ceSopenharmony_ci DfxSymbol &foundSymbol = symbolsMap_[ip]; 101648f512ceSopenharmony_ci if (!foundSymbol.matched_) { 101748f512ceSopenharmony_ci foundSymbol.matched_ = true; 101848f512ceSopenharmony_ci foundSymbol.symbolFileIndex_ = id_; 101948f512ceSopenharmony_ci matchedSymbols_.push_back(&(symbolsMap_[ip])); 102048f512ceSopenharmony_ci } 102148f512ceSopenharmony_ci 102248f512ceSopenharmony_ci HLOGD("ip : 0x%" PRIx64 " the symbol file is : %s, function is %s demangle_ : %s", ip, 102348f512ceSopenharmony_ci symbolsMap_[ip].module_.data(), jsFunc.functionName, matchedSymbols_.back()->demangle_.data()); 102448f512ceSopenharmony_ci return symbolsMap_[ip]; 102548f512ceSopenharmony_ci } 102648f512ceSopenharmony_ci#endif 102748f512ceSopenharmony_ci DfxSymbol symbol(ip, ""); 102848f512ceSopenharmony_ci return symbol; 102948f512ceSopenharmony_ci } 103048f512ceSopenharmony_ci}; 103148f512ceSopenharmony_ci 103248f512ceSopenharmony_ciclass UnknowFileSymbols : public SymbolsFile { 103348f512ceSopenharmony_cipublic: 103448f512ceSopenharmony_ci explicit UnknowFileSymbols(const std::string &symbolFilePath) 103548f512ceSopenharmony_ci : SymbolsFile(SYMBOL_UNKNOW_FILE, symbolFilePath) 103648f512ceSopenharmony_ci { 103748f512ceSopenharmony_ci } 103848f512ceSopenharmony_ci bool LoadSymbols(std::shared_ptr<DfxMap> map, const std::string &symbolFilePath) override 103948f512ceSopenharmony_ci { 104048f512ceSopenharmony_ci symbolsLoaded_ = true; 104148f512ceSopenharmony_ci return false; 104248f512ceSopenharmony_ci } 104348f512ceSopenharmony_ci ~UnknowFileSymbols() override {} 104448f512ceSopenharmony_ci}; 104548f512ceSopenharmony_ci 104648f512ceSopenharmony_ciSymbolsFile::~SymbolsFile() {} 104748f512ceSopenharmony_ci 104848f512ceSopenharmony_cistd::unique_ptr<SymbolsFile> SymbolsFile::CreateSymbolsFile(SymbolsFileType symbolType, 104948f512ceSopenharmony_ci const std::string symbolFilePath, pid_t pid) 105048f512ceSopenharmony_ci{ 105148f512ceSopenharmony_ci switch (symbolType) { 105248f512ceSopenharmony_ci case SYMBOL_KERNEL_FILE: 105348f512ceSopenharmony_ci return std::make_unique<KernelSymbols>(symbolFilePath.empty() ? KERNEL_MMAP_NAME 105448f512ceSopenharmony_ci : symbolFilePath); 105548f512ceSopenharmony_ci case SYMBOL_KERNEL_MODULE_FILE: 105648f512ceSopenharmony_ci return std::make_unique<KernelModuleSymbols>(symbolFilePath); 105748f512ceSopenharmony_ci case SYMBOL_KERNEL_THREAD_FILE: 105848f512ceSopenharmony_ci return std::make_unique<KernelThreadSymbols>(symbolFilePath); 105948f512ceSopenharmony_ci case SYMBOL_ELF_FILE: 106048f512ceSopenharmony_ci return std::make_unique<ElfFileSymbols>(symbolFilePath); 106148f512ceSopenharmony_ci case SYMBOL_JAVA_FILE: 106248f512ceSopenharmony_ci return std::make_unique<JavaFileSymbols>(symbolFilePath); 106348f512ceSopenharmony_ci case SYMBOL_JS_FILE: 106448f512ceSopenharmony_ci return std::make_unique<JSFileSymbols>(symbolFilePath); 106548f512ceSopenharmony_ci case SYMBOL_HAP_FILE: 106648f512ceSopenharmony_ci return std::make_unique<HapFileSymbols>(symbolFilePath, pid); 106748f512ceSopenharmony_ci default: 106848f512ceSopenharmony_ci return std::make_unique<SymbolsFile>(SYMBOL_UNKNOW_FILE, symbolFilePath); 106948f512ceSopenharmony_ci } 107048f512ceSopenharmony_ci} 107148f512ceSopenharmony_ci 107248f512ceSopenharmony_cistd::unique_ptr<SymbolsFile> SymbolsFile::CreateSymbolsFile(const std::string &symbolFilePath, pid_t pid) 107348f512ceSopenharmony_ci{ 107448f512ceSopenharmony_ci // we need check file name here 107548f512ceSopenharmony_ci if (symbolFilePath == KERNEL_MMAP_NAME) { 107648f512ceSopenharmony_ci return SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE, symbolFilePath); 107748f512ceSopenharmony_ci } else if (symbolFilePath == SYSMGR_FILE_NAME || 107848f512ceSopenharmony_ci symbolFilePath == DEVHOST_LINUX_FILE_NAME || 107948f512ceSopenharmony_ci StringStartsWith(symbolFilePath, DEVHOST_LINUX_PREFIX)) { 108048f512ceSopenharmony_ci return SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_THREAD_FILE, symbolFilePath); 108148f512ceSopenharmony_ci } else if (StringEndsWith(symbolFilePath, KERNEL_MODULES_EXT_NAME)) { 108248f512ceSopenharmony_ci return SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_MODULE_FILE, symbolFilePath); 108348f512ceSopenharmony_ci } else if (IsArkJsFile(symbolFilePath)) { 108448f512ceSopenharmony_ci return SymbolsFile::CreateSymbolsFile(SYMBOL_HAP_FILE, symbolFilePath, pid); 108548f512ceSopenharmony_ci } else { 108648f512ceSopenharmony_ci // default is elf, this may be problematic in the future. 108748f512ceSopenharmony_ci return SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, symbolFilePath); 108848f512ceSopenharmony_ci } 108948f512ceSopenharmony_ci} 109048f512ceSopenharmony_ci 109148f512ceSopenharmony_civoid SymbolsFile::AdjustSymbols() 109248f512ceSopenharmony_ci{ 109348f512ceSopenharmony_ci if (symbols_.size() <= 0) { 109448f512ceSopenharmony_ci return; 109548f512ceSopenharmony_ci } 109648f512ceSopenharmony_ci 109748f512ceSopenharmony_ci // order 109848f512ceSopenharmony_ci sort(symbols_.begin(), symbols_.end(), [](const DfxSymbol& a, const DfxSymbol& b) { 109948f512ceSopenharmony_ci return a.funcVaddr_ < b.funcVaddr_; 110048f512ceSopenharmony_ci }); 110148f512ceSopenharmony_ci HLOGV("sort completed"); 110248f512ceSopenharmony_ci 110348f512ceSopenharmony_ci size_t fullSize = symbols_.size(); 110448f512ceSopenharmony_ci size_t erased = 0; 110548f512ceSopenharmony_ci 110648f512ceSopenharmony_ci // Check for duplicate vaddr 110748f512ceSopenharmony_ci auto last = std::unique(symbols_.begin(), symbols_.end(), [](const DfxSymbol &a, const DfxSymbol &b) { 110848f512ceSopenharmony_ci return (a.funcVaddr_ == b.funcVaddr_); 110948f512ceSopenharmony_ci }); 111048f512ceSopenharmony_ci symbols_.erase(last, symbols_.end()); 111148f512ceSopenharmony_ci erased = fullSize - symbols_.size(); 111248f512ceSopenharmony_ci HLOGV("uniqued completed"); 111348f512ceSopenharmony_ci auto it = symbols_.begin(); 111448f512ceSopenharmony_ci while (it != symbols_.end()) { 111548f512ceSopenharmony_ci it->index_ = it - symbols_.begin(); 111648f512ceSopenharmony_ci it++; 111748f512ceSopenharmony_ci } 111848f512ceSopenharmony_ci HLOGV("indexed completed"); 111948f512ceSopenharmony_ci 112048f512ceSopenharmony_ci HLOG_ASSERT(symbols_.size() != 0); 112148f512ceSopenharmony_ci 112248f512ceSopenharmony_ci if (textExecVaddrRange_ == maxVaddr) { 112348f512ceSopenharmony_ci textExecVaddrRange_ = symbols_.back().funcVaddr_ - symbols_.front().funcVaddr_; 112448f512ceSopenharmony_ci } 112548f512ceSopenharmony_ci 112648f512ceSopenharmony_ci HLOGDDD("%zu symbols after adjust (%zu erased) 0x%016" PRIx64 " - 0x%016" PRIx64 112748f512ceSopenharmony_ci " @0x%016" PRIx64 " ", 112848f512ceSopenharmony_ci symbols_.size(), erased, symbols_.front().funcVaddr_, symbols_.back().funcVaddr_, 112948f512ceSopenharmony_ci textExecVaddrFileOffset_); 113048f512ceSopenharmony_ci} 113148f512ceSopenharmony_ci 113248f512ceSopenharmony_civoid SymbolsFile::SortMatchedSymbols() 113348f512ceSopenharmony_ci{ 113448f512ceSopenharmony_ci if (matchedSymbols_.size() <= 1u) { 113548f512ceSopenharmony_ci return; 113648f512ceSopenharmony_ci } 113748f512ceSopenharmony_ci sort(matchedSymbols_.begin(), matchedSymbols_.end(), [](const DfxSymbol* a, const DfxSymbol* b) { 113848f512ceSopenharmony_ci if (a == nullptr || b == nullptr) { 113948f512ceSopenharmony_ci return true; 114048f512ceSopenharmony_ci } 114148f512ceSopenharmony_ci return a->funcVaddr_ < b->funcVaddr_; 114248f512ceSopenharmony_ci }); 114348f512ceSopenharmony_ci} 114448f512ceSopenharmony_ci 114548f512ceSopenharmony_ciconst std::vector<DfxSymbol> &SymbolsFile::GetSymbols() 114648f512ceSopenharmony_ci{ 114748f512ceSopenharmony_ci return symbols_; 114848f512ceSopenharmony_ci} 114948f512ceSopenharmony_ci 115048f512ceSopenharmony_ciconst std::vector<DfxSymbol *> &SymbolsFile::GetMatchedSymbols() 115148f512ceSopenharmony_ci{ 115248f512ceSopenharmony_ci return matchedSymbols_; 115348f512ceSopenharmony_ci} 115448f512ceSopenharmony_ci 115548f512ceSopenharmony_ciconst DfxSymbol SymbolsFile::GetSymbolWithVaddr(uint64_t vaddrInFile) 115648f512ceSopenharmony_ci{ 115748f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 115848f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 115948f512ceSopenharmony_ci#endif 116048f512ceSopenharmony_ci DfxSymbol symbol; 116148f512ceSopenharmony_ci // it should be already order from small to large 116248f512ceSopenharmony_ci auto found = 116348f512ceSopenharmony_ci std::upper_bound(symbols_.begin(), symbols_.end(), vaddrInFile, DfxSymbol::ValueLessThen); 116448f512ceSopenharmony_ci /* 116548f512ceSopenharmony_ci if data is { 1, 2, 4, 5, 5, 6 }; 116648f512ceSopenharmony_ci upper_bound for each val : 116748f512ceSopenharmony_ci 0 < 1 at index 0 116848f512ceSopenharmony_ci 1 < 2 at index 1 116948f512ceSopenharmony_ci 2 < 4 at index 2 117048f512ceSopenharmony_ci 3 < 4 at index 2 117148f512ceSopenharmony_ci 4 < 5 at index 3 117248f512ceSopenharmony_ci 5 < 6 at index 5 117348f512ceSopenharmony_ci 6 < not found 117448f512ceSopenharmony_ci if key symbol vaddr is { 1, 2, 4, 5, 5, 6 }; 117548f512ceSopenharmony_ci check ip vaddr for each val : 117648f512ceSopenharmony_ci ip sym 117748f512ceSopenharmony_ci 0 not found 117848f512ceSopenharmony_ci 1 1 117948f512ceSopenharmony_ci 1 1 118048f512ceSopenharmony_ci 2 2 118148f512ceSopenharmony_ci 3 3 118248f512ceSopenharmony_ci 4 4 118348f512ceSopenharmony_ci 5 5 118448f512ceSopenharmony_ci 6 6 118548f512ceSopenharmony_ci 7 7 118648f512ceSopenharmony_ci */ 118748f512ceSopenharmony_ci if (found != symbols_.begin()) { 118848f512ceSopenharmony_ci found = std::prev(found); 118948f512ceSopenharmony_ci if (found != symbols_.end()) { 119048f512ceSopenharmony_ci if (found->Contain(vaddrInFile)) { 119148f512ceSopenharmony_ci found->offsetToVaddr_ = vaddrInFile - found->funcVaddr_; 119248f512ceSopenharmony_ci if (!found->matched_) { 119348f512ceSopenharmony_ci found->matched_ = true; 119448f512ceSopenharmony_ci matchedSymbols_.push_back(&(*found)); 119548f512ceSopenharmony_ci } 119648f512ceSopenharmony_ci symbol = *found; // copy 119748f512ceSopenharmony_ci HLOGV("found '%s' for vaddr 0x%016" PRIx64 "", symbol.ToString().c_str(), vaddrInFile); 119848f512ceSopenharmony_ci } 119948f512ceSopenharmony_ci } 120048f512ceSopenharmony_ci } 120148f512ceSopenharmony_ci 120248f512ceSopenharmony_ci if (!symbol.IsValid()) { 120348f512ceSopenharmony_ci HLOGV("NOT found vaddr 0x%" PRIx64 " in symbole file %s(%zu)", vaddrInFile, 120448f512ceSopenharmony_ci filePath_.c_str(), symbols_.size()); 120548f512ceSopenharmony_ci } 120648f512ceSopenharmony_ci symbol.fileVaddr_ = vaddrInFile; 120748f512ceSopenharmony_ci symbol.symbolFileIndex_ = id_; 120848f512ceSopenharmony_ci 120948f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 121048f512ceSopenharmony_ci auto usedTime = duration_cast<milliseconds>(steady_clock::now() - startTime); 121148f512ceSopenharmony_ci if (usedTime > 1ms) { 121248f512ceSopenharmony_ci HLOGW("cost %" PRId64 "ms to search ", usedTime.count()); 121348f512ceSopenharmony_ci } 121448f512ceSopenharmony_ci#endif 121548f512ceSopenharmony_ci return symbol; 121648f512ceSopenharmony_ci} 121748f512ceSopenharmony_ci 121848f512ceSopenharmony_cibool SymbolsFile::CheckPathReadable(const std::string &path) const 121948f512ceSopenharmony_ci{ 122048f512ceSopenharmony_ci if (access(path.c_str(), R_OK) == 0) { 122148f512ceSopenharmony_ci return true; 122248f512ceSopenharmony_ci } else { 122348f512ceSopenharmony_ci HLOGM("'%s' is unable read", path.c_str()); 122448f512ceSopenharmony_ci return false; 122548f512ceSopenharmony_ci } 122648f512ceSopenharmony_ci} 122748f512ceSopenharmony_ci 122848f512ceSopenharmony_cibool SymbolsFile::setSymbolsFilePath(const std::vector<std::string> &symbolsSearchPaths) 122948f512ceSopenharmony_ci{ 123048f512ceSopenharmony_ci symbolsFileSearchPaths_.clear(); 123148f512ceSopenharmony_ci for (auto &symbolsSearchPath : symbolsSearchPaths) { 123248f512ceSopenharmony_ci if (CheckPathReadable(symbolsSearchPath)) { 123348f512ceSopenharmony_ci symbolsFileSearchPaths_.emplace_back(symbolsSearchPath); 123448f512ceSopenharmony_ci HLOGV("'%s' is add to symbolsSearchPath", symbolsSearchPath.c_str()); 123548f512ceSopenharmony_ci } 123648f512ceSopenharmony_ci } 123748f512ceSopenharmony_ci return (symbolsFileSearchPaths_.size() > 0); 123848f512ceSopenharmony_ci} 123948f512ceSopenharmony_ci 124048f512ceSopenharmony_cistd::unique_ptr<SymbolsFile> SymbolsFile::LoadSymbolsFromSaved( 124148f512ceSopenharmony_ci const SymbolFileStruct &symbolFileStruct) 124248f512ceSopenharmony_ci{ 124348f512ceSopenharmony_ci bool isHapSymbolFile = static_cast<SymbolsFileType>(symbolFileStruct.symbolType_) == SYMBOL_HAP_FILE; 124448f512ceSopenharmony_ci HLOGD("isHapSymbolFile : %d", isHapSymbolFile); 124548f512ceSopenharmony_ci auto symbolsFile = CreateSymbolsFile(symbolFileStruct.filePath_); 124648f512ceSopenharmony_ci 124748f512ceSopenharmony_ci // default create elf file. but hap file need special operation. 124848f512ceSopenharmony_ci symbolsFile->filePath_ = symbolFileStruct.filePath_; 124948f512ceSopenharmony_ci symbolsFile->symbolFileType_ = static_cast<SymbolsFileType>(symbolFileStruct.symbolType_); 125048f512ceSopenharmony_ci symbolsFile->textExecVaddr_ = symbolFileStruct.textExecVaddr_; 125148f512ceSopenharmony_ci symbolsFile->textExecVaddrFileOffset_ = symbolFileStruct.textExecVaddrFileOffset_; 125248f512ceSopenharmony_ci symbolsFile->buildId_ = symbolFileStruct.buildId_; 125348f512ceSopenharmony_ci for (auto &symbolStruct : symbolFileStruct.symbolStructs_) { 125448f512ceSopenharmony_ci symbolsFile->symbols_.emplace_back(symbolStruct.vaddr_, symbolStruct.len_, 125548f512ceSopenharmony_ci symbolStruct.symbolName_, symbolFileStruct.filePath_); 125648f512ceSopenharmony_ci } 125748f512ceSopenharmony_ci symbolsFile->AdjustSymbols(); // reorder 125848f512ceSopenharmony_ci if (isHapSymbolFile) { 125948f512ceSopenharmony_ci for (const auto& symbol : symbolsFile->symbols_) { 126048f512ceSopenharmony_ci symbolsFile->symbolsMap_.emplace(symbol.funcVaddr_, symbol); 126148f512ceSopenharmony_ci } 126248f512ceSopenharmony_ci symbolsFile->SetBoolValue(true); 126348f512ceSopenharmony_ci } 126448f512ceSopenharmony_ci symbolsFile->debugInfoLoadResult_ = true; 126548f512ceSopenharmony_ci symbolsFile->symbolsLoaded_ = true; // all ready LoadFrom perf.data 126648f512ceSopenharmony_ci HLOGV("load %zu symbol from SymbolFileStruct for file '%s'", symbolsFile->symbols_.size(), 126748f512ceSopenharmony_ci symbolsFile->filePath_.c_str()); 126848f512ceSopenharmony_ci return symbolsFile; 126948f512ceSopenharmony_ci} 127048f512ceSopenharmony_ci 127148f512ceSopenharmony_civoid SymbolsFile::SetBoolValue(bool value) 127248f512ceSopenharmony_ci{ 127348f512ceSopenharmony_ci} 127448f512ceSopenharmony_ci 127548f512ceSopenharmony_civoid SymbolsFile::ExportSymbolToFileFormat(SymbolFileStruct &symbolFileStruct) 127648f512ceSopenharmony_ci{ 127748f512ceSopenharmony_ci symbolFileStruct.filePath_ = filePath_; 127848f512ceSopenharmony_ci symbolFileStruct.symbolType_ = symbolFileType_; 127948f512ceSopenharmony_ci symbolFileStruct.textExecVaddr_ = textExecVaddr_; 128048f512ceSopenharmony_ci symbolFileStruct.textExecVaddrFileOffset_ = textExecVaddrFileOffset_; 128148f512ceSopenharmony_ci symbolFileStruct.buildId_ = buildId_; 128248f512ceSopenharmony_ci 128348f512ceSopenharmony_ci SortMatchedSymbols(); 128448f512ceSopenharmony_ci auto symbols = GetMatchedSymbols(); 128548f512ceSopenharmony_ci symbolFileStruct.symbolStructs_.reserve(symbols.size()); 128648f512ceSopenharmony_ci for (const auto symbol : symbols) { 128748f512ceSopenharmony_ci auto &symbolStruct = symbolFileStruct.symbolStructs_.emplace_back(); 128848f512ceSopenharmony_ci symbolStruct.vaddr_ = symbol->funcVaddr_; 128948f512ceSopenharmony_ci symbolStruct.len_ = symbol->size_; 129048f512ceSopenharmony_ci symbolStruct.symbolName_ = symbol->GetName(); 129148f512ceSopenharmony_ci } 129248f512ceSopenharmony_ci 129348f512ceSopenharmony_ci HLOGV("export %zu symbol to SymbolFileStruct from %s", symbolFileStruct.symbolStructs_.size(), 129448f512ceSopenharmony_ci filePath_.c_str()); 129548f512ceSopenharmony_ci} 129648f512ceSopenharmony_ci 129748f512ceSopenharmony_ciuint64_t SymbolsFile::GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t mapOffset) const 129848f512ceSopenharmony_ci{ 129948f512ceSopenharmony_ci // no convert 130048f512ceSopenharmony_ci return ip; 130148f512ceSopenharmony_ci} 130248f512ceSopenharmony_ci 130348f512ceSopenharmony_civoid SymbolsFile::AddSymbol(DfxSymbol symbol) 130448f512ceSopenharmony_ci{ 130548f512ceSopenharmony_ci symbolsLoaded_ = true; 130648f512ceSopenharmony_ci symbols_.emplace_back(symbol); 130748f512ceSopenharmony_ci} 130848f512ceSopenharmony_ci} // namespace HiPerf 130948f512ceSopenharmony_ci} // namespace Developtools 131048f512ceSopenharmony_ci} // namespace OHOS 1311