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