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