/* * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <algorithm> #include "util/config_utils.h" #include "directory_ex.h" #include "hilog_wrapper.h" #include "dump_common_utils.h" #include "dump_utils.h" #include "parameter.h" #include "common/dumper_constant.h" #include "parameters.h" namespace OHOS { namespace HiviewDFX { namespace { constexpr int ROOT_UID = 0; constexpr int BMS_UID = 1000; constexpr int APP_FIRST_UID = 10000; static const std::string SMAPS_PATH = "smaps/"; static const std::string SMAPS_PATH_START = "/proc/"; static const std::string SMAPS_PATH_END = "/smaps"; } // namespace ConfigUtils::ConfigUtils(const std::shared_ptr<DumperParameter> ¶m) : dumperParam_(param) { } ConfigUtils::~ConfigUtils() { pidInfos_.clear(); cpuInfos_.clear(); currentPidInfos_.clear(); currentPidInfo_.Reset(); } DumpStatus ConfigUtils::GetDumperConfigs(const std::shared_ptr<DumperParameter> ¶m) { DUMPER_HILOGD(MODULE_COMMON, "enter|"); DumpStatus ret = DumpStatus::DUMP_FAIL; if (param == nullptr) { return ret; } ConfigUtils configUtils(param); ret = configUtils.GetDumperConfigs(); if (ret == DumpStatus::DUMP_OK) { auto dumpCfgs = param->GetExecutorConfigList(); for (size_t i = 0; i < dumpCfgs.size(); i++) { dumpCfgs[i]->Dump(); } } DUMPER_HILOGD(MODULE_COMMON, "leave|ret=%{public}d", ret); return ret; } DumpStatus ConfigUtils::GetDumperConfigs() { DUMPER_HILOGD(MODULE_COMMON, "enter|"); DumpCommonUtils::GetCpuInfos(cpuInfos_); DUMPER_HILOGD(MODULE_COMMON, "debug|cpuInfos=%{public}zu", cpuInfos_.size()); std::vector<std::shared_ptr<DumpCfg>> dumpCfgs; currentPidInfo_.Reset(); currentPidInfos_.clear(); HandleDumpSystem(dumpCfgs); HandleDumpCpuFreq(dumpCfgs); // cpuid HandleDumpCpuUsage(dumpCfgs); // pid HandleDumpMem(dumpCfgs); HandleDumpJsHeapMem(dumpCfgs); HandleDumpMemShowMaps(dumpCfgs); HandleDumpLog(dumpCfgs); HandleDumpStorage(dumpCfgs); HandleDumpNet(dumpCfgs); HandleDumpList(dumpCfgs); HandleDumpAbility(dumpCfgs); HandleDumpService(dumpCfgs); HandleDumpProcesses(dumpCfgs); HandleDumpFaultLog(dumpCfgs); HandleDumpAppendix(dumpCfgs); HandleDumpIpcStat(dumpCfgs); DUMPER_HILOGD(MODULE_COMMON, "debug|dumpCfgs=%{public}zu", dumpCfgs.size()); dumperParam_->SetExecutorConfigList(dumpCfgs); DUMPER_HILOGD(MODULE_COMMON, "leave|"); return DumpStatus::DUMP_OK; } DumpStatus ConfigUtils::GetSectionNames(const std::string &name, std::vector<std::string> &nameList) { std::vector<std::string> tmpUse; GetGroupNames(name, tmpUse); std::transform(tmpUse.begin(), tmpUse.end(), std::back_inserter(nameList), [](std::string &a) { return GetSectionName(a); }); DumpUtils::RemoveDuplicateString(nameList); // remove duplicate log names return DumpStatus::DUMP_OK; } DumpStatus ConfigUtils::GetGroupNames(const std::string &name, std::vector<std::string> &nameList) { bool check = !name.empty(); for (int i = 0; i < groupSum_; i++) { if (groups_[i].name_.empty()) { continue; } if (check && (groups_[i].name_.find(name) != 0)) { continue; } nameList.push_back(groups_[i].name_); } return DumpStatus::DUMP_OK; } std::string ConfigUtils::GetSectionName(const std::string &name) { std::string ret; std::size_t pos = name.find_last_of(CONFIG_NAME_SPLIT); if (pos != std::string::npos) { ret = name.substr(pos + 1); } return ret; } bool ConfigUtils::MergePidInfos(std::vector<DumpCommonUtils::PidInfo> &pidInfos, int pid) { pidInfos.clear(); if (pid < 0) { currentPidInfo_.pid_ = pid; currentPidInfo_.uid_ = -1; DumpCommonUtils::GetPidInfos(pidInfos_); DUMPER_HILOGI(MODULE_COMMON, "info|pidInfos=%{public}zu", pidInfos_.size()); pidInfos.assign(pidInfos_.begin(), pidInfos_.end()); } else { if (DumpCommonUtils::GetProcessInfo(pid, currentPidInfo_)) { pidInfos.push_back(currentPidInfo_); } } return true; } bool ConfigUtils::MergeDebugPidInfos(std::vector<DumpCommonUtils::PidInfo> &pidInfos, int pid) { pidInfos.clear(); if (pid < 0) { currentPidInfo_.pid_ = pid; currentPidInfo_.uid_ = -1; DumpCommonUtils::GetPidInfos(pidInfos_); std::copy_if(pidInfos_.begin(), pidInfos_.end(), std::back_inserter(pidInfos), [](auto &it) { return DumpUtils::CheckAppDebugVersion(it.pid_); }); if (pidInfos.size() == 0) { DUMPER_HILOGE(MODULE_COMMON, "not find release version pid"); return false; } DUMPER_HILOGI(MODULE_COMMON, "info|pidInfos=%{public}zu", pidInfos.size()); } else { if (DumpUtils::CheckAppDebugVersion(pid) && DumpCommonUtils::GetProcessInfo(pid, currentPidInfo_)) { pidInfos.push_back(currentPidInfo_); } else { DUMPER_HILOGE(MODULE_COMMON, "pid:%{public}d is release version", pid); return false; } } return true; } bool ConfigUtils::HandleDumpLog(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpLog_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|log"); currentPidInfo_.Reset(); currentPidInfos_.clear(); auto args = OptionArgs::Create(); args->SetStrList(dumperOpts.logArgs_); for (size_t i = 0; i < dumperOpts.logArgs_.size(); i++) { std::string name = CONFIG_GROUP_LOG_ + dumperOpts.logArgs_[i]; GetConfig(name, dumpCfgs, args); } currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpList(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpList_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|list"); currentPidInfo_.Reset(); currentPidInfos_.clear(); if (dumperOpts.isDumpSystemAbility_) { DUMPER_HILOGD(MODULE_COMMON, "debug|list ability"); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_DUMPER_LIST_SYSTEM_ABILITY, dumpCfgs, args); } if (dumperOpts.isDumpService_) { DUMPER_HILOGD(MODULE_COMMON, "debug|list service"); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_DUMPER_LIST_SERVICE, dumpCfgs, args); } if (dumperOpts.isDumpSystem_) { DUMPER_HILOGD(MODULE_COMMON, "debug|list system"); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_DUMPER_LIST_SYSTEM, dumpCfgs, args); } currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpService(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (dumperOpts.isDumpList_ || (!dumperOpts.isDumpService_)) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|service"); currentPidInfo_.Reset(); currentPidInfos_.clear(); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_SERVICE, dumpCfgs, args); currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpAbility(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (dumperOpts.isDumpList_ || (!dumperOpts.isDumpSystemAbility_)) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|ability"); currentPidInfo_.Reset(); currentPidInfos_.clear(); auto args = OptionArgs::Create(); args->SetNamesAndArgs(dumperOpts.abilitieNames_, dumperOpts.abilitieArgs_); GetConfig(CONFIG_GROUP_ABILITY, dumpCfgs, args); currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpSystem(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (dumperOpts.isDumpList_ || (!dumperOpts.isDumpSystem_)) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|system"); currentPidInfo_.Reset(); currentPidInfos_.clear(); if (dumperOpts.systemArgs_.empty()) { std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_SYSTEM_BASE, dumpCfgs, args); GetConfig(CONFIG_GROUP_SYSTEM_SYSTEM, dumpCfgs, args); isDumpSystemSystem = true; return true; } auto args = OptionArgs::Create(); args->SetStrList(dumperOpts.systemArgs_); for (size_t i = 0; i < dumperOpts.systemArgs_.size(); i++) { std::string name = CONFIG_GROUP_SYSTEM_ + dumperOpts.systemArgs_[i]; GetConfig(name, dumpCfgs, args); if (name == CONFIG_GROUP_SYSTEM_SYSTEM) { isDumpSystemSystem = true; } } currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpCpuFreq(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpCpuFreq_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d", isDumpSystemSystem); if (isDumpSystemSystem) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|cpu freq"); currentPidInfo_.Reset(); currentPidInfos_.clear(); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_CPU_FREQ, dumpCfgs, args); currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpCpuUsage(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpCpuUsage_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, cpuUsagePid=%{public}d", isDumpSystemSystem, dumperOpts.cpuUsagePid_); if (isDumpSystemSystem && (dumperOpts.cpuUsagePid_ < 0)) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|cpu usage"); currentPidInfo_.Reset(); currentPidInfos_.clear(); MergePidInfos(currentPidInfos_, dumperOpts.cpuUsagePid_); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_CPU_USAGE, dumpCfgs, args); currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpMem(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpMem_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, memPid=%{public}d", isDumpSystemSystem, dumperOpts.memPid_); if (isDumpSystemSystem && (dumperOpts.memPid_ < 0)) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|mem"); HandleDumpMemCommon(dumperParam_, dumpCfgs); return true; } bool ConfigUtils::HandleDumpJsHeapMem(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpJsHeapMem_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|memPid=%{public}d threadId=%{public}d", dumperOpts.dumpJsHeapMemPid_, dumperOpts.threadId_); if ((dumperOpts.dumpJsHeapMemPid_ <= 0) || (dumperOpts.threadId_ < 0)) { return false; } std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_DUMPER_JSHEAP_MEMORY, dumpCfgs, args); return true; } bool ConfigUtils::HandleDumpMemShowMaps(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isShowSmaps_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, memPid=%{public}d", isDumpSystemSystem, dumperOpts.memPid_); if (isDumpSystemSystem && (dumperOpts.memPid_ < 0)) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|mem-smaps"); HandleDumpMemCommon(dumperParam_, dumpCfgs); return true; } void ConfigUtils::HandleDumpMemCommon(std::shared_ptr<DumperParameter> dumpParam, std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { currentPidInfo_.Reset(); currentPidInfos_.clear(); MergePidInfos(currentPidInfos_, dumpParam->GetOpts().memPid_); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_MEMORY, dumpCfgs, args); currentPidInfos_.clear(); currentPidInfo_.Reset(); } bool ConfigUtils::HandleDumpStorage(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpStorage_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, storagePid=%{public}d", isDumpSystemSystem, dumperOpts.storagePid_); if (isDumpSystemSystem && (dumperOpts.memPid_ < 0)) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|storage"); currentPidInfo_.Reset(); currentPidInfos_.clear(); MergePidInfos(currentPidInfos_, dumperOpts.storagePid_); std::shared_ptr<OptionArgs> args; if (dumperOpts.storagePid_ < 0) { GetConfig(CONFIG_GROUP_STORAGE, dumpCfgs, args); } else { GetConfig(CONFIG_GROUP_STORAGE_IO, dumpCfgs, args); } currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpNet(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpNet_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, netPid=%{public}d", isDumpSystemSystem, dumperOpts.netPid_); if (isDumpSystemSystem && (dumperOpts.netPid_ < 0)) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|net"); currentPidInfo_.Reset(); currentPidInfos_.clear(); MergePidInfos(currentPidInfos_, dumperOpts.netPid_); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_NET_TRAFFIC, dumpCfgs, args); if (dumperOpts.netPid_ < 0) { GetConfig(CONFIG_GROUP_NET, dumpCfgs, args); } currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpProcesses(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); std::string path = dumperOpts.path_; if (!dumperOpts.isDumpProcesses_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|processes"); currentPidInfo_.Reset(); currentPidInfos_.clear(); bool isUserMode = DumpUtils::IsUserMode(); if (isUserMode) { if (!MergeDebugPidInfos(currentPidInfos_, dumperOpts.processPid_)) { DUMPER_HILOGE(MODULE_COMMON, "dump process failed"); return false; } } else { MergePidInfos(currentPidInfos_, dumperOpts.processPid_); } std::shared_ptr<OptionArgs> args; if (isUserMode) { // release mode if (dumperOpts.processPid_ < 0) { GetConfig(CONFIG_GROUP_PROCESSES, dumpCfgs, args); } else { GetConfig(CONFIG_GROUP_PROCESSES_PID, dumpCfgs, args); } } else { // engine mode if (dumperOpts.processPid_ < 0) { GetConfig(CONFIG_GROUP_PROCESSES_ENG, dumpCfgs, args); } else { GetConfig(CONFIG_GROUP_PROCESSES_PID_ENG, dumpCfgs, args); } if (dumperOpts.IsDumpZip()) { CopySmaps(); } } currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpFaultLog(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isFaultLog_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|fault log"); currentPidInfo_.Reset(); currentPidInfos_.clear(); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_FAULT_LOG, dumpCfgs, args); currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpAppendix(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isAppendix_) { return false; } DUMPER_HILOGD(MODULE_COMMON, "debug|appendix"); currentPidInfo_.Reset(); currentPidInfos_.clear(); MergePidInfos(currentPidInfos_, -1); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_LOG_KERNEL, dumpCfgs, args); GetConfig(CONFIG_GROUP_LOG_INIT, dumpCfgs, args); GetConfig(CONFIG_GROUP_LOG_HILOG, dumpCfgs, args); int callingUid = dumperParam_->GetUid(); if (callingUid == ROOT_UID || callingUid == BMS_UID) { GetConfig(CONFIG_GROUP_STACK, dumpCfgs, args); } else { DUMPER_HILOGE(MODULE_COMMON, "No permission to perform dump stack operation, uid=%{public}d", callingUid); } currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } bool ConfigUtils::HandleDumpIpcStat(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs) { const DumperOpts &dumperOpts = dumperParam_->GetOpts(); if (!dumperOpts.isDumpIpc_) { return false; } currentPidInfo_.Reset(); currentPidInfos_.clear(); MergePidInfos(currentPidInfos_, dumperOpts.ipcStatPid_); std::shared_ptr<OptionArgs> args; GetConfig(CONFIG_GROUP_IPC_STAT, dumpCfgs, args); currentPidInfos_.clear(); currentPidInfo_.Reset(); return true; } int ConfigUtils::GetDumpLevelByPid(int uid, const DumpCommonUtils::PidInfo &pidInfo) { int ret = DumperConstant::LEVEL_NONE; if (uid == ROOT_UID) { ret = DumperConstant::LEVEL_HIGH; } else if (uid < APP_FIRST_UID) { ret = DumperConstant::LEVEL_MIDDLE; } else { if (uid == pidInfo.uid_) { ret = DumperConstant::LEVEL_MIDDLE; } } return ret; } DumpStatus ConfigUtils::GetConfig(const std::string &name, std::vector<std::shared_ptr<DumpCfg>> &result, std::shared_ptr<OptionArgs> args) { DumpStatus ret = DumpStatus::DUMP_FAIL; if (name.find(CONFIG_DUMPER_) == 0) { DUMPER_HILOGD(MODULE_COMMON, "debug|dumper, name=%{public}s", name.c_str()); ret = GetDumper(name, result, args); } else if (name.find(CONFIG_GROUP_) == 0) { DUMPER_HILOGD(MODULE_COMMON, "debug|group, name=%{public}s", name.c_str()); ret = GetGroup(name, result, args); } else { DUMPER_HILOGE(MODULE_COMMON, "error|name=%{public}s", name.c_str()); } return ret; } DumpStatus ConfigUtils::GetDumper(int index, std::vector<std::shared_ptr<DumpCfg>> &result, std::shared_ptr<OptionArgs> args, int level) { if ((index < 0) || (index >= dumperSum_)) { return DumpStatus::DUMP_INVALID_ARG; } auto itemlist = dumpers_[index].list_; auto itemsize = dumpers_[index].size_; for (int i = 0; i < itemsize; i++) { if (DumpCfg::IsFilter(itemlist[i].class_) && DumpCfg::IsLevel(level)) { if ((itemlist[i].level_ != DumperConstant::LEVEL_ALL) && (itemlist[i].level_ != level)) { continue; } } auto dumpCfg = DumpCfg::Create(); dumpCfg->name_ = itemlist[i].name_; dumpCfg->desc_ = itemlist[i].desc_; dumpCfg->target_ = itemlist[i].target_; dumpCfg->section_ = itemlist[i].section_; dumpCfg->class_ = itemlist[i].class_; dumpCfg->level_ = itemlist[i].level_; dumpCfg->loop_ = itemlist[i].loop_; dumpCfg->filterCfg_ = itemlist[i].filterCfg_; dumpCfg->args_ = dumpCfg->IsDumper() ? args : nullptr; result.push_back(dumpCfg); } return DumpStatus::DUMP_OK; } DumpStatus ConfigUtils::GetDumper(const std::string &name, std::vector<std::shared_ptr<DumpCfg>> &result, std::shared_ptr<OptionArgs> args, int level) { DumpStatus ret = DumpStatus::DUMP_FAIL; int index = -1; for (int i = 0; i < dumperSum_; i++) { if (dumpers_[i].name_.empty()) { continue; } if (name != dumpers_[i].name_) { continue; } index = i; break; } if (index > -1) { ret = GetDumper(index, result, args, level); } return ret; } DumpStatus ConfigUtils::GetGroupSimple(const GroupCfg &groupCfg, std::vector<std::shared_ptr<DumpCfg>> &result, std::shared_ptr<OptionArgs> args, int level, int nest) { if (nest > NEST_MAX) { return DumpStatus::DUMP_INVALID_ARG; } if ((groupCfg.list_ == nullptr) || (groupCfg.size_ < 1)) { return DumpStatus::DUMP_OK; } auto dumpGroup = DumpCfg::Create(); if (groupCfg.expand_) { dumpGroup->class_ = DumperConstant::GROUP; dumpGroup->name_ = groupCfg.name_; dumpGroup->desc_ = groupCfg.desc_; dumpGroup->type_ = groupCfg.type_; dumpGroup->expand_ = groupCfg.expand_; result.push_back(dumpGroup); } auto &outlist = (groupCfg.expand_) ? dumpGroup->childs_ : result; for (int i = 0; i < groupCfg.size_; i++) { if (groupCfg.list_[i].empty()) { continue; } if (DumpCommonUtils::StartWith(groupCfg.list_[i], CONFIG_DUMPER_)) { GetDumper(groupCfg.list_[i], outlist, args, level); } else if (DumpCommonUtils::StartWith(groupCfg.list_[i], CONFIG_MINIGROUP_)) { GetGroup(groupCfg.list_[i], outlist, args, level, nest + 1); } else { DUMPER_HILOGE(MODULE_COMMON, "error|name=%{public}s", groupCfg.name_.c_str()); return DumpStatus::DUMP_INVALID_ARG; } } return DumpStatus::DUMP_OK; } DumpStatus ConfigUtils::GetGroup(int index, std::vector<std::shared_ptr<DumpCfg>> &result, std::shared_ptr<OptionArgs> args, int level, int nest) { if (nest > NEST_MAX) { return DumpStatus::DUMP_INVALID_ARG; } auto dumpGroup = DumpCfg::Create(); dumpGroup->class_ = DumperConstant::GROUP; dumpGroup->name_ = groups_[index].name_; dumpGroup->desc_ = groups_[index].desc_; dumpGroup->type_ = groups_[index].type_; dumpGroup->expand_ = groups_[index].expand_; result.push_back(dumpGroup); if (dumpGroup->expand_ && (dumpGroup->type_ == DumperConstant::GROUPTYPE_PID)) { for (auto pidInfo : currentPidInfos_) { int newLevel = GetDumpLevelByPid(dumperParam_->GetUid(), pidInfo); if (newLevel == DumperConstant::LEVEL_NONE) { continue; } auto newArgs = OptionArgs::Clone(args); newArgs->SetPid(pidInfo.pid_, pidInfo.uid_); GetGroupSimple(groups_[index], dumpGroup->childs_, newArgs, newLevel, nest); } } else if (dumpGroup->expand_ && (dumpGroup->type_ == DumperConstant::GROUPTYPE_CPUID)) { for (auto cpuInfo : cpuInfos_) { auto newArgs = OptionArgs::Clone(args); newArgs->SetCpuId(cpuInfo.id_); GetGroupSimple(groups_[index], dumpGroup->childs_, newArgs, level, nest); } } else if (dumpGroup->type_ == DumperConstant::GROUPTYPE_PID) { int newLevel = GetDumpLevelByPid(dumperParam_->GetUid(), currentPidInfo_); if (newLevel != DumperConstant::LEVEL_NONE) { auto newArgs = OptionArgs::Clone(args); newArgs->SetPid(currentPidInfo_.pid_, currentPidInfo_.uid_); GetGroupSimple(groups_[index], dumpGroup->childs_, newArgs, level, nest); } } else if (dumpGroup->type_ == DumperConstant::GROUPTYPE_CPUID) { auto newArgs = OptionArgs::Clone(args); newArgs->SetCpuId(-1); GetGroupSimple(groups_[index], dumpGroup->childs_, newArgs, level, nest); } else if (dumpGroup->type_ == DumperConstant::NONE) { GetGroupSimple(groups_[index], dumpGroup->childs_, args, level, nest); } else { DUMPER_HILOGE(MODULE_COMMON, "error|type=%{public}d", dumpGroup->type_); return DumpStatus::DUMP_INVALID_ARG; } return DumpStatus::DUMP_OK; } DumpStatus ConfigUtils::GetGroup(const std::string &name, std::vector<std::shared_ptr<DumpCfg>> &result, std::shared_ptr<OptionArgs> args, int level, int nest) { if (nest > NEST_MAX) { return DumpStatus::DUMP_INVALID_ARG; } DumpStatus ret = DumpStatus::DUMP_FAIL; int index = -1; // find group for (int i = 0; i < groupSum_; i++) { if (groups_[i].name_.empty()) { continue; } if (name != groups_[i].name_) { continue; } index = i; break; } // add dump config to tmpUse std::vector<std::shared_ptr<DumpCfg>> tmpUse; if (index > -1) { ret = GetGroup(index, tmpUse, args, level); } if (nest) { result.insert(result.end(), tmpUse.begin(), tmpUse.end()); } else { // add section & add config to result SetSection(tmpUse, GetSectionName(name)); ConvertTreeToList(tmpUse, result); } return ret; } void ConfigUtils::ConvertTreeToList(std::vector<std::shared_ptr<DumpCfg>> &tree, std::vector<std::shared_ptr<DumpCfg>> &list, int nest) { if (nest > NEST_MAX) { return; } std::vector<std::shared_ptr<DumpCfg>> tmpUsed; for (auto item : tree) { if (item == nullptr) { continue; } tmpUsed.push_back(item); if (item->childs_.empty()) { continue; } for (auto child : item->childs_) { child->parent_ = item; // after point to parent, childs must be cleared. } ConvertTreeToList(item->childs_, tmpUsed, nest + 1); item->childs_.clear(); // must clear } list.insert(list.end(), tmpUsed.begin(), tmpUsed.end()); } void ConfigUtils::SetSection(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs, const std::string §ion, int nest) { if (nest > NEST_MAX) { return; } for (auto dumpCfg : dumpCfgs) { if (dumpCfg == nullptr) { continue; } if (dumpCfg->IsDumper()) { dumpCfg->section_ = section; } if (dumpCfg->childs_.empty()) { continue; } SetSection(dumpCfg->childs_, section, nest + 1); } } bool ConfigUtils::CopySmaps() { DUMPER_HILOGD(MODULE_COMMON, "CopySmaps enter|"); std::shared_ptr<RawParam> callback = dumperParam_->getClientCallback(); if (callback == nullptr) { DUMPER_HILOGE(MODULE_COMMON, "CopySmaps leave|callback"); return false; } callback->SetProgressEnabled(true); std::string logFolder = callback->GetFolder(); int uid = dumperParam_->GetUid(); for (auto &pidInfo : currentPidInfos_) { int newLevel = GetDumpLevelByPid(uid, pidInfo); if (newLevel == DumperConstant::LEVEL_NONE) { continue; } if (callback->IsCanceled()) { DUMPER_HILOGD(MODULE_COMMON, "CopySmaps debug|Canceled"); break; } callback->UpdateProgress(0); std::string pid = std::to_string(pidInfo.pid_); std::string desfolder = logFolder + SMAPS_PATH + pidInfo.name_ + "-" + pid; std::string src = SMAPS_PATH_START + pid + SMAPS_PATH_END; std::string des = desfolder + SMAPS_PATH_END; ForceCreateDirectory(IncludeTrailingPathDelimiter(desfolder)); DumpUtils::CopyFile(src, des); } DUMPER_HILOGD(MODULE_COMMON, "CopySmaps leave|true"); return true; } } // namespace HiviewDFX } // namespace OHOS