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