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