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> ¶m) : 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> ¶m)
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 §ion, 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