148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci
1648f512ceSopenharmony_ci#define HILOG_TAG "Record"
1748f512ceSopenharmony_ci
1848f512ceSopenharmony_ci#include "subcommand_record.h"
1948f512ceSopenharmony_ci
2048f512ceSopenharmony_ci#include <csignal>
2148f512ceSopenharmony_ci#include <cstdlib>
2248f512ceSopenharmony_ci#include <ctime>
2348f512ceSopenharmony_ci#include <memory>
2448f512ceSopenharmony_ci#include <poll.h>
2548f512ceSopenharmony_ci#if defined(CONFIG_HAS_SYSPARA)
2648f512ceSopenharmony_ci#include <parameters.h>
2748f512ceSopenharmony_ci#endif
2848f512ceSopenharmony_ci#include <sys/stat.h>
2948f512ceSopenharmony_ci#include <sys/utsname.h>
3048f512ceSopenharmony_ci#include <unistd.h>
3148f512ceSopenharmony_ci
3248f512ceSopenharmony_ci#include "command.h"
3348f512ceSopenharmony_ci#include "debug_logger.h"
3448f512ceSopenharmony_ci#include "hiperf_client.h"
3548f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos
3648f512ceSopenharmony_ci#include "hiperf_hilog.h"
3748f512ceSopenharmony_ci#endif
3848f512ceSopenharmony_ci#include "option.h"
3948f512ceSopenharmony_ci#include "perf_event_record.h"
4048f512ceSopenharmony_ci#include "perf_file_reader.h"
4148f512ceSopenharmony_ci#include "utilities.h"
4248f512ceSopenharmony_ci#include "subcommand_report.h"
4348f512ceSopenharmony_ci
4448f512ceSopenharmony_ciusing namespace std::chrono;
4548f512ceSopenharmony_cinamespace OHOS {
4648f512ceSopenharmony_cinamespace Developtools {
4748f512ceSopenharmony_cinamespace HiPerf {
4848f512ceSopenharmony_ciconst std::string CONTROL_CMD_PREPARE = "prepare";
4948f512ceSopenharmony_ciconst std::string CONTROL_CMD_START = "start";
5048f512ceSopenharmony_ciconst std::string CONTROL_CMD_PAUSE = "pause";
5148f512ceSopenharmony_ciconst std::string CONTROL_CMD_RESUME = "resume";
5248f512ceSopenharmony_ciconst std::string CONTROL_CMD_STOP = "stop";
5348f512ceSopenharmony_ciconst std::string CONTROL_FIFO_FILE_C2S = "/data/local/tmp/.hiperf_record_control_c2s";
5448f512ceSopenharmony_ciconst std::string CONTROL_FIFO_FILE_S2C = "/data/local/tmp/.hiperf_record_control_s2c";
5548f512ceSopenharmony_ci
5648f512ceSopenharmony_ciconst std::string PERF_CPU_TIME_MAX_PERCENT = "/proc/sys/kernel/perf_cpu_time_max_percent";
5748f512ceSopenharmony_ciconst std::string PERF_EVENT_MAX_SAMPLE_RATE = "/proc/sys/kernel/perf_event_max_sample_rate";
5848f512ceSopenharmony_ciconst std::string PERF_EVENT_MLOCK_KB = "/proc/sys/kernel/perf_event_mlock_kb";
5948f512ceSopenharmony_ciconst std::string SCHED_SWITCH = "/sys/kernel/tracing/events/sched/sched_switch/enable";
6048f512ceSopenharmony_ciconst std::string SCHED_SWITCH_DEBUG = "/sys/kernel/debug/tracing/events/sched/sched_switch/enable";
6148f512ceSopenharmony_ciconst std::string PROC_VERSION = "/proc/version";
6248f512ceSopenharmony_ciconst std::string SAVED_CMDLINES_SIZE = "/sys/kernel/tracing/saved_cmdlines_size";
6348f512ceSopenharmony_ci
6448f512ceSopenharmony_ci// when there are many events, start record will take more time.
6548f512ceSopenharmony_ciconst std::chrono::milliseconds CONTROL_WAITREPY_TOMEOUT = 2000ms;
6648f512ceSopenharmony_ciconst std::chrono::milliseconds CONTROL_WAITREPY_TOMEOUT_CHECK = 1000ms;
6748f512ceSopenharmony_ci
6848f512ceSopenharmony_ciconstexpr uint64_t MASK_ALIGNED_8 = 7;
6948f512ceSopenharmony_ciconstexpr size_t MAX_DWARF_CALL_CHAIN = 2;
7048f512ceSopenharmony_ciconstexpr uint64_t TYPE_PERF_SAMPLE_BRANCH = PERF_SAMPLE_BRANCH_ANY | PERF_SAMPLE_BRANCH_ANY_CALL |
7148f512ceSopenharmony_ci                                             PERF_SAMPLE_BRANCH_ANY_RETURN | PERF_SAMPLE_BRANCH_IND_JUMP |
7248f512ceSopenharmony_ci                                             PERF_SAMPLE_BRANCH_IND_CALL | PERF_SAMPLE_BRANCH_COND |
7348f512ceSopenharmony_ci                                             PERF_SAMPLE_BRANCH_CALL;
7448f512ceSopenharmony_ci
7548f512ceSopenharmony_ciint GetClockId(const std::string &name)
7648f512ceSopenharmony_ci{
7748f512ceSopenharmony_ci    static std::map<std::string, int> mapClockid = {
7848f512ceSopenharmony_ci        {"realtime", CLOCK_REALTIME},   {"boottime", CLOCK_BOOTTIME},
7948f512ceSopenharmony_ci        {"monotonic", CLOCK_MONOTONIC}, {"monotonic_raw", CLOCK_MONOTONIC_RAW},
8048f512ceSopenharmony_ci        {"clock_tai", CLOCK_TAI},
8148f512ceSopenharmony_ci    };
8248f512ceSopenharmony_ci
8348f512ceSopenharmony_ci    auto it = mapClockid.find(name);
8448f512ceSopenharmony_ci    if (it == mapClockid.end()) {
8548f512ceSopenharmony_ci        return -1;
8648f512ceSopenharmony_ci    } else {
8748f512ceSopenharmony_ci        return it->second;
8848f512ceSopenharmony_ci    }
8948f512ceSopenharmony_ci}
9048f512ceSopenharmony_ci
9148f512ceSopenharmony_ciuint64_t GetBranchSampleType(const std::string &name)
9248f512ceSopenharmony_ci{
9348f512ceSopenharmony_ci    static std::map<std::string, uint64_t> mapBranchSampleType = {
9448f512ceSopenharmony_ci        {"u", PERF_SAMPLE_BRANCH_USER},
9548f512ceSopenharmony_ci        {"k", PERF_SAMPLE_BRANCH_KERNEL},
9648f512ceSopenharmony_ci        {"any", PERF_SAMPLE_BRANCH_ANY},
9748f512ceSopenharmony_ci        {"any_call", PERF_SAMPLE_BRANCH_ANY_CALL},
9848f512ceSopenharmony_ci        {"any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN},
9948f512ceSopenharmony_ci        {"ind_call", PERF_SAMPLE_BRANCH_IND_CALL},
10048f512ceSopenharmony_ci        {"ind_jmp", PERF_SAMPLE_BRANCH_IND_JUMP},
10148f512ceSopenharmony_ci        {"cond", PERF_SAMPLE_BRANCH_COND},
10248f512ceSopenharmony_ci        {"call", PERF_SAMPLE_BRANCH_CALL},
10348f512ceSopenharmony_ci    };
10448f512ceSopenharmony_ci
10548f512ceSopenharmony_ci    auto it = mapBranchSampleType.find(name);
10648f512ceSopenharmony_ci    if (it == mapBranchSampleType.end()) {
10748f512ceSopenharmony_ci        return 0;
10848f512ceSopenharmony_ci    } else {
10948f512ceSopenharmony_ci        return it->second;
11048f512ceSopenharmony_ci    }
11148f512ceSopenharmony_ci}
11248f512ceSopenharmony_ci
11348f512ceSopenharmony_ciSubCommandRecord::~SubCommandRecord()
11448f512ceSopenharmony_ci{
11548f512ceSopenharmony_ci    CloseClientThread();
11648f512ceSopenharmony_ci}
11748f512ceSopenharmony_ci
11848f512ceSopenharmony_civoid SubCommandRecord::DumpOptions() const
11948f512ceSopenharmony_ci{
12048f512ceSopenharmony_ci    printf("DumpOptions:\n");
12148f512ceSopenharmony_ci    printf(" targetSystemWide:\t%s\n", targetSystemWide_ ? "true" : "false");
12248f512ceSopenharmony_ci    printf(" selectCpus:\t%s\n", VectorToString(selectCpus_).c_str());
12348f512ceSopenharmony_ci    printf(" timeStopSec:\t%f sec\n", timeStopSec_);
12448f512ceSopenharmony_ci    printf(" frequency:\t%d\n", frequency_);
12548f512ceSopenharmony_ci    printf(" selectEvents:\t%s\n", VectorToString(selectEvents_).c_str());
12648f512ceSopenharmony_ci    int i = 0;
12748f512ceSopenharmony_ci    for (auto &group : selectGroups_) {
12848f512ceSopenharmony_ci        i++;
12948f512ceSopenharmony_ci        printf(" selectGroups:\t%2d:%s\n", i, VectorToString(group).c_str());
13048f512ceSopenharmony_ci    }
13148f512ceSopenharmony_ci    printf(" no_inherit:\t%s\n", noInherit_ ? "true" : "false");
13248f512ceSopenharmony_ci    printf(" selectPids:\t%s\n", VectorToString(selectPids_).c_str());
13348f512ceSopenharmony_ci    printf(" selectTids:\t%s\n", VectorToString(selectTids_).c_str());
13448f512ceSopenharmony_ci    printf(" excludeTids:\t%s\n", VectorToString(excludeTids_).c_str());
13548f512ceSopenharmony_ci    printf(" excludeThreads:\t%s\n", VectorToString(excludeThreadNames_).c_str());
13648f512ceSopenharmony_ci    printf(" kernelCallChain:\t%s\n", kernelCallChain_ ? "true" : "false");
13748f512ceSopenharmony_ci    printf(" callChainUserOnly_:\t%s\n", callChainUserOnly_ ? "true" : "false");
13848f512ceSopenharmony_ci    printf(" restart:\t%s\n", restart_ ? "true" : "false");
13948f512ceSopenharmony_ci    printf(" verbose:\t%s\n", verboseReport_ ? "true" : "false");
14048f512ceSopenharmony_ci    printf(" excludePerf:\t%d\n", excludeHiperf_);
14148f512ceSopenharmony_ci    printf(" cpuPercent:\t%d\n", cpuPercent_);
14248f512ceSopenharmony_ci    printf(" offCPU_:\t%d\n", offCPU_);
14348f512ceSopenharmony_ci    printf(" delayUnwind_:\t%d\n", delayUnwind_);
14448f512ceSopenharmony_ci    printf(" disableUnwind_:\t%d\n", disableUnwind_);
14548f512ceSopenharmony_ci    printf(" disableCallstackExpend_:\t%d\n", disableCallstackExpend_);
14648f512ceSopenharmony_ci    printf(" enableDebugInfoSymbolic:\t%d\n", enableDebugInfoSymbolic_);
14748f512ceSopenharmony_ci    printf(" symbolDir_:\t%s\n", VectorToString(symbolDir_).c_str());
14848f512ceSopenharmony_ci    printf(" outputFilename_:\t%s\n", outputFilename_.c_str());
14948f512ceSopenharmony_ci    printf(" appPackage_:\t%s\n", appPackage_.c_str());
15048f512ceSopenharmony_ci    printf(" checkAppMs_:\t%d\n", checkAppMs_);
15148f512ceSopenharmony_ci    printf(" clockId_:\t%s\n", clockId_.c_str());
15248f512ceSopenharmony_ci    printf(" mmapPages_:\t%d\n", mmapPages_);
15348f512ceSopenharmony_ci    printf(" dataLimit:\t%s\n", strLimit_.c_str());
15448f512ceSopenharmony_ci    printf(" callStack:\t%s\n", VectorToString(callStackType_).c_str());
15548f512ceSopenharmony_ci    printf(" branchSampleTypes:\t%s\n", VectorToString(vecBranchFilters_).c_str());
15648f512ceSopenharmony_ci    printf(" trackedCommand:\t%s\n", VectorToString(trackedCommand_).c_str());
15748f512ceSopenharmony_ci    printf(" pipe_input:\t%d\n", clientPipeInput_);
15848f512ceSopenharmony_ci    printf(" pipe_output:\t%d\n", clientPipeOutput_);
15948f512ceSopenharmony_ci    printf(" cmdlinesSize_:\t%d\n", cmdlinesSize_);
16048f512ceSopenharmony_ci    printf(" report_:\t%s\n", report_ ? "true" : "false");
16148f512ceSopenharmony_ci}
16248f512ceSopenharmony_ci
16348f512ceSopenharmony_cibool SubCommandRecord::GetSpeOptions()
16448f512ceSopenharmony_ci{
16548f512ceSopenharmony_ci    std::string speName;
16648f512ceSopenharmony_ci
16748f512ceSopenharmony_ci    for (size_t i = 0; i < selectEvents_.size(); i++) {
16848f512ceSopenharmony_ci        std::string optionValue = selectEvents_[i];
16948f512ceSopenharmony_ci
17048f512ceSopenharmony_ci        std::vector<std::string> valueExpressions = StringSplit(optionValue, "/");
17148f512ceSopenharmony_ci        if (i == 0) {
17248f512ceSopenharmony_ci            if (valueExpressions.size() > 1) {
17348f512ceSopenharmony_ci                speName = valueExpressions[0];
17448f512ceSopenharmony_ci                valueExpressions.erase(valueExpressions.begin());
17548f512ceSopenharmony_ci            } else {
17648f512ceSopenharmony_ci                break;
17748f512ceSopenharmony_ci            }
17848f512ceSopenharmony_ci        }
17948f512ceSopenharmony_ci
18048f512ceSopenharmony_ci        for (auto item: valueExpressions) {
18148f512ceSopenharmony_ci            std::vector<std::string> expressions = StringSplit(item, "=");
18248f512ceSopenharmony_ci            size_t itemNum = 2;
18348f512ceSopenharmony_ci            if (expressions.size() == itemNum) {
18448f512ceSopenharmony_ci                std::string name = expressions[0];
18548f512ceSopenharmony_ci                unsigned long long num = std::stoull(expressions[1]);
18648f512ceSopenharmony_ci                if (speOptMap_.find(name) != speOptMap_.end()) {
18748f512ceSopenharmony_ci                    speOptMap_[name] = num;
18848f512ceSopenharmony_ci                }
18948f512ceSopenharmony_ci                if (num != 0) {
19048f512ceSopenharmony_ci                    speOptions_.emplace_back(name);
19148f512ceSopenharmony_ci                }
19248f512ceSopenharmony_ci            }
19348f512ceSopenharmony_ci        }
19448f512ceSopenharmony_ci    }
19548f512ceSopenharmony_ci    if (speName.size() > 0) {
19648f512ceSopenharmony_ci        selectEvents_.clear();
19748f512ceSopenharmony_ci        selectEvents_.emplace_back(speName);
19848f512ceSopenharmony_ci    }
19948f512ceSopenharmony_ci    return true;
20048f512ceSopenharmony_ci}
20148f512ceSopenharmony_ci
20248f512ceSopenharmony_cibool SubCommandRecord::GetOptions(std::vector<std::string> &args)
20348f512ceSopenharmony_ci{
20448f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-a", targetSystemWide_)) {
20548f512ceSopenharmony_ci        return false;
20648f512ceSopenharmony_ci    }
20748f512ceSopenharmony_ci    if (targetSystemWide_ && !IsSupportNonDebuggableApp()) {
20848f512ceSopenharmony_ci        HLOGD("-a option needs root privilege for system wide profiling.");
20948f512ceSopenharmony_ci        printf("-a option needs root privilege for system wide profiling.\n");
21048f512ceSopenharmony_ci        return false;
21148f512ceSopenharmony_ci    }
21248f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--exclude-hiperf", excludeHiperf_)) {
21348f512ceSopenharmony_ci        return false;
21448f512ceSopenharmony_ci    }
21548f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-z", compressData_)) {
21648f512ceSopenharmony_ci        return false;
21748f512ceSopenharmony_ci    }
21848f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--no-inherit", noInherit_)) {
21948f512ceSopenharmony_ci        return false;
22048f512ceSopenharmony_ci    }
22148f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--offcpu", offCPU_)) {
22248f512ceSopenharmony_ci        return false;
22348f512ceSopenharmony_ci    }
22448f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--delay-unwind", delayUnwind_)) {
22548f512ceSopenharmony_ci        return false;
22648f512ceSopenharmony_ci    }
22748f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--disable-unwind", disableUnwind_)) {
22848f512ceSopenharmony_ci        return false;
22948f512ceSopenharmony_ci    }
23048f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--disable-callstack-expand", disableCallstackExpend_)) {
23148f512ceSopenharmony_ci        return false;
23248f512ceSopenharmony_ci    }
23348f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--enable-debuginfo-symbolic", enableDebugInfoSymbolic_)) {
23448f512ceSopenharmony_ci        return false;
23548f512ceSopenharmony_ci    }
23648f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--verbose", verboseReport_)) {
23748f512ceSopenharmony_ci        return false;
23848f512ceSopenharmony_ci    }
23948f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-d", timeStopSec_)) {
24048f512ceSopenharmony_ci        return false;
24148f512ceSopenharmony_ci    }
24248f512ceSopenharmony_ci    if (!GetOptionFrequencyAndPeriod(args)) {
24348f512ceSopenharmony_ci        return false;
24448f512ceSopenharmony_ci    }
24548f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--cpu-limit", cpuPercent_)) {
24648f512ceSopenharmony_ci        return false;
24748f512ceSopenharmony_ci    }
24848f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-m", mmapPages_)) {
24948f512ceSopenharmony_ci        return false;
25048f512ceSopenharmony_ci    }
25148f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--symbol-dir", symbolDir_)) {
25248f512ceSopenharmony_ci        return false;
25348f512ceSopenharmony_ci    }
25448f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-o", outputFilename_)) {
25548f512ceSopenharmony_ci        return false;
25648f512ceSopenharmony_ci    }
25748f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--app", appPackage_)) {
25848f512ceSopenharmony_ci        return false;
25948f512ceSopenharmony_ci    }
26048f512ceSopenharmony_ci    if (!IsExistDebugByApp(appPackage_)) {
26148f512ceSopenharmony_ci        return false;
26248f512ceSopenharmony_ci    }
26348f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--chkms", checkAppMs_)) {
26448f512ceSopenharmony_ci        return false;
26548f512ceSopenharmony_ci    }
26648f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--clockid", clockId_)) {
26748f512ceSopenharmony_ci        return false;
26848f512ceSopenharmony_ci    }
26948f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-c", selectCpus_)) {
27048f512ceSopenharmony_ci        return false;
27148f512ceSopenharmony_ci    }
27248f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-p", selectPids_)) {
27348f512ceSopenharmony_ci        return false;
27448f512ceSopenharmony_ci    }
27548f512ceSopenharmony_ci    if (!IsExistDebugByPid(selectPids_)) {
27648f512ceSopenharmony_ci        return false;
27748f512ceSopenharmony_ci    }
27848f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-t", selectTids_)) {
27948f512ceSopenharmony_ci        return false;
28048f512ceSopenharmony_ci    }
28148f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-e", selectEvents_)) {
28248f512ceSopenharmony_ci        return false;
28348f512ceSopenharmony_ci    }
28448f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-g", selectGroups_)) {
28548f512ceSopenharmony_ci        return false;
28648f512ceSopenharmony_ci    }
28748f512ceSopenharmony_ci    if (!GetSpeOptions()) {
28848f512ceSopenharmony_ci        return false;
28948f512ceSopenharmony_ci    }
29048f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-s", callStackType_)) {
29148f512ceSopenharmony_ci        return false;
29248f512ceSopenharmony_ci    }
29348f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--kernel-callchain", kernelCallChain_)) {
29448f512ceSopenharmony_ci        return false;
29548f512ceSopenharmony_ci    }
29648f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--callchain-useronly", callChainUserOnly_)) {
29748f512ceSopenharmony_ci        return false;
29848f512ceSopenharmony_ci    }
29948f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--exclude-tid", excludeTids_)) {
30048f512ceSopenharmony_ci        return false;
30148f512ceSopenharmony_ci    }
30248f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--exclude-thread", excludeThreadNames_)) {
30348f512ceSopenharmony_ci        return false;
30448f512ceSopenharmony_ci    }
30548f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--restart", restart_)) {
30648f512ceSopenharmony_ci        return false;
30748f512ceSopenharmony_ci    }
30848f512ceSopenharmony_ci    std::vector<std::string> callStackType = {};
30948f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--call-stack", callStackType)) {
31048f512ceSopenharmony_ci        return false;
31148f512ceSopenharmony_ci    }
31248f512ceSopenharmony_ci    if (!callStackType_.empty()) {
31348f512ceSopenharmony_ci        if (!callStackType.empty()) {
31448f512ceSopenharmony_ci            printf("'-s %s --call-stack %s' option usage error, please check usage.\n",
31548f512ceSopenharmony_ci                VectorToString(callStackType_).c_str(), VectorToString(callStackType).c_str());
31648f512ceSopenharmony_ci            return false;
31748f512ceSopenharmony_ci        }
31848f512ceSopenharmony_ci    } else {
31948f512ceSopenharmony_ci        callStackType_ = callStackType;
32048f512ceSopenharmony_ci    }
32148f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--data-limit", strLimit_)) {
32248f512ceSopenharmony_ci        return false;
32348f512ceSopenharmony_ci    }
32448f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "-j", vecBranchFilters_)) {
32548f512ceSopenharmony_ci        return false;
32648f512ceSopenharmony_ci    }
32748f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--pipe_input", clientPipeInput_)) {
32848f512ceSopenharmony_ci        return false;
32948f512ceSopenharmony_ci    }
33048f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--pipe_output", clientPipeOutput_)) {
33148f512ceSopenharmony_ci        return false;
33248f512ceSopenharmony_ci    }
33348f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--control", controlCmd_)) {
33448f512ceSopenharmony_ci        return false;
33548f512ceSopenharmony_ci    }
33648f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--dedup_stack", dedupStack_)) {
33748f512ceSopenharmony_ci        return false;
33848f512ceSopenharmony_ci    }
33948f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--cmdline-size", cmdlinesSize_)) {
34048f512ceSopenharmony_ci        return false;
34148f512ceSopenharmony_ci    }
34248f512ceSopenharmony_ci    if (!Option::GetOptionValue(args, "--report", report_)) {
34348f512ceSopenharmony_ci        return false;
34448f512ceSopenharmony_ci    }
34548f512ceSopenharmony_ci    if (targetSystemWide_ && dedupStack_) {
34648f512ceSopenharmony_ci        printf("-a option is conflict with --dedup_stack.\n");
34748f512ceSopenharmony_ci        return false;
34848f512ceSopenharmony_ci    }
34948f512ceSopenharmony_ci    CHECK_TRUE(!Option::GetOptionTrackedCommand(args, trackedCommand_), false, 0, "");
35048f512ceSopenharmony_ci    CHECK_TRUE(!args.empty(), false, LOG_TYPE_PRINTF,
35148f512ceSopenharmony_ci               "'%s' option usage error, please check usage.\n", VectorToString(args).c_str());
35248f512ceSopenharmony_ci    return true;
35348f512ceSopenharmony_ci}
35448f512ceSopenharmony_ci
35548f512ceSopenharmony_cibool SubCommandRecord::GetOptionFrequencyAndPeriod(std::vector<std::string> &args)
35648f512ceSopenharmony_ci{
35748f512ceSopenharmony_ci    if (Option::FindOption(args, "-f") != args.end()) {
35848f512ceSopenharmony_ci        if (!Option::GetOptionValue(args, "-f", frequency_)) {
35948f512ceSopenharmony_ci            return false;
36048f512ceSopenharmony_ci        }
36148f512ceSopenharmony_ci        if (frequency_ < MIN_SAMPLE_FREQUENCY || frequency_ > MAX_SAMPLE_FREQUENCY) {
36248f512ceSopenharmony_ci            printf("Invalid -f value '%d', frequency should be in %d~%d \n", frequency_,
36348f512ceSopenharmony_ci                   MIN_SAMPLE_FREQUENCY, MAX_SAMPLE_FREQUENCY);
36448f512ceSopenharmony_ci            return false;
36548f512ceSopenharmony_ci        }
36648f512ceSopenharmony_ci    }
36748f512ceSopenharmony_ci    if (Option::FindOption(args, "--period") != args.end()) {
36848f512ceSopenharmony_ci        if (frequency_ != 0) {
36948f512ceSopenharmony_ci            printf("option -f and --period is conflict, please check usage\n");
37048f512ceSopenharmony_ci            return false;
37148f512ceSopenharmony_ci        }
37248f512ceSopenharmony_ci        if (!Option::GetOptionValue(args, "--period", period_)) {
37348f512ceSopenharmony_ci            return false;
37448f512ceSopenharmony_ci        }
37548f512ceSopenharmony_ci        if (period_ <= 0) {
37648f512ceSopenharmony_ci            printf("Invalid --period value '%d', period should be greater than 0\n", period_);
37748f512ceSopenharmony_ci            return false;
37848f512ceSopenharmony_ci        }
37948f512ceSopenharmony_ci    }
38048f512ceSopenharmony_ci    return true;
38148f512ceSopenharmony_ci}
38248f512ceSopenharmony_ci
38348f512ceSopenharmony_cibool SubCommandRecord::CheckDataLimitOption()
38448f512ceSopenharmony_ci{
38548f512ceSopenharmony_ci    if (!strLimit_.empty()) {
38648f512ceSopenharmony_ci        if (!ParseDataLimitOption(strLimit_)) {
38748f512ceSopenharmony_ci            printf("Invalid --data-limit value %s\n", strLimit_.c_str());
38848f512ceSopenharmony_ci            return false;
38948f512ceSopenharmony_ci        }
39048f512ceSopenharmony_ci    }
39148f512ceSopenharmony_ci    return true;
39248f512ceSopenharmony_ci}
39348f512ceSopenharmony_ci
39448f512ceSopenharmony_cibool SubCommandRecord::CheckSelectCpuPidOption()
39548f512ceSopenharmony_ci{
39648f512ceSopenharmony_ci    if (!selectCpus_.empty()) {
39748f512ceSopenharmony_ci        int maxCpuid = sysconf(_SC_NPROCESSORS_CONF) - 1;
39848f512ceSopenharmony_ci        for (auto cpu : selectCpus_) {
39948f512ceSopenharmony_ci            if (cpu < 0 || cpu > maxCpuid) {
40048f512ceSopenharmony_ci                printf("Invalid -c value '%d', the CPU ID should be in 0~%d \n", cpu, maxCpuid);
40148f512ceSopenharmony_ci                return false;
40248f512ceSopenharmony_ci            }
40348f512ceSopenharmony_ci        }
40448f512ceSopenharmony_ci    }
40548f512ceSopenharmony_ci
40648f512ceSopenharmony_ci    if (!selectPids_.empty()) {
40748f512ceSopenharmony_ci        for (auto pid : selectPids_) {
40848f512ceSopenharmony_ci            if (pid <= 0) {
40948f512ceSopenharmony_ci                printf("Invalid -p value '%d', the pid should be larger than 0\n", pid);
41048f512ceSopenharmony_ci                return false;
41148f512ceSopenharmony_ci            }
41248f512ceSopenharmony_ci        }
41348f512ceSopenharmony_ci    }
41448f512ceSopenharmony_ci    if (!selectTids_.empty()) {
41548f512ceSopenharmony_ci        for (auto tid : selectTids_) {
41648f512ceSopenharmony_ci            if (tid <= 0) {
41748f512ceSopenharmony_ci                printf("Invalid -t value '%d', the tid should be larger than 0\n", tid);
41848f512ceSopenharmony_ci                return false;
41948f512ceSopenharmony_ci            }
42048f512ceSopenharmony_ci        }
42148f512ceSopenharmony_ci    }
42248f512ceSopenharmony_ci    return true;
42348f512ceSopenharmony_ci}
42448f512ceSopenharmony_ci
42548f512ceSopenharmony_cibool SubCommandRecord::CheckArgsRange()
42648f512ceSopenharmony_ci{
42748f512ceSopenharmony_ci    if (timeStopSec_ < MIN_STOP_SECONDS || timeStopSec_ > MAX_STOP_SECONDS) {
42848f512ceSopenharmony_ci        printf("Invalid -d value '%.3f', the seconds should be in %.3f~%.3f  \n", timeStopSec_,
42948f512ceSopenharmony_ci               MIN_STOP_SECONDS, MAX_STOP_SECONDS);
43048f512ceSopenharmony_ci        return false;
43148f512ceSopenharmony_ci    }
43248f512ceSopenharmony_ci    if (cpuPercent_ < MIN_CPU_PERCENT || cpuPercent_ > MAX_CPU_PERCENT) {
43348f512ceSopenharmony_ci        printf("Invalid --cpu-limit value '%d', CPU percent should be in %d~%d \n", cpuPercent_,
43448f512ceSopenharmony_ci               MIN_CPU_PERCENT, MAX_CPU_PERCENT);
43548f512ceSopenharmony_ci        return false;
43648f512ceSopenharmony_ci    }
43748f512ceSopenharmony_ci    if (checkAppMs_ < MIN_CHECK_APP_MS || checkAppMs_ > MAX_CHECK_APP_MS) {
43848f512ceSopenharmony_ci        printf("Invalid --chkms value '%d', the milliseconds should be in %d~%d \n", checkAppMs_,
43948f512ceSopenharmony_ci               MIN_CHECK_APP_MS, MAX_CHECK_APP_MS);
44048f512ceSopenharmony_ci        return false;
44148f512ceSopenharmony_ci    }
44248f512ceSopenharmony_ci    if (mmapPages_ < MIN_PERF_MMAP_PAGE || mmapPages_ > MAX_PERF_MMAP_PAGE ||
44348f512ceSopenharmony_ci        !PowerOfTwo(mmapPages_)) {
44448f512ceSopenharmony_ci        printf("Invalid -m value '%d', value should be in %d~%d and must be a power of two \n",
44548f512ceSopenharmony_ci               mmapPages_, MIN_PERF_MMAP_PAGE, MAX_PERF_MMAP_PAGE);
44648f512ceSopenharmony_ci        return false;
44748f512ceSopenharmony_ci    }
44848f512ceSopenharmony_ci    if (cmdlinesSize_ < MIN_SAVED_CMDLINES_SIZE || cmdlinesSize_ > MAX_SAVED_CMDLINES_SIZE ||
44948f512ceSopenharmony_ci        !PowerOfTwo(cmdlinesSize_)) {
45048f512ceSopenharmony_ci        printf("Invalid --cmdline-size value '%d', value should be in %d~%d and must be a power of two \n",
45148f512ceSopenharmony_ci               cmdlinesSize_, MIN_SAVED_CMDLINES_SIZE, MAX_SAVED_CMDLINES_SIZE);
45248f512ceSopenharmony_ci        return false;
45348f512ceSopenharmony_ci    }
45448f512ceSopenharmony_ci    if (!clockId_.empty() && GetClockId(clockId_) == -1) {
45548f512ceSopenharmony_ci        printf("Invalid --clockid value %s\n", clockId_.c_str());
45648f512ceSopenharmony_ci        return false;
45748f512ceSopenharmony_ci    }
45848f512ceSopenharmony_ci    if (!targetSystemWide_ && excludeHiperf_) {
45948f512ceSopenharmony_ci        printf("--exclude-hiperf must be used with -a\n");
46048f512ceSopenharmony_ci        return false;
46148f512ceSopenharmony_ci    }
46248f512ceSopenharmony_ci    return true;
46348f512ceSopenharmony_ci}
46448f512ceSopenharmony_ci
46548f512ceSopenharmony_cibool SubCommandRecord::CheckOptions()
46648f512ceSopenharmony_ci{
46748f512ceSopenharmony_ci    if (!CheckArgsRange()) {
46848f512ceSopenharmony_ci        return false;
46948f512ceSopenharmony_ci    }
47048f512ceSopenharmony_ci    if (!CheckDataLimitOption()) {
47148f512ceSopenharmony_ci        return false;
47248f512ceSopenharmony_ci    }
47348f512ceSopenharmony_ci    if (!ParseCallStackOption(callStackType_)) {
47448f512ceSopenharmony_ci        return false;
47548f512ceSopenharmony_ci    }
47648f512ceSopenharmony_ci    if (!ParseBranchSampleType(vecBranchFilters_)) {
47748f512ceSopenharmony_ci        return false;
47848f512ceSopenharmony_ci    }
47948f512ceSopenharmony_ci    if (!CheckSelectCpuPidOption()) {
48048f512ceSopenharmony_ci        return false;
48148f512ceSopenharmony_ci    }
48248f512ceSopenharmony_ci    if (!ParseControlCmd(controlCmd_)) {
48348f512ceSopenharmony_ci        return false;
48448f512ceSopenharmony_ci    }
48548f512ceSopenharmony_ci    if (!CheckTargetProcessOptions()) {
48648f512ceSopenharmony_ci        return false;
48748f512ceSopenharmony_ci    }
48848f512ceSopenharmony_ci    if (!CheckReportOption()) {
48948f512ceSopenharmony_ci        return false;
49048f512ceSopenharmony_ci    }
49148f512ceSopenharmony_ci    return true;
49248f512ceSopenharmony_ci}
49348f512ceSopenharmony_ci
49448f512ceSopenharmony_cibool SubCommandRecord::ParseOption(std::vector<std::string> &args)
49548f512ceSopenharmony_ci{
49648f512ceSopenharmony_ci    if (!GetOptions(args)) {
49748f512ceSopenharmony_ci        return false;
49848f512ceSopenharmony_ci    }
49948f512ceSopenharmony_ci    CHECK_TRUE(!args.empty(), false, LOG_TYPE_PRINTF, "unknown option %s\n", args.begin()->c_str());
50048f512ceSopenharmony_ci    if (controlCmd_.empty()) {
50148f512ceSopenharmony_ci        if (!CheckRestartOption(appPackage_, targetSystemWide_, restart_, selectPids_)) {
50248f512ceSopenharmony_ci            return false;
50348f512ceSopenharmony_ci        }
50448f512ceSopenharmony_ci    }
50548f512ceSopenharmony_ci    return CheckOptions();
50648f512ceSopenharmony_ci}
50748f512ceSopenharmony_ci
50848f512ceSopenharmony_cibool SubCommandRecord::CheckTargetProcessOptions()
50948f512ceSopenharmony_ci{
51048f512ceSopenharmony_ci    bool hasTarget = false;
51148f512ceSopenharmony_ci    if (targetSystemWide_) {
51248f512ceSopenharmony_ci        hasTarget = true;
51348f512ceSopenharmony_ci    }
51448f512ceSopenharmony_ci    if (!selectPids_.empty() || !selectTids_.empty()) {
51548f512ceSopenharmony_ci        CHECK_TRUE(hasTarget, false, LOG_TYPE_PRINTF,
51648f512ceSopenharmony_ci                   "-p/-t %s options conflict, please check usage\n", VectorToString(selectPids_).c_str());
51748f512ceSopenharmony_ci        hasTarget = true;
51848f512ceSopenharmony_ci    }
51948f512ceSopenharmony_ci    if (!trackedCommand_.empty()) {
52048f512ceSopenharmony_ci        if (hasTarget) {
52148f512ceSopenharmony_ci            printf("%s options conflict, please check usage\n",
52248f512ceSopenharmony_ci                   VectorToString(trackedCommand_).c_str());
52348f512ceSopenharmony_ci            return false;
52448f512ceSopenharmony_ci        }
52548f512ceSopenharmony_ci        if (!IsRoot()) {
52648f512ceSopenharmony_ci            printf("%s options needs root privilege, please check usage\n",
52748f512ceSopenharmony_ci                   VectorToString(trackedCommand_).c_str());
52848f512ceSopenharmony_ci            return false;
52948f512ceSopenharmony_ci        }
53048f512ceSopenharmony_ci        hasTarget = true;
53148f512ceSopenharmony_ci    }
53248f512ceSopenharmony_ci    if (appPackage_ != "") {
53348f512ceSopenharmony_ci        if (hasTarget) {
53448f512ceSopenharmony_ci            printf("--app %s options conflict, please check usage\n", appPackage_.c_str());
53548f512ceSopenharmony_ci            return false;
53648f512ceSopenharmony_ci        }
53748f512ceSopenharmony_ci        hasTarget = true;
53848f512ceSopenharmony_ci    }
53948f512ceSopenharmony_ci    if (!hasTarget and (controlCmd_.empty() or controlCmd_ == CONTROL_CMD_PREPARE)) {
54048f512ceSopenharmony_ci        printf("please select a target process\n");
54148f512ceSopenharmony_ci        return false;
54248f512ceSopenharmony_ci    }
54348f512ceSopenharmony_ci    if (controlCmd_ == CONTROL_CMD_PREPARE) {
54448f512ceSopenharmony_ci        CHECK_TRUE(!CheckRestartOption(appPackage_, targetSystemWide_, restart_, selectPids_), false, 0, "");
54548f512ceSopenharmony_ci    }
54648f512ceSopenharmony_ci    return CheckTargetPids();
54748f512ceSopenharmony_ci}
54848f512ceSopenharmony_ci
54948f512ceSopenharmony_cibool SubCommandRecord::CheckTargetPids()
55048f512ceSopenharmony_ci{
55148f512ceSopenharmony_ci    for (auto pid : selectPids_) {
55248f512ceSopenharmony_ci        if (!IsDir("/proc/" + std::to_string(pid))) {
55348f512ceSopenharmony_ci            printf("not exist pid %d\n", pid);
55448f512ceSopenharmony_ci            return false;
55548f512ceSopenharmony_ci        }
55648f512ceSopenharmony_ci    }
55748f512ceSopenharmony_ci    for (auto tid : selectTids_) {
55848f512ceSopenharmony_ci        if (!IsDir("/proc/" + std::to_string(tid))) {
55948f512ceSopenharmony_ci            printf("not exist tid %d\n", tid);
56048f512ceSopenharmony_ci            return false;
56148f512ceSopenharmony_ci        }
56248f512ceSopenharmony_ci    }
56348f512ceSopenharmony_ci    if (!CheckAppIsRunning(selectPids_, appPackage_, checkAppMs_)) {
56448f512ceSopenharmony_ci        return false;
56548f512ceSopenharmony_ci    }
56648f512ceSopenharmony_ci    if (!selectPids_.empty()) {
56748f512ceSopenharmony_ci        for (auto pid : selectPids_) {
56848f512ceSopenharmony_ci            auto tids = GetSubthreadIDs(pid);
56948f512ceSopenharmony_ci            if (!tids.empty()) {
57048f512ceSopenharmony_ci                selectTids_.insert(selectTids_.end(), tids.begin(), tids.end());
57148f512ceSopenharmony_ci                mapPids_[pid] = tids;
57248f512ceSopenharmony_ci            }
57348f512ceSopenharmony_ci        }
57448f512ceSopenharmony_ci    }
57548f512ceSopenharmony_ci    if (!SubCommand::HandleSubCommandExclude(excludeTids_, excludeThreadNames_, selectTids_)) {
57648f512ceSopenharmony_ci        return false;
57748f512ceSopenharmony_ci    }
57848f512ceSopenharmony_ci    selectPids_.insert(selectPids_.end(), selectTids_.begin(), selectTids_.end());
57948f512ceSopenharmony_ci
58048f512ceSopenharmony_ci    return true;
58148f512ceSopenharmony_ci}
58248f512ceSopenharmony_ci
58348f512ceSopenharmony_cibool SubCommandRecord::CheckReportOption()
58448f512ceSopenharmony_ci{
58548f512ceSopenharmony_ci    if (targetSystemWide_ && report_) {
58648f512ceSopenharmony_ci        printf("--report options conflict, please check usage\n");
58748f512ceSopenharmony_ci        return false;
58848f512ceSopenharmony_ci    }
58948f512ceSopenharmony_ci    return true;
59048f512ceSopenharmony_ci}
59148f512ceSopenharmony_ci
59248f512ceSopenharmony_cibool SubCommandRecord::ParseDataLimitOption(const std::string &str)
59348f512ceSopenharmony_ci{
59448f512ceSopenharmony_ci    uint unit = 1;
59548f512ceSopenharmony_ci    char c = str.at(str.size() >= 1 ? str.size() - 1 : 0);
59648f512ceSopenharmony_ci    if (c == 'K' or c == 'k') {
59748f512ceSopenharmony_ci        unit = KILO;
59848f512ceSopenharmony_ci    } else if (c == 'm' or c == 'M') {
59948f512ceSopenharmony_ci        unit = KILO * KILO;
60048f512ceSopenharmony_ci    } else if (c == 'g' or c == 'G') {
60148f512ceSopenharmony_ci        unit = KILO * KILO * KILO;
60248f512ceSopenharmony_ci    } else {
60348f512ceSopenharmony_ci        return false;
60448f512ceSopenharmony_ci    }
60548f512ceSopenharmony_ci
60648f512ceSopenharmony_ci    std::string num = str.substr(0, str.size() >= 1 ? str.size() - 1 : 0);
60748f512ceSopenharmony_ci    int64_t size = 0;
60848f512ceSopenharmony_ci    try {
60948f512ceSopenharmony_ci        size = std::stoul(num);
61048f512ceSopenharmony_ci    } catch (...) {
61148f512ceSopenharmony_ci        return false;
61248f512ceSopenharmony_ci    }
61348f512ceSopenharmony_ci    if (size <= 0) {
61448f512ceSopenharmony_ci        return false;
61548f512ceSopenharmony_ci    }
61648f512ceSopenharmony_ci
61748f512ceSopenharmony_ci    dataSizeLimit_ = size * unit;
61848f512ceSopenharmony_ci
61948f512ceSopenharmony_ci    return true;
62048f512ceSopenharmony_ci}
62148f512ceSopenharmony_ci
62248f512ceSopenharmony_cibool SubCommandRecord::ParseCallStackOption(const std::vector<std::string> &callStackType)
62348f512ceSopenharmony_ci{
62448f512ceSopenharmony_ci    if (callStackType.empty()) {
62548f512ceSopenharmony_ci        return true;
62648f512ceSopenharmony_ci    } else if (callStackType[0] == "fp") {
62748f512ceSopenharmony_ci        if (callStackType.size() != 1) {
62848f512ceSopenharmony_ci            printf("Invalid -s value %s.\n", VectorToString(callStackType).c_str());
62948f512ceSopenharmony_ci            return false;
63048f512ceSopenharmony_ci        }
63148f512ceSopenharmony_ci        isCallStackFp_ = true;
63248f512ceSopenharmony_ci    } else if (callStackType[0] == "dwarf") {
63348f512ceSopenharmony_ci        if (callStackType.size() > MAX_DWARF_CALL_CHAIN) {
63448f512ceSopenharmony_ci            printf("Invalid -s value %s.\n", VectorToString(callStackType).c_str());
63548f512ceSopenharmony_ci            return false;
63648f512ceSopenharmony_ci        } else if (callStackType.size() == MAX_DWARF_CALL_CHAIN) {
63748f512ceSopenharmony_ci            try {
63848f512ceSopenharmony_ci                callStackDwarfSize_ = std::stoul(callStackType.at(1));
63948f512ceSopenharmony_ci            } catch (...) {
64048f512ceSopenharmony_ci                printf("Invalid -s value, dwarf stack size, '%s' is illegal.\n",
64148f512ceSopenharmony_ci                       callStackType.at(1).c_str());
64248f512ceSopenharmony_ci                return false;
64348f512ceSopenharmony_ci            }
64448f512ceSopenharmony_ci            if (callStackDwarfSize_ < MIN_SAMPLE_STACK_SIZE) {
64548f512ceSopenharmony_ci                printf("Invalid -s value, dwarf stack size, '%s' is too small.\n",
64648f512ceSopenharmony_ci                       callStackType.at(1).c_str());
64748f512ceSopenharmony_ci                return false;
64848f512ceSopenharmony_ci            }
64948f512ceSopenharmony_ci            if (callStackDwarfSize_ > MAX_SAMPLE_STACK_SIZE) {
65048f512ceSopenharmony_ci                printf("Invalid -s value, dwarf stack size, '%s' is bigger than max value %u.\n",
65148f512ceSopenharmony_ci                       callStackType.at(1).c_str(), MAX_SAMPLE_STACK_SIZE);
65248f512ceSopenharmony_ci                return false;
65348f512ceSopenharmony_ci            }
65448f512ceSopenharmony_ci            if ((callStackDwarfSize_ & MASK_ALIGNED_8) != 0) {
65548f512ceSopenharmony_ci                printf("Invalid -s value, dwarf stack size, '%s' is not 8 byte aligned.\n",
65648f512ceSopenharmony_ci                       callStackType.at(1).c_str());
65748f512ceSopenharmony_ci                return false;
65848f512ceSopenharmony_ci            }
65948f512ceSopenharmony_ci        }
66048f512ceSopenharmony_ci        isCallStackDwarf_ = true;
66148f512ceSopenharmony_ci        SymbolsFile::needParseJsFunc_ = true; // only in record and dwarf mode need to parse
66248f512ceSopenharmony_ci    } else {
66348f512ceSopenharmony_ci        printf("Invalid -s value '%s'.\n", callStackType.at(0).c_str());
66448f512ceSopenharmony_ci        return false;
66548f512ceSopenharmony_ci    }
66648f512ceSopenharmony_ci    return true;
66748f512ceSopenharmony_ci}
66848f512ceSopenharmony_ci
66948f512ceSopenharmony_cibool SubCommandRecord::ParseBranchSampleType(const std::vector<std::string> &vecBranchSampleTypes)
67048f512ceSopenharmony_ci{
67148f512ceSopenharmony_ci    if (!vecBranchSampleTypes.empty()) {
67248f512ceSopenharmony_ci        for (auto &item : vecBranchSampleTypes) {
67348f512ceSopenharmony_ci            uint64_t type = GetBranchSampleType(item);
67448f512ceSopenharmony_ci            if (type != 0) {
67548f512ceSopenharmony_ci                branchSampleType_ |= type;
67648f512ceSopenharmony_ci            } else {
67748f512ceSopenharmony_ci                printf("Invalid -j value '%s'\n", item.c_str());
67848f512ceSopenharmony_ci                return false;
67948f512ceSopenharmony_ci            }
68048f512ceSopenharmony_ci        }
68148f512ceSopenharmony_ci        if ((branchSampleType_ & TYPE_PERF_SAMPLE_BRANCH) == 0) {
68248f512ceSopenharmony_ci            printf("Invalid -j value, requires at least one of "
68348f512ceSopenharmony_ci                   "any, any_call, any_ret, ind_call, ind_jmp, cond, call.\n");
68448f512ceSopenharmony_ci            return false;
68548f512ceSopenharmony_ci        }
68648f512ceSopenharmony_ci    }
68748f512ceSopenharmony_ci    return true;
68848f512ceSopenharmony_ci}
68948f512ceSopenharmony_ci
69048f512ceSopenharmony_cibool SubCommandRecord::ParseControlCmd(const std::string cmd)
69148f512ceSopenharmony_ci{
69248f512ceSopenharmony_ci    if (cmd.empty() or cmd == CONTROL_CMD_PREPARE or cmd == CONTROL_CMD_START or
69348f512ceSopenharmony_ci        cmd == CONTROL_CMD_PAUSE or cmd == CONTROL_CMD_RESUME or cmd == CONTROL_CMD_STOP) {
69448f512ceSopenharmony_ci        return true;
69548f512ceSopenharmony_ci    }
69648f512ceSopenharmony_ci
69748f512ceSopenharmony_ci    printf("Invalid --control %s option, command should be: prepare, start, pause, resume, stop.\n",
69848f512ceSopenharmony_ci           cmd.c_str());
69948f512ceSopenharmony_ci    return false;
70048f512ceSopenharmony_ci}
70148f512ceSopenharmony_ci
70248f512ceSopenharmony_cibool SubCommandRecord::SetPerfLimit(const std::string& file, int value, std::function<bool (int, int)> const& cmp,
70348f512ceSopenharmony_ci    const std::string& param)
70448f512ceSopenharmony_ci{
70548f512ceSopenharmony_ci    int oldValue = 0;
70648f512ceSopenharmony_ci    CHECK_TRUE(!ReadIntFromProcFile(file, oldValue), false, LOG_TYPE_PRINTF, "read %s fail.\n", file.c_str());
70748f512ceSopenharmony_ci
70848f512ceSopenharmony_ci    if (cmp(oldValue, value)) {
70948f512ceSopenharmony_ci        HLOGI("cmp return true.");
71048f512ceSopenharmony_ci        return true;
71148f512ceSopenharmony_ci    }
71248f512ceSopenharmony_ci
71348f512ceSopenharmony_ci    if (IsRoot()) {
71448f512ceSopenharmony_ci        bool ret = WriteIntToProcFile(file, value);
71548f512ceSopenharmony_ci        if (!ret) {
71648f512ceSopenharmony_ci            printf("please set %s to %d manually if perf limit is wanted.\n", file.c_str(), value);
71748f512ceSopenharmony_ci        }
71848f512ceSopenharmony_ci    }
71948f512ceSopenharmony_ci
72048f512ceSopenharmony_ci    CHECK_TRUE(!OHOS::system::SetParameter(param, std::to_string(value)), false, LOG_TYPE_PRINTF,
72148f512ceSopenharmony_ci               "set parameter %s fail.\n", param.c_str());
72248f512ceSopenharmony_ci    isNeedSetPerfHarden_ = true;
72348f512ceSopenharmony_ci    return true;
72448f512ceSopenharmony_ci}
72548f512ceSopenharmony_ci
72648f512ceSopenharmony_cibool SubCommandRecord::SetPerfCpuMaxPercent()
72748f512ceSopenharmony_ci{
72848f512ceSopenharmony_ci    auto cmp = [](int oldValue, int newValue) { return oldValue == newValue; };
72948f512ceSopenharmony_ci    return SetPerfLimit(PERF_CPU_TIME_MAX_PERCENT, cpuPercent_, cmp, "hiviewdfx.hiperf.perf_cpu_time_max_percent");
73048f512ceSopenharmony_ci}
73148f512ceSopenharmony_ci
73248f512ceSopenharmony_cibool SubCommandRecord::SetPerfMaxSampleRate()
73348f512ceSopenharmony_ci{
73448f512ceSopenharmony_ci    auto cmp = [](int oldValue, int newValue) { return oldValue == newValue; };
73548f512ceSopenharmony_ci    int frequency = frequency_ != 0 ? frequency_ : PerfEvents::DEFAULT_SAMPLE_FREQUNCY;
73648f512ceSopenharmony_ci    int maxRate = 0;
73748f512ceSopenharmony_ci    CHECK_TRUE(!ReadIntFromProcFile(PERF_EVENT_MAX_SAMPLE_RATE, maxRate), false, LOG_TYPE_PRINTF,
73848f512ceSopenharmony_ci               "read %s fail.\n", PERF_EVENT_MAX_SAMPLE_RATE.c_str());
73948f512ceSopenharmony_ci    if (maxRate > frequency) {
74048f512ceSopenharmony_ci        return true;
74148f512ceSopenharmony_ci    }
74248f512ceSopenharmony_ci    int newRate = frequency > static_cast<int>(PerfEvents::DEFAULT_EVENT_MAX_SAMPLE_RATE) ? frequency :
74348f512ceSopenharmony_ci                  static_cast<int>(PerfEvents::DEFAULT_EVENT_MAX_SAMPLE_RATE);
74448f512ceSopenharmony_ci    return SetPerfLimit(PERF_EVENT_MAX_SAMPLE_RATE, newRate, cmp,
74548f512ceSopenharmony_ci                        "hiviewdfx.hiperf.perf_event_max_sample_rate");
74648f512ceSopenharmony_ci}
74748f512ceSopenharmony_ci
74848f512ceSopenharmony_cibool SubCommandRecord::SetPerfEventMlock()
74948f512ceSopenharmony_ci{
75048f512ceSopenharmony_ci    auto cmp = [](int oldValue, int newValue) { return oldValue == newValue; };
75148f512ceSopenharmony_ci    int mlock_kb = sysconf(_SC_NPROCESSORS_CONF) * (mmapPages_ + 1) * 4;
75248f512ceSopenharmony_ci    return SetPerfLimit(PERF_EVENT_MLOCK_KB, mlock_kb, cmp, "hiviewdfx.hiperf.perf_event_mlock_kb");
75348f512ceSopenharmony_ci}
75448f512ceSopenharmony_ci
75548f512ceSopenharmony_cibool SubCommandRecord::SetPerfHarden()
75648f512ceSopenharmony_ci{
75748f512ceSopenharmony_ci    if (!isNeedSetPerfHarden_) {
75848f512ceSopenharmony_ci        return true;
75948f512ceSopenharmony_ci    }
76048f512ceSopenharmony_ci
76148f512ceSopenharmony_ci    std::string perfHarden = OHOS::system::GetParameter(PERF_DISABLE_PARAM, "1");
76248f512ceSopenharmony_ci    if (perfHarden == "1") {
76348f512ceSopenharmony_ci        CHECK_TRUE(!OHOS::system::SetParameter(PERF_DISABLE_PARAM, "0"), false, LOG_TYPE_PRINTF,
76448f512ceSopenharmony_ci                   "set parameter security.perf_harden to 0 fail.");
76548f512ceSopenharmony_ci    }
76648f512ceSopenharmony_ci
76748f512ceSopenharmony_ci    CHECK_TRUE(!OHOS::system::SetParameter(PERF_DISABLE_PARAM, "1"), false, LOG_TYPE_PRINTF,
76848f512ceSopenharmony_ci               "set parameter security.perf_harden to 1 fail.");
76948f512ceSopenharmony_ci    return true;
77048f512ceSopenharmony_ci}
77148f512ceSopenharmony_ci
77248f512ceSopenharmony_cibool SubCommandRecord::TraceOffCpu()
77348f512ceSopenharmony_ci{
77448f512ceSopenharmony_ci    // whether system support sched_switch event
77548f512ceSopenharmony_ci    int enable = -1;
77648f512ceSopenharmony_ci    std::string node = SCHED_SWITCH;
77748f512ceSopenharmony_ci    const std::string nodeDebug = SCHED_SWITCH_DEBUG;
77848f512ceSopenharmony_ci    CHECK_TRUE(!ReadIntFromProcFile(node.c_str(), enable) and !ReadIntFromProcFile(nodeDebug.c_str(), enable),
77948f512ceSopenharmony_ci               false, LOG_TYPE_PRINTF, "Cannot trace off CPU, event sched:sched_switch is not available (%s or %s)\n",
78048f512ceSopenharmony_ci               node.c_str(), nodeDebug.c_str());
78148f512ceSopenharmony_ci
78248f512ceSopenharmony_ci    return true;
78348f512ceSopenharmony_ci}
78448f512ceSopenharmony_ci
78548f512ceSopenharmony_civoid SubCommandRecord::SetSavedCmdlinesSize()
78648f512ceSopenharmony_ci{
78748f512ceSopenharmony_ci    if (!ReadIntFromProcFile(SAVED_CMDLINES_SIZE, oldCmdlinesSize_)) {
78848f512ceSopenharmony_ci        printf("Failed to read from %s.\n", SAVED_CMDLINES_SIZE.c_str());
78948f512ceSopenharmony_ci    }
79048f512ceSopenharmony_ci    if (!WriteIntToProcFile(SAVED_CMDLINES_SIZE, cmdlinesSize_)) {
79148f512ceSopenharmony_ci        printf("Failed to write size:%d to %s.\n", cmdlinesSize_, SAVED_CMDLINES_SIZE.c_str());
79248f512ceSopenharmony_ci    }
79348f512ceSopenharmony_ci}
79448f512ceSopenharmony_ci
79548f512ceSopenharmony_civoid SubCommandRecord::RecoverSavedCmdlinesSize()
79648f512ceSopenharmony_ci{
79748f512ceSopenharmony_ci    CHECK_TRUE(oldCmdlinesSize_ == 0, NO_RETVAL, 0, "");
79848f512ceSopenharmony_ci    if (!WriteIntToProcFile(SAVED_CMDLINES_SIZE, oldCmdlinesSize_)) {
79948f512ceSopenharmony_ci        printf("Failed to recover value of %s.\n", SAVED_CMDLINES_SIZE.c_str());
80048f512ceSopenharmony_ci    }
80148f512ceSopenharmony_ci}
80248f512ceSopenharmony_ci
80348f512ceSopenharmony_cibool SubCommandRecord::PreparePerfEvent()
80448f512ceSopenharmony_ci{
80548f512ceSopenharmony_ci    // we need to notify perfEvents_ sampling mode by SetRecordCallBack first
80648f512ceSopenharmony_ci    auto processRecord = [this](std::unique_ptr<PerfEventRecord> record) -> bool {
80748f512ceSopenharmony_ci        return this->ProcessRecord(std::move(record));
80848f512ceSopenharmony_ci    };
80948f512ceSopenharmony_ci    perfEvents_.SetRecordCallBack(processRecord);
81048f512ceSopenharmony_ci
81148f512ceSopenharmony_ci    if (selectEvents_.size() > 0 && selectEvents_[0] == "arm_spe_0") {
81248f512ceSopenharmony_ci        if (!IsRoot()) {
81348f512ceSopenharmony_ci            printf("%s options needs root privilege, please check usage\n", selectEvents_[0].c_str());
81448f512ceSopenharmony_ci            return false;
81548f512ceSopenharmony_ci        }
81648f512ceSopenharmony_ci        selectEvents_.insert(selectEvents_.begin(), "sw-dummy");
81748f512ceSopenharmony_ci        perfEvents_.isSpe_ = true;
81848f512ceSopenharmony_ci        perfEvents_.SetConfig(speOptMap_);
81948f512ceSopenharmony_ci        isSpe_ = true;
82048f512ceSopenharmony_ci    }
82148f512ceSopenharmony_ci
82248f512ceSopenharmony_ci    perfEvents_.SetCpu(selectCpus_);
82348f512ceSopenharmony_ci    perfEvents_.SetPid(selectPids_); // Tids has insert Pids in CheckTargetProcessOptions()
82448f512ceSopenharmony_ci
82548f512ceSopenharmony_ci    perfEvents_.SetSystemTarget(targetSystemWide_);
82648f512ceSopenharmony_ci    perfEvents_.SetTimeOut(timeStopSec_);
82748f512ceSopenharmony_ci    perfEvents_.SetVerboseReport(verboseReport_);
82848f512ceSopenharmony_ci    perfEvents_.SetMmapPages(mmapPages_);
82948f512ceSopenharmony_ci    if (isCallStackFp_) {
83048f512ceSopenharmony_ci        perfEvents_.SetSampleStackType(PerfEvents::SampleStackType::FP);
83148f512ceSopenharmony_ci    } else if (isCallStackDwarf_) {
83248f512ceSopenharmony_ci        perfEvents_.SetSampleStackType(PerfEvents::SampleStackType::DWARF);
83348f512ceSopenharmony_ci        perfEvents_.SetDwarfSampleStackSize(callStackDwarfSize_);
83448f512ceSopenharmony_ci    }
83548f512ceSopenharmony_ci    if (!perfEvents_.SetBranchSampleType(branchSampleType_)) {
83648f512ceSopenharmony_ci        printf("branch sample %s is not supported\n", VectorToString(vecBranchFilters_).c_str());
83748f512ceSopenharmony_ci        HLOGE("Fail to SetBranchSampleType %" PRIx64 "", branchSampleType_);
83848f512ceSopenharmony_ci        return false;
83948f512ceSopenharmony_ci    }
84048f512ceSopenharmony_ci    if (!clockId_.empty()) {
84148f512ceSopenharmony_ci        perfEvents_.SetClockId(GetClockId(clockId_));
84248f512ceSopenharmony_ci    }
84348f512ceSopenharmony_ci
84448f512ceSopenharmony_ci    if (frequency_ > 0) {
84548f512ceSopenharmony_ci        perfEvents_.SetSampleFrequency(frequency_);
84648f512ceSopenharmony_ci    } else if (period_ > 0) {
84748f512ceSopenharmony_ci        perfEvents_.SetSamplePeriod(period_);
84848f512ceSopenharmony_ci    }
84948f512ceSopenharmony_ci
85048f512ceSopenharmony_ci    perfEvents_.SetInherit(!noInherit_);
85148f512ceSopenharmony_ci    perfEvents_.SetTrackedCommand(trackedCommand_);
85248f512ceSopenharmony_ci
85348f512ceSopenharmony_ci    // set default sample event
85448f512ceSopenharmony_ci    if (selectEvents_.empty() && selectGroups_.empty()) {
85548f512ceSopenharmony_ci        selectEvents_.push_back("hw-cpu-cycles");
85648f512ceSopenharmony_ci    }
85748f512ceSopenharmony_ci
85848f512ceSopenharmony_ci    CHECK_TRUE(!perfEvents_.AddEvents(selectEvents_), false, 1, "Fail to AddEvents events");
85948f512ceSopenharmony_ci    for (auto &group : selectGroups_) {
86048f512ceSopenharmony_ci        CHECK_TRUE(!perfEvents_.AddEvents(group, true), false, 1, "Fail to AddEvents groups");
86148f512ceSopenharmony_ci    }
86248f512ceSopenharmony_ci    // cpu off add after default event (we need both sched_switch and user selected events)
86348f512ceSopenharmony_ci    if (offCPU_) {
86448f512ceSopenharmony_ci        CHECK_TRUE(std::find(selectEvents_.begin(), selectEvents_.end(), "sched_switch") != selectEvents_.end(),
86548f512ceSopenharmony_ci                   false, LOG_TYPE_PRINTF, "--offcpu is not supported event sched_switch\n");
86648f512ceSopenharmony_ci        // insert a sched_switch event to trace offcpu event
86748f512ceSopenharmony_ci        CHECK_TRUE(!perfEvents_.AddOffCpuEvent(), false, 1, "Fail to AddEOffCpuvent");
86848f512ceSopenharmony_ci    }
86948f512ceSopenharmony_ci
87048f512ceSopenharmony_ci    return true;
87148f512ceSopenharmony_ci}
87248f512ceSopenharmony_ci
87348f512ceSopenharmony_cibool SubCommandRecord::PrepareSysKernel()
87448f512ceSopenharmony_ci{
87548f512ceSopenharmony_ci    SetHM();
87648f512ceSopenharmony_ci    SetSavedCmdlinesSize();
87748f512ceSopenharmony_ci    CHECK_TRUE(!SetPerfMaxSampleRate(), false, 1, "Fail to call SetPerfMaxSampleRate(%d)", frequency_);
87848f512ceSopenharmony_ci
87948f512ceSopenharmony_ci    CHECK_TRUE(!SetPerfCpuMaxPercent(), false, 1, "Fail to set perf event cpu limit to %d\n", cpuPercent_);
88048f512ceSopenharmony_ci
88148f512ceSopenharmony_ci    CHECK_TRUE(!SetPerfEventMlock(), false, 1, "Fail to set perf event mlock limit\n");
88248f512ceSopenharmony_ci
88348f512ceSopenharmony_ci    CHECK_TRUE(!SetPerfHarden(), false, 1, "Fail to set perf event harden\n");
88448f512ceSopenharmony_ci
88548f512ceSopenharmony_ci    CHECK_TRUE(offCPU_ && !TraceOffCpu(), false, 1, "Fail to TraceOffCpu");
88648f512ceSopenharmony_ci
88748f512ceSopenharmony_ci    return true;
88848f512ceSopenharmony_ci}
88948f512ceSopenharmony_ci
89048f512ceSopenharmony_cibool SubCommandRecord::PrepareVirtualRuntime()
89148f512ceSopenharmony_ci{
89248f512ceSopenharmony_ci    auto saveRecord = [this](std::unique_ptr<PerfEventRecord> record) -> bool {
89348f512ceSopenharmony_ci        return this->SaveRecord(std::move(record), false);
89448f512ceSopenharmony_ci    };
89548f512ceSopenharmony_ci    virtualRuntime_.SetRecordMode(saveRecord);
89648f512ceSopenharmony_ci
89748f512ceSopenharmony_ci    // do some config for virtualRuntime_
89848f512ceSopenharmony_ci    virtualRuntime_.SetCallStackExpend(disableCallstackExpend_ ? 0 : 1);
89948f512ceSopenharmony_ci    // these is same for virtual runtime
90048f512ceSopenharmony_ci    virtualRuntime_.SetDisableUnwind(disableUnwind_ or delayUnwind_);
90148f512ceSopenharmony_ci    virtualRuntime_.EnableDebugInfoSymbolic(enableDebugInfoSymbolic_);
90248f512ceSopenharmony_ci    if (!symbolDir_.empty()) {
90348f512ceSopenharmony_ci        if (!virtualRuntime_.SetSymbolsPaths(symbolDir_)) {
90448f512ceSopenharmony_ci            printf("Failed to set symbol path(%s)\n", VectorToString(symbolDir_).c_str());
90548f512ceSopenharmony_ci            return false;
90648f512ceSopenharmony_ci        }
90748f512ceSopenharmony_ci    }
90848f512ceSopenharmony_ci
90948f512ceSopenharmony_ci    // load vsdo first
91048f512ceSopenharmony_ci    virtualRuntime_.LoadVdso();
91148f512ceSopenharmony_ci
91248f512ceSopenharmony_ci    if (!callChainUserOnly_) {
91348f512ceSopenharmony_ci        // prepare from kernel and ko
91448f512ceSopenharmony_ci        virtualRuntime_.SetNeedKernelCallChain(!callChainUserOnly_);
91548f512ceSopenharmony_ci        virtualRuntime_.UpdateKernelSpaceMaps();
91648f512ceSopenharmony_ci        virtualRuntime_.UpdateKernelModulesSpaceMaps();
91748f512ceSopenharmony_ci        if (isHM_) {
91848f512ceSopenharmony_ci            virtualRuntime_.UpdateServiceSpaceMaps();
91948f512ceSopenharmony_ci        }
92048f512ceSopenharmony_ci    }
92148f512ceSopenharmony_ci
92248f512ceSopenharmony_ci    if (isHM_) {
92348f512ceSopenharmony_ci        virtualRuntime_.UpdateDevhostSpaceMaps();
92448f512ceSopenharmony_ci    }
92548f512ceSopenharmony_ci    if (dedupStack_) {
92648f512ceSopenharmony_ci        virtualRuntime_.SetDedupStack();
92748f512ceSopenharmony_ci        auto collectSymbol = [this](PerfRecordSample *sample) {
92848f512ceSopenharmony_ci            this->CollectSymbol(std::move(sample));
92948f512ceSopenharmony_ci        };
93048f512ceSopenharmony_ci        virtualRuntime_.SetCollectSymbolCallBack(collectSymbol);
93148f512ceSopenharmony_ci    }
93248f512ceSopenharmony_ci    return true;
93348f512ceSopenharmony_ci}
93448f512ceSopenharmony_ci
93548f512ceSopenharmony_civoid SubCommandRecord::WriteCommEventBeforeSampling()
93648f512ceSopenharmony_ci{
93748f512ceSopenharmony_ci    CHECK_TRUE(restart_, NO_RETVAL, 0, "");
93848f512ceSopenharmony_ci    for (auto it = mapPids_.begin(); it != mapPids_.end(); ++it) {
93948f512ceSopenharmony_ci        virtualRuntime_.GetThread(it->first, it->first);
94048f512ceSopenharmony_ci        for (auto tid : it->second) {
94148f512ceSopenharmony_ci            virtualRuntime_.GetThread(it->first, tid);
94248f512ceSopenharmony_ci        }
94348f512ceSopenharmony_ci    }
94448f512ceSopenharmony_ci    if (mapPids_.empty()) {
94548f512ceSopenharmony_ci        if (!selectPids_.empty()) {
94648f512ceSopenharmony_ci            for (auto pid : selectPids_) {
94748f512ceSopenharmony_ci                virtualRuntime_.GetThread(pid, pid);
94848f512ceSopenharmony_ci            }
94948f512ceSopenharmony_ci        }
95048f512ceSopenharmony_ci    }
95148f512ceSopenharmony_ci}
95248f512ceSopenharmony_ci
95348f512ceSopenharmony_cibool SubCommandRecord::ClientCommandResponse(bool OK)
95448f512ceSopenharmony_ci{
95548f512ceSopenharmony_ci    using namespace HiperfClient;
95648f512ceSopenharmony_ci    if (OK) {
95748f512ceSopenharmony_ci        size_t size = write(clientPipeOutput_, ReplyOK.c_str(), ReplyOK.size());
95848f512ceSopenharmony_ci        if (size != ReplyOK.size()) {
95948f512ceSopenharmony_ci            char errInfo[ERRINFOLEN] = { 0 };
96048f512ceSopenharmony_ci            strerror_r(errno, errInfo, ERRINFOLEN);
96148f512ceSopenharmony_ci            HLOGD("Server:%s -> %d : %zd %d:%s", ReplyOK.c_str(), clientPipeOutput_, size, errno,
96248f512ceSopenharmony_ci                  errInfo);
96348f512ceSopenharmony_ci            return false;
96448f512ceSopenharmony_ci        }
96548f512ceSopenharmony_ci        return true;
96648f512ceSopenharmony_ci    } else {
96748f512ceSopenharmony_ci        size_t size = write(clientPipeOutput_, ReplyFAIL.c_str(), ReplyFAIL.size());
96848f512ceSopenharmony_ci        if (size != ReplyFAIL.size()) {
96948f512ceSopenharmony_ci            char errInfo[ERRINFOLEN] = { 0 };
97048f512ceSopenharmony_ci            strerror_r(errno, errInfo, ERRINFOLEN);
97148f512ceSopenharmony_ci            HLOGD("Server:%s -> %d : %zd %d:%s", ReplyFAIL.c_str(), clientPipeOutput_, size, errno,
97248f512ceSopenharmony_ci                  errInfo);
97348f512ceSopenharmony_ci            return false;
97448f512ceSopenharmony_ci        }
97548f512ceSopenharmony_ci        return true;
97648f512ceSopenharmony_ci    }
97748f512ceSopenharmony_ci}
97848f512ceSopenharmony_ci
97948f512ceSopenharmony_cibool SubCommandRecord::IsSamplingRunning()
98048f512ceSopenharmony_ci{
98148f512ceSopenharmony_ci    constexpr int maxWaitTrackingCount = 3000 / 100; // wait 3 second
98248f512ceSopenharmony_ci    int waitTrackingCount = maxWaitTrackingCount;
98348f512ceSopenharmony_ci    while (!perfEvents_.IsTrackRunning()) {
98448f512ceSopenharmony_ci        waitTrackingCount--;
98548f512ceSopenharmony_ci        if (waitTrackingCount <= 0) {
98648f512ceSopenharmony_ci            return false;
98748f512ceSopenharmony_ci        }
98848f512ceSopenharmony_ci        constexpr uint64_t waitTrackingSleepMs = 100;
98948f512ceSopenharmony_ci        std::this_thread::sleep_for(milliseconds(waitTrackingSleepMs));
99048f512ceSopenharmony_ci    }
99148f512ceSopenharmony_ci    return true;
99248f512ceSopenharmony_ci}
99348f512ceSopenharmony_ci
99448f512ceSopenharmony_civoid SubCommandRecord::ClientCommandHandle()
99548f512ceSopenharmony_ci{
99648f512ceSopenharmony_ci    using namespace HiperfClient;
99748f512ceSopenharmony_ci    CHECK_TRUE(!IsSamplingRunning(), NO_RETVAL, 0, "");
99848f512ceSopenharmony_ci    // tell the caller if Exist
99948f512ceSopenharmony_ci    ClientCommandResponse(true);
100048f512ceSopenharmony_ci
100148f512ceSopenharmony_ci    bool hasRead = true;
100248f512ceSopenharmony_ci    while (!clientExit_) {
100348f512ceSopenharmony_ci        if (isFifoServer_ && hasRead) {
100448f512ceSopenharmony_ci            if (clientPipeInput_ != -1) {
100548f512ceSopenharmony_ci                // after read(), block is disabled, the poll will be waked neven if no data
100648f512ceSopenharmony_ci                close(clientPipeInput_);
100748f512ceSopenharmony_ci            }
100848f512ceSopenharmony_ci            clientPipeInput_ = open(CONTROL_FIFO_FILE_C2S.c_str(), O_RDONLY | O_NONBLOCK);
100948f512ceSopenharmony_ci        }
101048f512ceSopenharmony_ci        struct pollfd pollFd {
101148f512ceSopenharmony_ci            clientPipeInput_, POLLIN, 0
101248f512ceSopenharmony_ci        };
101348f512ceSopenharmony_ci        int polled = poll(&pollFd, 1, CONTROL_WAITREPY_TOMEOUT.count());
101448f512ceSopenharmony_ci        if (polled <= 0) {
101548f512ceSopenharmony_ci            hasRead = false;
101648f512ceSopenharmony_ci            continue;
101748f512ceSopenharmony_ci        }
101848f512ceSopenharmony_ci        hasRead = true;
101948f512ceSopenharmony_ci        std::string command;
102048f512ceSopenharmony_ci        while (true) {
102148f512ceSopenharmony_ci            char c;
102248f512ceSopenharmony_ci            ssize_t result = TEMP_FAILURE_RETRY(read(clientPipeInput_, &c, 1));
102348f512ceSopenharmony_ci            if (result <= 0) {
102448f512ceSopenharmony_ci                HLOGD("server :read from pipe file failed");
102548f512ceSopenharmony_ci                break;
102648f512ceSopenharmony_ci            }
102748f512ceSopenharmony_ci            command.push_back(c);
102848f512ceSopenharmony_ci            if (c == '\n') {
102948f512ceSopenharmony_ci                break;
103048f512ceSopenharmony_ci            }
103148f512ceSopenharmony_ci        }
103248f512ceSopenharmony_ci        HLOGD("server:new command %s", command.c_str());
103348f512ceSopenharmony_ci        if (command == ReplyStart) {
103448f512ceSopenharmony_ci            ClientCommandResponse(perfEvents_.EnableTracking());
103548f512ceSopenharmony_ci        } else if (command == ReplyCheck) {
103648f512ceSopenharmony_ci            ClientCommandResponse(!clientExit_);
103748f512ceSopenharmony_ci        } else if (command == ReplyStop) {
103848f512ceSopenharmony_ci            ClientCommandResponse(perfEvents_.StopTracking());
103948f512ceSopenharmony_ci        } else if (command == ReplyPause) {
104048f512ceSopenharmony_ci            ClientCommandResponse(perfEvents_.PauseTracking());
104148f512ceSopenharmony_ci        } else if (command == ReplyResume) {
104248f512ceSopenharmony_ci            ClientCommandResponse(perfEvents_.ResumeTracking());
104348f512ceSopenharmony_ci        }
104448f512ceSopenharmony_ci    }
104548f512ceSopenharmony_ci}
104648f512ceSopenharmony_ci
104748f512ceSopenharmony_cibool SubCommandRecord::ProcessControl()
104848f512ceSopenharmony_ci{
104948f512ceSopenharmony_ci    if (controlCmd_.empty()) {
105048f512ceSopenharmony_ci        return true;
105148f512ceSopenharmony_ci    }
105248f512ceSopenharmony_ci
105348f512ceSopenharmony_ci    if (controlCmd_ == CONTROL_CMD_PREPARE) {
105448f512ceSopenharmony_ci        CHECK_TRUE(!CreateFifoServer(), false, 0, "");
105548f512ceSopenharmony_ci        return true;
105648f512ceSopenharmony_ci    }
105748f512ceSopenharmony_ci
105848f512ceSopenharmony_ci    isFifoClient_ = true;
105948f512ceSopenharmony_ci    bool ret = false;
106048f512ceSopenharmony_ci    if (controlCmd_ == CONTROL_CMD_START) {
106148f512ceSopenharmony_ci        ret = SendFifoAndWaitReply(HiperfClient::ReplyStart, CONTROL_WAITREPY_TOMEOUT);
106248f512ceSopenharmony_ci    } else if (controlCmd_ == CONTROL_CMD_RESUME) {
106348f512ceSopenharmony_ci        ret = SendFifoAndWaitReply(HiperfClient::ReplyResume, CONTROL_WAITREPY_TOMEOUT);
106448f512ceSopenharmony_ci    } else if (controlCmd_ == CONTROL_CMD_PAUSE) {
106548f512ceSopenharmony_ci        ret = SendFifoAndWaitReply(HiperfClient::ReplyPause, CONTROL_WAITREPY_TOMEOUT);
106648f512ceSopenharmony_ci    } else if (controlCmd_ == CONTROL_CMD_STOP) {
106748f512ceSopenharmony_ci        ret = SendFifoAndWaitReply(HiperfClient::ReplyStop, CONTROL_WAITREPY_TOMEOUT);
106848f512ceSopenharmony_ci        if (ret) {
106948f512ceSopenharmony_ci            // wait sampling process exit really
107048f512ceSopenharmony_ci            static constexpr uint64_t waitCheckSleepMs = 200;
107148f512ceSopenharmony_ci            std::this_thread::sleep_for(milliseconds(waitCheckSleepMs));
107248f512ceSopenharmony_ci            while (SendFifoAndWaitReply(HiperfClient::ReplyCheck, CONTROL_WAITREPY_TOMEOUT_CHECK)) {
107348f512ceSopenharmony_ci                std::this_thread::sleep_for(milliseconds(waitCheckSleepMs));
107448f512ceSopenharmony_ci            }
107548f512ceSopenharmony_ci            HLOGI("wait reply check end.");
107648f512ceSopenharmony_ci        }
107748f512ceSopenharmony_ci        remove(CONTROL_FIFO_FILE_C2S.c_str());
107848f512ceSopenharmony_ci        remove(CONTROL_FIFO_FILE_S2C.c_str());
107948f512ceSopenharmony_ci    }
108048f512ceSopenharmony_ci
108148f512ceSopenharmony_ci    if (ret) {
108248f512ceSopenharmony_ci        printf("%s sampling success.\n", controlCmd_.c_str());
108348f512ceSopenharmony_ci    } else {
108448f512ceSopenharmony_ci        printf("%s sampling failed.\n", controlCmd_.c_str());
108548f512ceSopenharmony_ci    }
108648f512ceSopenharmony_ci    return ret;
108748f512ceSopenharmony_ci}
108848f512ceSopenharmony_ci
108948f512ceSopenharmony_cibool SubCommandRecord::CreateFifoServer()
109048f512ceSopenharmony_ci{
109148f512ceSopenharmony_ci    char errInfo[ERRINFOLEN] = { 0 };
109248f512ceSopenharmony_ci    const mode_t fifoMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
109348f512ceSopenharmony_ci    if (mkfifo(CONTROL_FIFO_FILE_S2C.c_str(), fifoMode) != 0 or
109448f512ceSopenharmony_ci        mkfifo(CONTROL_FIFO_FILE_C2S.c_str(), fifoMode) != 0) {
109548f512ceSopenharmony_ci        if (errno == EEXIST) {
109648f512ceSopenharmony_ci            printf("another sampling service is running.\n");
109748f512ceSopenharmony_ci        } else {
109848f512ceSopenharmony_ci            remove(CONTROL_FIFO_FILE_S2C.c_str());
109948f512ceSopenharmony_ci            remove(CONTROL_FIFO_FILE_C2S.c_str());
110048f512ceSopenharmony_ci        }
110148f512ceSopenharmony_ci        strerror_r(errno, errInfo, ERRINFOLEN);
110248f512ceSopenharmony_ci        HLOGE("create fifo file failed. %d:%s", errno, errInfo);
110348f512ceSopenharmony_ci        return false;
110448f512ceSopenharmony_ci    }
110548f512ceSopenharmony_ci
110648f512ceSopenharmony_ci    pid_t pid = fork();
110748f512ceSopenharmony_ci    if (pid == -1) {
110848f512ceSopenharmony_ci        strerror_r(errno, errInfo, ERRINFOLEN);
110948f512ceSopenharmony_ci        HLOGE("fork failed. %d:%s", errno, errInfo);
111048f512ceSopenharmony_ci        return false;
111148f512ceSopenharmony_ci    } else if (pid == 0) { // child process
111248f512ceSopenharmony_ci        close(STDIN_FILENO);
111348f512ceSopenharmony_ci        close(STDERR_FILENO);
111448f512ceSopenharmony_ci        isFifoServer_ = true;
111548f512ceSopenharmony_ci        clientPipeOutput_ = open(CONTROL_FIFO_FILE_S2C.c_str(), O_WRONLY);
111648f512ceSopenharmony_ci        if (clientPipeOutput_ == -1) {
111748f512ceSopenharmony_ci            strerror_r(errno, errInfo, ERRINFOLEN);
111848f512ceSopenharmony_ci            HLOGE("open fifo file(%s) failed. %d:%s", CONTROL_FIFO_FILE_S2C.c_str(), errno, errInfo);
111948f512ceSopenharmony_ci            return false;
112048f512ceSopenharmony_ci        }
112148f512ceSopenharmony_ci        nullFd_ = open("/dev/null", O_WRONLY);
112248f512ceSopenharmony_ci        (void)dup2(nullFd_, STDOUT_FILENO); // redirect stdout to /dev/null
112348f512ceSopenharmony_ci    } else {            // parent process
112448f512ceSopenharmony_ci        isFifoClient_ = true;
112548f512ceSopenharmony_ci        int fd = open(CONTROL_FIFO_FILE_S2C.c_str(), O_RDONLY | O_NONBLOCK);
112648f512ceSopenharmony_ci        if (fd == -1 or !WaitFifoReply(fd, CONTROL_WAITREPY_TOMEOUT)) {
112748f512ceSopenharmony_ci            close(fd);
112848f512ceSopenharmony_ci            kill(pid, SIGKILL);
112948f512ceSopenharmony_ci            remove(CONTROL_FIFO_FILE_C2S.c_str());
113048f512ceSopenharmony_ci            remove(CONTROL_FIFO_FILE_S2C.c_str());
113148f512ceSopenharmony_ci            strerror_r(errno, errInfo, ERRINFOLEN);
113248f512ceSopenharmony_ci            printf("create control hiperf sampling failed. %d:%s\n", errno, errInfo);
113348f512ceSopenharmony_ci            return false;
113448f512ceSopenharmony_ci        }
113548f512ceSopenharmony_ci        close(fd);
113648f512ceSopenharmony_ci        printf("%s control hiperf sampling success.\n", restart_ ? "start" : "create");
113748f512ceSopenharmony_ci    }
113848f512ceSopenharmony_ci    return true;
113948f512ceSopenharmony_ci}
114048f512ceSopenharmony_ci
114148f512ceSopenharmony_cibool SubCommandRecord::SendFifoAndWaitReply(const std::string &cmd, const std::chrono::milliseconds &timeOut)
114248f512ceSopenharmony_ci{
114348f512ceSopenharmony_ci    // need open for read first, because server maybe send reply before client wait to read
114448f512ceSopenharmony_ci    int fdRead = open(CONTROL_FIFO_FILE_S2C.c_str(), O_RDONLY | O_NONBLOCK);
114548f512ceSopenharmony_ci    if (fdRead == -1) {
114648f512ceSopenharmony_ci        HLOGE("can not open fifo file(%s)", CONTROL_FIFO_FILE_S2C.c_str());
114748f512ceSopenharmony_ci        return false;
114848f512ceSopenharmony_ci    }
114948f512ceSopenharmony_ci    int fdWrite = open(CONTROL_FIFO_FILE_C2S.c_str(), O_WRONLY | O_NONBLOCK);
115048f512ceSopenharmony_ci    if (fdWrite == -1) {
115148f512ceSopenharmony_ci        HLOGE("can not open fifo file(%s)", CONTROL_FIFO_FILE_C2S.c_str());
115248f512ceSopenharmony_ci        close(fdRead);
115348f512ceSopenharmony_ci        return false;
115448f512ceSopenharmony_ci    }
115548f512ceSopenharmony_ci    size_t size = write(fdWrite, cmd.c_str(), cmd.size());
115648f512ceSopenharmony_ci    if (size != cmd.size()) {
115748f512ceSopenharmony_ci        HLOGE("failed to write fifo file(%s) command(%s)", CONTROL_FIFO_FILE_C2S.c_str(),
115848f512ceSopenharmony_ci              cmd.c_str());
115948f512ceSopenharmony_ci        close(fdWrite);
116048f512ceSopenharmony_ci        close(fdRead);
116148f512ceSopenharmony_ci        return false;
116248f512ceSopenharmony_ci    }
116348f512ceSopenharmony_ci    close(fdWrite);
116448f512ceSopenharmony_ci
116548f512ceSopenharmony_ci    bool ret = WaitFifoReply(fdRead, timeOut);
116648f512ceSopenharmony_ci    close(fdRead);
116748f512ceSopenharmony_ci    return ret;
116848f512ceSopenharmony_ci}
116948f512ceSopenharmony_ci
117048f512ceSopenharmony_cibool SubCommandRecord::WaitFifoReply(int fd, const std::chrono::milliseconds &timeOut)
117148f512ceSopenharmony_ci{
117248f512ceSopenharmony_ci    struct pollfd pollFd {
117348f512ceSopenharmony_ci        fd, POLLIN, 0
117448f512ceSopenharmony_ci    };
117548f512ceSopenharmony_ci    int polled = poll(&pollFd, 1, timeOut.count());
117648f512ceSopenharmony_ci    std::string reply;
117748f512ceSopenharmony_ci    if (polled > 0) {
117848f512ceSopenharmony_ci        while (true) {
117948f512ceSopenharmony_ci            char c;
118048f512ceSopenharmony_ci            ssize_t result = TEMP_FAILURE_RETRY(read(fd, &c, 1));
118148f512ceSopenharmony_ci            if (result <= 0) {
118248f512ceSopenharmony_ci                HLOGD("read from fifo file(%s) failed", CONTROL_FIFO_FILE_S2C.c_str());
118348f512ceSopenharmony_ci                break;
118448f512ceSopenharmony_ci            }
118548f512ceSopenharmony_ci            reply.push_back(c);
118648f512ceSopenharmony_ci            if (c == '\n') {
118748f512ceSopenharmony_ci                break;
118848f512ceSopenharmony_ci            }
118948f512ceSopenharmony_ci        }
119048f512ceSopenharmony_ci    } else if (polled == 0) {
119148f512ceSopenharmony_ci        HLOGD("wait fifo file(%s) timeout", CONTROL_FIFO_FILE_S2C.c_str());
119248f512ceSopenharmony_ci    } else {
119348f512ceSopenharmony_ci        HLOGD("wait fifo file(%s) failed", CONTROL_FIFO_FILE_S2C.c_str());
119448f512ceSopenharmony_ci    }
119548f512ceSopenharmony_ci
119648f512ceSopenharmony_ci    if (reply == HiperfClient::ReplyOK) {
119748f512ceSopenharmony_ci        return true;
119848f512ceSopenharmony_ci    }
119948f512ceSopenharmony_ci    return false;
120048f512ceSopenharmony_ci}
120148f512ceSopenharmony_ci
120248f512ceSopenharmony_cibool SubCommandRecord::OnSubCommand(std::vector<std::string> &args)
120348f512ceSopenharmony_ci{
120448f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "SubCommandRecord onSubCommand start");
120548f512ceSopenharmony_ci    if (!ProcessControl()) {
120648f512ceSopenharmony_ci        return false;
120748f512ceSopenharmony_ci    } else if (isFifoClient_) {
120848f512ceSopenharmony_ci        return true;
120948f512ceSopenharmony_ci    }
121048f512ceSopenharmony_ci
121148f512ceSopenharmony_ci    // prepare PerfEvents
121248f512ceSopenharmony_ci    if (!PrepareSysKernel() or !PreparePerfEvent()) {
121348f512ceSopenharmony_ci        return false;
121448f512ceSopenharmony_ci    }
121548f512ceSopenharmony_ci
121648f512ceSopenharmony_ci    // prepar some attr before CreateInitRecordFile
121748f512ceSopenharmony_ci    CHECK_TRUE(!perfEvents_.PrepareTracking(), false, LOG_TYPE_WITH_HILOG, "Fail to prepare tracking ");
121848f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "SubCommandRecord perfEvents prepared");
121948f512ceSopenharmony_ci
122048f512ceSopenharmony_ci    if (!CreateInitRecordFile(delayUnwind_ ? false : compressData_)) {
122148f512ceSopenharmony_ci        HLOGE("Fail to create record file %s", outputFilename_.c_str());
122248f512ceSopenharmony_ci        HIPERF_HILOGE(MODULE_DEFAULT, "Fail to create record file %s", outputFilename_.c_str());
122348f512ceSopenharmony_ci        return false;
122448f512ceSopenharmony_ci    }
122548f512ceSopenharmony_ci
122648f512ceSopenharmony_ci    if (!PrepareVirtualRuntime()) {
122748f512ceSopenharmony_ci        return false;
122848f512ceSopenharmony_ci    }
122948f512ceSopenharmony_ci
123048f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "SubCommandRecord virtualRuntime prepared");
123148f512ceSopenharmony_ci
123248f512ceSopenharmony_ci    // make a thread wait the other command
123348f512ceSopenharmony_ci    if (clientPipeOutput_ != -1) {
123448f512ceSopenharmony_ci        clientCommandHanle_ = std::thread(&SubCommandRecord::ClientCommandHandle, this);
123548f512ceSopenharmony_ci    }
123648f512ceSopenharmony_ci
123748f512ceSopenharmony_ci    //write comm event
123848f512ceSopenharmony_ci    WriteCommEventBeforeSampling();
123948f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "SubCommandRecord StartTracking");
124048f512ceSopenharmony_ci    // start tracking
124148f512ceSopenharmony_ci    if (isDataSizeLimitStop_) {
124248f512ceSopenharmony_ci        // mmap record size has been larger than limit, dont start sampling.
124348f512ceSopenharmony_ci    } else if (restart_ && controlCmd_ == CONTROL_CMD_PREPARE) {
124448f512ceSopenharmony_ci        CHECK_TRUE(!perfEvents_.StartTracking(isFifoServer_), false, 0, "");
124548f512ceSopenharmony_ci    } else {
124648f512ceSopenharmony_ci        if (!perfEvents_.StartTracking((!isFifoServer_) && (clientPipeInput_ == -1))) {
124748f512ceSopenharmony_ci            return false;
124848f512ceSopenharmony_ci        }
124948f512ceSopenharmony_ci    }
125048f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "SubCommandRecord perfEvents tracking finish");
125148f512ceSopenharmony_ci
125248f512ceSopenharmony_ci    startSaveFileTimes_ = steady_clock::now();
125348f512ceSopenharmony_ci    if (!FinishWriteRecordFile()) {
125448f512ceSopenharmony_ci        HLOGE("Fail to finish record file %s", outputFilename_.c_str());
125548f512ceSopenharmony_ci        HIPERF_HILOGE(MODULE_DEFAULT, "Fail to finish record file %s", outputFilename_.c_str());
125648f512ceSopenharmony_ci        return false;
125748f512ceSopenharmony_ci    } else if (!PostProcessRecordFile()) {
125848f512ceSopenharmony_ci        HLOGE("Fail to post process record file");
125948f512ceSopenharmony_ci        HIPERF_HILOGE(MODULE_DEFAULT, "Fail to post process record file");
126048f512ceSopenharmony_ci        return false;
126148f512ceSopenharmony_ci    }
126248f512ceSopenharmony_ci
126348f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "SubCommandRecord final report");
126448f512ceSopenharmony_ci    // finial report
126548f512ceSopenharmony_ci    RecordCompleted();
126648f512ceSopenharmony_ci    RecoverSavedCmdlinesSize();
126748f512ceSopenharmony_ci    OnlineReportData();
126848f512ceSopenharmony_ci    CloseClientThread();
126948f512ceSopenharmony_ci    RemoveVdsoTmpFile();
127048f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "SubCommandRecord finish");
127148f512ceSopenharmony_ci    return true;
127248f512ceSopenharmony_ci}
127348f512ceSopenharmony_ci
127448f512ceSopenharmony_civoid SubCommandRecord::CloseClientThread()
127548f512ceSopenharmony_ci{
127648f512ceSopenharmony_ci    if (clientCommandHanle_.joinable()) {
127748f512ceSopenharmony_ci        clientExit_ = true;
127848f512ceSopenharmony_ci        HLOGI("CloseClientThread");
127948f512ceSopenharmony_ci        if (nullFd_ != -1) {
128048f512ceSopenharmony_ci            close(nullFd_);
128148f512ceSopenharmony_ci        }
128248f512ceSopenharmony_ci        clientCommandHanle_.join();
128348f512ceSopenharmony_ci        close(clientPipeInput_);
128448f512ceSopenharmony_ci        close(clientPipeOutput_);
128548f512ceSopenharmony_ci        if (isFifoServer_) {
128648f512ceSopenharmony_ci            remove(CONTROL_FIFO_FILE_C2S.c_str());
128748f512ceSopenharmony_ci            remove(CONTROL_FIFO_FILE_S2C.c_str());
128848f512ceSopenharmony_ci        }
128948f512ceSopenharmony_ci    }
129048f512ceSopenharmony_ci}
129148f512ceSopenharmony_ci
129248f512ceSopenharmony_civoid SubCommandRecord::RemoveVdsoTmpFile()
129348f512ceSopenharmony_ci{
129448f512ceSopenharmony_ci    std::vector<std::string> fileName = {"/data/local/tmp/[shmm]", "/data/local/tmp/[vdso]"};
129548f512ceSopenharmony_ci    for (auto name : fileName) {
129648f512ceSopenharmony_ci        if (access(name.c_str(), F_OK) == 0) {
129748f512ceSopenharmony_ci            if (remove(name.c_str()) != 0) {
129848f512ceSopenharmony_ci                char errInfo[ERRINFOLEN] = { 0 };
129948f512ceSopenharmony_ci                strerror_r(errno, errInfo, ERRINFOLEN);
130048f512ceSopenharmony_ci                HLOGE("remove file %s failed,errno:%d,errinfo:%s", name.c_str(), errno, errInfo);
130148f512ceSopenharmony_ci            }
130248f512ceSopenharmony_ci        }
130348f512ceSopenharmony_ci    }
130448f512ceSopenharmony_ci}
130548f512ceSopenharmony_ci
130648f512ceSopenharmony_cibool SubCommandRecord::ProcessRecord(std::unique_ptr<PerfEventRecord> record)
130748f512ceSopenharmony_ci{
130848f512ceSopenharmony_ci    CHECK_TRUE(record == nullptr, false, 1, "record is null");
130948f512ceSopenharmony_ci#if HIDEBUG_RECORD_NOT_PROCESS
131048f512ceSopenharmony_ci    // some times we want to check performance
131148f512ceSopenharmony_ci    // but we still want to see the record number
131248f512ceSopenharmony_ci    if (record->GetType() == PERF_RECORD_SAMPLE) {
131348f512ceSopenharmony_ci        recordSamples_++;
131448f512ceSopenharmony_ci    } else {
131548f512ceSopenharmony_ci        recordNoSamples_++;
131648f512ceSopenharmony_ci    }
131748f512ceSopenharmony_ci    if (record->GetType() == PERF_RECORD_SAMPLE) {
131848f512ceSopenharmony_ci        // when the record is allowed from a cache memory, does not free memory after use
131948f512ceSopenharmony_ci        record.release();
132048f512ceSopenharmony_ci    }
132148f512ceSopenharmony_ci    return true;
132248f512ceSopenharmony_ci#else
132348f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME
132448f512ceSopenharmony_ci    const auto startTime = steady_clock::now();
132548f512ceSopenharmony_ci#endif
132648f512ceSopenharmony_ci    if (excludeHiperf_) {
132748f512ceSopenharmony_ci        static pid_t pid = getpid();
132848f512ceSopenharmony_ci        if (record->GetPid() == pid) {
132948f512ceSopenharmony_ci            if (record->GetType() == PERF_RECORD_SAMPLE) {
133048f512ceSopenharmony_ci                // when the record is allowed from a cache memory, does not free memory after use
133148f512ceSopenharmony_ci                record.release();
133248f512ceSopenharmony_ci            }
133348f512ceSopenharmony_ci            // discard record
133448f512ceSopenharmony_ci            return true;
133548f512ceSopenharmony_ci        }
133648f512ceSopenharmony_ci    }
133748f512ceSopenharmony_ci
133848f512ceSopenharmony_ci    // May create some simulated events
133948f512ceSopenharmony_ci    // it will call ProcessRecord before next line
134048f512ceSopenharmony_ci#if !HIDEBUG_RECORD_NOT_PROCESS_VM
134148f512ceSopenharmony_ci    virtualRuntime_.UpdateFromRecord(*record);
134248f512ceSopenharmony_ci#endif
134348f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME
134448f512ceSopenharmony_ci    prcessRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime);
134548f512ceSopenharmony_ci#endif
134648f512ceSopenharmony_ci    return SaveRecord(std::move(record), true);
134748f512ceSopenharmony_ci#endif
134848f512ceSopenharmony_ci}
134948f512ceSopenharmony_ci
135048f512ceSopenharmony_cibool SubCommandRecord::SaveRecord(std::unique_ptr<PerfEventRecord> record, bool ptrReleaseFlag)
135148f512ceSopenharmony_ci{
135248f512ceSopenharmony_ci    ON_SCOPE_EXIT {
135348f512ceSopenharmony_ci        if (ptrReleaseFlag && record->GetType() == PERF_RECORD_SAMPLE) {
135448f512ceSopenharmony_ci            // when the record is allowed from a cache memory, does not free memory after use
135548f512ceSopenharmony_ci            record.release();
135648f512ceSopenharmony_ci        }
135748f512ceSopenharmony_ci    };
135848f512ceSopenharmony_ci#if HIDEBUG_RECORD_NOT_SAVE
135948f512ceSopenharmony_ci    return true;
136048f512ceSopenharmony_ci#endif
136148f512ceSopenharmony_ci    if (dataSizeLimit_ > 0u) {
136248f512ceSopenharmony_ci        if (dataSizeLimit_ <= fileWriter_->GetDataSize()) {
136348f512ceSopenharmony_ci            CHECK_TRUE(isDataSizeLimitStop_, false, 0, "");
136448f512ceSopenharmony_ci            printf("record size %" PRIu64 " is large than limit %" PRIu64 ". stop sampling.\n",
136548f512ceSopenharmony_ci                fileWriter_->GetDataSize(), dataSizeLimit_);
136648f512ceSopenharmony_ci            perfEvents_.StopTracking();
136748f512ceSopenharmony_ci            isDataSizeLimitStop_ = true;
136848f512ceSopenharmony_ci            return false;
136948f512ceSopenharmony_ci        }
137048f512ceSopenharmony_ci    }
137148f512ceSopenharmony_ci
137248f512ceSopenharmony_ci    if (record) {
137348f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME
137448f512ceSopenharmony_ci        const auto saveTime = steady_clock::now();
137548f512ceSopenharmony_ci#endif
137648f512ceSopenharmony_ci        if (!fileWriter_->WriteRecord(*record)) {
137748f512ceSopenharmony_ci            // write file failed, need stop record
137848f512ceSopenharmony_ci            perfEvents_.StopTracking();
137948f512ceSopenharmony_ci            HLOGV("fail to write record %s", record->GetName().c_str());
138048f512ceSopenharmony_ci            return false;
138148f512ceSopenharmony_ci        }
138248f512ceSopenharmony_ci        if (record->GetType() == PERF_RECORD_SAMPLE) {
138348f512ceSopenharmony_ci            recordSamples_++;
138448f512ceSopenharmony_ci        } else {
138548f512ceSopenharmony_ci            recordNoSamples_++;
138648f512ceSopenharmony_ci        }
138748f512ceSopenharmony_ci        HLOGV(" write done. size=%zu name=%s", record->GetSize(), record->GetName().c_str());
138848f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME
138948f512ceSopenharmony_ci        saveRecordTimes_ += duration_cast<microseconds>(steady_clock::now() - saveTime);
139048f512ceSopenharmony_ci#endif
139148f512ceSopenharmony_ci        return true;
139248f512ceSopenharmony_ci    }
139348f512ceSopenharmony_ci    return false;
139448f512ceSopenharmony_ci}
139548f512ceSopenharmony_ci
139648f512ceSopenharmony_ciuint32_t SubCommandRecord::GetCountFromFile(const std::string &fileName)
139748f512ceSopenharmony_ci{
139848f512ceSopenharmony_ci    uint32_t ret = 0;
139948f512ceSopenharmony_ci    std::string str = ReadFileToString(fileName);
140048f512ceSopenharmony_ci    std::vector<std::string> subStrs = StringSplit(str);
140148f512ceSopenharmony_ci    for (auto subStr : subStrs) {
140248f512ceSopenharmony_ci        ret++;
140348f512ceSopenharmony_ci        std::vector<std::string> vSubstr = StringSplit(subStr, "-");
140448f512ceSopenharmony_ci        static const size_t BEGIN_END = 2;
140548f512ceSopenharmony_ci        if (vSubstr.size() == BEGIN_END) {
140648f512ceSopenharmony_ci            ret += (std::stoi(vSubstr[1]) - std::stoi(vSubstr[0]));
140748f512ceSopenharmony_ci        }
140848f512ceSopenharmony_ci    }
140948f512ceSopenharmony_ci    return ret;
141048f512ceSopenharmony_ci}
141148f512ceSopenharmony_ci
141248f512ceSopenharmony_cistd::string SubCommandRecord::GetCpuDescFromFile()
141348f512ceSopenharmony_ci{
141448f512ceSopenharmony_ci    std::string str = ReadFileToString("/proc/cpuinfo");
141548f512ceSopenharmony_ci    std::vector<std::string> subStrs = StringSplit(str, "\n");
141648f512ceSopenharmony_ci    for (auto subStr : subStrs) {
141748f512ceSopenharmony_ci        if (subStr.find("model name") == std::string::npos) {
141848f512ceSopenharmony_ci            continue;
141948f512ceSopenharmony_ci        }
142048f512ceSopenharmony_ci
142148f512ceSopenharmony_ci        std::vector<std::string> vSubstr = StringSplit(subStr, ": ");
142248f512ceSopenharmony_ci        static const size_t NAME_VALUE = 2;
142348f512ceSopenharmony_ci        if (vSubstr.size() == NAME_VALUE) {
142448f512ceSopenharmony_ci            return vSubstr[1];
142548f512ceSopenharmony_ci        } else {
142648f512ceSopenharmony_ci            return "";
142748f512ceSopenharmony_ci        }
142848f512ceSopenharmony_ci    }
142948f512ceSopenharmony_ci    return "";
143048f512ceSopenharmony_ci}
143148f512ceSopenharmony_ci
143248f512ceSopenharmony_cibool SubCommandRecord::AddCpuFeature()
143348f512ceSopenharmony_ci{
143448f512ceSopenharmony_ci    utsname unameBuf;
143548f512ceSopenharmony_ci    if ((uname(&unameBuf)) != 0) {
143648f512ceSopenharmony_ci        perror("uname() failed");
143748f512ceSopenharmony_ci        return false;
143848f512ceSopenharmony_ci    }
143948f512ceSopenharmony_ci
144048f512ceSopenharmony_ci    fileWriter_->AddStringFeature(FEATURE::OSRELEASE, unameBuf.release);
144148f512ceSopenharmony_ci    fileWriter_->AddStringFeature(FEATURE::HOSTNAME, unameBuf.nodename);
144248f512ceSopenharmony_ci    fileWriter_->AddStringFeature(FEATURE::ARCH, unameBuf.machine);
144348f512ceSopenharmony_ci
144448f512ceSopenharmony_ci    try {
144548f512ceSopenharmony_ci        uint32_t cpuPresent = GetCountFromFile("/sys/devices/system/cpu/present");
144648f512ceSopenharmony_ci        uint32_t cpuOnline = GetCountFromFile("/sys/devices/system/cpu/online");
144748f512ceSopenharmony_ci        fileWriter_->AddNrCpusFeature(FEATURE::NRCPUS, cpuPresent - cpuOnline, cpuOnline);
144848f512ceSopenharmony_ci    } catch (...) {
144948f512ceSopenharmony_ci        HLOGD("get NRCPUS failed");
145048f512ceSopenharmony_ci        return false;
145148f512ceSopenharmony_ci    }
145248f512ceSopenharmony_ci    std::string cpuDesc = GetCpuDescFromFile();
145348f512ceSopenharmony_ci    if (!fileWriter_->AddStringFeature(FEATURE::CPUDESC, cpuDesc)) {
145448f512ceSopenharmony_ci        return false;
145548f512ceSopenharmony_ci    }
145648f512ceSopenharmony_ci
145748f512ceSopenharmony_ci    // CPUID(vendor,family,model,stepping in /proc/cpuinfo) isn't supported on Hi3516DV300
145848f512ceSopenharmony_ci    // CPU_TOPOLOGY(sockets,dies,threads), isn't supported on Hi3516DV300
145948f512ceSopenharmony_ci    // NUMA_TOPOLOGY
146048f512ceSopenharmony_ci    // HEADER_PMU_MAPPINGS(/sys/bus/event_source/devices/cpu/type) isn't supported on Hi3516DV300
146148f512ceSopenharmony_ci
146248f512ceSopenharmony_ci    return true;
146348f512ceSopenharmony_ci}
146448f512ceSopenharmony_ci
146548f512ceSopenharmony_civoid SubCommandRecord::AddMemTotalFeature()
146648f512ceSopenharmony_ci{
146748f512ceSopenharmony_ci    std::string str = ReadFileToString("/proc/meminfo");
146848f512ceSopenharmony_ci    std::vector<std::string> subStrs = StringSplit(str, " ");
146948f512ceSopenharmony_ci    for (auto it = subStrs.begin(); it != subStrs.end(); it++) {
147048f512ceSopenharmony_ci        if (it->find("MemTotal:") == std::string::npos) {
147148f512ceSopenharmony_ci            continue;
147248f512ceSopenharmony_ci        }
147348f512ceSopenharmony_ci
147448f512ceSopenharmony_ci        if ((it + 1) != subStrs.end()) {
147548f512ceSopenharmony_ci            uint64_t memTotal = std::stoul(*(it + 1));
147648f512ceSopenharmony_ci            fileWriter_->AddU64Feature(FEATURE::TOTAL_MEM, memTotal);
147748f512ceSopenharmony_ci        }
147848f512ceSopenharmony_ci        break;
147948f512ceSopenharmony_ci    }
148048f512ceSopenharmony_ci}
148148f512ceSopenharmony_ci
148248f512ceSopenharmony_civoid SubCommandRecord::AddEventDescFeature()
148348f512ceSopenharmony_ci{
148448f512ceSopenharmony_ci    fileWriter_->AddEventDescFeature(FEATURE::EVENT_DESC, perfEvents_.GetAttrWithId());
148548f512ceSopenharmony_ci}
148648f512ceSopenharmony_ci
148748f512ceSopenharmony_civoid SubCommandRecord::AddRecordTimeFeature()
148848f512ceSopenharmony_ci{
148948f512ceSopenharmony_ci    // create time
149048f512ceSopenharmony_ci    std::time_t time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
149148f512ceSopenharmony_ci    // clang-format off
149248f512ceSopenharmony_ci    char buf[256] = { 0 };
149348f512ceSopenharmony_ci    ctime_r(&time, buf);
149448f512ceSopenharmony_ci    fileWriter_->AddStringFeature(FEATURE::HIPERF_RECORD_TIME,
149548f512ceSopenharmony_ci                                  StringReplace(buf, "\n", ""));
149648f512ceSopenharmony_ci    // clang-format on
149748f512ceSopenharmony_ci    return;
149848f512ceSopenharmony_ci}
149948f512ceSopenharmony_ci
150048f512ceSopenharmony_civoid SubCommandRecord::AddWorkloadCmdFeature()
150148f512ceSopenharmony_ci{
150248f512ceSopenharmony_ci    if (trackedCommand_.size() > 0) {
150348f512ceSopenharmony_ci        fileWriter_->AddStringFeature(FEATURE::HIPERF_WORKLOAD_CMD, trackedCommand_.at(0));
150448f512ceSopenharmony_ci    } else {
150548f512ceSopenharmony_ci        HLOGD("no trackedCommand");
150648f512ceSopenharmony_ci    }
150748f512ceSopenharmony_ci}
150848f512ceSopenharmony_ci
150948f512ceSopenharmony_civoid SubCommandRecord::AddCommandLineFeature()
151048f512ceSopenharmony_ci{
151148f512ceSopenharmony_ci    // cmdline may end with some no ascii code
151248f512ceSopenharmony_ci    // so we cp it with c_str again
151348f512ceSopenharmony_ci    std::string fullCommandline =
151448f512ceSopenharmony_ci        ReadFileToString("/proc/self/cmdline").c_str() + Command::fullArgument;
151548f512ceSopenharmony_ci    fileWriter_->AddStringFeature(FEATURE::CMDLINE, fullCommandline);
151648f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "cmd : %{public}s", fullCommandline.c_str());
151748f512ceSopenharmony_ci}
151848f512ceSopenharmony_ci
151948f512ceSopenharmony_civoid SubCommandRecord::AddCpuOffFeature()
152048f512ceSopenharmony_ci{
152148f512ceSopenharmony_ci    if (offCPU_) {
152248f512ceSopenharmony_ci        fileWriter_->AddBoolFeature(FEATURE::HIPERF_CPU_OFF);
152348f512ceSopenharmony_ci    }
152448f512ceSopenharmony_ci}
152548f512ceSopenharmony_ci
152648f512ceSopenharmony_civoid SubCommandRecord::AddDevhostFeature()
152748f512ceSopenharmony_ci{
152848f512ceSopenharmony_ci    if (isHM_) {
152948f512ceSopenharmony_ci        fileWriter_->AddStringFeature(FEATURE::HIPERF_HM_DEVHOST,
153048f512ceSopenharmony_ci            StringPrintf("%d", virtualRuntime_.devhostPid_));
153148f512ceSopenharmony_ci    }
153248f512ceSopenharmony_ci}
153348f512ceSopenharmony_ci
153448f512ceSopenharmony_cibool SubCommandRecord::AddFeatureRecordFile()
153548f512ceSopenharmony_ci{
153648f512ceSopenharmony_ci    // VERSION
153748f512ceSopenharmony_ci    CHECK_TRUE(!AddCpuFeature(), false, 0, "");
153848f512ceSopenharmony_ci    AddMemTotalFeature();
153948f512ceSopenharmony_ci
154048f512ceSopenharmony_ci    AddCommandLineFeature();
154148f512ceSopenharmony_ci
154248f512ceSopenharmony_ci    AddEventDescFeature();
154348f512ceSopenharmony_ci
154448f512ceSopenharmony_ci    AddRecordTimeFeature();
154548f512ceSopenharmony_ci
154648f512ceSopenharmony_ci    AddWorkloadCmdFeature();
154748f512ceSopenharmony_ci
154848f512ceSopenharmony_ci    AddCpuOffFeature();
154948f512ceSopenharmony_ci
155048f512ceSopenharmony_ci    AddDevhostFeature();
155148f512ceSopenharmony_ci
155248f512ceSopenharmony_ci    return true;
155348f512ceSopenharmony_ci}
155448f512ceSopenharmony_ci
155548f512ceSopenharmony_cibool SubCommandRecord::CreateInitRecordFile(bool compressData)
155648f512ceSopenharmony_ci{
155748f512ceSopenharmony_ci    if (fileWriter_ == nullptr) {
155848f512ceSopenharmony_ci        fileWriter_ = std::make_unique<PerfFileWriter>();
155948f512ceSopenharmony_ci    }
156048f512ceSopenharmony_ci
156148f512ceSopenharmony_ci    if (!fileWriter_->Open(outputFilename_, compressData)) {
156248f512ceSopenharmony_ci        return false;
156348f512ceSopenharmony_ci    }
156448f512ceSopenharmony_ci
156548f512ceSopenharmony_ci    CHECK_TRUE(!fileWriter_->WriteAttrAndId(perfEvents_.GetAttrWithId()), false, 0, "");
156648f512ceSopenharmony_ci
156748f512ceSopenharmony_ci    CHECK_TRUE(!AddFeatureRecordFile(), false, 0, "");
156848f512ceSopenharmony_ci
156948f512ceSopenharmony_ci    HLOGD("create new record file %s", outputFilename_.c_str());
157048f512ceSopenharmony_ci    return true;
157148f512ceSopenharmony_ci}
157248f512ceSopenharmony_ci
157348f512ceSopenharmony_cibool SubCommandRecord::PostProcessRecordFile()
157448f512ceSopenharmony_ci{
157548f512ceSopenharmony_ci    if (delayUnwind_) {
157648f512ceSopenharmony_ci        // 1. prepare file to rewrite
157748f512ceSopenharmony_ci        std::string tempFileName = outputFilename_ + ".tmp";
157848f512ceSopenharmony_ci        if (rename(outputFilename_.c_str(), tempFileName.c_str()) != 0) {
157948f512ceSopenharmony_ci            HLOGE("rename failed. unabel to do delay unwind");
158048f512ceSopenharmony_ci            perror("Fail to rename data file");
158148f512ceSopenharmony_ci            return false;
158248f512ceSopenharmony_ci        } else {
158348f512ceSopenharmony_ci            HLOGD("use temp file '%s' for delay unwind", tempFileName.c_str());
158448f512ceSopenharmony_ci        }
158548f512ceSopenharmony_ci
158648f512ceSopenharmony_ci        // renew record file
158748f512ceSopenharmony_ci        // release the old one
158848f512ceSopenharmony_ci        fileWriter_.reset();
158948f512ceSopenharmony_ci        if (!CreateInitRecordFile(compressData_)) {
159048f512ceSopenharmony_ci            // create again
159148f512ceSopenharmony_ci            HLOGEP("Fail to open data file %s ", outputFilename_.c_str());
159248f512ceSopenharmony_ci            return false;
159348f512ceSopenharmony_ci        }
159448f512ceSopenharmony_ci
159548f512ceSopenharmony_ci        // read temp file
159648f512ceSopenharmony_ci        auto fileReader = PerfFileReader::Instance(tempFileName);
159748f512ceSopenharmony_ci        if (fileReader == nullptr) {
159848f512ceSopenharmony_ci            HLOGEP("Fail to open data file %s ", tempFileName.c_str());
159948f512ceSopenharmony_ci            return false;
160048f512ceSopenharmony_ci        }
160148f512ceSopenharmony_ci
160248f512ceSopenharmony_ci        // 2. read out the file and unwind
160348f512ceSopenharmony_ci        auto record_callback = [&](std::unique_ptr<PerfEventRecord> record) {
160448f512ceSopenharmony_ci            if (record == nullptr) {
160548f512ceSopenharmony_ci                // return false in callback can stop the read process
160648f512ceSopenharmony_ci                return false;
160748f512ceSopenharmony_ci            } else if (record->GetType() == PERF_RECORD_SAMPLE) {
160848f512ceSopenharmony_ci                HLOGM("readback record for unwind");
160948f512ceSopenharmony_ci                virtualRuntime_.UnwindFromRecord(static_cast<PerfRecordSample &>(*record));
161048f512ceSopenharmony_ci            }
161148f512ceSopenharmony_ci            SaveRecord(std::move(record));
161248f512ceSopenharmony_ci            return true;
161348f512ceSopenharmony_ci        };
161448f512ceSopenharmony_ci        fileReader->ReadDataSection(record_callback);
161548f512ceSopenharmony_ci
161648f512ceSopenharmony_ci        // 3. close again
161748f512ceSopenharmony_ci
161848f512ceSopenharmony_ci        // lte FinishWriteRecordFile write matched only symbols
161948f512ceSopenharmony_ci        delayUnwind_ = false;
162048f512ceSopenharmony_ci        CHECK_TRUE(!FinishWriteRecordFile(), false, 1, "Fail to finish record file %s", outputFilename_.c_str());
162148f512ceSopenharmony_ci
162248f512ceSopenharmony_ci        remove(tempFileName.c_str());
162348f512ceSopenharmony_ci    }
162448f512ceSopenharmony_ci    return true;
162548f512ceSopenharmony_ci}
162648f512ceSopenharmony_ci
162748f512ceSopenharmony_ci#if USE_COLLECT_SYMBOLIC
162848f512ceSopenharmony_civoid SubCommandRecord::SymbolicHits()
162948f512ceSopenharmony_ci{
163048f512ceSopenharmony_ci    if (isHM_) {
163148f512ceSopenharmony_ci        for (auto &processPair : kernelThreadSymbolsHits_) {
163248f512ceSopenharmony_ci            for (auto &vaddr : processPair.second) {
163348f512ceSopenharmony_ci                virtualRuntime_.GetSymbol(vaddr, processPair.first, processPair.first,
163448f512ceSopenharmony_ci                                          PERF_CONTEXT_MAX);
163548f512ceSopenharmony_ci            }
163648f512ceSopenharmony_ci        }
163748f512ceSopenharmony_ci    }
163848f512ceSopenharmony_ci
163948f512ceSopenharmony_ci    for (auto &vaddr : kernelSymbolsHits_) {
164048f512ceSopenharmony_ci        virtualRuntime_.GetSymbol(vaddr, 0, 0, PERF_CONTEXT_KERNEL);
164148f512ceSopenharmony_ci    }
164248f512ceSopenharmony_ci
164348f512ceSopenharmony_ci    for (auto &processPair : userSymbolsHits_) {
164448f512ceSopenharmony_ci        for (auto &vaddr : processPair.second) {
164548f512ceSopenharmony_ci            virtualRuntime_.GetSymbol(vaddr, processPair.first, processPair.first,
164648f512ceSopenharmony_ci                                      PERF_CONTEXT_USER);
164748f512ceSopenharmony_ci        }
164848f512ceSopenharmony_ci    }
164948f512ceSopenharmony_ci}
165048f512ceSopenharmony_ci#endif
165148f512ceSopenharmony_ci
165248f512ceSopenharmony_cibool SubCommandRecord::CollectionSymbol(std::unique_ptr<PerfEventRecord> record)
165348f512ceSopenharmony_ci{
165448f512ceSopenharmony_ci    CHECK_TRUE(record == nullptr, false, 0, "");
165548f512ceSopenharmony_ci    if (record->GetType() == PERF_RECORD_SAMPLE) {
165648f512ceSopenharmony_ci        PerfRecordSample *sample = static_cast<PerfRecordSample *>(record.get());
165748f512ceSopenharmony_ci#if USE_COLLECT_SYMBOLIC
165848f512ceSopenharmony_ci        CollectSymbol(sample);
165948f512ceSopenharmony_ci#else
166048f512ceSopenharmony_ci        virtualRuntime_.SymbolicRecord(*sample);
166148f512ceSopenharmony_ci#endif
166248f512ceSopenharmony_ci        // the record is allowed from a cache memory, does not free memory after use
166348f512ceSopenharmony_ci        record.release();
166448f512ceSopenharmony_ci    }
166548f512ceSopenharmony_ci
166648f512ceSopenharmony_ci    if (isSpe_ && record->GetType() == PERF_RECORD_AUXTRACE) {
166748f512ceSopenharmony_ci        PerfRecordAuxtrace *sample = static_cast<PerfRecordAuxtrace *>(record.get());
166848f512ceSopenharmony_ci        virtualRuntime_.SymbolSpeRecord(*sample);
166948f512ceSopenharmony_ci    }
167048f512ceSopenharmony_ci
167148f512ceSopenharmony_ci    return true;
167248f512ceSopenharmony_ci}
167348f512ceSopenharmony_ci
167448f512ceSopenharmony_civoid SubCommandRecord::CollectSymbol(PerfRecordSample *sample)
167548f512ceSopenharmony_ci{
167648f512ceSopenharmony_ci    CHECK_TRUE(sample == nullptr, NO_RETVAL, 0, "");
167748f512ceSopenharmony_ci    perf_callchain_context context = sample->inKernel() ? PERF_CONTEXT_KERNEL
167848f512ceSopenharmony_ci                                                        : PERF_CONTEXT_USER;
167948f512ceSopenharmony_ci    pid_t serverPid;
168048f512ceSopenharmony_ci    // if no nr use ip ? remove stack nr == 0?
168148f512ceSopenharmony_ci    if (sample->data_.nr == 0) {
168248f512ceSopenharmony_ci        serverPid = sample->GetServerPidof(0);
168348f512ceSopenharmony_ci        if (virtualRuntime_.IsKernelThread(serverPid)) {
168448f512ceSopenharmony_ci            kernelThreadSymbolsHits_[serverPid].insert(sample->data_.ip);
168548f512ceSopenharmony_ci        } else if (context == PERF_CONTEXT_KERNEL) {
168648f512ceSopenharmony_ci            kernelSymbolsHits_.insert(sample->data_.ip);
168748f512ceSopenharmony_ci        } else {
168848f512ceSopenharmony_ci            userSymbolsHits_[sample->data_.pid].insert(sample->data_.ip);
168948f512ceSopenharmony_ci        }
169048f512ceSopenharmony_ci    } else {
169148f512ceSopenharmony_ci        for (u64 i = 0; i < sample->data_.nr; i++) {
169248f512ceSopenharmony_ci            if (sample->data_.ips[i] >= PERF_CONTEXT_MAX) {
169348f512ceSopenharmony_ci                if (sample->data_.ips[i] == PERF_CONTEXT_KERNEL) {
169448f512ceSopenharmony_ci                    context = PERF_CONTEXT_KERNEL;
169548f512ceSopenharmony_ci                } else {
169648f512ceSopenharmony_ci                    context = PERF_CONTEXT_USER;
169748f512ceSopenharmony_ci                }
169848f512ceSopenharmony_ci            } else {
169948f512ceSopenharmony_ci                serverPid = sample->GetServerPidof(i);
170048f512ceSopenharmony_ci                if (virtualRuntime_.IsKernelThread(serverPid)) {
170148f512ceSopenharmony_ci                    kernelThreadSymbolsHits_[serverPid].insert(sample->data_.ips[i]);
170248f512ceSopenharmony_ci                } else if (context == PERF_CONTEXT_KERNEL) {
170348f512ceSopenharmony_ci                    kernelSymbolsHits_.insert(sample->data_.ips[i]);
170448f512ceSopenharmony_ci                } else {
170548f512ceSopenharmony_ci                    userSymbolsHits_[sample->data_.pid].insert(sample->data_.ips[i]);
170648f512ceSopenharmony_ci                }
170748f512ceSopenharmony_ci            }
170848f512ceSopenharmony_ci        }
170948f512ceSopenharmony_ci    }
171048f512ceSopenharmony_ci}
171148f512ceSopenharmony_ci
171248f512ceSopenharmony_ci// finish writing data file, then close file
171348f512ceSopenharmony_cibool SubCommandRecord::FinishWriteRecordFile()
171448f512ceSopenharmony_ci{
171548f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME
171648f512ceSopenharmony_ci    const auto startTime = steady_clock::now();
171748f512ceSopenharmony_ci#endif
171848f512ceSopenharmony_ci#if !HIDEBUG_SKIP_PROCESS_SYMBOLS
171948f512ceSopenharmony_ci    if (!delayUnwind_) {
172048f512ceSopenharmony_ci#if !HIDEBUG_SKIP_LOAD_KERNEL_SYMBOLS
172148f512ceSopenharmony_ci        if (!callChainUserOnly_) {
172248f512ceSopenharmony_ci            virtualRuntime_.UpdateKernelSymbols();
172348f512ceSopenharmony_ci            virtualRuntime_.UpdateKernelModulesSymbols();
172448f512ceSopenharmony_ci            if (isHM_) {
172548f512ceSopenharmony_ci                virtualRuntime_.UpdateServiceSymbols();
172648f512ceSopenharmony_ci            }
172748f512ceSopenharmony_ci        }
172848f512ceSopenharmony_ci        if (isHM_) {
172948f512ceSopenharmony_ci            virtualRuntime_.UpdateDevhostSymbols();
173048f512ceSopenharmony_ci        }
173148f512ceSopenharmony_ci#endif
173248f512ceSopenharmony_ci        HLOGD("Load user symbols");
173348f512ceSopenharmony_ci        if (dedupStack_) {
173448f512ceSopenharmony_ci            virtualRuntime_.CollectDedupSymbol(kernelSymbolsHits_, userSymbolsHits_);
173548f512ceSopenharmony_ci        } else {
173648f512ceSopenharmony_ci            fileWriter_->ReadDataSection(
173748f512ceSopenharmony_ci                [this] (std::unique_ptr<PerfEventRecord> record) -> bool {
173848f512ceSopenharmony_ci                    return this->CollectionSymbol(std::move(record));
173948f512ceSopenharmony_ci                });
174048f512ceSopenharmony_ci        }
174148f512ceSopenharmony_ci#if USE_COLLECT_SYMBOLIC
174248f512ceSopenharmony_ci        SymbolicHits();
174348f512ceSopenharmony_ci#endif
174448f512ceSopenharmony_ci#if HIDEBUG_SKIP_MATCH_SYMBOLS
174548f512ceSopenharmony_ci        disableUnwind_ = true;
174648f512ceSopenharmony_ci#endif
174748f512ceSopenharmony_ci#if !HIDEBUG_SKIP_SAVE_SYMBOLS
174848f512ceSopenharmony_ci        CHECK_TRUE(!fileWriter_->AddSymbolsFeature(virtualRuntime_.GetSymbolsFiles()),
174948f512ceSopenharmony_ci                   false, 1, "Fail to AddSymbolsFeature");
175048f512ceSopenharmony_ci#endif
175148f512ceSopenharmony_ci    }
175248f512ceSopenharmony_ci#endif
175348f512ceSopenharmony_ci    CHECK_TRUE(dedupStack_ && !fileWriter_->AddUniStackTableFeature(virtualRuntime_.GetUniStackTable()), false, 0, "");
175448f512ceSopenharmony_ci    CHECK_TRUE(!fileWriter_->Close(), false, 1, "Fail to close record file %s", outputFilename_.c_str());
175548f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME
175648f512ceSopenharmony_ci    saveFeatureTimes_ += duration_cast<microseconds>(steady_clock::now() - startTime);
175748f512ceSopenharmony_ci#endif
175848f512ceSopenharmony_ci    return true;
175948f512ceSopenharmony_ci}
176048f512ceSopenharmony_ci
176148f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME
176248f512ceSopenharmony_civoid SubCommandRecord::ReportTime()
176348f512ceSopenharmony_ci{
176448f512ceSopenharmony_ci    printf("updateSymbolsTimes: %0.3f ms\n",
176548f512ceSopenharmony_ci           virtualRuntime_.updateSymbolsTimes_.count() / MS_DURATION);
176648f512ceSopenharmony_ci    printf("saveFeatureTimes: %0.3f ms\n", saveFeatureTimes_.count() / MS_DURATION);
176748f512ceSopenharmony_ci
176848f512ceSopenharmony_ci    printf("prcessRecordTimes: %0.3f ms\n", prcessRecordTimes_.count() / MS_DURATION);
176948f512ceSopenharmony_ci    printf("-prcessSampleRecordTimes: %0.3f ms\n",
177048f512ceSopenharmony_ci           virtualRuntime_.processSampleRecordTimes_.count() / MS_DURATION);
177148f512ceSopenharmony_ci    printf("--unwindFromRecordTimes: %0.3f ms\n",
177248f512ceSopenharmony_ci           virtualRuntime_.unwindFromRecordTimes_.count() / MS_DURATION);
177348f512ceSopenharmony_ci    printf("-prcessMmapRecordTimes: %0.3f ms\n",
177448f512ceSopenharmony_ci           virtualRuntime_.processMmapRecordTimes_.count() / MS_DURATION);
177548f512ceSopenharmony_ci    printf("-prcessMmap2RecordTimes: %0.3f ms\n",
177648f512ceSopenharmony_ci           virtualRuntime_.processMmap2RecordTimes_.count() / MS_DURATION);
177748f512ceSopenharmony_ci    printf("-prcessCommRecordTimes: %0.3f ms\n",
177848f512ceSopenharmony_ci           virtualRuntime_.processCommRecordTimes_.count() / MS_DURATION);
177948f512ceSopenharmony_ci    printf("-prcessMmap2RecordTimes: %0.3f ms\n",
178048f512ceSopenharmony_ci           virtualRuntime_.processMmap2RecordTimes_.count() / MS_DURATION);
178148f512ceSopenharmony_ci    printf("--updateThreadTimes: %0.3f ms\n",
178248f512ceSopenharmony_ci           virtualRuntime_.updateThreadTimes_.count() / MS_DURATION);
178348f512ceSopenharmony_ci    printf("---threadParseMapsTimes: %0.3f ms\n",
178448f512ceSopenharmony_ci           virtualRuntime_.threadParseMapsTimes_.count() / MS_DURATION);
178548f512ceSopenharmony_ci    printf("---threadCreateMmapTimes: %0.3f ms\n",
178648f512ceSopenharmony_ci           virtualRuntime_.threadCreateMmapTimes_.count() / MS_DURATION);
178748f512ceSopenharmony_ci    printf("--unwindCallStackTimes: %0.3f ms\n",
178848f512ceSopenharmony_ci           virtualRuntime_.unwindCallStackTimes_.count() / MS_DURATION);
178948f512ceSopenharmony_ci    printf("-symbolicRecordTimes: %0.3f ms\n",
179048f512ceSopenharmony_ci           virtualRuntime_.symbolicRecordTimes_.count() / MS_DURATION);
179148f512ceSopenharmony_ci    printf("saveRecordTimes: %0.3f ms\n", saveRecordTimes_.count() / MS_DURATION);
179248f512ceSopenharmony_ci    printf("-writeTimes: %0.3f ms\n", fileWriter_->writeTimes_.count() / MS_DURATION);
179348f512ceSopenharmony_ci
179448f512ceSopenharmony_ci    printf("logTimes: %0.3f ms\n", DebugLogger::GetInstance()->logTimes_.count() / MS_DURATION);
179548f512ceSopenharmony_ci    printf("-logSprintfTimes: %0.3f ms\n",
179648f512ceSopenharmony_ci           DebugLogger::GetInstance()->logSprintfTimes_.count() / MS_DURATION);
179748f512ceSopenharmony_ci    printf("-logWriteTimes: %0.3f ms\n",
179848f512ceSopenharmony_ci           DebugLogger::GetInstance()->logWriteTimes_.count() / MS_DURATION);
179948f512ceSopenharmony_ci    printf("logCount: %zu (%4.2f ms/log)\n", DebugLogger::GetInstance()->logCount_,
180048f512ceSopenharmony_ci           DebugLogger::GetInstance()->logTimes_.count() /
180148f512ceSopenharmony_ci               static_cast<double>(DebugLogger::GetInstance()->logCount_) / MS_DURATION);
180248f512ceSopenharmony_ci}
180348f512ceSopenharmony_ci#endif
180448f512ceSopenharmony_ci
180548f512ceSopenharmony_cibool SubCommandRecord::RecordCompleted()
180648f512ceSopenharmony_ci{
180748f512ceSopenharmony_ci    if (verboseReport_) {
180848f512ceSopenharmony_ci        printf("Save Record used %0.3f ms.\n",
180948f512ceSopenharmony_ci               duration_cast<microseconds>(steady_clock::now() - startSaveFileTimes_).count() /
181048f512ceSopenharmony_ci                   MS_DURATION);
181148f512ceSopenharmony_ci    }
181248f512ceSopenharmony_ci    HLOGV("Save Record used %0.3f ms.\n",
181348f512ceSopenharmony_ci          duration_cast<microseconds>(steady_clock::now() - startSaveFileTimes_).count() /
181448f512ceSopenharmony_ci              MS_DURATION);
181548f512ceSopenharmony_ci
181648f512ceSopenharmony_ci    // print brief file info
181748f512ceSopenharmony_ci    double mb = static_cast<double>(fileWriter_->GetDataSize()) / (KILO * KILO);
181848f512ceSopenharmony_ci    if (compressData_) {
181948f512ceSopenharmony_ci        printf("[ hiperf record: Captured and compressed %.3f MB perf data. ]\n", mb);
182048f512ceSopenharmony_ci    } else {
182148f512ceSopenharmony_ci        printf("[ hiperf record: Captured %.3f MB perf data. ]\n", mb);
182248f512ceSopenharmony_ci    }
182348f512ceSopenharmony_ci    printf("[ Sample records: %zu, Non sample records: %zu ]\n", recordSamples_, recordNoSamples_);
182448f512ceSopenharmony_ci    // Show brief sample lost.
182548f512ceSopenharmony_ci    size_t lostSamples = 0;
182648f512ceSopenharmony_ci    size_t lostNonSamples = 0;
182748f512ceSopenharmony_ci    perfEvents_.GetLostSamples(lostSamples, lostNonSamples);
182848f512ceSopenharmony_ci    printf("[ Sample lost: %zu, Non sample lost: %zu ]\n", lostSamples, lostNonSamples);
182948f512ceSopenharmony_ci
183048f512ceSopenharmony_ci#ifdef HIPERF_DEBUG_TIME
183148f512ceSopenharmony_ci    ReportTime();
183248f512ceSopenharmony_ci#endif
183348f512ceSopenharmony_ci    return true;
183448f512ceSopenharmony_ci}
183548f512ceSopenharmony_ci
183648f512ceSopenharmony_cibool SubCommandRecord::RegisterSubCommandRecord(void)
183748f512ceSopenharmony_ci{
183848f512ceSopenharmony_ci    return SubCommand::RegisterSubCommand("record", std::make_unique<SubCommandRecord>());
183948f512ceSopenharmony_ci}
184048f512ceSopenharmony_ci
184148f512ceSopenharmony_civoid SubCommandRecord::SetHM()
184248f512ceSopenharmony_ci{
184348f512ceSopenharmony_ci    utsname unameBuf;
184448f512ceSopenharmony_ci    if ((uname(&unameBuf)) == 0) {
184548f512ceSopenharmony_ci        std::string osrelease = unameBuf.release;
184648f512ceSopenharmony_ci        isHM_ = osrelease.find(HMKERNEL) != std::string::npos;
184748f512ceSopenharmony_ci    }
184848f512ceSopenharmony_ci    virtualRuntime_.SetHM(isHM_);
184948f512ceSopenharmony_ci    perfEvents_.SetHM(isHM_);
185048f512ceSopenharmony_ci    HLOGD("Set isHM_: %d", isHM_);
185148f512ceSopenharmony_ci    if (isHM_) {
185248f512ceSopenharmony_ci        // find devhost pid
185348f512ceSopenharmony_ci        const std::string basePath {"/proc/"};
185448f512ceSopenharmony_ci        std::vector<std::string> subDirs = GetSubDirs(basePath);
185548f512ceSopenharmony_ci        for (const auto &subDir : subDirs) {
185648f512ceSopenharmony_ci            if (!IsDigits(subDir)) {
185748f512ceSopenharmony_ci                continue;
185848f512ceSopenharmony_ci            }
185948f512ceSopenharmony_ci            pid_t pid = std::stoll(subDir);
186048f512ceSopenharmony_ci            std::string cmdline = GetProcessName(pid);
186148f512ceSopenharmony_ci            if (cmdline == "/bin/" + DEVHOST_FILE_NAME) {
186248f512ceSopenharmony_ci                virtualRuntime_.SetDevhostPid(pid);
186348f512ceSopenharmony_ci                break;
186448f512ceSopenharmony_ci            }
186548f512ceSopenharmony_ci        }
186648f512ceSopenharmony_ci    }
186748f512ceSopenharmony_ci}
186848f512ceSopenharmony_ci
186948f512ceSopenharmony_cibool SubCommandRecord::OnlineReportData()
187048f512ceSopenharmony_ci{
187148f512ceSopenharmony_ci    if (!report_) {
187248f512ceSopenharmony_ci        return true;
187348f512ceSopenharmony_ci    }
187448f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "%" HILOG_PUBLIC "s begin to report file %" HILOG_PUBLIC "s",
187548f512ceSopenharmony_ci                  __FUNCTION__, outputFilename_.c_str());
187648f512ceSopenharmony_ci    bool ret = false;
187748f512ceSopenharmony_ci    std::string tempFileName = outputFilename_ + ".tmp";
187848f512ceSopenharmony_ci    if (rename(outputFilename_.c_str(), tempFileName.c_str()) != 0) {
187948f512ceSopenharmony_ci        char errInfo[ERRINFOLEN] = { 0 };
188048f512ceSopenharmony_ci        strerror_r(errno, errInfo, ERRINFOLEN);
188148f512ceSopenharmony_ci        HIPERF_HILOGI(MODULE_DEFAULT, "%" HILOG_PUBLIC "s can't rename file %" HILOG_PUBLIC "s"
188248f512ceSopenharmony_ci                      "errno:%" HILOG_PUBLIC "d , errInfo: %" HILOG_PUBLIC "s\n",
188348f512ceSopenharmony_ci                      __FUNCTION__, outputFilename_.c_str(), errno, errInfo);
188448f512ceSopenharmony_ci        return false;
188548f512ceSopenharmony_ci    }
188648f512ceSopenharmony_ci
188748f512ceSopenharmony_ci    std::unique_ptr<SubCommandReport> reporter = std::make_unique<SubCommandReport>();
188848f512ceSopenharmony_ci    HLOGD("report the file %s to report file %s \n", tempFileName.c_str(), outputFilename_.c_str());
188948f512ceSopenharmony_ci    std::vector<std::string> args;
189048f512ceSopenharmony_ci    args.emplace_back("-i");
189148f512ceSopenharmony_ci    args.emplace_back(tempFileName);
189248f512ceSopenharmony_ci    args.emplace_back("-o");
189348f512ceSopenharmony_ci    args.emplace_back(outputFilename_);
189448f512ceSopenharmony_ci    args.emplace_back("-s");
189548f512ceSopenharmony_ci    if (reporter->ParseOption(args)) {
189648f512ceSopenharmony_ci        ret =  reporter->OnSubCommand(args);
189748f512ceSopenharmony_ci    }
189848f512ceSopenharmony_ci
189948f512ceSopenharmony_ci    if (remove(tempFileName.c_str()) != 0) {
190048f512ceSopenharmony_ci        char errInfo[ERRINFOLEN] = { 0 };
190148f512ceSopenharmony_ci        strerror_r(errno, errInfo, ERRINFOLEN);
190248f512ceSopenharmony_ci        HIPERF_HILOGI(MODULE_DEFAULT, "%" HILOG_PUBLIC "s remove file failed %" HILOG_PUBLIC "s"
190348f512ceSopenharmony_ci                      "errno:%" HILOG_PUBLIC "d , errInfo: %" HILOG_PUBLIC "s\n",
190448f512ceSopenharmony_ci                      __FUNCTION__, tempFileName.c_str(), errno, errInfo);
190548f512ceSopenharmony_ci    }
190648f512ceSopenharmony_ci    HIPERF_HILOGI(MODULE_DEFAULT, "%" HILOG_PUBLIC "s report result %" HILOG_PUBLIC "s",
190748f512ceSopenharmony_ci                  __FUNCTION__, ret ? "success" : "fail");
190848f512ceSopenharmony_ci    return ret;
190948f512ceSopenharmony_ci}
191048f512ceSopenharmony_ci} // namespace HiPerf
191148f512ceSopenharmony_ci} // namespace Developtools
191248f512ceSopenharmony_ci} // namespace OHOS
1913