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