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