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