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#define HILOG_TAG "Runtime" 1648f512ceSopenharmony_ci 1748f512ceSopenharmony_ci#include "virtual_runtime.h" 1848f512ceSopenharmony_ci 1948f512ceSopenharmony_ci#include <cinttypes> 2048f512ceSopenharmony_ci#include <iostream> 2148f512ceSopenharmony_ci#include <sstream> 2248f512ceSopenharmony_ci#include <unistd.h> 2348f512ceSopenharmony_ci#if !is_mingw 2448f512ceSopenharmony_ci#include <sys/mman.h> 2548f512ceSopenharmony_ci#endif 2648f512ceSopenharmony_ci 2748f512ceSopenharmony_ci#include "dfx_map.h" 2848f512ceSopenharmony_ci#include "hiperf_hilog.h" 2948f512ceSopenharmony_ci#include "register.h" 3048f512ceSopenharmony_ci#include "spe_decoder.h" 3148f512ceSopenharmony_ci#include "symbols_file.h" 3248f512ceSopenharmony_ci#include "utilities.h" 3348f512ceSopenharmony_ci 3448f512ceSopenharmony_ciusing namespace std::chrono; 3548f512ceSopenharmony_cinamespace OHOS { 3648f512ceSopenharmony_cinamespace Developtools { 3748f512ceSopenharmony_cinamespace HiPerf { 3848f512ceSopenharmony_cinamespace { 3948f512ceSopenharmony_ci// if ip is 0 , 1 both not useful 4048f512ceSopenharmony_ciconst uint64_t BAD_IP_ADDRESS = 2; 4148f512ceSopenharmony_ci} 4248f512ceSopenharmony_ci// we unable to access 'swapper' from /proc/0/ 4348f512ceSopenharmony_ciVirtualRuntime::VirtualRuntime(bool onDevice) 4448f512ceSopenharmony_ci{ 4548f512ceSopenharmony_ci UpdateThread(0, 0, "swapper"); 4648f512ceSopenharmony_ci} 4748f512ceSopenharmony_ci 4848f512ceSopenharmony_ciVirtualRuntime::~VirtualRuntime() 4948f512ceSopenharmony_ci{ 5048f512ceSopenharmony_ci if (savedCmdLines_.is_open()) { 5148f512ceSopenharmony_ci savedCmdLines_.close(); 5248f512ceSopenharmony_ci } 5348f512ceSopenharmony_ci} 5448f512ceSopenharmony_ci 5548f512ceSopenharmony_cistd::string VirtualRuntime::ReadFromSavedCmdLines(pid_t tid) 5648f512ceSopenharmony_ci{ 5748f512ceSopenharmony_ci if (!savedCmdLines_.is_open()) { 5848f512ceSopenharmony_ci savedCmdLines_.open(SAVED_CMDLINES, std::ios::in); 5948f512ceSopenharmony_ci } 6048f512ceSopenharmony_ci if (!savedCmdLines_.is_open()) { 6148f512ceSopenharmony_ci return EMPTY_STRING; 6248f512ceSopenharmony_ci } 6348f512ceSopenharmony_ci savedCmdLines_.seekg(0, std::ios::beg); 6448f512ceSopenharmony_ci std::string line; 6548f512ceSopenharmony_ci std::string threadid = std::to_string(tid); 6648f512ceSopenharmony_ci while (getline(savedCmdLines_, line)) { 6748f512ceSopenharmony_ci if (line.find(threadid) != std::string::npos) { 6848f512ceSopenharmony_ci constexpr size_t sizeLimit {2}; 6948f512ceSopenharmony_ci std::vector<std::string> linesToken = StringSplit(line, " "); 7048f512ceSopenharmony_ci if (linesToken.size() < sizeLimit) { 7148f512ceSopenharmony_ci return EMPTY_STRING; 7248f512ceSopenharmony_ci } 7348f512ceSopenharmony_ci if (threadid != linesToken[0]) { 7448f512ceSopenharmony_ci continue; 7548f512ceSopenharmony_ci } 7648f512ceSopenharmony_ci return linesToken[1]; 7748f512ceSopenharmony_ci } 7848f512ceSopenharmony_ci } 7948f512ceSopenharmony_ci return EMPTY_STRING; 8048f512ceSopenharmony_ci} 8148f512ceSopenharmony_ci 8248f512ceSopenharmony_cistd::string VirtualRuntime::ReadThreadName(pid_t tid, bool isThread) 8348f512ceSopenharmony_ci{ 8448f512ceSopenharmony_ci std::string comm = ""; 8548f512ceSopenharmony_ci if (tid == SYSMGR_PID) { 8648f512ceSopenharmony_ci comm = SYSMGR_NAME; 8748f512ceSopenharmony_ci } else if (tid == devhostPid_) { 8848f512ceSopenharmony_ci comm = DEVHOST_FILE_NAME; 8948f512ceSopenharmony_ci } else if (isThread) { 9048f512ceSopenharmony_ci comm = ReadFileToString(StringPrintf("/proc/%d/comm", tid)).c_str(); 9148f512ceSopenharmony_ci } else { 9248f512ceSopenharmony_ci comm = ReadFileToString(StringPrintf("/proc/%d/cmdline", tid)).c_str(); 9348f512ceSopenharmony_ci } 9448f512ceSopenharmony_ci if (comm == EMPTY_STRING) { 9548f512ceSopenharmony_ci comm = ReadFromSavedCmdLines(tid); 9648f512ceSopenharmony_ci } 9748f512ceSopenharmony_ci comm.erase(std::remove(comm.begin(), comm.end(), '\r'), comm.end()); 9848f512ceSopenharmony_ci comm.erase(std::remove(comm.begin(), comm.end(), '\n'), comm.end()); 9948f512ceSopenharmony_ci return comm; 10048f512ceSopenharmony_ci} 10148f512ceSopenharmony_ci 10248f512ceSopenharmony_ciVirtualThread &VirtualRuntime::UpdateThread(pid_t pid, pid_t tid, const std::string name) 10348f512ceSopenharmony_ci{ 10448f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 10548f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 10648f512ceSopenharmony_ci#endif 10748f512ceSopenharmony_ci VirtualThread &thread = GetThread(pid, tid, name); 10848f512ceSopenharmony_ci if (!name.empty()) { 10948f512ceSopenharmony_ci thread.name_ = name; 11048f512ceSopenharmony_ci } 11148f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 11248f512ceSopenharmony_ci updateThreadTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 11348f512ceSopenharmony_ci#endif 11448f512ceSopenharmony_ci return thread; 11548f512ceSopenharmony_ci} 11648f512ceSopenharmony_ci 11748f512ceSopenharmony_ciVirtualThread &VirtualRuntime::CreateThread(pid_t pid, pid_t tid, const std::string name) 11848f512ceSopenharmony_ci{ 11948f512ceSopenharmony_ci // make a new one 12048f512ceSopenharmony_ci if (pid == tid) { 12148f512ceSopenharmony_ci userSpaceThreadMap_.emplace(std::piecewise_construct, std::forward_as_tuple(tid), 12248f512ceSopenharmony_ci std::forward_as_tuple(pid, symbolsFiles_)); 12348f512ceSopenharmony_ci } else { 12448f512ceSopenharmony_ci // for thread we need give it process info( for same mmap) 12548f512ceSopenharmony_ci userSpaceThreadMap_.emplace( 12648f512ceSopenharmony_ci std::piecewise_construct, std::forward_as_tuple(tid), 12748f512ceSopenharmony_ci std::forward_as_tuple(pid, tid, GetThread(pid, pid), symbolsFiles_)); 12848f512ceSopenharmony_ci } 12948f512ceSopenharmony_ci VirtualThread &thread = userSpaceThreadMap_.at(tid); 13048f512ceSopenharmony_ci if (recordCallBack_) { 13148f512ceSopenharmony_ci if (pid == tid && !IsKernelThread(pid)) { 13248f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 13348f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 13448f512ceSopenharmony_ci#endif 13548f512ceSopenharmony_ci thread.ParseMap(); 13648f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 13748f512ceSopenharmony_ci threadParseMapsTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 13848f512ceSopenharmony_ci#endif 13948f512ceSopenharmony_ci } 14048f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 14148f512ceSopenharmony_ci const auto startCreateMmapTime = steady_clock::now(); 14248f512ceSopenharmony_ci#endif 14348f512ceSopenharmony_ci thread.name_ = name; 14448f512ceSopenharmony_ci if (thread.name_.empty()) { 14548f512ceSopenharmony_ci thread.name_ = ReadThreadName(tid, pid != tid); 14648f512ceSopenharmony_ci } 14748f512ceSopenharmony_ci HLOGD("create a new thread record for %u:%u:%s with %zu dso", pid, tid, 14848f512ceSopenharmony_ci thread.name_.c_str(), thread.GetMaps().size()); 14948f512ceSopenharmony_ci // we need make a PerfRecordComm 15048f512ceSopenharmony_ci auto commRecord = std::make_unique<PerfRecordComm>(IsKernelThread(pid), pid, tid, thread.name_); 15148f512ceSopenharmony_ci recordCallBack_(std::move(commRecord)); 15248f512ceSopenharmony_ci // only work for pid 15348f512ceSopenharmony_ci if (pid == tid) { 15448f512ceSopenharmony_ci if (isHM_) { 15548f512ceSopenharmony_ci thread.FixHMBundleMap(); 15648f512ceSopenharmony_ci } 15748f512ceSopenharmony_ci std::shared_ptr<DfxMap> prevMap = nullptr; 15848f512ceSopenharmony_ci for (auto &map : thread.GetMaps()) { 15948f512ceSopenharmony_ci // so in hap is load before start perf record 16048f512ceSopenharmony_ci // dynamic load library should be treat in the same way 16148f512ceSopenharmony_ci bool updateNormalSymbol = true; 16248f512ceSopenharmony_ci if (map->name.find(".hap") != std::string::npos && (map->prots & PROT_EXEC)) { 16348f512ceSopenharmony_ci map->prevMap = prevMap; 16448f512ceSopenharmony_ci updateNormalSymbol = !UpdateHapSymbols(map); 16548f512ceSopenharmony_ci HLOGD("UpdateHapSymbols"); 16648f512ceSopenharmony_ci } 16748f512ceSopenharmony_ci auto mmapRecord = 16848f512ceSopenharmony_ci std::make_unique<PerfRecordMmap2>(false, thread.pid_, thread.tid_, map); 16948f512ceSopenharmony_ci HLOGD("make PerfRecordMmap2 %d:%d:%s:%s(0x%" PRIx64 "-0x%" PRIx64 ")@%" PRIx64 " ", 17048f512ceSopenharmony_ci thread.pid_, thread.tid_, thread.name_.c_str(), map->name.c_str(), 17148f512ceSopenharmony_ci map->begin, map->end, map->offset); 17248f512ceSopenharmony_ci recordCallBack_(std::move(mmapRecord)); 17348f512ceSopenharmony_ci if (updateNormalSymbol) { 17448f512ceSopenharmony_ci UpdateSymbols(map, pid); 17548f512ceSopenharmony_ci } 17648f512ceSopenharmony_ci prevMap = map; 17748f512ceSopenharmony_ci } 17848f512ceSopenharmony_ci } 17948f512ceSopenharmony_ci HLOGV("thread created"); 18048f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 18148f512ceSopenharmony_ci threadCreateMmapTimes_ += 18248f512ceSopenharmony_ci duration_cast<microseconds>(steady_clock::now() - startCreateMmapTime); 18348f512ceSopenharmony_ci#endif 18448f512ceSopenharmony_ci } 18548f512ceSopenharmony_ci return thread; 18648f512ceSopenharmony_ci} 18748f512ceSopenharmony_ci 18848f512ceSopenharmony_cibool VirtualRuntime::UpdateHapSymbols(std::shared_ptr<DfxMap> map) 18948f512ceSopenharmony_ci{ 19048f512ceSopenharmony_ci if (map == nullptr) { 19148f512ceSopenharmony_ci return false; 19248f512ceSopenharmony_ci } 19348f512ceSopenharmony_ci HLOGV("hap name:%s", map->name.c_str()); 19448f512ceSopenharmony_ci // found it by name 19548f512ceSopenharmony_ci auto symbolsFile = SymbolsFile::CreateSymbolsFile(map->name); 19648f512ceSopenharmony_ci CHECK_TRUE(symbolsFile == nullptr, false, 1, 19748f512ceSopenharmony_ci "Failed to load CreateSymbolsFile for exec section in hap(%s)", map->name.c_str()); 19848f512ceSopenharmony_ci symbolsFile->SetMapsInfo(map); 19948f512ceSopenharmony_ci // update maps name if load debuginfo successfully 20048f512ceSopenharmony_ci CHECK_TRUE(!symbolsFile->LoadDebugInfo(map), false, 1, 20148f512ceSopenharmony_ci "Failed to load debuginfo for exec section in hap(%s)", map->name.c_str()); 20248f512ceSopenharmony_ci 20348f512ceSopenharmony_ci if (!loadSymboleWhenNeeded_) { // todo misspelling 20448f512ceSopenharmony_ci symbolsFile->LoadSymbols(map); 20548f512ceSopenharmony_ci } 20648f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(symbolsFile)); 20748f512ceSopenharmony_ci return true; 20848f512ceSopenharmony_ci} 20948f512ceSopenharmony_ci 21048f512ceSopenharmony_ciVirtualThread &VirtualRuntime::GetThread(pid_t pid, pid_t tid, const std::string name) 21148f512ceSopenharmony_ci{ 21248f512ceSopenharmony_ci if (userSpaceThreadMap_.find(pid) == userSpaceThreadMap_.end()) { 21348f512ceSopenharmony_ci // no pid found 21448f512ceSopenharmony_ci // create process first 21548f512ceSopenharmony_ci CreateThread(pid, pid); 21648f512ceSopenharmony_ci } 21748f512ceSopenharmony_ci 21848f512ceSopenharmony_ci auto it = userSpaceThreadMap_.find(tid); 21948f512ceSopenharmony_ci if (it == userSpaceThreadMap_.end()) { 22048f512ceSopenharmony_ci // we also need thread 22148f512ceSopenharmony_ci return CreateThread(pid, tid, name); 22248f512ceSopenharmony_ci } else { 22348f512ceSopenharmony_ci return it->second; 22448f512ceSopenharmony_ci } 22548f512ceSopenharmony_ci} 22648f512ceSopenharmony_ci 22748f512ceSopenharmony_cistd::shared_ptr<DfxMap> VirtualRuntime::UpdateThreadMaps(pid_t pid, pid_t tid, const std::string filename, 22848f512ceSopenharmony_ci uint64_t begin, uint64_t len, uint64_t offset, uint32_t prot) 22948f512ceSopenharmony_ci{ 23048f512ceSopenharmony_ci VirtualThread &thread = GetThread(pid, tid); 23148f512ceSopenharmony_ci std::shared_ptr<DfxMap> map = thread.CreateMapItem(filename, begin, len, offset, prot); 23248f512ceSopenharmony_ci if (isHM_) { 23348f512ceSopenharmony_ci thread.FixHMBundleMap(); 23448f512ceSopenharmony_ci } 23548f512ceSopenharmony_ci return map; 23648f512ceSopenharmony_ci} 23748f512ceSopenharmony_ci 23848f512ceSopenharmony_civoid VirtualRuntime::UpdateKernelModulesSpaceMaps() 23948f512ceSopenharmony_ci{ 24048f512ceSopenharmony_ci // found the kernel modules 24148f512ceSopenharmony_ci std::vector<DfxMap> koMaps; 24248f512ceSopenharmony_ci std::ifstream ifs("/proc/modules", std::ifstream::in); 24348f512ceSopenharmony_ci if (!ifs.is_open()) { 24448f512ceSopenharmony_ci perror("kernel modules read failed(/proc/modules)\n"); 24548f512ceSopenharmony_ci return; 24648f512ceSopenharmony_ci } 24748f512ceSopenharmony_ci std::string line; 24848f512ceSopenharmony_ci while (getline(ifs, line)) { 24948f512ceSopenharmony_ci uint64_t addr = 0; 25048f512ceSopenharmony_ci uint64_t size = 0; 25148f512ceSopenharmony_ci char module[line.size()]; 25248f512ceSopenharmony_ci /* 25348f512ceSopenharmony_ci name size load map 25448f512ceSopenharmony_ci hi_mipi_rx 53248 0 - Live 0xbf109000 (O) 25548f512ceSopenharmony_ci hi3516cv500_hdmi 237568 0 - Live 0xbf0bb000 (O) 25648f512ceSopenharmony_ci hifb 143360 0 - Live 0xbf089000 (O) 25748f512ceSopenharmony_ci hi3516cv500_vo_dev 98304 0 - Live 0xbf070000 (O) 25848f512ceSopenharmony_ci hi3516cv500_tde 110592 0 - Live 0xbf04a000 (O) 25948f512ceSopenharmony_ci hi3516cv500_sys 36864 0 - Live 0xbf03a000 (O) 26048f512ceSopenharmony_ci hi3516cv500_base 20480 5 26148f512ceSopenharmony_ci hi_mipi_rx,hi3516cv500_hdmi,hifb,hi3516cv500_vo_dev,hi3516cv500_tde,hi3516cv500_sys, 26248f512ceSopenharmony_ci hi3516cv500_base,sys_config,hi_proc,hi_irq,Live 0xbf000000 (O) 26348f512ceSopenharmony_ci */ 26448f512ceSopenharmony_ci int ret = sscanf_s(line.c_str(), "%s%" PRIu64 "%*u%*s%*s 0x%" PRIx64 "", module, 26548f512ceSopenharmony_ci sizeof(module), &size, &addr, sizeof(addr)); 26648f512ceSopenharmony_ci constexpr int numSlices {3}; 26748f512ceSopenharmony_ci if (ret == numSlices) { 26848f512ceSopenharmony_ci auto &map = koMaps.emplace_back(addr, addr + size, 0, "", std::string(module)); 26948f512ceSopenharmony_ci HLOGV("add ko map %s", map.ToString().c_str()); 27048f512ceSopenharmony_ci } else { 27148f512ceSopenharmony_ci HLOGE("unknown line %d: '%s'", ret, line.c_str()); 27248f512ceSopenharmony_ci } 27348f512ceSopenharmony_ci } 27448f512ceSopenharmony_ci 27548f512ceSopenharmony_ci if (std::all_of(koMaps.begin(), koMaps.end(), 27648f512ceSopenharmony_ci [](const DfxMap &item) { return item.begin == 0; })) { 27748f512ceSopenharmony_ci koMaps.clear(); 27848f512ceSopenharmony_ci HLOGW("no addr found in /proc/modules. remove all the ko"); 27948f512ceSopenharmony_ci } 28048f512ceSopenharmony_ci if (recordCallBack_) { 28148f512ceSopenharmony_ci for (const auto &map : koMaps) { 28248f512ceSopenharmony_ci auto record = std::make_unique<PerfRecordMmap>(true, 0, 0, map.begin, 28348f512ceSopenharmony_ci map.end - map.begin, 0, map.name); 28448f512ceSopenharmony_ci recordCallBack_(std::move(record)); 28548f512ceSopenharmony_ci } 28648f512ceSopenharmony_ci } 28748f512ceSopenharmony_ci std::move(koMaps.begin(), koMaps.end(), std::back_inserter(kernelSpaceMemMaps_)); 28848f512ceSopenharmony_ci} 28948f512ceSopenharmony_ci 29048f512ceSopenharmony_civoid VirtualRuntime::UpdateKernelSpaceMaps() 29148f512ceSopenharmony_ci{ 29248f512ceSopenharmony_ci // add kernel first 29348f512ceSopenharmony_ci auto &map = kernelSpaceMemMaps_.emplace_back(0, std::numeric_limits<uint64_t>::max(), 0, "", KERNEL_MMAP_NAME); 29448f512ceSopenharmony_ci if (recordCallBack_) { 29548f512ceSopenharmony_ci auto record = std::make_unique<PerfRecordMmap>(true, 0, 0, map.begin, 29648f512ceSopenharmony_ci map.end - map.begin, 0, map.name); 29748f512ceSopenharmony_ci recordCallBack_(std::move(record)); 29848f512ceSopenharmony_ci } 29948f512ceSopenharmony_ci} 30048f512ceSopenharmony_ci 30148f512ceSopenharmony_civoid VirtualRuntime::UpdateKernelModulesSymbols() 30248f512ceSopenharmony_ci{ 30348f512ceSopenharmony_ci HLOGD("load ko symbol and build id"); 30448f512ceSopenharmony_ci for (auto &map : kernelSpaceMemMaps_) { 30548f512ceSopenharmony_ci if (map.name == KERNEL_MMAP_NAME) { 30648f512ceSopenharmony_ci continue; 30748f512ceSopenharmony_ci } 30848f512ceSopenharmony_ci auto kernelModuleFile = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_MODULE_FILE, map.name); 30948f512ceSopenharmony_ci if (symbolsPaths_.size() > 0) { 31048f512ceSopenharmony_ci kernelModuleFile->setSymbolsFilePath(symbolsPaths_); // also load from search path 31148f512ceSopenharmony_ci } 31248f512ceSopenharmony_ci kernelModuleFile->LoadSymbols(); 31348f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(kernelModuleFile)); 31448f512ceSopenharmony_ci } 31548f512ceSopenharmony_ci} 31648f512ceSopenharmony_ci 31748f512ceSopenharmony_civoid VirtualRuntime::UpdateKernelSymbols() 31848f512ceSopenharmony_ci{ 31948f512ceSopenharmony_ci HLOGD("create a kernel mmap record"); 32048f512ceSopenharmony_ci // found kernel source 32148f512ceSopenharmony_ci auto kernelFile = SymbolsFile::CreateSymbolsFile(KERNEL_MMAP_NAME); 32248f512ceSopenharmony_ci // set symbol path If it exists 32348f512ceSopenharmony_ci if (symbolsPaths_.size() > 0) { 32448f512ceSopenharmony_ci kernelFile->setSymbolsFilePath(symbolsPaths_); // also load from search path 32548f512ceSopenharmony_ci } 32648f512ceSopenharmony_ci if (!IsRoot()) { 32748f512ceSopenharmony_ci HLOGD("user mode do not load kernel syms"); 32848f512ceSopenharmony_ci printf("Hiperf is not running as root mode. Do not need load kernel syms\n"); 32948f512ceSopenharmony_ci } 33048f512ceSopenharmony_ci if (kernelFile->LoadSymbols()) { 33148f512ceSopenharmony_ci auto record = std::make_unique<PerfRecordMmap>( 33248f512ceSopenharmony_ci true, 0, 0, kernelFile->textExecVaddr_, kernelFile->textExecVaddrRange_, 33348f512ceSopenharmony_ci kernelFile->textExecVaddrFileOffset_, KERNEL_MMAP_NAME); 33448f512ceSopenharmony_ci 33548f512ceSopenharmony_ci if (recordCallBack_) { 33648f512ceSopenharmony_ci recordCallBack_(std::move(record)); 33748f512ceSopenharmony_ci } 33848f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(kernelFile)); 33948f512ceSopenharmony_ci } else { 34048f512ceSopenharmony_ci HLOGW("kernel symbol not found.\n"); 34148f512ceSopenharmony_ci } 34248f512ceSopenharmony_ci} 34348f512ceSopenharmony_ci 34448f512ceSopenharmony_civoid VirtualRuntime::UpdatekernelMap(uint64_t begin, uint64_t end, uint64_t offset, 34548f512ceSopenharmony_ci std::string filename) 34648f512ceSopenharmony_ci{ 34748f512ceSopenharmony_ci HLOGV("update kernel map name:'%s' 0x%" PRIx64 " - 0x%" PRIx64 "@0x%08" PRIx64 "", 34848f512ceSopenharmony_ci filename.c_str(), begin, end, offset); 34948f512ceSopenharmony_ci 35048f512ceSopenharmony_ci HLOG_ASSERT(!filename.empty()); 35148f512ceSopenharmony_ci auto it = find(kernelSpaceMemMaps_.begin(), kernelSpaceMemMaps_.end(), filename); 35248f512ceSopenharmony_ci if (it == kernelSpaceMemMaps_.end()) { 35348f512ceSopenharmony_ci kernelSpaceMemMaps_.emplace_back(begin, end, offset, "", filename); 35448f512ceSopenharmony_ci } else { 35548f512ceSopenharmony_ci it->begin = begin; 35648f512ceSopenharmony_ci it->end = end; 35748f512ceSopenharmony_ci it->offset = offset; 35848f512ceSopenharmony_ci it->name = filename; 35948f512ceSopenharmony_ci } 36048f512ceSopenharmony_ci} 36148f512ceSopenharmony_ci 36248f512ceSopenharmony_civoid VirtualRuntime::DedupFromRecord(PerfRecordSample *recordSample) 36348f512ceSopenharmony_ci{ 36448f512ceSopenharmony_ci CHECK_TRUE(recordSample == nullptr, NO_RETVAL, 0, ""); 36548f512ceSopenharmony_ci u64 nr = recordSample->data_.nr; 36648f512ceSopenharmony_ci if (nr == 0) { 36748f512ceSopenharmony_ci collectSymbolCallBack_(recordSample); 36848f512ceSopenharmony_ci return; 36948f512ceSopenharmony_ci } 37048f512ceSopenharmony_ci u32 pid = recordSample->data_.pid; 37148f512ceSopenharmony_ci u64 *ips = recordSample->data_.ips; 37248f512ceSopenharmony_ci StackId stackId; 37348f512ceSopenharmony_ci stackId.value = 0; 37448f512ceSopenharmony_ci auto entry = processStackMap_.find(pid); 37548f512ceSopenharmony_ci std::shared_ptr<UniqueStackTable> table = nullptr; 37648f512ceSopenharmony_ci if (entry != processStackMap_.end()) { 37748f512ceSopenharmony_ci table = entry->second; 37848f512ceSopenharmony_ci } else { 37948f512ceSopenharmony_ci table = std::make_shared<UniqueStackTable>(pid); 38048f512ceSopenharmony_ci processStackMap_[pid] = table; 38148f512ceSopenharmony_ci } 38248f512ceSopenharmony_ci CHECK_TRUE(table == nullptr, NO_RETVAL, 0, ""); 38348f512ceSopenharmony_ci while (table->PutIpsInTable(&stackId, ips, nr) == 0) { 38448f512ceSopenharmony_ci // try expand hashtable if collison can not resolved 38548f512ceSopenharmony_ci if (!table->Resize()) { 38648f512ceSopenharmony_ci HLOGW("Hashtable size limit, ip compress failed!"); 38748f512ceSopenharmony_ci collectSymbolCallBack_(recordSample); 38848f512ceSopenharmony_ci return; 38948f512ceSopenharmony_ci } 39048f512ceSopenharmony_ci } 39148f512ceSopenharmony_ci // callstack dedup success 39248f512ceSopenharmony_ci recordSample->stackId_.value = stackId.value; 39348f512ceSopenharmony_ci recordSample->header.size -= (sizeof(u64) * nr - sizeof(stackId)); 39448f512ceSopenharmony_ci recordSample->data_.nr = 0; 39548f512ceSopenharmony_ci recordSample->data_.ips = nullptr; 39648f512ceSopenharmony_ci recordSample->removeStack_ = true; 39748f512ceSopenharmony_ci} 39848f512ceSopenharmony_ci 39948f512ceSopenharmony_civoid VirtualRuntime::CollectDedupSymbol(kSymbolsHits &kernelSymbolsHits, 40048f512ceSopenharmony_ci uSymbolsHits &userSymbolsHits) 40148f512ceSopenharmony_ci{ 40248f512ceSopenharmony_ci Node *node = nullptr; 40348f512ceSopenharmony_ci Node *head = nullptr; 40448f512ceSopenharmony_ci u32 pid; 40548f512ceSopenharmony_ci for (const auto &tableEntry : processStackMap_) { 40648f512ceSopenharmony_ci const auto &table = tableEntry.second; 40748f512ceSopenharmony_ci if (table == nullptr) { 40848f512ceSopenharmony_ci continue; 40948f512ceSopenharmony_ci } 41048f512ceSopenharmony_ci pid = table->GetPid(); 41148f512ceSopenharmony_ci head = table->GetHeadNode(); 41248f512ceSopenharmony_ci const auto &idxes = table->GetUsedIndexes(); 41348f512ceSopenharmony_ci for (const auto idx : idxes) { 41448f512ceSopenharmony_ci node = head + idx; 41548f512ceSopenharmony_ci if (node == nullptr) { 41648f512ceSopenharmony_ci continue; 41748f512ceSopenharmony_ci } 41848f512ceSopenharmony_ci if (node->value != 0) { 41948f512ceSopenharmony_ci if (node->section.inKernel) { 42048f512ceSopenharmony_ci uint64_t ip = node->section.ip | KERNEL_PREFIX; 42148f512ceSopenharmony_ci if (ip == PERF_CONTEXT_KERNEL || ip == PERF_CONTEXT_USER) { 42248f512ceSopenharmony_ci continue; 42348f512ceSopenharmony_ci } 42448f512ceSopenharmony_ci kernelSymbolsHits.insert(ip); 42548f512ceSopenharmony_ci } else { 42648f512ceSopenharmony_ci userSymbolsHits[pid].insert(node->section.ip); 42748f512ceSopenharmony_ci } 42848f512ceSopenharmony_ci } else { 42948f512ceSopenharmony_ci HLOGD("node value error 0x%x", idx); 43048f512ceSopenharmony_ci } 43148f512ceSopenharmony_ci } 43248f512ceSopenharmony_ci } 43348f512ceSopenharmony_ci} 43448f512ceSopenharmony_ci 43548f512ceSopenharmony_civoid VirtualRuntime::UpdateFromRecord(PerfEventRecord &record) 43648f512ceSopenharmony_ci{ 43748f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 43848f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 43948f512ceSopenharmony_ci#endif 44048f512ceSopenharmony_ci if (record.GetType() == PERF_RECORD_SAMPLE) { 44148f512ceSopenharmony_ci auto recordSample = static_cast<PerfRecordSample *>(&record); 44248f512ceSopenharmony_ci UpdateFromRecord(*recordSample); 44348f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 44448f512ceSopenharmony_ci processSampleRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 44548f512ceSopenharmony_ci#endif 44648f512ceSopenharmony_ci } else if (record.GetType() == PERF_RECORD_MMAP) { 44748f512ceSopenharmony_ci auto recordMmap = static_cast<PerfRecordMmap *>(&record); 44848f512ceSopenharmony_ci UpdateFromRecord(*recordMmap); 44948f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 45048f512ceSopenharmony_ci processMmapRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 45148f512ceSopenharmony_ci#endif 45248f512ceSopenharmony_ci } else if (record.GetType() == PERF_RECORD_MMAP2) { 45348f512ceSopenharmony_ci auto recordMmap2 = static_cast<PerfRecordMmap2 *>(&record); 45448f512ceSopenharmony_ci UpdateFromRecord(*recordMmap2); 45548f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 45648f512ceSopenharmony_ci processMmap2RecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 45748f512ceSopenharmony_ci#endif 45848f512ceSopenharmony_ci } else if (record.GetType() == PERF_RECORD_COMM) { 45948f512ceSopenharmony_ci auto recordComm = static_cast<PerfRecordComm *>(&record); 46048f512ceSopenharmony_ci UpdateFromRecord(*recordComm); 46148f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 46248f512ceSopenharmony_ci processCommRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 46348f512ceSopenharmony_ci#endif 46448f512ceSopenharmony_ci } else if (record.GetType() == PERF_RECORD_AUXTRACE) { 46548f512ceSopenharmony_ci auto recordAuxTrace = static_cast<PerfRecordAuxtrace *>(&record); 46648f512ceSopenharmony_ci UpdateFromRecord(*recordAuxTrace); 46748f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 46848f512ceSopenharmony_ci processCommRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 46948f512ceSopenharmony_ci#endif 47048f512ceSopenharmony_ci } else { 47148f512ceSopenharmony_ci HLOGW("skip record type %d", record.GetType()); 47248f512ceSopenharmony_ci } 47348f512ceSopenharmony_ci} 47448f512ceSopenharmony_ci 47548f512ceSopenharmony_civoid VirtualRuntime::MakeCallFrame(DfxSymbol &symbol, DfxFrame &callFrame) 47648f512ceSopenharmony_ci{ 47748f512ceSopenharmony_ci callFrame.funcOffset = symbol.funcVaddr_; 47848f512ceSopenharmony_ci callFrame.mapOffset = symbol.offsetToVaddr_; 47948f512ceSopenharmony_ci callFrame.symbolFileIndex = symbol.symbolFileIndex_; 48048f512ceSopenharmony_ci callFrame.funcName = symbol.GetName(); 48148f512ceSopenharmony_ci if (callFrame.funcName.empty()) { 48248f512ceSopenharmony_ci HLOGD("callFrame.funcName:%s, GetName:%s\n", callFrame.funcName.c_str(), symbol.GetName().data()); 48348f512ceSopenharmony_ci } 48448f512ceSopenharmony_ci 48548f512ceSopenharmony_ci callFrame.index = static_cast<size_t>(symbol.index_); 48648f512ceSopenharmony_ci callFrame.mapName = symbol.module_.empty() ? symbol.comm_ : symbol.module_; 48748f512ceSopenharmony_ci HLOG_ASSERT_MESSAGE(!callFrame.funcName.empty(), "%s", symbol.ToDebugString().c_str()); 48848f512ceSopenharmony_ci} 48948f512ceSopenharmony_ci 49048f512ceSopenharmony_civoid VirtualRuntime::SymbolicCallFrame(PerfRecordSample &recordSample, uint64_t ip, 49148f512ceSopenharmony_ci pid_t serverPid, perf_callchain_context context) 49248f512ceSopenharmony_ci{ 49348f512ceSopenharmony_ci pid_t pid = static_cast<pid_t>(recordSample.data_.pid); 49448f512ceSopenharmony_ci pid_t tid = static_cast<pid_t>(recordSample.data_.tid); 49548f512ceSopenharmony_ci if (serverPid != pid) { 49648f512ceSopenharmony_ci pid = tid = serverPid; 49748f512ceSopenharmony_ci } 49848f512ceSopenharmony_ci auto symbol = GetSymbol(ip, pid, tid, context); 49948f512ceSopenharmony_ci MakeCallFrame(symbol, recordSample.callFrames_.emplace_back(ip, 0)); 50048f512ceSopenharmony_ci HLOGV(" (%zu)unwind symbol: %*s%s", recordSample.callFrames_.size(), 50148f512ceSopenharmony_ci static_cast<int>(recordSample.callFrames_.size()), "", 50248f512ceSopenharmony_ci recordSample.callFrames_.back().ToSymbolString().c_str()); 50348f512ceSopenharmony_ci} 50448f512ceSopenharmony_ci 50548f512ceSopenharmony_cibool VirtualRuntime::RecoverCallStack(PerfRecordSample &recordSample) 50648f512ceSopenharmony_ci{ 50748f512ceSopenharmony_ci auto StackTable = processStackMap_.find(recordSample.data_.pid); 50848f512ceSopenharmony_ci CHECK_TRUE(StackTable == processStackMap_.end(), false, 1, "not found %" PRIu32 " pid", recordSample.data_.pid); 50948f512ceSopenharmony_ci recordSample.ips_.clear(); 51048f512ceSopenharmony_ci if (StackTable->second != nullptr) { 51148f512ceSopenharmony_ci StackTable->second->GetIpsByStackId(recordSample.stackId_, recordSample.ips_); 51248f512ceSopenharmony_ci } 51348f512ceSopenharmony_ci recordSample.RecoverCallStack(); 51448f512ceSopenharmony_ci return true; 51548f512ceSopenharmony_ci} 51648f512ceSopenharmony_ci 51748f512ceSopenharmony_civoid VirtualRuntime::SymbolicRecord(PerfRecordSample &recordSample) 51848f512ceSopenharmony_ci{ 51948f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 52048f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 52148f512ceSopenharmony_ci#endif 52248f512ceSopenharmony_ci // Symbolic the Call Stack 52348f512ceSopenharmony_ci recordSample.callFrames_.clear(); 52448f512ceSopenharmony_ci perf_callchain_context context = PERF_CONTEXT_MAX; 52548f512ceSopenharmony_ci pid_t serverPid; 52648f512ceSopenharmony_ci if (recordSample.data_.nr == 0) { 52748f512ceSopenharmony_ci serverPid = recordSample.GetServerPidof(0); 52848f512ceSopenharmony_ci SymbolicCallFrame(recordSample, recordSample.data_.ip, serverPid, PERF_CONTEXT_MAX); 52948f512ceSopenharmony_ci } 53048f512ceSopenharmony_ci for (u64 i = 0; i < recordSample.data_.nr; i++) { 53148f512ceSopenharmony_ci uint64_t ip = recordSample.data_.ips[i]; 53248f512ceSopenharmony_ci if (ip >= PERF_CONTEXT_MAX) { 53348f512ceSopenharmony_ci std::string contextName = UpdatePerfContext(ip, context); 53448f512ceSopenharmony_ci HLOGV("context switch to %s", contextName.c_str()); 53548f512ceSopenharmony_ci continue; 53648f512ceSopenharmony_ci } else if (ip < BAD_IP_ADDRESS) { 53748f512ceSopenharmony_ci // ip 0 or 1 or less than 0 53848f512ceSopenharmony_ci continue; 53948f512ceSopenharmony_ci } 54048f512ceSopenharmony_ci serverPid = recordSample.GetServerPidof(i); 54148f512ceSopenharmony_ci SymbolicCallFrame(recordSample, ip, serverPid, context); 54248f512ceSopenharmony_ci } 54348f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 54448f512ceSopenharmony_ci auto usedTime = duration_cast<microseconds>(steady_clock::now() - startTime); 54548f512ceSopenharmony_ci if (usedTime.count() != 0) { 54648f512ceSopenharmony_ci HLOGV("cost %0.3f ms to symbolic ", usedTime.count() / MS_DURATION); 54748f512ceSopenharmony_ci } 54848f512ceSopenharmony_ci symbolicRecordTimes_ += usedTime; 54948f512ceSopenharmony_ci#endif 55048f512ceSopenharmony_ci} 55148f512ceSopenharmony_ci 55248f512ceSopenharmony_civoid VirtualRuntime::NeedDropKernelCallChain(PerfRecordSample &sample) 55348f512ceSopenharmony_ci{ 55448f512ceSopenharmony_ci // only do this in record mode. 55548f512ceSopenharmony_ci if (recordCallBack_ == nullptr || needkernelCallChain_ || 55648f512ceSopenharmony_ci !sample.inKernel() || sample.data_.nr == 0) { 55748f512ceSopenharmony_ci return; 55848f512ceSopenharmony_ci } 55948f512ceSopenharmony_ci 56048f512ceSopenharmony_ci u64 skip = 0; 56148f512ceSopenharmony_ci u64 skipPid = 0; 56248f512ceSopenharmony_ci u64 *ips = sample.data_.ips; 56348f512ceSopenharmony_ci for (; skip < sample.data_.nr; skip++) { 56448f512ceSopenharmony_ci if (ips[skip] == PERF_CONTEXT_KERNEL) { 56548f512ceSopenharmony_ci skipPid++; 56648f512ceSopenharmony_ci } 56748f512ceSopenharmony_ci if (ips[skip] == PERF_CONTEXT_USER) { 56848f512ceSopenharmony_ci break; 56948f512ceSopenharmony_ci } 57048f512ceSopenharmony_ci } 57148f512ceSopenharmony_ci sample.skipKernel_ = skip; 57248f512ceSopenharmony_ci sample.data_.nr -= skip; 57348f512ceSopenharmony_ci sample.header.size -= sizeof(u64) * skip; 57448f512ceSopenharmony_ci if (sample.data_.server_nr > 0) { 57548f512ceSopenharmony_ci sample.skipPid_ = skipPid; 57648f512ceSopenharmony_ci sample.data_.server_nr -= skipPid; 57748f512ceSopenharmony_ci sample.header.size -= sizeof(u64) * skipPid; 57848f512ceSopenharmony_ci } 57948f512ceSopenharmony_ci} 58048f512ceSopenharmony_ci 58148f512ceSopenharmony_civoid VirtualRuntime::UnwindFromRecord(PerfRecordSample &recordSample) 58248f512ceSopenharmony_ci{ 58348f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos 58448f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 58548f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 58648f512ceSopenharmony_ci#endif 58748f512ceSopenharmony_ci HLOGV("unwind record (time:%llu)", recordSample.data_.time); 58848f512ceSopenharmony_ci // if we have userstack ? 58948f512ceSopenharmony_ci if (recordSample.data_.stack_size > 0) { 59048f512ceSopenharmony_ci pid_t serverPid = recordSample.GetUstackServerPid(); 59148f512ceSopenharmony_ci pid_t pid = static_cast<pid_t>(recordSample.data_.pid); 59248f512ceSopenharmony_ci pid_t tid = static_cast<pid_t>(recordSample.data_.tid); 59348f512ceSopenharmony_ci if (serverPid != pid) { 59448f512ceSopenharmony_ci pid = tid = serverPid; 59548f512ceSopenharmony_ci } 59648f512ceSopenharmony_ci auto &thread = UpdateThread(pid, tid); 59748f512ceSopenharmony_ci callstack_.UnwindCallStack(thread, recordSample.data_.user_abi == PERF_SAMPLE_REGS_ABI_32, 59848f512ceSopenharmony_ci recordSample.data_.user_regs, recordSample.data_.reg_nr, 59948f512ceSopenharmony_ci recordSample.data_.stack_data, recordSample.data_.dyn_size, 60048f512ceSopenharmony_ci recordSample.callFrames_); 60148f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 60248f512ceSopenharmony_ci unwindCallStackTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 60348f512ceSopenharmony_ci#endif 60448f512ceSopenharmony_ci size_t oldSize = recordSample.callFrames_.size(); 60548f512ceSopenharmony_ci HLOGV("unwind %zu", recordSample.callFrames_.size()); 60648f512ceSopenharmony_ci callstack_.ExpandCallStack(thread.tid_, recordSample.callFrames_, callstackMergeLevel_); 60748f512ceSopenharmony_ci HLOGV("expand %zu (+%zu)", recordSample.callFrames_.size(), 60848f512ceSopenharmony_ci recordSample.callFrames_.size() - oldSize); 60948f512ceSopenharmony_ci 61048f512ceSopenharmony_ci recordSample.ReplaceWithCallStack(oldSize); 61148f512ceSopenharmony_ci } 61248f512ceSopenharmony_ci 61348f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 61448f512ceSopenharmony_ci unwindFromRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime); 61548f512ceSopenharmony_ci#endif 61648f512ceSopenharmony_ci 61748f512ceSopenharmony_ci NeedDropKernelCallChain(recordSample); 61848f512ceSopenharmony_ci // we will not do this in non record mode. 61948f512ceSopenharmony_ci if (dedupStack_ && recordCallBack_ != nullptr) { 62048f512ceSopenharmony_ci DedupFromRecord(&recordSample); 62148f512ceSopenharmony_ci } 62248f512ceSopenharmony_ci#endif 62348f512ceSopenharmony_ci 62448f512ceSopenharmony_ci // we will not do this in record mode 62548f512ceSopenharmony_ci if (recordCallBack_ == nullptr) { 62648f512ceSopenharmony_ci if (dedupStack_ && recordSample.stackId_.section.id > 0 && recordSample.data_.nr == 0) { 62748f512ceSopenharmony_ci RecoverCallStack(recordSample); 62848f512ceSopenharmony_ci } 62948f512ceSopenharmony_ci // find the symbols , reabuild frame info 63048f512ceSopenharmony_ci SymbolicRecord(recordSample); 63148f512ceSopenharmony_ci } 63248f512ceSopenharmony_ci} 63348f512ceSopenharmony_ci 63448f512ceSopenharmony_civoid VirtualRuntime::SetCollectSymbolCallBack(CollectSymbolCallBack collectSymbolCallBack) 63548f512ceSopenharmony_ci{ 63648f512ceSopenharmony_ci collectSymbolCallBack_ = collectSymbolCallBack; 63748f512ceSopenharmony_ci} 63848f512ceSopenharmony_ci 63948f512ceSopenharmony_civoid VirtualRuntime::UpdateFromRecord(PerfRecordSample &recordSample) 64048f512ceSopenharmony_ci{ 64148f512ceSopenharmony_ci UpdateThread(recordSample.data_.pid, recordSample.data_.tid); 64248f512ceSopenharmony_ci if (recordSample.data_.server_nr) { 64348f512ceSopenharmony_ci // update all server threads 64448f512ceSopenharmony_ci for (size_t i = 0; i < recordSample.data_.server_nr; i++) { 64548f512ceSopenharmony_ci pid_t pid = static_cast<pid_t>(recordSample.data_.server_pids[i]); 64648f512ceSopenharmony_ci UpdateThread(pid, pid); 64748f512ceSopenharmony_ci } 64848f512ceSopenharmony_ci } 64948f512ceSopenharmony_ci // unwind 65048f512ceSopenharmony_ci if (disableUnwind_) { 65148f512ceSopenharmony_ci return; 65248f512ceSopenharmony_ci } else { 65348f512ceSopenharmony_ci UnwindFromRecord(recordSample); 65448f512ceSopenharmony_ci } 65548f512ceSopenharmony_ci} 65648f512ceSopenharmony_ci 65748f512ceSopenharmony_civoid VirtualRuntime::UpdateFromRecord(PerfRecordMmap &recordMmap) 65848f512ceSopenharmony_ci{ 65948f512ceSopenharmony_ci HLOGV(" MMAP: size %d pid %u tid %u", recordMmap.header.size, recordMmap.data_.pid, 66048f512ceSopenharmony_ci recordMmap.data_.tid); 66148f512ceSopenharmony_ci HLOGV(" MMAP: %s dso '%s' (0x%llx-0x%llx)@0x%llx", recordMmap.inKernel() ? "kernel" : "user", 66248f512ceSopenharmony_ci recordMmap.data_.filename, recordMmap.data_.addr, 66348f512ceSopenharmony_ci recordMmap.data_.addr + recordMmap.data_.len, recordMmap.data_.pgoff); 66448f512ceSopenharmony_ci // kernel mmap 66548f512ceSopenharmony_ci // don't overwrite the vailed mmap , so we also check the recordMmap.data_.len 66648f512ceSopenharmony_ci if (IsKernelThread(recordMmap.data_.pid)) { 66748f512ceSopenharmony_ci UpdateKernelThreadMap(recordMmap.data_.pid, recordMmap.data_.addr, 66848f512ceSopenharmony_ci recordMmap.data_.len, recordMmap.data_.filename); 66948f512ceSopenharmony_ci } else if (recordMmap.inKernel()) { 67048f512ceSopenharmony_ci UpdatekernelMap(recordMmap.data_.addr, recordMmap.data_.addr + recordMmap.data_.len, 67148f512ceSopenharmony_ci recordMmap.data_.pgoff, recordMmap.data_.filename); 67248f512ceSopenharmony_ci } else { 67348f512ceSopenharmony_ci NeedAdaptSandboxPath(recordMmap.data_.filename, recordMmap.data_.pid, recordMmap.header.size); 67448f512ceSopenharmony_ci FixHMBundleMmap(recordMmap.data_.filename, recordMmap.data_.pid, recordMmap.header.size); 67548f512ceSopenharmony_ci auto map = UpdateThreadMaps(recordMmap.data_.pid, recordMmap.data_.tid, recordMmap.data_.filename, 67648f512ceSopenharmony_ci recordMmap.data_.addr, recordMmap.data_.len, recordMmap.data_.pgoff); 67748f512ceSopenharmony_ci UpdateSymbols(map, recordMmap.data_.pid); 67848f512ceSopenharmony_ci } 67948f512ceSopenharmony_ci} 68048f512ceSopenharmony_ci 68148f512ceSopenharmony_cibool VirtualRuntime::CheckValidSandBoxMmap(PerfRecordMmap2 &recordMmap2) 68248f512ceSopenharmony_ci{ 68348f512ceSopenharmony_ci static std::shared_ptr<DfxMap> prevMap; 68448f512ceSopenharmony_ci if ((recordMmap2.data_.prot & PROT_EXEC) != 0) { 68548f512ceSopenharmony_ci // fake first segment, when second segment come. 68648f512ceSopenharmony_ci auto symFile = SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, recordMmap2.data_.filename); 68748f512ceSopenharmony_ci CHECK_TRUE(symFile == nullptr, false, 1, "CheckValidSandBoxMmap Failed to create symbolFile!"); 68848f512ceSopenharmony_ci 68948f512ceSopenharmony_ci std::shared_ptr<DfxMap> curMap; 69048f512ceSopenharmony_ci if (strstr(recordMmap2.data_.filename, ".hap") != nullptr) { 69148f512ceSopenharmony_ci curMap = std::make_shared<DfxMap>( 69248f512ceSopenharmony_ci recordMmap2.data_.addr, 69348f512ceSopenharmony_ci recordMmap2.data_.addr + recordMmap2.data_.len, 69448f512ceSopenharmony_ci recordMmap2.data_.pgoff, 69548f512ceSopenharmony_ci "", // prot 69648f512ceSopenharmony_ci recordMmap2.data_.filename 69748f512ceSopenharmony_ci ); 69848f512ceSopenharmony_ci curMap->prevMap = prevMap; 69948f512ceSopenharmony_ci } 70048f512ceSopenharmony_ci 70148f512ceSopenharmony_ci CHECK_TRUE(!symFile->LoadDebugInfo(curMap), false, 1, "CheckValidSandBoxMmap Failed to load debuginfo!"); 70248f512ceSopenharmony_ci 70348f512ceSopenharmony_ci if (!loadSymboleWhenNeeded_) { 70448f512ceSopenharmony_ci symFile->LoadSymbols(curMap); 70548f512ceSopenharmony_ci } 70648f512ceSopenharmony_ci 70748f512ceSopenharmony_ci if (strstr(recordMmap2.data_.filename, ".hap") == nullptr) { 70848f512ceSopenharmony_ci auto elfLoadInfoMap = symFile->GetPtLoads(); 70948f512ceSopenharmony_ci u64 begin = recordMmap2.data_.addr - elfLoadInfoMap[0].mmapLen; 71048f512ceSopenharmony_ci u64 len = elfLoadInfoMap[0].mmapLen; 71148f512ceSopenharmony_ci u64 pgoff = elfLoadInfoMap[0].offset & (~(elfLoadInfoMap[0].align >= 1 ? elfLoadInfoMap[0].align - 1 : 0)); 71248f512ceSopenharmony_ci std::unique_ptr<PerfRecordMmap2> mmap2FirstSeg = 71348f512ceSopenharmony_ci std::make_unique<PerfRecordMmap2>(recordMmap2.inKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid, 71448f512ceSopenharmony_ci begin, len, pgoff, 0, 0, 0, PROT_READ, 0, std::string(recordMmap2.data_.filename)); 71548f512ceSopenharmony_ci UpdateThreadMaps(mmap2FirstSeg->data_.pid, mmap2FirstSeg->data_.tid, mmap2FirstSeg->data_.filename, 71648f512ceSopenharmony_ci mmap2FirstSeg->data_.addr, mmap2FirstSeg->data_.len, mmap2FirstSeg->data_.pgoff); 71748f512ceSopenharmony_ci recordCallBack_(std::move(mmap2FirstSeg)); 71848f512ceSopenharmony_ci } else { 71948f512ceSopenharmony_ci auto elfLoadInfoMap = symFile->GetPtLoads(); 72048f512ceSopenharmony_ci u64 begin = recordMmap2.data_.addr - elfLoadInfoMap[0].mmapLen; 72148f512ceSopenharmony_ci u64 len = elfLoadInfoMap[0].mmapLen; 72248f512ceSopenharmony_ci u64 pgoff = elfLoadInfoMap[0].offset & 72348f512ceSopenharmony_ci (~(elfLoadInfoMap[0].align >= 1 ? elfLoadInfoMap[0].align - 1 : 0)); 72448f512ceSopenharmony_ci std::unique_ptr<PerfRecordMmap2> mmap2FirstSeg = 72548f512ceSopenharmony_ci std::make_unique<PerfRecordMmap2>(recordMmap2.inKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid, 72648f512ceSopenharmony_ci begin, len, pgoff, 0, 0, 0, PROT_READ, 0, curMap->name); 72748f512ceSopenharmony_ci UpdateThreadMaps(mmap2FirstSeg->data_.pid, mmap2FirstSeg->data_.tid, curMap->name, 72848f512ceSopenharmony_ci mmap2FirstSeg->data_.addr, mmap2FirstSeg->data_.len, mmap2FirstSeg->data_.pgoff); 72948f512ceSopenharmony_ci recordCallBack_(std::move(mmap2FirstSeg)); 73048f512ceSopenharmony_ci 73148f512ceSopenharmony_ci std::unique_ptr<PerfRecordMmap2> mmap2SecondSegment = 73248f512ceSopenharmony_ci std::make_unique<PerfRecordMmap2>(recordMmap2.inKernel(), recordMmap2.data_.pid, recordMmap2.data_.tid, 73348f512ceSopenharmony_ci recordMmap2.data_.addr, 73448f512ceSopenharmony_ci recordMmap2.data_.len, 73548f512ceSopenharmony_ci recordMmap2.data_.pgoff - prevMap->offset, // minus load offset of hap 73648f512ceSopenharmony_ci 0, 0, 0, recordMmap2.data_.prot, 0, curMap->name); 73748f512ceSopenharmony_ci UpdateThreadMaps(mmap2SecondSegment->data_.pid, mmap2SecondSegment->data_.tid, curMap->name, 73848f512ceSopenharmony_ci mmap2SecondSegment->data_.addr, mmap2SecondSegment->data_.len, mmap2SecondSegment->data_.pgoff); 73948f512ceSopenharmony_ci recordCallBack_(std::move(mmap2SecondSegment)); 74048f512ceSopenharmony_ci recordMmap2.discard_ = true; 74148f512ceSopenharmony_ci } 74248f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(symFile)); 74348f512ceSopenharmony_ci return true; 74448f512ceSopenharmony_ci } else if (recordMmap2.data_.pgoff == 0) { 74548f512ceSopenharmony_ci recordMmap2.discard_ = true; 74648f512ceSopenharmony_ci } 74748f512ceSopenharmony_ci 74848f512ceSopenharmony_ci if (strstr(recordMmap2.data_.filename, ".hap") != nullptr) { 74948f512ceSopenharmony_ci prevMap = std::make_shared<DfxMap>( 75048f512ceSopenharmony_ci recordMmap2.data_.addr, 75148f512ceSopenharmony_ci recordMmap2.data_.addr + recordMmap2.data_.len, 75248f512ceSopenharmony_ci recordMmap2.data_.pgoff, 75348f512ceSopenharmony_ci "", // prot 75448f512ceSopenharmony_ci recordMmap2.data_.filename 75548f512ceSopenharmony_ci ); 75648f512ceSopenharmony_ci HLOGD("CheckValidSandBoxMmap Update prev map!"); 75748f512ceSopenharmony_ci } 75848f512ceSopenharmony_ci return !recordMmap2.discard_; 75948f512ceSopenharmony_ci} 76048f512ceSopenharmony_ci 76148f512ceSopenharmony_civoid VirtualRuntime::UpdateFromRecord(PerfRecordMmap2 &recordMmap2) 76248f512ceSopenharmony_ci{ 76348f512ceSopenharmony_ci if (!OHOS::HiviewDFX::DfxMaps::IsLegalMapItem(recordMmap2.data_.filename)) { 76448f512ceSopenharmony_ci return; 76548f512ceSopenharmony_ci } 76648f512ceSopenharmony_ci 76748f512ceSopenharmony_ci HLOGV(" MMAP2: size %d pid %u tid %u", recordMmap2.header.size, recordMmap2.data_.pid, 76848f512ceSopenharmony_ci recordMmap2.data_.tid); 76948f512ceSopenharmony_ci HLOGV(" MMAP2: %s dso '%s' (0x%llx-0x%llx)@0x%llx prot:%u", recordMmap2.inKernel() ? "kernel" : "user", 77048f512ceSopenharmony_ci recordMmap2.data_.filename, recordMmap2.data_.addr, 77148f512ceSopenharmony_ci recordMmap2.data_.addr + recordMmap2.data_.len, recordMmap2.data_.pgoff, recordMmap2.data_.prot); 77248f512ceSopenharmony_ci 77348f512ceSopenharmony_ci if (recordCallBack_) { 77448f512ceSopenharmony_ci if (NeedAdaptSandboxPath(recordMmap2.data_.filename, recordMmap2.data_.pid, recordMmap2.header.size)) { 77548f512ceSopenharmony_ci FixHMBundleMmap(recordMmap2.data_.filename, recordMmap2.data_.pid, recordMmap2.header.size); 77648f512ceSopenharmony_ci CHECK_TRUE(!CheckValidSandBoxMmap(recordMmap2), NO_RETVAL, 0, ""); 77748f512ceSopenharmony_ci } 77848f512ceSopenharmony_ci } 77948f512ceSopenharmony_ci auto map = UpdateThreadMaps(recordMmap2.data_.pid, recordMmap2.data_.tid, recordMmap2.data_.filename, 78048f512ceSopenharmony_ci recordMmap2.data_.addr, recordMmap2.data_.len, recordMmap2.data_.pgoff, 78148f512ceSopenharmony_ci recordMmap2.data_.prot); 78248f512ceSopenharmony_ci UpdateSymbols(map, recordMmap2.data_.pid); 78348f512ceSopenharmony_ci} 78448f512ceSopenharmony_ci 78548f512ceSopenharmony_civoid VirtualRuntime::UpdateFromRecord(PerfRecordComm &recordComm) 78648f512ceSopenharmony_ci{ 78748f512ceSopenharmony_ci recordComm.DumpLog(__FUNCTION__); 78848f512ceSopenharmony_ci UpdateThread(recordComm.data_.pid, recordComm.data_.tid, recordComm.data_.comm); 78948f512ceSopenharmony_ci} 79048f512ceSopenharmony_ci 79148f512ceSopenharmony_civoid VirtualRuntime::UpdateFromRecord(PerfRecordAuxtrace &recordAuxTrace) 79248f512ceSopenharmony_ci{ 79348f512ceSopenharmony_ci if (recordCallBack_ == nullptr) { 79448f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos 79548f512ceSopenharmony_ci recordAuxTrace.DumpLog(__FUNCTION__); 79648f512ceSopenharmony_ci SpeDecoder *decoder = SpeDecoderDataNew(recordAuxTrace.rawData_, recordAuxTrace.data_.size); 79748f512ceSopenharmony_ci CHECK_TRUE(decoder == nullptr, NO_RETVAL, 0, ""); 79848f512ceSopenharmony_ci std::vector<SpeRecord> records; 79948f512ceSopenharmony_ci while (true) { 80048f512ceSopenharmony_ci int ret = SpeDecode(decoder); 80148f512ceSopenharmony_ci if (ret <= 0) { 80248f512ceSopenharmony_ci break; 80348f512ceSopenharmony_ci } 80448f512ceSopenharmony_ci struct SpeRecord record = SpeRecord(decoder->record); 80548f512ceSopenharmony_ci records.emplace_back(record); 80648f512ceSopenharmony_ci } 80748f512ceSopenharmony_ci std::vector<ReportItemAuxRawData> auxRawData; 80848f512ceSopenharmony_ci for (auto rec: records) { 80948f512ceSopenharmony_ci u64 pc = 0; 81048f512ceSopenharmony_ci if (rec.from_ip) { 81148f512ceSopenharmony_ci pc = rec.from_ip; 81248f512ceSopenharmony_ci } else if (rec.to_ip) { 81348f512ceSopenharmony_ci pc = rec.to_ip; 81448f512ceSopenharmony_ci } else { 81548f512ceSopenharmony_ci continue; 81648f512ceSopenharmony_ci } 81748f512ceSopenharmony_ci DfxSymbol symbol = GetSymbol(pc, recordAuxTrace.data_.reserved__, recordAuxTrace.data_.tid); 81848f512ceSopenharmony_ci HLOGV("pc 0x%llx symbol %s", pc, symbol.ToDebugString().c_str()); 81948f512ceSopenharmony_ci struct ReportItemAuxRawData reportItem = {rec.type, 0.0f, 1, symbol.comm_.data(), pc, 82048f512ceSopenharmony_ci symbol.module_.data(), symbol.GetName().data(), 82148f512ceSopenharmony_ci symbol.fileVaddr_}; 82248f512ceSopenharmony_ci auxRawData.emplace_back(reportItem); 82348f512ceSopenharmony_ci HLOGV("type %u, from_ip: 0x%llx, to_ip: 0x%llx, timestamp: %llu, virt_addr: 0x%llx, phys_addr: 0x%llx", 82448f512ceSopenharmony_ci rec.type, rec.from_ip, rec.to_ip, rec.timestamp, rec.virt_addr, rec.phys_addr); 82548f512ceSopenharmony_ci } 82648f512ceSopenharmony_ci AddReportItems(auxRawData); 82748f512ceSopenharmony_ci SpeDecoderFree(decoder); 82848f512ceSopenharmony_ci#endif 82948f512ceSopenharmony_ci } 83048f512ceSopenharmony_ci} 83148f512ceSopenharmony_ci 83248f512ceSopenharmony_civoid VirtualRuntime::SymbolSpeRecord(PerfRecordAuxtrace &recordAuxTrace) 83348f512ceSopenharmony_ci{ 83448f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos 83548f512ceSopenharmony_ci recordAuxTrace.DumpLog(__FUNCTION__); 83648f512ceSopenharmony_ci SpeDecoder *decoder = SpeDecoderDataNew(recordAuxTrace.rawData_, recordAuxTrace.data_.size); 83748f512ceSopenharmony_ci CHECK_TRUE(decoder == nullptr, NO_RETVAL, 0, ""); 83848f512ceSopenharmony_ci while (true) { 83948f512ceSopenharmony_ci int ret = SpeDecode(decoder); 84048f512ceSopenharmony_ci if (ret <= 0) { 84148f512ceSopenharmony_ci break; 84248f512ceSopenharmony_ci } 84348f512ceSopenharmony_ci struct SpeRecord record = SpeRecord(decoder->record); 84448f512ceSopenharmony_ci u64 pc = 0; 84548f512ceSopenharmony_ci if (record.from_ip) { 84648f512ceSopenharmony_ci pc = record.from_ip; 84748f512ceSopenharmony_ci } else if (record.to_ip) { 84848f512ceSopenharmony_ci pc = record.to_ip; 84948f512ceSopenharmony_ci } else { 85048f512ceSopenharmony_ci continue; 85148f512ceSopenharmony_ci } 85248f512ceSopenharmony_ci 85348f512ceSopenharmony_ci DfxSymbol symbol = GetSymbol(pc, recordAuxTrace.data_.reserved__, recordAuxTrace.data_.tid); 85448f512ceSopenharmony_ci HLOGV("pc 0x%llx symbol %s", pc, symbol.ToDebugString().c_str()); 85548f512ceSopenharmony_ci } 85648f512ceSopenharmony_ci SpeDecoderFree(decoder); 85748f512ceSopenharmony_ci#endif 85848f512ceSopenharmony_ci} 85948f512ceSopenharmony_ci 86048f512ceSopenharmony_civoid VirtualRuntime::SetRecordMode(RecordCallBack recordCallBack) 86148f512ceSopenharmony_ci{ 86248f512ceSopenharmony_ci recordCallBack_ = recordCallBack; 86348f512ceSopenharmony_ci} 86448f512ceSopenharmony_ci 86548f512ceSopenharmony_civoid VirtualRuntime::UpdateSymbols(std::shared_ptr<DfxMap> map, pid_t pid) 86648f512ceSopenharmony_ci{ 86748f512ceSopenharmony_ci CHECK_TRUE(map == nullptr || map->symbolFileIndex != -1, NO_RETVAL, 0, ""); 86848f512ceSopenharmony_ci HLOGD("try to find symbols for file: %s", map->name.c_str()); 86948f512ceSopenharmony_ci for (size_t i = 0; i < symbolsFiles_.size(); ++i) { 87048f512ceSopenharmony_ci if (symbolsFiles_[i]->filePath_ == map->name) { 87148f512ceSopenharmony_ci map->symbolFileIndex = static_cast<int32_t>(i); 87248f512ceSopenharmony_ci HLOGV("already have '%s', symbol index:%zu", map->name.c_str(), i); 87348f512ceSopenharmony_ci return; 87448f512ceSopenharmony_ci } 87548f512ceSopenharmony_ci } 87648f512ceSopenharmony_ci 87748f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 87848f512ceSopenharmony_ci const auto startTime = steady_clock::now(); 87948f512ceSopenharmony_ci#endif 88048f512ceSopenharmony_ci /** 88148f512ceSopenharmony_ci * map[] map.name = SymbolsFile.filePath_ prot SymbolsFileType 88248f512ceSopenharmony_ci * seg1 /data/storage/el1/bundle/entry.hap r--p ABC 88348f512ceSopenharmony_ci * seg2 /data/storage/el1/bundle/entry.hap r-xp ELF 88448f512ceSopenharmony_ci * seg3 /data/storage/el1/bundle/entry.hap r--p ABC 88548f512ceSopenharmony_ci * seg4 /data/storage/el1/bundle/entry.hap r--p ABC 88648f512ceSopenharmony_ci * seg1 /system/app/SceneBoard/SceneBoard.hap r--p ABC 88748f512ceSopenharmony_ci * seg2 /system/app/SceneBoard/SceneBoard.hap r--p ABC 88848f512ceSopenharmony_ci * seg3 /system/app/SceneBoard/SceneBoard.hap r--p ABC 88948f512ceSopenharmony_ci * segN .hap r--p .an/jit/etc 89048f512ceSopenharmony_ci * 1.map.name == symbolsFile.filePath_ 89148f512ceSopenharmony_ci * 2.map.FileType == symbolsFiles_[map.symbolFileIndex] 89248f512ceSopenharmony_ci * 3.cache pc->map->symbolsFiles[map.symbolFileIndex] 89348f512ceSopenharmony_ci * 4.must ensure map.mapType assigned with SymbolsFile constructions at the same time. 89448f512ceSopenharmony_ci */ 89548f512ceSopenharmony_ci auto symbolsFile = SymbolsFile::CreateSymbolsFile(map->name, pid); 89648f512ceSopenharmony_ci symbolsFile->SetMapsInfo(map); 89748f512ceSopenharmony_ci if (enableDebugInfoSymbolic_ && symbolsFile->symbolFileType_ == SymbolsFileType::SYMBOL_ELF_FILE) { 89848f512ceSopenharmony_ci symbolsFile->EnableMiniDebugInfo(); 89948f512ceSopenharmony_ci } 90048f512ceSopenharmony_ci // set symbol path If it exists 90148f512ceSopenharmony_ci if (symbolsPaths_.size() > 0) { 90248f512ceSopenharmony_ci // also load from search path 90348f512ceSopenharmony_ci symbolsFile->setSymbolsFilePath(symbolsPaths_); 90448f512ceSopenharmony_ci } 90548f512ceSopenharmony_ci if (loadSymboleWhenNeeded_) { 90648f512ceSopenharmony_ci // load it when we need it 90748f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(symbolsFile)); 90848f512ceSopenharmony_ci } else if (symbolsFile->LoadSymbols()) { 90948f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(symbolsFile)); 91048f512ceSopenharmony_ci } else { 91148f512ceSopenharmony_ci HLOGW("symbols file for '%s' not found.", map->name.c_str()); 91248f512ceSopenharmony_ci } 91348f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME 91448f512ceSopenharmony_ci auto usedTime = duration_cast<microseconds>(steady_clock::now() - startTime); 91548f512ceSopenharmony_ci if (usedTime.count() != 0) { 91648f512ceSopenharmony_ci HLOGV("cost %0.3f ms to load '%s'", usedTime.count() / MS_DURATION, map->name.c_str()); 91748f512ceSopenharmony_ci } 91848f512ceSopenharmony_ci updateSymbolsTimes_ += usedTime; 91948f512ceSopenharmony_ci#endif 92048f512ceSopenharmony_ci} 92148f512ceSopenharmony_ci 92248f512ceSopenharmony_ciconst DfxSymbol VirtualRuntime::GetKernelSymbol(uint64_t ip, const std::vector<DfxMap> &memMaps, 92348f512ceSopenharmony_ci const VirtualThread &thread) 92448f512ceSopenharmony_ci{ 92548f512ceSopenharmony_ci DfxSymbol vaddrSymbol(ip, thread.name_); 92648f512ceSopenharmony_ci for (auto &map : memMaps) { 92748f512ceSopenharmony_ci if (ip > map.begin && ip < map.end) { 92848f512ceSopenharmony_ci HLOGM("found addr 0x%" PRIx64 " in kernel map 0x%" PRIx64 " - 0x%" PRIx64 " from %s", 92948f512ceSopenharmony_ci ip, map.begin, map.end, map.name.c_str()); 93048f512ceSopenharmony_ci vaddrSymbol.module_ = map.name; 93148f512ceSopenharmony_ci // found symbols by file name 93248f512ceSopenharmony_ci for (auto &symbolsFile : symbolsFiles_) { 93348f512ceSopenharmony_ci if (symbolsFile->filePath_ == map.name) { 93448f512ceSopenharmony_ci vaddrSymbol.symbolFileIndex_ = symbolsFile->id_; 93548f512ceSopenharmony_ci vaddrSymbol.fileVaddr_ = 93648f512ceSopenharmony_ci symbolsFile->GetVaddrInSymbols(ip, map.begin, map.offset); 93748f512ceSopenharmony_ci perf_callchain_context context = PERF_CONTEXT_KERNEL; 93848f512ceSopenharmony_ci if (GetSymbolCache(vaddrSymbol.fileVaddr_, vaddrSymbol, context)) { 93948f512ceSopenharmony_ci return vaddrSymbol; 94048f512ceSopenharmony_ci } 94148f512ceSopenharmony_ci HLOGV("found symbol vaddr 0x%" PRIx64 " for runtime vaddr 0x%" PRIx64 94248f512ceSopenharmony_ci " at '%s'", 94348f512ceSopenharmony_ci vaddrSymbol.fileVaddr_, ip, map.name.c_str()); 94448f512ceSopenharmony_ci if (!symbolsFile->SymbolsLoaded()) { 94548f512ceSopenharmony_ci symbolsFile->LoadSymbols(); 94648f512ceSopenharmony_ci } 94748f512ceSopenharmony_ci DfxSymbol foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_); 94848f512ceSopenharmony_ci foundSymbols.taskVaddr_ = ip; 94948f512ceSopenharmony_ci if (!foundSymbols.IsValid()) { 95048f512ceSopenharmony_ci HLOGW("addr 0x%" PRIx64 " vaddr 0x%" PRIx64 " NOT found in symbol file %s", 95148f512ceSopenharmony_ci ip, vaddrSymbol.fileVaddr_, map.name.c_str()); 95248f512ceSopenharmony_ci return vaddrSymbol; 95348f512ceSopenharmony_ci } else { 95448f512ceSopenharmony_ci return foundSymbols; 95548f512ceSopenharmony_ci } 95648f512ceSopenharmony_ci } 95748f512ceSopenharmony_ci } 95848f512ceSopenharmony_ci HLOGW("addr 0x%" PRIx64 " in map but NOT found the symbol file %s", ip, 95948f512ceSopenharmony_ci map.name.c_str()); 96048f512ceSopenharmony_ci } else { 96148f512ceSopenharmony_ci HLOGM("addr 0x%" PRIx64 " not in map 0x%" PRIx64 " - 0x%" PRIx64 " from %s", ip, 96248f512ceSopenharmony_ci map.begin, map.end, map.name.c_str()); 96348f512ceSopenharmony_ci } 96448f512ceSopenharmony_ci } 96548f512ceSopenharmony_ci return vaddrSymbol; 96648f512ceSopenharmony_ci} 96748f512ceSopenharmony_ci 96848f512ceSopenharmony_ciconst DfxSymbol VirtualRuntime::GetKernelThreadSymbol(uint64_t ip, const VirtualThread &thread) 96948f512ceSopenharmony_ci{ 97048f512ceSopenharmony_ci DfxSymbol vaddrSymbol(ip, thread.name_); 97148f512ceSopenharmony_ci int64_t mapIndex = thread.FindMapIndexByAddr(ip); 97248f512ceSopenharmony_ci if (mapIndex < 0) { 97348f512ceSopenharmony_ci HLOGV("not found in any map"); 97448f512ceSopenharmony_ci return vaddrSymbol; 97548f512ceSopenharmony_ci } 97648f512ceSopenharmony_ci 97748f512ceSopenharmony_ci auto map = thread.GetMaps()[mapIndex]; 97848f512ceSopenharmony_ci CHECK_TRUE(map == nullptr, vaddrSymbol, 0, ""); 97948f512ceSopenharmony_ci HLOGM("found addr 0x%" PRIx64 " in kthread map 0x%" PRIx64 " - 0x%" PRIx64 " from %s", 98048f512ceSopenharmony_ci ip, map->begin, map->end, map->name.c_str()); 98148f512ceSopenharmony_ci // found symbols by file name 98248f512ceSopenharmony_ci for (auto &symbolsFile : symbolsFiles_) { 98348f512ceSopenharmony_ci if (symbolsFile->filePath_ == map->name) { 98448f512ceSopenharmony_ci vaddrSymbol.symbolFileIndex_ = symbolsFile->id_; 98548f512ceSopenharmony_ci vaddrSymbol.module_ = map->name; 98648f512ceSopenharmony_ci vaddrSymbol.fileVaddr_ = 98748f512ceSopenharmony_ci symbolsFile->GetVaddrInSymbols(ip, map->begin, map->offset); 98848f512ceSopenharmony_ci perf_callchain_context context = PERF_CONTEXT_MAX; 98948f512ceSopenharmony_ci if (GetSymbolCache(vaddrSymbol.fileVaddr_, vaddrSymbol, context)) { 99048f512ceSopenharmony_ci return vaddrSymbol; 99148f512ceSopenharmony_ci } 99248f512ceSopenharmony_ci HLOGV("found symbol vaddr 0x%" PRIx64 " for runtime vaddr 0x%" PRIx64 " at '%s'", 99348f512ceSopenharmony_ci vaddrSymbol.fileVaddr_, ip, map->name.c_str()); 99448f512ceSopenharmony_ci if (!symbolsFile->SymbolsLoaded()) { 99548f512ceSopenharmony_ci symbolsFile->LoadDebugInfo(); 99648f512ceSopenharmony_ci symbolsFile->LoadSymbols(map); 99748f512ceSopenharmony_ci } 99848f512ceSopenharmony_ci auto foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_); 99948f512ceSopenharmony_ci foundSymbols.taskVaddr_ = ip; 100048f512ceSopenharmony_ci if (!foundSymbols.IsValid()) { 100148f512ceSopenharmony_ci HLOGW("addr 0x%" PRIx64 " vaddr 0x%" PRIx64 " NOT found in symbol file %s", 100248f512ceSopenharmony_ci ip, vaddrSymbol.fileVaddr_, map->name.c_str()); 100348f512ceSopenharmony_ci return vaddrSymbol; 100448f512ceSopenharmony_ci } else { 100548f512ceSopenharmony_ci return foundSymbols; 100648f512ceSopenharmony_ci } 100748f512ceSopenharmony_ci } 100848f512ceSopenharmony_ci } 100948f512ceSopenharmony_ci HLOGW("addr 0x%" PRIx64 " in map but NOT found the symbol file %s", ip, 101048f512ceSopenharmony_ci map->name.c_str()); 101148f512ceSopenharmony_ci return vaddrSymbol; 101248f512ceSopenharmony_ci} 101348f512ceSopenharmony_ci 101448f512ceSopenharmony_ciconst DfxSymbol VirtualRuntime::GetUserSymbol(uint64_t ip, const VirtualThread &thread) 101548f512ceSopenharmony_ci{ 101648f512ceSopenharmony_ci DfxSymbol vaddrSymbol(ip, thread.name_); 101748f512ceSopenharmony_ci int64_t mapIndex = thread.FindMapIndexByAddr(ip); 101848f512ceSopenharmony_ci if (mapIndex >= 0) { 101948f512ceSopenharmony_ci auto map = thread.GetMaps()[mapIndex]; 102048f512ceSopenharmony_ci SymbolsFile *symbolsFile = thread.FindSymbolsFileByMap(map); 102148f512ceSopenharmony_ci if (symbolsFile != nullptr) { 102248f512ceSopenharmony_ci vaddrSymbol.symbolFileIndex_ = symbolsFile->id_; 102348f512ceSopenharmony_ci vaddrSymbol.module_ = map->name; 102448f512ceSopenharmony_ci vaddrSymbol.fileVaddr_ = symbolsFile->GetVaddrInSymbols(ip, map->begin, map->offset); 102548f512ceSopenharmony_ci perf_callchain_context context = PERF_CONTEXT_USER; 102648f512ceSopenharmony_ci if (GetSymbolCache(vaddrSymbol.fileVaddr_, vaddrSymbol, context)) { 102748f512ceSopenharmony_ci return vaddrSymbol; 102848f512ceSopenharmony_ci } 102948f512ceSopenharmony_ci HLOGV("found symbol vaddr 0x%" PRIx64 " for runtime vaddr 0x%" PRIx64 " at '%s'", 103048f512ceSopenharmony_ci vaddrSymbol.fileVaddr_, ip, map->name.c_str()); 103148f512ceSopenharmony_ci if (!symbolsFile->SymbolsLoaded()) { 103248f512ceSopenharmony_ci symbolsFile->LoadDebugInfo(map); 103348f512ceSopenharmony_ci symbolsFile->LoadSymbols(map); 103448f512ceSopenharmony_ci } 103548f512ceSopenharmony_ci DfxSymbol foundSymbols; 103648f512ceSopenharmony_ci if (!symbolsFile->IsAbc()) { 103748f512ceSopenharmony_ci foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_); 103848f512ceSopenharmony_ci } else { 103948f512ceSopenharmony_ci HLOGD("symbolsFile:%s is ABC :%d", symbolsFile->filePath_.c_str(), symbolsFile->IsAbc()); 104048f512ceSopenharmony_ci foundSymbols = symbolsFile->GetSymbolWithPcAndMap(ip, map); 104148f512ceSopenharmony_ci } 104248f512ceSopenharmony_ci 104348f512ceSopenharmony_ci if (foundSymbols.IsValid()) { 104448f512ceSopenharmony_ci return foundSymbols; 104548f512ceSopenharmony_ci } else { 104648f512ceSopenharmony_ci HLOGW("addr 0x%" PRIx64 " vaddr 0x%" PRIx64 " NOT found in symbol file %s", ip, 104748f512ceSopenharmony_ci vaddrSymbol.fileVaddr_, map->name.c_str()); 104848f512ceSopenharmony_ci if (symbolsFile->IsAbc()) { 104948f512ceSopenharmony_ci symbolsFile->symbolsMap_.insert(std::make_pair(ip, vaddrSymbol)); 105048f512ceSopenharmony_ci } 105148f512ceSopenharmony_ci return vaddrSymbol; 105248f512ceSopenharmony_ci } 105348f512ceSopenharmony_ci } else { 105448f512ceSopenharmony_ci HLOGW("addr 0x%" PRIx64 " in map but NOT found the symbol file %s", ip, map->name.c_str()); 105548f512ceSopenharmony_ci } 105648f512ceSopenharmony_ci } else { 105748f512ceSopenharmony_ci HLOGV("not found in any map"); 105848f512ceSopenharmony_ci } 105948f512ceSopenharmony_ci return vaddrSymbol; 106048f512ceSopenharmony_ci} 106148f512ceSopenharmony_ci 106248f512ceSopenharmony_cibool VirtualRuntime::GetSymbolCache(uint64_t fileVaddr, DfxSymbol &symbol, 106348f512ceSopenharmony_ci const perf_callchain_context &context) 106448f512ceSopenharmony_ci{ 106548f512ceSopenharmony_ci if (context == PERF_CONTEXT_MAX and kThreadSymbolCache_.count(fileVaddr)) { 106648f512ceSopenharmony_ci CHECK_TRUE(kThreadSymbolCache_.find(symbol.fileVaddr_) == kThreadSymbolCache_.end(), false, 0, ""); 106748f512ceSopenharmony_ci symbol = kThreadSymbolCache_[symbol.fileVaddr_]; 106848f512ceSopenharmony_ci symbol.hit_++; 106948f512ceSopenharmony_ci HLOGV("hit kernel thread cache 0x%" PRIx64 " %d", fileVaddr, symbol.hit_); 107048f512ceSopenharmony_ci return true; 107148f512ceSopenharmony_ci } else if (context != PERF_CONTEXT_USER and kernelSymbolCache_.count(fileVaddr)) { 107248f512ceSopenharmony_ci CHECK_TRUE(kernelSymbolCache_.find(symbol.fileVaddr_) == kernelSymbolCache_.end(), false, 0, ""); 107348f512ceSopenharmony_ci symbol = kernelSymbolCache_[symbol.fileVaddr_]; 107448f512ceSopenharmony_ci symbol.hit_++; 107548f512ceSopenharmony_ci HLOGV("hit kernel cache 0x%" PRIx64 " %d", fileVaddr, symbol.hit_); 107648f512ceSopenharmony_ci return true; 107748f512ceSopenharmony_ci } else if (userSymbolCache_.count(symbol.fileVaddr_) != 0) { 107848f512ceSopenharmony_ci const DfxSymbol &cachedSymbol = userSymbolCache_[symbol.fileVaddr_]; 107948f512ceSopenharmony_ci // must be the same file 108048f512ceSopenharmony_ci if (cachedSymbol.module_ != symbol.module_) { 108148f512ceSopenharmony_ci return false; 108248f512ceSopenharmony_ci } 108348f512ceSopenharmony_ci symbol = cachedSymbol; 108448f512ceSopenharmony_ci symbol.hit_++; 108548f512ceSopenharmony_ci HLOGV("hit user cache 0x%" PRIx64 " %d %s", fileVaddr, symbol.hit_, 108648f512ceSopenharmony_ci symbol.ToDebugString().c_str()); 108748f512ceSopenharmony_ci return true; 108848f512ceSopenharmony_ci } else { 108948f512ceSopenharmony_ci HLOGM("cache miss k %zu u %zu kt %zu", kernelSymbolCache_.size(), 109048f512ceSopenharmony_ci userSymbolCache_.size(), kThreadSymbolCache_.size()); 109148f512ceSopenharmony_ci } 109248f512ceSopenharmony_ci return false; 109348f512ceSopenharmony_ci} 109448f512ceSopenharmony_ci 109548f512ceSopenharmony_ciDfxSymbol VirtualRuntime::GetSymbol(uint64_t ip, pid_t pid, pid_t tid, const perf_callchain_context &context) 109648f512ceSopenharmony_ci{ 109748f512ceSopenharmony_ci HLOGV("try find tid %u ip 0x%" PRIx64 " in %zu symbolsFiles\n", tid, ip, symbolsFiles_.size()); 109848f512ceSopenharmony_ci DfxSymbol symbol; 109948f512ceSopenharmony_ci 110048f512ceSopenharmony_ci if (IsKernelThread(pid)) { 110148f512ceSopenharmony_ci VirtualThread &kthread = GetThread(pid, tid); 110248f512ceSopenharmony_ci HLOGM("try found addr in kernel thread %u with %zu maps", pid, 110348f512ceSopenharmony_ci kthread.GetMaps().size()); 110448f512ceSopenharmony_ci symbol = GetKernelThreadSymbol(ip, kthread); 110548f512ceSopenharmony_ci HLOGM("add addr to kernel thread cache 0x%" PRIx64 " cache size %zu", ip, 110648f512ceSopenharmony_ci kThreadSymbolCache_.size()); 110748f512ceSopenharmony_ci kThreadSymbolCache_[symbol.fileVaddr_] = symbol; 110848f512ceSopenharmony_ci if (symbol.IsValid()) { 110948f512ceSopenharmony_ci return symbol; 111048f512ceSopenharmony_ci } 111148f512ceSopenharmony_ci } 111248f512ceSopenharmony_ci 111348f512ceSopenharmony_ci if (context == PERF_CONTEXT_USER or (context == PERF_CONTEXT_MAX and !symbol.IsValid())) { 111448f512ceSopenharmony_ci // check userspace memmap 111548f512ceSopenharmony_ci symbol = GetUserSymbol(ip, GetThread(pid, tid)); 111648f512ceSopenharmony_ci if (userSymbolCache_.find(symbol.fileVaddr_) == userSymbolCache_.end()) { 111748f512ceSopenharmony_ci userSymbolCache_.reserve(USER_SYMBOL_CACHE_LIMIT); 111848f512ceSopenharmony_ci } 111948f512ceSopenharmony_ci userSymbolCache_[symbol.fileVaddr_] = symbol; 112048f512ceSopenharmony_ci HLOGV("cache ip 0x%" PRIx64 " to %s", ip, 112148f512ceSopenharmony_ci userSymbolCache_[symbol.fileVaddr_].ToDebugString().c_str()); 112248f512ceSopenharmony_ci } 112348f512ceSopenharmony_ci 112448f512ceSopenharmony_ci if (context == PERF_CONTEXT_KERNEL or (context == PERF_CONTEXT_MAX and !symbol.IsValid())) { 112548f512ceSopenharmony_ci // check kernelspace 112648f512ceSopenharmony_ci HLOGM("try found addr in kernelspace %zu maps", kernelSpaceMemMaps_.size()); 112748f512ceSopenharmony_ci symbol = GetKernelSymbol(ip, kernelSpaceMemMaps_, GetThread(pid, tid)); 112848f512ceSopenharmony_ci HLOGM("add addr to kernel cache 0x%" PRIx64 " cache size %zu", ip, 112948f512ceSopenharmony_ci kernelSymbolCache_.size()); 113048f512ceSopenharmony_ci kernelSymbolCache_[symbol.fileVaddr_] = symbol; 113148f512ceSopenharmony_ci } 113248f512ceSopenharmony_ci return symbol; 113348f512ceSopenharmony_ci} 113448f512ceSopenharmony_ci 113548f512ceSopenharmony_cibool VirtualRuntime::SetSymbolsPaths(const std::vector<std::string> &symbolsPaths) 113648f512ceSopenharmony_ci{ 113748f512ceSopenharmony_ci std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE); 113848f512ceSopenharmony_ci CHECK_TRUE(symbolsFile == nullptr, false, 0, ""); 113948f512ceSopenharmony_ci // we need check if the path is accessible 114048f512ceSopenharmony_ci bool accessible = symbolsFile->setSymbolsFilePath(symbolsPaths); 114148f512ceSopenharmony_ci if (accessible) { 114248f512ceSopenharmony_ci symbolsPaths_ = symbolsPaths; 114348f512ceSopenharmony_ci } else { 114448f512ceSopenharmony_ci if (!symbolsPaths.empty()) { 114548f512ceSopenharmony_ci HLOGE("some symbols path unable access"); 114648f512ceSopenharmony_ci } 114748f512ceSopenharmony_ci } 114848f512ceSopenharmony_ci return accessible; 114948f512ceSopenharmony_ci} 115048f512ceSopenharmony_ci 115148f512ceSopenharmony_civoid VirtualRuntime::UpdateFromPerfData(const std::vector<SymbolFileStruct> &symbolFileStructs) 115248f512ceSopenharmony_ci{ 115348f512ceSopenharmony_ci // review: if we need move to some other place ? 115448f512ceSopenharmony_ci HLOG_ASSERT_MESSAGE(symbolsFiles_.size() == 0, " symbolsFiles_ size is %zu", 115548f512ceSopenharmony_ci symbolsFiles_.size()); 115648f512ceSopenharmony_ci for (const auto &symbolFileStruct : symbolFileStructs) { 115748f512ceSopenharmony_ci HLOGV("symbolFileStruct.filePath_:'%s'", symbolFileStruct.filePath_.c_str()); 115848f512ceSopenharmony_ci HLOGV("symbolFileStruct.buildId_:'%s'", symbolFileStruct.buildId_.c_str()); 115948f512ceSopenharmony_ci HLOGV("process symbols file:'%s':'%s'", symbolFileStruct.filePath_.c_str(), 116048f512ceSopenharmony_ci symbolFileStruct.buildId_.c_str()); 116148f512ceSopenharmony_ci 116248f512ceSopenharmony_ci // load from symbolFileStruct (perf.data) 116348f512ceSopenharmony_ci std::unique_ptr<SymbolsFile> symbolsFile = SymbolsFile::LoadSymbolsFromSaved(symbolFileStruct); 116448f512ceSopenharmony_ci if (symbolsFile == nullptr) { 116548f512ceSopenharmony_ci continue; 116648f512ceSopenharmony_ci } 116748f512ceSopenharmony_ci // reaload from sybol path If it exists 116848f512ceSopenharmony_ci if (symbolsPaths_.size() > 0) { 116948f512ceSopenharmony_ci HLOGV("try again with symbolsPaths setup"); 117048f512ceSopenharmony_ci symbolsFile->setSymbolsFilePath(symbolsPaths_); // also load from search path 117148f512ceSopenharmony_ci // use give us path ,we must reload it. 117248f512ceSopenharmony_ci symbolsFile->LoadSymbols(); 117348f512ceSopenharmony_ci } 117448f512ceSopenharmony_ci symbolsFile->id_ = static_cast<int32_t>(symbolsFiles_.size()); 117548f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(symbolsFile)); 117648f512ceSopenharmony_ci } 117748f512ceSopenharmony_ci} 117848f512ceSopenharmony_ci 117948f512ceSopenharmony_civoid VirtualRuntime::ImportUniqueStackNodes(const std::vector<UniStackTableInfo>& uniStackTableInfos) 118048f512ceSopenharmony_ci{ 118148f512ceSopenharmony_ci for (const UniStackTableInfo& item : uniStackTableInfos) { 118248f512ceSopenharmony_ci auto stackTable = std::make_shared<UniqueStackTable>(item.pid, item.tableSize); 118348f512ceSopenharmony_ci for (const UniStackNode& node : item.nodes) { 118448f512ceSopenharmony_ci stackTable->ImportNode(node.index, node.node); 118548f512ceSopenharmony_ci } 118648f512ceSopenharmony_ci processStackMap_[item.pid] = std::move(stackTable); 118748f512ceSopenharmony_ci } 118848f512ceSopenharmony_ci} 118948f512ceSopenharmony_ci 119048f512ceSopenharmony_ci/* 119148f512ceSopenharmony_ci ARM functions 119248f512ceSopenharmony_ci The table below lists the symbols exported by the vDSO. 119348f512ceSopenharmony_ci 119448f512ceSopenharmony_ci symbol version 119548f512ceSopenharmony_ci ──────────────────────────────────────────────────────────── 119648f512ceSopenharmony_ci __vdso_gettimeofday LINUX_2.6 (exported since Linux 4.1) 119748f512ceSopenharmony_ci __vdso_clock_gettime LINUX_2.6 (exported since Linux 4.1) 119848f512ceSopenharmony_ci 119948f512ceSopenharmony_ci Additionally, the ARM port has a code page full of utility 120048f512ceSopenharmony_ci functions. Since it's just a raw page of code, there is no ELF 120148f512ceSopenharmony_ci information for doing symbol lookups or versioning. It does 120248f512ceSopenharmony_ci provide support for different versions though. 120348f512ceSopenharmony_ci 120448f512ceSopenharmony_ci For information on this code page, it's best to refer to the 120548f512ceSopenharmony_ci kernel documentation as it's extremely detailed and covers 120648f512ceSopenharmony_ci everything you need to know: 120748f512ceSopenharmony_ci Documentation/arm/kernel_user_helpers.txt. 120848f512ceSopenharmony_ci 120948f512ceSopenharmony_ci aarch64 functions 121048f512ceSopenharmony_ci The table below lists the symbols exported by the vDSO. 121148f512ceSopenharmony_ci 121248f512ceSopenharmony_ci symbol version 121348f512ceSopenharmony_ci ────────────────────────────────────── 121448f512ceSopenharmony_ci __kernel_rt_sigreturn LINUX_2.6.39 121548f512ceSopenharmony_ci __kernel_gettimeofday LINUX_2.6.39 121648f512ceSopenharmony_ci __kernel_clock_gettime LINUX_2.6.39 121748f512ceSopenharmony_ci __kernel_clock_getres LINUX_2.6.39 121848f512ceSopenharmony_ci*/ 121948f512ceSopenharmony_civoid VirtualRuntime::LoadVdso() 122048f512ceSopenharmony_ci{ 122148f512ceSopenharmony_ci#if !is_mingw 122248f512ceSopenharmony_ci VirtualThread myThread(getpid(), symbolsFiles_); 122348f512ceSopenharmony_ci myThread.ParseMap(); 122448f512ceSopenharmony_ci for (const auto &map : myThread.GetMaps()) { 122548f512ceSopenharmony_ci if (map->IsVdsoMap()) { 122648f512ceSopenharmony_ci std::string memory(map->end - map->begin, '\0'); 122748f512ceSopenharmony_ci std::copy(reinterpret_cast<char *>((map->begin)), reinterpret_cast<char *>((map->end)), 122848f512ceSopenharmony_ci &memory[0]); 122948f512ceSopenharmony_ci std::string tempPath("/data/local/tmp/"); 123048f512ceSopenharmony_ci std::string tempFileName = tempPath + map->name; 123148f512ceSopenharmony_ci if (!WriteStringToFile(tempFileName, memory)) { 123248f512ceSopenharmony_ci printf("vdso temp file create fail at %s\n", tempFileName.c_str()); 123348f512ceSopenharmony_ci } else { 123448f512ceSopenharmony_ci HLOGD("vdso temp file create at %s:%zu", tempFileName.c_str(), memory.size()); 123548f512ceSopenharmony_ci auto symbolsFile = SymbolsFile::CreateSymbolsFile(map->name); 123648f512ceSopenharmony_ci symbolsFile->setSymbolsFilePath(tempPath); // also load from search path 123748f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(symbolsFile)); 123848f512ceSopenharmony_ci return; 123948f512ceSopenharmony_ci } 124048f512ceSopenharmony_ci } 124148f512ceSopenharmony_ci } 124248f512ceSopenharmony_ci HLOGD("no vdso found"); 124348f512ceSopenharmony_ci#endif 124448f512ceSopenharmony_ci} 124548f512ceSopenharmony_ci 124648f512ceSopenharmony_civoid VirtualRuntime::UpdateServiceSpaceMaps() 124748f512ceSopenharmony_ci{ 124848f512ceSopenharmony_ci VirtualThread &kthread = GetThread(SYSMGR_PID, SYSMGR_PID); 124948f512ceSopenharmony_ci kthread.ParseServiceMap(SYSMGR_FILE_NAME); 125048f512ceSopenharmony_ci if (recordCallBack_) { 125148f512ceSopenharmony_ci for (const auto &map : kthread.GetMaps()) { 125248f512ceSopenharmony_ci auto record = 125348f512ceSopenharmony_ci std::make_unique<PerfRecordMmap>(true, SYSMGR_PID, SYSMGR_PID, 125448f512ceSopenharmony_ci map->begin, map->end - map->begin, 125548f512ceSopenharmony_ci 0, SYSMGR_FILE_NAME); 125648f512ceSopenharmony_ci recordCallBack_(std::move(record)); 125748f512ceSopenharmony_ci } 125848f512ceSopenharmony_ci } 125948f512ceSopenharmony_ci} 126048f512ceSopenharmony_ci 126148f512ceSopenharmony_civoid VirtualRuntime::UpdateServiceSymbols() 126248f512ceSopenharmony_ci{ 126348f512ceSopenharmony_ci HLOGD("try to update kernel thread symbols for kernel service"); 126448f512ceSopenharmony_ci std::string fileName = SYSMGR_FILE_NAME; 126548f512ceSopenharmony_ci auto symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_THREAD_FILE, fileName); 126648f512ceSopenharmony_ci 126748f512ceSopenharmony_ci HLOGD("add kernel service symbol file: %s", fileName.c_str()); 126848f512ceSopenharmony_ci if (symbolsFile->LoadSymbols()) { 126948f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(symbolsFile)); 127048f512ceSopenharmony_ci } else { 127148f512ceSopenharmony_ci HLOGW("symbols file for '%s' not found.", fileName.c_str()); 127248f512ceSopenharmony_ci } 127348f512ceSopenharmony_ci} 127448f512ceSopenharmony_ci 127548f512ceSopenharmony_civoid VirtualRuntime::UpdateKernelThreadMap(pid_t pid, uint64_t begin, uint64_t len, 127648f512ceSopenharmony_ci std::string filename) 127748f512ceSopenharmony_ci{ 127848f512ceSopenharmony_ci HLOGV("update kernel thread map pid %u name:'%s'", pid, filename.c_str()); 127948f512ceSopenharmony_ci 128048f512ceSopenharmony_ci VirtualThread &thread = GetThread(pid, pid); 128148f512ceSopenharmony_ci thread.CreateMapItem(filename, begin, len, 0u); 128248f512ceSopenharmony_ci} 128348f512ceSopenharmony_ci 128448f512ceSopenharmony_civoid VirtualRuntime::UpdateDevhostSpaceMaps() 128548f512ceSopenharmony_ci{ 128648f512ceSopenharmony_ci VirtualThread &kthread = GetThread(devhostPid_, devhostPid_); 128748f512ceSopenharmony_ci kthread.ParseDevhostMap(devhostPid_); 128848f512ceSopenharmony_ci if (recordCallBack_) { 128948f512ceSopenharmony_ci for (const auto &map : kthread.GetMaps()) { 129048f512ceSopenharmony_ci auto record = 129148f512ceSopenharmony_ci std::make_unique<PerfRecordMmap>(false, devhostPid_, devhostPid_, 129248f512ceSopenharmony_ci map->begin, map->end - map->begin, 129348f512ceSopenharmony_ci 0, map->name); 129448f512ceSopenharmony_ci recordCallBack_(std::move(record)); 129548f512ceSopenharmony_ci } 129648f512ceSopenharmony_ci } 129748f512ceSopenharmony_ci} 129848f512ceSopenharmony_ci 129948f512ceSopenharmony_civoid VirtualRuntime::UpdateDevhostSymbols() 130048f512ceSopenharmony_ci{ 130148f512ceSopenharmony_ci HLOGD("try to update kernel thread symbols for devhost"); 130248f512ceSopenharmony_ci auto kallsyms = SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_THREAD_FILE, DEVHOST_FILE_NAME); 130348f512ceSopenharmony_ci // file name of devhost.ko 130448f512ceSopenharmony_ci std::map<std::string_view, std::unique_ptr<SymbolsFile>> koMaps; 130548f512ceSopenharmony_ci koMaps[DEVHOST_FILE_NAME] = 130648f512ceSopenharmony_ci SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_THREAD_FILE, DEVHOST_LINUX_FILE_NAME); 130748f512ceSopenharmony_ci 130848f512ceSopenharmony_ci if (kallsyms->LoadSymbols()) { 130948f512ceSopenharmony_ci for (auto &symbol : kallsyms->GetSymbols()) { 131048f512ceSopenharmony_ci if (koMaps.find(symbol.module_) == koMaps.end()) { 131148f512ceSopenharmony_ci std::string filename = std::string(symbol.module_); 131248f512ceSopenharmony_ci // [devhost] to /liblinux/devhost.ko 131348f512ceSopenharmony_ci filename.erase(filename.begin()); 131448f512ceSopenharmony_ci filename.erase(filename.end() - 1); 131548f512ceSopenharmony_ci filename = DEVHOST_LINUX_PREFIX + filename + KERNEL_MODULES_EXT_NAME; 131648f512ceSopenharmony_ci koMaps[symbol.module_] = 131748f512ceSopenharmony_ci SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_THREAD_FILE, filename); 131848f512ceSopenharmony_ci } 131948f512ceSopenharmony_ci if (koMaps[symbol.module_] == nullptr) { 132048f512ceSopenharmony_ci continue; 132148f512ceSopenharmony_ci } 132248f512ceSopenharmony_ci koMaps[symbol.module_]->AddSymbol(std::move(symbol)); 132348f512ceSopenharmony_ci } 132448f512ceSopenharmony_ci 132548f512ceSopenharmony_ci HLOGD("devhost loaded %zu symbolfiles", koMaps.size()); 132648f512ceSopenharmony_ci for (auto &it : koMaps) { 132748f512ceSopenharmony_ci if (it.second == nullptr) { 132848f512ceSopenharmony_ci continue; 132948f512ceSopenharmony_ci } 133048f512ceSopenharmony_ci HLOGD("Load %zu symbols to %s", it.second->GetSymbols().size(), 133148f512ceSopenharmony_ci it.second->filePath_.c_str()); 133248f512ceSopenharmony_ci symbolsFiles_.emplace_back(std::move(it.second)); 133348f512ceSopenharmony_ci } 133448f512ceSopenharmony_ci } else { 133548f512ceSopenharmony_ci HLOGW("symbols file for devhost parse failed."); 133648f512ceSopenharmony_ci } 133748f512ceSopenharmony_ci 133848f512ceSopenharmony_ci // update normal symbole files 133948f512ceSopenharmony_ci VirtualThread &kthread = GetThread(devhostPid_, devhostPid_); 134048f512ceSopenharmony_ci for (const auto &map : kthread.GetMaps()) { 134148f512ceSopenharmony_ci UpdateSymbols(map, devhostPid_); 134248f512ceSopenharmony_ci } 134348f512ceSopenharmony_ci} 134448f512ceSopenharmony_ci 134548f512ceSopenharmony_civoid VirtualRuntime::FixHMBundleMmap(char *filename, int pid, u16 &headerSize) 134648f512ceSopenharmony_ci{ 134748f512ceSopenharmony_ci if (!isHM_) { 134848f512ceSopenharmony_ci return; 134948f512ceSopenharmony_ci } 135048f512ceSopenharmony_ci // fix bundle path in mmap 135148f512ceSopenharmony_ci std::string newFilename = filename; 135248f512ceSopenharmony_ci VirtualThread &thread = GetThread(pid, pid); 135348f512ceSopenharmony_ci if (NeedAdaptHMBundlePath(newFilename, thread.name_)) { 135448f512ceSopenharmony_ci size_t oldSize = strlen(filename); 135548f512ceSopenharmony_ci (void)memset_s(filename, KILO, '\0', KILO); 135648f512ceSopenharmony_ci if (strncpy_s(filename, KILO, newFilename.c_str(), newFilename.size()) != 0) { 135748f512ceSopenharmony_ci HLOGD("strncpy_s recordMmap2 failed!"); 135848f512ceSopenharmony_ci } 135948f512ceSopenharmony_ci headerSize += newFilename.size() - oldSize; 136048f512ceSopenharmony_ci } 136148f512ceSopenharmony_ci} 136248f512ceSopenharmony_ci 136348f512ceSopenharmony_civoid VirtualRuntime::SetDevhostPid(pid_t devhost) 136448f512ceSopenharmony_ci{ 136548f512ceSopenharmony_ci HLOGD("Set devhost pid: %d", devhost); 136648f512ceSopenharmony_ci devhostPid_ = devhost; 136748f512ceSopenharmony_ci} 136848f512ceSopenharmony_ci 136948f512ceSopenharmony_cibool VirtualRuntime::IsKernelThread(pid_t pid) 137048f512ceSopenharmony_ci{ 137148f512ceSopenharmony_ci if (!isHM_) { 137248f512ceSopenharmony_ci return false; 137348f512ceSopenharmony_ci } 137448f512ceSopenharmony_ci return pid == SYSMGR_PID || pid == devhostPid_; 137548f512ceSopenharmony_ci} 137648f512ceSopenharmony_ci 137748f512ceSopenharmony_ci} // namespace HiPerf 137848f512ceSopenharmony_ci} // namespace Developtools 137948f512ceSopenharmony_ci} // namespace OHOS 1380