1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <algorithm>
16 #include "util/config_utils.h"
17 #include "directory_ex.h"
18 #include "hilog_wrapper.h"
19 #include "dump_common_utils.h"
20 #include "dump_utils.h"
21 #include "parameter.h"
22 #include "common/dumper_constant.h"
23 #include "parameters.h"
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace {
27 constexpr int ROOT_UID = 0;
28 constexpr int BMS_UID = 1000;
29 constexpr int APP_FIRST_UID = 10000;
30 static const std::string SMAPS_PATH = "smaps/";
31 static const std::string SMAPS_PATH_START = "/proc/";
32 static const std::string SMAPS_PATH_END = "/smaps";
33 } // namespace
34 
ConfigUtils(const std::shared_ptr<DumperParameter> & param)35 ConfigUtils::ConfigUtils(const std::shared_ptr<DumperParameter> &param) : dumperParam_(param)
36 {
37 }
38 
~ConfigUtils()39 ConfigUtils::~ConfigUtils()
40 {
41     pidInfos_.clear();
42     cpuInfos_.clear();
43     currentPidInfos_.clear();
44     currentPidInfo_.Reset();
45 }
46 
GetDumperConfigs(const std::shared_ptr<DumperParameter> & param)47 DumpStatus ConfigUtils::GetDumperConfigs(const std::shared_ptr<DumperParameter> &param)
48 {
49     DUMPER_HILOGD(MODULE_COMMON, "enter|");
50     DumpStatus ret = DumpStatus::DUMP_FAIL;
51 
52     if (param == nullptr) {
53         return ret;
54     }
55     ConfigUtils configUtils(param);
56     ret = configUtils.GetDumperConfigs();
57     if (ret == DumpStatus::DUMP_OK) {
58         auto dumpCfgs = param->GetExecutorConfigList();
59         for (size_t i = 0; i < dumpCfgs.size(); i++) {
60             dumpCfgs[i]->Dump();
61         }
62     }
63 
64     DUMPER_HILOGD(MODULE_COMMON, "leave|ret=%{public}d", ret);
65     return ret;
66 }
67 
GetDumperConfigs()68 DumpStatus ConfigUtils::GetDumperConfigs()
69 {
70     DUMPER_HILOGD(MODULE_COMMON, "enter|");
71 
72     DumpCommonUtils::GetCpuInfos(cpuInfos_);
73     DUMPER_HILOGD(MODULE_COMMON, "debug|cpuInfos=%{public}zu", cpuInfos_.size());
74 
75     std::vector<std::shared_ptr<DumpCfg>> dumpCfgs;
76 
77     currentPidInfo_.Reset();
78     currentPidInfos_.clear();
79 
80     HandleDumpSystem(dumpCfgs);
81     HandleDumpCpuFreq(dumpCfgs);  // cpuid
82     HandleDumpCpuUsage(dumpCfgs); // pid
83     HandleDumpMem(dumpCfgs);
84     HandleDumpJsHeapMem(dumpCfgs);
85     HandleDumpMemShowMaps(dumpCfgs);
86     HandleDumpLog(dumpCfgs);
87     HandleDumpStorage(dumpCfgs);
88     HandleDumpNet(dumpCfgs);
89     HandleDumpList(dumpCfgs);
90     HandleDumpAbility(dumpCfgs);
91     HandleDumpService(dumpCfgs);
92     HandleDumpProcesses(dumpCfgs);
93     HandleDumpFaultLog(dumpCfgs);
94     HandleDumpAppendix(dumpCfgs);
95     HandleDumpIpcStat(dumpCfgs);
96     DUMPER_HILOGD(MODULE_COMMON, "debug|dumpCfgs=%{public}zu", dumpCfgs.size());
97     dumperParam_->SetExecutorConfigList(dumpCfgs);
98     DUMPER_HILOGD(MODULE_COMMON, "leave|");
99     return DumpStatus::DUMP_OK;
100 }
101 
GetSectionNames(const std::string & name,std::vector<std::string> & nameList)102 DumpStatus ConfigUtils::GetSectionNames(const std::string &name, std::vector<std::string> &nameList)
103 {
104     std::vector<std::string> tmpUse;
105     GetGroupNames(name, tmpUse);
106     std::transform(tmpUse.begin(), tmpUse.end(), std::back_inserter(nameList),
107                    [](std::string &a) { return GetSectionName(a); });
108     DumpUtils::RemoveDuplicateString(nameList); // remove duplicate log names
109     return DumpStatus::DUMP_OK;
110 }
111 
GetGroupNames(const std::string & name,std::vector<std::string> & nameList)112 DumpStatus ConfigUtils::GetGroupNames(const std::string &name, std::vector<std::string> &nameList)
113 {
114     bool check = !name.empty();
115     for (int i = 0; i < groupSum_; i++) {
116         if (groups_[i].name_.empty()) {
117             continue;
118         }
119         if (check && (groups_[i].name_.find(name) != 0)) {
120             continue;
121         }
122         nameList.push_back(groups_[i].name_);
123     }
124     return DumpStatus::DUMP_OK;
125 }
126 
GetSectionName(const std::string & name)127 std::string ConfigUtils::GetSectionName(const std::string &name)
128 {
129     std::string ret;
130     std::size_t pos = name.find_last_of(CONFIG_NAME_SPLIT);
131     if (pos != std::string::npos) {
132         ret = name.substr(pos + 1);
133     }
134     return ret;
135 }
136 
MergePidInfos(std::vector<DumpCommonUtils::PidInfo> & pidInfos,int pid)137 bool ConfigUtils::MergePidInfos(std::vector<DumpCommonUtils::PidInfo> &pidInfos, int pid)
138 {
139     pidInfos.clear();
140     if (pid < 0) {
141         currentPidInfo_.pid_ = pid;
142         currentPidInfo_.uid_ = -1;
143         DumpCommonUtils::GetPidInfos(pidInfos_);
144         DUMPER_HILOGI(MODULE_COMMON, "info|pidInfos=%{public}zu", pidInfos_.size());
145         pidInfos.assign(pidInfos_.begin(), pidInfos_.end());
146     } else {
147         if (DumpCommonUtils::GetProcessInfo(pid, currentPidInfo_)) {
148             pidInfos.push_back(currentPidInfo_);
149         }
150     }
151     return true;
152 }
153 
MergeDebugPidInfos(std::vector<DumpCommonUtils::PidInfo> & pidInfos,int pid)154 bool ConfigUtils::MergeDebugPidInfos(std::vector<DumpCommonUtils::PidInfo> &pidInfos, int pid)
155 {
156     pidInfos.clear();
157     if (pid < 0) {
158         currentPidInfo_.pid_ = pid;
159         currentPidInfo_.uid_ = -1;
160         DumpCommonUtils::GetPidInfos(pidInfos_);
161         std::copy_if(pidInfos_.begin(), pidInfos_.end(), std::back_inserter(pidInfos),
162             [](auto &it) { return DumpUtils::CheckAppDebugVersion(it.pid_); });
163         if (pidInfos.size() == 0) {
164             DUMPER_HILOGE(MODULE_COMMON, "not find release version pid");
165             return false;
166         }
167         DUMPER_HILOGI(MODULE_COMMON, "info|pidInfos=%{public}zu", pidInfos.size());
168     } else {
169         if (DumpUtils::CheckAppDebugVersion(pid) && DumpCommonUtils::GetProcessInfo(pid, currentPidInfo_)) {
170             pidInfos.push_back(currentPidInfo_);
171         } else {
172             DUMPER_HILOGE(MODULE_COMMON, "pid:%{public}d is release version", pid);
173             return false;
174         }
175     }
176     return true;
177 }
178 
HandleDumpLog(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)179 bool ConfigUtils::HandleDumpLog(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
180 {
181     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
182     if (!dumperOpts.isDumpLog_) {
183         return false;
184     }
185 
186     DUMPER_HILOGD(MODULE_COMMON, "debug|log");
187     currentPidInfo_.Reset();
188     currentPidInfos_.clear();
189 
190     auto args = OptionArgs::Create();
191     args->SetStrList(dumperOpts.logArgs_);
192     for (size_t i = 0; i < dumperOpts.logArgs_.size(); i++) {
193         std::string name = CONFIG_GROUP_LOG_ + dumperOpts.logArgs_[i];
194         GetConfig(name, dumpCfgs, args);
195     }
196 
197     currentPidInfos_.clear();
198     currentPidInfo_.Reset();
199     return true;
200 }
201 
HandleDumpList(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)202 bool ConfigUtils::HandleDumpList(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
203 {
204     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
205     if (!dumperOpts.isDumpList_) {
206         return false;
207     }
208 
209     DUMPER_HILOGD(MODULE_COMMON, "debug|list");
210     currentPidInfo_.Reset();
211     currentPidInfos_.clear();
212 
213     if (dumperOpts.isDumpSystemAbility_) {
214         DUMPER_HILOGD(MODULE_COMMON, "debug|list ability");
215         std::shared_ptr<OptionArgs> args;
216         GetConfig(CONFIG_DUMPER_LIST_SYSTEM_ABILITY, dumpCfgs, args);
217     }
218 
219     if (dumperOpts.isDumpService_) {
220         DUMPER_HILOGD(MODULE_COMMON, "debug|list service");
221         std::shared_ptr<OptionArgs> args;
222         GetConfig(CONFIG_DUMPER_LIST_SERVICE, dumpCfgs, args);
223     }
224 
225     if (dumperOpts.isDumpSystem_) {
226         DUMPER_HILOGD(MODULE_COMMON, "debug|list system");
227         std::shared_ptr<OptionArgs> args;
228         GetConfig(CONFIG_DUMPER_LIST_SYSTEM, dumpCfgs, args);
229     }
230 
231     currentPidInfos_.clear();
232     currentPidInfo_.Reset();
233     return true;
234 }
235 
HandleDumpService(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)236 bool ConfigUtils::HandleDumpService(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
237 {
238     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
239     if (dumperOpts.isDumpList_ || (!dumperOpts.isDumpService_)) {
240         return false;
241     }
242 
243     DUMPER_HILOGD(MODULE_COMMON, "debug|service");
244     currentPidInfo_.Reset();
245     currentPidInfos_.clear();
246 
247     std::shared_ptr<OptionArgs> args;
248     GetConfig(CONFIG_GROUP_SERVICE, dumpCfgs, args);
249 
250     currentPidInfos_.clear();
251     currentPidInfo_.Reset();
252     return true;
253 }
254 
HandleDumpAbility(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)255 bool ConfigUtils::HandleDumpAbility(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
256 {
257     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
258     if (dumperOpts.isDumpList_ || (!dumperOpts.isDumpSystemAbility_)) {
259         return false;
260     }
261 
262     DUMPER_HILOGD(MODULE_COMMON, "debug|ability");
263     currentPidInfo_.Reset();
264     currentPidInfos_.clear();
265 
266     auto args = OptionArgs::Create();
267     args->SetNamesAndArgs(dumperOpts.abilitieNames_, dumperOpts.abilitieArgs_);
268     GetConfig(CONFIG_GROUP_ABILITY, dumpCfgs, args);
269 
270     currentPidInfos_.clear();
271     currentPidInfo_.Reset();
272     return true;
273 }
274 
HandleDumpSystem(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)275 bool ConfigUtils::HandleDumpSystem(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
276 {
277     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
278     if (dumperOpts.isDumpList_ || (!dumperOpts.isDumpSystem_)) {
279         return false;
280     }
281 
282     DUMPER_HILOGD(MODULE_COMMON, "debug|system");
283     currentPidInfo_.Reset();
284     currentPidInfos_.clear();
285 
286     if (dumperOpts.systemArgs_.empty()) {
287         std::shared_ptr<OptionArgs> args;
288         GetConfig(CONFIG_GROUP_SYSTEM_BASE, dumpCfgs, args);
289         GetConfig(CONFIG_GROUP_SYSTEM_SYSTEM, dumpCfgs, args);
290         isDumpSystemSystem = true;
291         return true;
292     }
293 
294     auto args = OptionArgs::Create();
295     args->SetStrList(dumperOpts.systemArgs_);
296     for (size_t i = 0; i < dumperOpts.systemArgs_.size(); i++) {
297         std::string name = CONFIG_GROUP_SYSTEM_ + dumperOpts.systemArgs_[i];
298         GetConfig(name, dumpCfgs, args);
299         if (name == CONFIG_GROUP_SYSTEM_SYSTEM) {
300             isDumpSystemSystem = true;
301         }
302     }
303 
304     currentPidInfos_.clear();
305     currentPidInfo_.Reset();
306     return true;
307 }
308 
HandleDumpCpuFreq(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)309 bool ConfigUtils::HandleDumpCpuFreq(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
310 {
311     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
312     if (!dumperOpts.isDumpCpuFreq_) {
313         return false;
314     }
315 
316     DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d", isDumpSystemSystem);
317     if (isDumpSystemSystem) {
318         return false;
319     }
320 
321     DUMPER_HILOGD(MODULE_COMMON, "debug|cpu freq");
322     currentPidInfo_.Reset();
323     currentPidInfos_.clear();
324 
325     std::shared_ptr<OptionArgs> args;
326     GetConfig(CONFIG_GROUP_CPU_FREQ, dumpCfgs, args);
327 
328     currentPidInfos_.clear();
329     currentPidInfo_.Reset();
330     return true;
331 }
332 
HandleDumpCpuUsage(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)333 bool ConfigUtils::HandleDumpCpuUsage(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
334 {
335     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
336     if (!dumperOpts.isDumpCpuUsage_) {
337         return false;
338     }
339 
340     DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, cpuUsagePid=%{public}d",
341         isDumpSystemSystem, dumperOpts.cpuUsagePid_);
342     if (isDumpSystemSystem && (dumperOpts.cpuUsagePid_ < 0)) {
343         return false;
344     }
345 
346     DUMPER_HILOGD(MODULE_COMMON, "debug|cpu usage");
347     currentPidInfo_.Reset();
348     currentPidInfos_.clear();
349     MergePidInfos(currentPidInfos_, dumperOpts.cpuUsagePid_);
350 
351     std::shared_ptr<OptionArgs> args;
352     GetConfig(CONFIG_GROUP_CPU_USAGE, dumpCfgs, args);
353 
354     currentPidInfos_.clear();
355     currentPidInfo_.Reset();
356     return true;
357 }
358 
HandleDumpMem(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)359 bool ConfigUtils::HandleDumpMem(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
360 {
361     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
362     if (!dumperOpts.isDumpMem_) {
363         return false;
364     }
365 
366     DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, memPid=%{public}d",
367         isDumpSystemSystem, dumperOpts.memPid_);
368     if (isDumpSystemSystem && (dumperOpts.memPid_ < 0)) {
369         return false;
370     }
371 
372     DUMPER_HILOGD(MODULE_COMMON, "debug|mem");
373     HandleDumpMemCommon(dumperParam_, dumpCfgs);
374     return true;
375 }
376 
HandleDumpJsHeapMem(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)377 bool ConfigUtils::HandleDumpJsHeapMem(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
378 {
379     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
380     if (!dumperOpts.isDumpJsHeapMem_) {
381         return false;
382     }
383     DUMPER_HILOGD(MODULE_COMMON, "debug|memPid=%{public}d threadId=%{public}d",
384         dumperOpts.dumpJsHeapMemPid_, dumperOpts.threadId_);
385     if ((dumperOpts.dumpJsHeapMemPid_ <= 0) || (dumperOpts.threadId_ < 0)) {
386         return false;
387     }
388     std::shared_ptr<OptionArgs> args;
389     GetConfig(CONFIG_DUMPER_JSHEAP_MEMORY, dumpCfgs, args);
390     return true;
391 }
392 
HandleDumpMemShowMaps(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)393 bool ConfigUtils::HandleDumpMemShowMaps(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
394 {
395     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
396     if (!dumperOpts.isShowSmaps_) {
397         return false;
398     }
399 
400     DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, memPid=%{public}d",
401         isDumpSystemSystem, dumperOpts.memPid_);
402     if (isDumpSystemSystem && (dumperOpts.memPid_ < 0)) {
403         return false;
404     }
405 
406     DUMPER_HILOGD(MODULE_COMMON, "debug|mem-smaps");
407     HandleDumpMemCommon(dumperParam_, dumpCfgs);
408     return true;
409 }
410 
HandleDumpMemCommon(std::shared_ptr<DumperParameter> dumpParam,std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)411 void ConfigUtils::HandleDumpMemCommon(std::shared_ptr<DumperParameter> dumpParam,
412     std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
413 {
414     currentPidInfo_.Reset();
415     currentPidInfos_.clear();
416     MergePidInfos(currentPidInfos_, dumpParam->GetOpts().memPid_);
417     std::shared_ptr<OptionArgs> args;
418     GetConfig(CONFIG_GROUP_MEMORY, dumpCfgs, args);
419     currentPidInfos_.clear();
420     currentPidInfo_.Reset();
421 }
422 
HandleDumpStorage(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)423 bool ConfigUtils::HandleDumpStorage(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
424 {
425     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
426     if (!dumperOpts.isDumpStorage_) {
427         return false;
428     }
429 
430     DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, storagePid=%{public}d",
431         isDumpSystemSystem, dumperOpts.storagePid_);
432     if (isDumpSystemSystem && (dumperOpts.memPid_ < 0)) {
433         return false;
434     }
435 
436     DUMPER_HILOGD(MODULE_COMMON, "debug|storage");
437     currentPidInfo_.Reset();
438     currentPidInfos_.clear();
439     MergePidInfos(currentPidInfos_, dumperOpts.storagePid_);
440 
441     std::shared_ptr<OptionArgs> args;
442     if (dumperOpts.storagePid_ < 0) {
443         GetConfig(CONFIG_GROUP_STORAGE, dumpCfgs, args);
444     } else {
445         GetConfig(CONFIG_GROUP_STORAGE_IO, dumpCfgs, args);
446     }
447 
448     currentPidInfos_.clear();
449     currentPidInfo_.Reset();
450     return true;
451 }
452 
HandleDumpNet(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)453 bool ConfigUtils::HandleDumpNet(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
454 {
455     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
456     if (!dumperOpts.isDumpNet_) {
457         return false;
458     }
459 
460     DUMPER_HILOGD(MODULE_COMMON, "debug|isDumpSystem=%{public}d, netPid=%{public}d",
461         isDumpSystemSystem, dumperOpts.netPid_);
462     if (isDumpSystemSystem && (dumperOpts.netPid_ < 0)) {
463         return false;
464     }
465 
466     DUMPER_HILOGD(MODULE_COMMON, "debug|net");
467     currentPidInfo_.Reset();
468     currentPidInfos_.clear();
469     MergePidInfos(currentPidInfos_, dumperOpts.netPid_);
470 
471     std::shared_ptr<OptionArgs> args;
472     GetConfig(CONFIG_GROUP_NET_TRAFFIC, dumpCfgs, args);
473     if (dumperOpts.netPid_ < 0) {
474         GetConfig(CONFIG_GROUP_NET, dumpCfgs, args);
475     }
476 
477     currentPidInfos_.clear();
478     currentPidInfo_.Reset();
479     return true;
480 }
481 
HandleDumpProcesses(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)482 bool ConfigUtils::HandleDumpProcesses(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
483 {
484     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
485     std::string path = dumperOpts.path_;
486     if (!dumperOpts.isDumpProcesses_) {
487         return false;
488     }
489 
490     DUMPER_HILOGD(MODULE_COMMON, "debug|processes");
491     currentPidInfo_.Reset();
492     currentPidInfos_.clear();
493 
494     bool isUserMode = DumpUtils::IsUserMode();
495     if (isUserMode) {
496         if (!MergeDebugPidInfos(currentPidInfos_, dumperOpts.processPid_)) {
497             DUMPER_HILOGE(MODULE_COMMON, "dump process failed");
498             return false;
499         }
500     } else {
501         MergePidInfos(currentPidInfos_, dumperOpts.processPid_);
502     }
503 
504     std::shared_ptr<OptionArgs> args;
505     if (isUserMode) {  // release mode
506         if (dumperOpts.processPid_ < 0) {
507             GetConfig(CONFIG_GROUP_PROCESSES, dumpCfgs, args);
508         } else {
509             GetConfig(CONFIG_GROUP_PROCESSES_PID, dumpCfgs, args);
510         }
511     } else {  // engine mode
512         if (dumperOpts.processPid_ < 0) {
513             GetConfig(CONFIG_GROUP_PROCESSES_ENG, dumpCfgs, args);
514         } else {
515             GetConfig(CONFIG_GROUP_PROCESSES_PID_ENG, dumpCfgs, args);
516         }
517 
518         if (dumperOpts.IsDumpZip()) {
519             CopySmaps();
520         }
521     }
522 
523     currentPidInfos_.clear();
524     currentPidInfo_.Reset();
525     return true;
526 }
527 
HandleDumpFaultLog(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)528 bool ConfigUtils::HandleDumpFaultLog(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
529 {
530     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
531     if (!dumperOpts.isFaultLog_) {
532         return false;
533     }
534 
535     DUMPER_HILOGD(MODULE_COMMON, "debug|fault log");
536     currentPidInfo_.Reset();
537     currentPidInfos_.clear();
538 
539     std::shared_ptr<OptionArgs> args;
540     GetConfig(CONFIG_GROUP_FAULT_LOG, dumpCfgs, args);
541 
542     currentPidInfos_.clear();
543     currentPidInfo_.Reset();
544     return true;
545 }
546 
HandleDumpAppendix(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)547 bool ConfigUtils::HandleDumpAppendix(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
548 {
549     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
550     if (!dumperOpts.isAppendix_) {
551         return false;
552     }
553 
554     DUMPER_HILOGD(MODULE_COMMON, "debug|appendix");
555     currentPidInfo_.Reset();
556     currentPidInfos_.clear();
557 
558     MergePidInfos(currentPidInfos_, -1);
559     std::shared_ptr<OptionArgs> args;
560 
561     GetConfig(CONFIG_GROUP_LOG_KERNEL, dumpCfgs, args);
562     GetConfig(CONFIG_GROUP_LOG_INIT, dumpCfgs, args);
563     GetConfig(CONFIG_GROUP_LOG_HILOG, dumpCfgs, args);
564     int callingUid = dumperParam_->GetUid();
565     if (callingUid == ROOT_UID || callingUid == BMS_UID) {
566         GetConfig(CONFIG_GROUP_STACK, dumpCfgs, args);
567     } else {
568         DUMPER_HILOGE(MODULE_COMMON, "No permission to perform dump stack operation, uid=%{public}d", callingUid);
569     }
570     currentPidInfos_.clear();
571     currentPidInfo_.Reset();
572     return true;
573 }
574 
HandleDumpIpcStat(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs)575 bool ConfigUtils::HandleDumpIpcStat(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs)
576 {
577     const DumperOpts &dumperOpts = dumperParam_->GetOpts();
578     if (!dumperOpts.isDumpIpc_) {
579         return false;
580     }
581 
582     currentPidInfo_.Reset();
583     currentPidInfos_.clear();
584     MergePidInfos(currentPidInfos_, dumperOpts.ipcStatPid_);
585 
586     std::shared_ptr<OptionArgs> args;
587     GetConfig(CONFIG_GROUP_IPC_STAT, dumpCfgs, args);
588 
589     currentPidInfos_.clear();
590     currentPidInfo_.Reset();
591     return true;
592 }
593 
GetDumpLevelByPid(int uid,const DumpCommonUtils::PidInfo & pidInfo)594 int ConfigUtils::GetDumpLevelByPid(int uid, const DumpCommonUtils::PidInfo &pidInfo)
595 {
596     int ret = DumperConstant::LEVEL_NONE;
597     if (uid == ROOT_UID) {
598         ret = DumperConstant::LEVEL_HIGH;
599     } else if (uid < APP_FIRST_UID) {
600         ret = DumperConstant::LEVEL_MIDDLE;
601     } else {
602         if (uid == pidInfo.uid_) {
603             ret = DumperConstant::LEVEL_MIDDLE;
604         }
605     }
606     return ret;
607 }
608 
GetConfig(const std::string & name,std::vector<std::shared_ptr<DumpCfg>> & result,std::shared_ptr<OptionArgs> args)609 DumpStatus ConfigUtils::GetConfig(const std::string &name, std::vector<std::shared_ptr<DumpCfg>> &result,
610                                   std::shared_ptr<OptionArgs> args)
611 {
612     DumpStatus ret = DumpStatus::DUMP_FAIL;
613     if (name.find(CONFIG_DUMPER_) == 0) {
614         DUMPER_HILOGD(MODULE_COMMON, "debug|dumper, name=%{public}s", name.c_str());
615         ret = GetDumper(name, result, args);
616     } else if (name.find(CONFIG_GROUP_) == 0) {
617         DUMPER_HILOGD(MODULE_COMMON, "debug|group, name=%{public}s", name.c_str());
618         ret = GetGroup(name, result, args);
619     } else {
620         DUMPER_HILOGE(MODULE_COMMON, "error|name=%{public}s", name.c_str());
621     }
622     return ret;
623 }
624 
GetDumper(int index,std::vector<std::shared_ptr<DumpCfg>> & result,std::shared_ptr<OptionArgs> args,int level)625 DumpStatus ConfigUtils::GetDumper(int index, std::vector<std::shared_ptr<DumpCfg>> &result,
626                                   std::shared_ptr<OptionArgs> args, int level)
627 {
628     if ((index < 0) || (index >= dumperSum_)) {
629         return DumpStatus::DUMP_INVALID_ARG;
630     }
631     auto itemlist = dumpers_[index].list_;
632     auto itemsize = dumpers_[index].size_;
633     for (int i = 0; i < itemsize; i++) {
634         if (DumpCfg::IsFilter(itemlist[i].class_) && DumpCfg::IsLevel(level)) {
635             if ((itemlist[i].level_ != DumperConstant::LEVEL_ALL) && (itemlist[i].level_ != level)) {
636                 continue;
637             }
638         }
639         auto dumpCfg = DumpCfg::Create();
640         dumpCfg->name_ = itemlist[i].name_;
641         dumpCfg->desc_ = itemlist[i].desc_;
642         dumpCfg->target_ = itemlist[i].target_;
643         dumpCfg->section_ = itemlist[i].section_;
644         dumpCfg->class_ = itemlist[i].class_;
645         dumpCfg->level_ = itemlist[i].level_;
646         dumpCfg->loop_ = itemlist[i].loop_;
647         dumpCfg->filterCfg_ = itemlist[i].filterCfg_;
648         dumpCfg->args_ = dumpCfg->IsDumper() ? args : nullptr;
649         result.push_back(dumpCfg);
650     }
651     return DumpStatus::DUMP_OK;
652 }
653 
GetDumper(const std::string & name,std::vector<std::shared_ptr<DumpCfg>> & result,std::shared_ptr<OptionArgs> args,int level)654 DumpStatus ConfigUtils::GetDumper(const std::string &name, std::vector<std::shared_ptr<DumpCfg>> &result,
655                                   std::shared_ptr<OptionArgs> args, int level)
656 {
657     DumpStatus ret = DumpStatus::DUMP_FAIL;
658     int index = -1;
659     for (int i = 0; i < dumperSum_; i++) {
660         if (dumpers_[i].name_.empty()) {
661             continue;
662         }
663         if (name != dumpers_[i].name_) {
664             continue;
665         }
666         index = i;
667         break;
668     }
669     if (index > -1) {
670         ret = GetDumper(index, result, args, level);
671     }
672     return ret;
673 }
674 
GetGroupSimple(const GroupCfg & groupCfg,std::vector<std::shared_ptr<DumpCfg>> & result,std::shared_ptr<OptionArgs> args,int level,int nest)675 DumpStatus ConfigUtils::GetGroupSimple(const GroupCfg &groupCfg, std::vector<std::shared_ptr<DumpCfg>> &result,
676                                        std::shared_ptr<OptionArgs> args, int level, int nest)
677 {
678     if (nest > NEST_MAX) {
679         return DumpStatus::DUMP_INVALID_ARG;
680     }
681     if ((groupCfg.list_ == nullptr) || (groupCfg.size_ < 1)) {
682         return DumpStatus::DUMP_OK;
683     }
684 
685     auto dumpGroup = DumpCfg::Create();
686     if (groupCfg.expand_) {
687         dumpGroup->class_ = DumperConstant::GROUP;
688         dumpGroup->name_ = groupCfg.name_;
689         dumpGroup->desc_ = groupCfg.desc_;
690         dumpGroup->type_ = groupCfg.type_;
691         dumpGroup->expand_ = groupCfg.expand_;
692         result.push_back(dumpGroup);
693     }
694     auto &outlist = (groupCfg.expand_) ? dumpGroup->childs_ : result;
695 
696     for (int i = 0; i < groupCfg.size_; i++) {
697         if (groupCfg.list_[i].empty()) {
698             continue;
699         }
700         if (DumpCommonUtils::StartWith(groupCfg.list_[i], CONFIG_DUMPER_)) {
701             GetDumper(groupCfg.list_[i], outlist, args, level);
702         } else if (DumpCommonUtils::StartWith(groupCfg.list_[i], CONFIG_MINIGROUP_)) {
703             GetGroup(groupCfg.list_[i], outlist, args, level, nest + 1);
704         } else {
705             DUMPER_HILOGE(MODULE_COMMON, "error|name=%{public}s", groupCfg.name_.c_str());
706             return DumpStatus::DUMP_INVALID_ARG;
707         }
708     }
709 
710     return DumpStatus::DUMP_OK;
711 }
712 
GetGroup(int index,std::vector<std::shared_ptr<DumpCfg>> & result,std::shared_ptr<OptionArgs> args,int level,int nest)713 DumpStatus ConfigUtils::GetGroup(int index, std::vector<std::shared_ptr<DumpCfg>> &result,
714                                  std::shared_ptr<OptionArgs> args, int level, int nest)
715 {
716     if (nest > NEST_MAX) {
717         return DumpStatus::DUMP_INVALID_ARG;
718     }
719     auto dumpGroup = DumpCfg::Create();
720     dumpGroup->class_ = DumperConstant::GROUP;
721     dumpGroup->name_ = groups_[index].name_;
722     dumpGroup->desc_ = groups_[index].desc_;
723     dumpGroup->type_ = groups_[index].type_;
724     dumpGroup->expand_ = groups_[index].expand_;
725     result.push_back(dumpGroup);
726     if (dumpGroup->expand_ && (dumpGroup->type_ == DumperConstant::GROUPTYPE_PID)) {
727         for (auto pidInfo : currentPidInfos_) {
728             int newLevel = GetDumpLevelByPid(dumperParam_->GetUid(), pidInfo);
729             if (newLevel == DumperConstant::LEVEL_NONE) {
730                 continue;
731             }
732             auto newArgs = OptionArgs::Clone(args);
733             newArgs->SetPid(pidInfo.pid_, pidInfo.uid_);
734             GetGroupSimple(groups_[index], dumpGroup->childs_, newArgs, newLevel, nest);
735         }
736     } else if (dumpGroup->expand_ && (dumpGroup->type_ == DumperConstant::GROUPTYPE_CPUID)) {
737         for (auto cpuInfo : cpuInfos_) {
738             auto newArgs = OptionArgs::Clone(args);
739             newArgs->SetCpuId(cpuInfo.id_);
740             GetGroupSimple(groups_[index], dumpGroup->childs_, newArgs, level, nest);
741         }
742     } else if (dumpGroup->type_ == DumperConstant::GROUPTYPE_PID) {
743         int newLevel = GetDumpLevelByPid(dumperParam_->GetUid(), currentPidInfo_);
744         if (newLevel != DumperConstant::LEVEL_NONE) {
745             auto newArgs = OptionArgs::Clone(args);
746             newArgs->SetPid(currentPidInfo_.pid_, currentPidInfo_.uid_);
747             GetGroupSimple(groups_[index], dumpGroup->childs_, newArgs, level, nest);
748         }
749     } else if (dumpGroup->type_ == DumperConstant::GROUPTYPE_CPUID) {
750         auto newArgs = OptionArgs::Clone(args);
751         newArgs->SetCpuId(-1);
752         GetGroupSimple(groups_[index], dumpGroup->childs_, newArgs, level, nest);
753     } else if (dumpGroup->type_ == DumperConstant::NONE) {
754         GetGroupSimple(groups_[index], dumpGroup->childs_, args, level, nest);
755     } else {
756         DUMPER_HILOGE(MODULE_COMMON, "error|type=%{public}d", dumpGroup->type_);
757         return DumpStatus::DUMP_INVALID_ARG;
758     }
759     return DumpStatus::DUMP_OK;
760 }
761 
GetGroup(const std::string & name,std::vector<std::shared_ptr<DumpCfg>> & result,std::shared_ptr<OptionArgs> args,int level,int nest)762 DumpStatus ConfigUtils::GetGroup(const std::string &name, std::vector<std::shared_ptr<DumpCfg>> &result,
763                                  std::shared_ptr<OptionArgs> args, int level, int nest)
764 {
765     if (nest > NEST_MAX) {
766         return DumpStatus::DUMP_INVALID_ARG;
767     }
768     DumpStatus ret = DumpStatus::DUMP_FAIL;
769     int index = -1;
770     // find group
771     for (int i = 0; i < groupSum_; i++) {
772         if (groups_[i].name_.empty()) {
773             continue;
774         }
775         if (name != groups_[i].name_) {
776             continue;
777         }
778         index = i;
779         break;
780     }
781 
782     // add dump config to tmpUse
783     std::vector<std::shared_ptr<DumpCfg>> tmpUse;
784     if (index > -1) {
785         ret = GetGroup(index, tmpUse, args, level);
786     }
787 
788     if (nest) {
789         result.insert(result.end(), tmpUse.begin(), tmpUse.end());
790     } else {
791         // add section & add config to result
792         SetSection(tmpUse, GetSectionName(name));
793         ConvertTreeToList(tmpUse, result);
794     }
795 
796     return ret;
797 }
798 
ConvertTreeToList(std::vector<std::shared_ptr<DumpCfg>> & tree,std::vector<std::shared_ptr<DumpCfg>> & list,int nest)799 void ConfigUtils::ConvertTreeToList(std::vector<std::shared_ptr<DumpCfg>> &tree,
800                                     std::vector<std::shared_ptr<DumpCfg>> &list, int nest)
801 {
802     if (nest > NEST_MAX) {
803         return;
804     }
805 
806     std::vector<std::shared_ptr<DumpCfg>> tmpUsed;
807     for (auto item : tree) {
808         if (item == nullptr) {
809             continue;
810         }
811         tmpUsed.push_back(item);
812         if (item->childs_.empty()) {
813             continue;
814         }
815         for (auto child : item->childs_) {
816             child->parent_ = item; // after point to parent, childs must be cleared.
817         }
818         ConvertTreeToList(item->childs_, tmpUsed, nest + 1);
819         item->childs_.clear(); // must clear
820     }
821 
822     list.insert(list.end(), tmpUsed.begin(), tmpUsed.end());
823 }
824 
SetSection(std::vector<std::shared_ptr<DumpCfg>> & dumpCfgs,const std::string & section,int nest)825 void ConfigUtils::SetSection(std::vector<std::shared_ptr<DumpCfg>> &dumpCfgs, const std::string &section, int nest)
826 {
827     if (nest > NEST_MAX) {
828         return;
829     }
830 
831     for (auto dumpCfg : dumpCfgs) {
832         if (dumpCfg == nullptr) {
833             continue;
834         }
835         if (dumpCfg->IsDumper()) {
836             dumpCfg->section_ = section;
837         }
838         if (dumpCfg->childs_.empty()) {
839             continue;
840         }
841         SetSection(dumpCfg->childs_, section, nest + 1);
842     }
843 }
844 
CopySmaps()845 bool ConfigUtils::CopySmaps()
846 {
847     DUMPER_HILOGD(MODULE_COMMON, "CopySmaps enter|");
848 
849     std::shared_ptr<RawParam> callback = dumperParam_->getClientCallback();
850     if (callback == nullptr) {
851         DUMPER_HILOGE(MODULE_COMMON, "CopySmaps leave|callback");
852         return false;
853     }
854 
855     callback->SetProgressEnabled(true);
856     std::string logFolder = callback->GetFolder();
857     int uid = dumperParam_->GetUid();
858     for (auto &pidInfo : currentPidInfos_) {
859         int newLevel = GetDumpLevelByPid(uid, pidInfo);
860         if (newLevel == DumperConstant::LEVEL_NONE) {
861             continue;
862         }
863         if (callback->IsCanceled()) {
864             DUMPER_HILOGD(MODULE_COMMON, "CopySmaps debug|Canceled");
865             break;
866         }
867         callback->UpdateProgress(0);
868         std::string pid = std::to_string(pidInfo.pid_);
869         std::string desfolder = logFolder + SMAPS_PATH + pidInfo.name_ + "-" + pid;
870         std::string src = SMAPS_PATH_START + pid + SMAPS_PATH_END;
871         std::string des = desfolder + SMAPS_PATH_END;
872         ForceCreateDirectory(IncludeTrailingPathDelimiter(desfolder));
873         DumpUtils::CopyFile(src, des);
874     }
875 
876     DUMPER_HILOGD(MODULE_COMMON, "CopySmaps leave|true");
877     return true;
878 }
879 } // namespace HiviewDFX
880 } // namespace OHOS
881