1 /*
2 * Copyright (c) 2021-2022 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 "manager/dump_implement.h"
16 #include <ipc_skeleton.h>
17 #include "iservice_registry.h"
18 #include "hilog_wrapper.h"
19 #include "util/config_utils.h"
20 #include "factory/cpu_dumper_factory.h"
21 #include "factory/file_dumper_factory.h"
22 #include "factory/env_param_dumper_factory.h"
23 #include "factory/cmd_dumper_factory.h"
24 #include "factory/api_dumper_factory.h"
25 #include "factory/properties_dumper_factory.h"
26 #include "factory/sa_dumper_factory.h"
27 #include "factory/list_dumper_factory.h"
28 #include "factory/version_dumper_factory.h"
29 #include "factory/column_rows_filter_factory.h"
30 #include "factory/file_format_dump_filter_factory.h"
31 #include "factory/fd_output_factory.h"
32 #include "factory/zip_output_factory.h"
33 #include "factory/dumper_group_factory.h"
34 #include "factory/memory_dumper_factory.h"
35 #include "factory/jsheap_memory_dumper_factory.h"
36 #include "factory/cjheap_memory_dumper_factory.h"
37 #include "factory/traffic_dumper_factory.h"
38 #include "factory/ipc_stat_dumper_factory.h"
39 #include "dump_utils.h"
40 #include "string_ex.h"
41 #include "file_ex.h"
42 #include "util/string_utils.h"
43 #include "common/dumper_constant.h"
44 #include "securec.h"
45 #include "parameters.h"
46 #include "parameter.h"
47 #ifdef HIDUMPER_HIVIEWDFX_HISYSEVENT_ENABLE
48 #include "hisysevent.h"
49 #endif
50
51 namespace OHOS {
52 namespace HiviewDFX {
53 static struct option LONG_OPTIONS[] = {{"cpufreq", no_argument, 0, 0},
54 #ifdef HIDUMPER_HIVIEWDFX_HIVIEW_ENABLE
55 {"cpuusage", optional_argument, 0, 0},
56 #endif
57 {"mem", optional_argument, 0, 0},
58 {"net", no_argument, 0, 0},
59 {"storage", no_argument, 0, 0},
60 {"zip", no_argument, 0, 0},
61 {"mem-smaps", required_argument, 0, 0},
62 {"mem-jsheap", required_argument, 0, 0},
63 {"mem-cjheap", required_argument, 0, 0},
64 {"gc", no_argument, 0, 0},
65 {"leakobj", no_argument, 0, 0},
66 {"raw", no_argument, 0, 0},
67 {"prune", no_argument, 0, 0},
68 {"show-ashmem", no_argument, 0, 0},
69 {"show-dmabuf", no_argument, 0, 0},
70 {"ipc", optional_argument, 0, 0},
71 {"start-stat", no_argument, 0, 0},
72 {"stop-stat", no_argument, 0, 0},
73 {"stat", no_argument, 0, 0},
74 {0, 0, 0, 0}};
75
76 thread_local std::unique_ptr<DumperSysEventParams> DumpImplement::dumperSysEventParams_{nullptr};
77
DumpImplement()78 DumpImplement::DumpImplement()
79 {
80 AddExecutorFactoryToMap();
81 }
82
~DumpImplement()83 DumpImplement::~DumpImplement()
84 {
85 }
86
AddExecutorFactoryToMap()87 void DumpImplement::AddExecutorFactoryToMap()
88 {
89 ptrExecutorFactoryMap_ = std::make_shared<ExecutorFactoryMap>();
90 #ifdef HIDUMPER_HIVIEWDFX_HIVIEW_ENABLE
91 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::CPU_DUMPER, std::make_shared<CPUDumperFactory>()));
92 #endif
93 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::FILE_DUMPER, std::make_shared<FileDumperFactory>()));
94 ptrExecutorFactoryMap_->insert(
95 std::make_pair(DumperConstant::ENV_PARAM_DUMPER, std::make_shared<EnvParamDumperFactory>()));
96 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::CMD_DUMPER, std::make_shared<CMDDumperFactory>()));
97 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::API_DUMPER, std::make_shared<APIDumperFactory>()));
98 ptrExecutorFactoryMap_->insert(
99 std::make_pair(DumperConstant::PROPERTIES_DUMPER, std::make_shared<PropertiesDumperFactory>()));
100 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::LIST_DUMPER, std::make_shared<ListDumperFactory>()));
101 ptrExecutorFactoryMap_->insert(
102 std::make_pair(DumperConstant::VERSION_DUMPER, std::make_shared<VersionDumperFactory>()));
103 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::SA_DUMPER, std::make_shared<SADumperFactory>()));
104 ptrExecutorFactoryMap_->insert(
105 std::make_pair(DumperConstant::COLUMN_ROWS_FILTER, std::make_shared<ColumnRowsFilterFactory>()));
106 ptrExecutorFactoryMap_->insert(
107 std::make_pair(DumperConstant::FILE_FORMAT_DUMP_FILTER, std::make_shared<FileFormatDumpFilterFactory>()));
108 ptrExecutorFactoryMap_->insert(std::make_pair(DumperConstant::GROUP, std::make_shared<DumperGroupFactory>()));
109 ptrExecutorFactoryMap_->insert(
110 std::make_pair(DumperConstant::MEMORY_DUMPER, std::make_shared<MemoryDumperFactory>()));
111 ptrExecutorFactoryMap_->insert(
112 std::make_pair(DumperConstant::JSHEAP_MEMORY_DUMPER, std::make_shared<JsHeapMemoryDumperFactory>()));
113 ptrExecutorFactoryMap_->insert(
114 std::make_pair(DumperConstant::CJHEAP_MEMORY_DUMPER, std::make_shared<CjHeapMemoryDumperFactory>()));
115 ptrExecutorFactoryMap_->insert(
116 std::make_pair(DumperConstant::TRAFFIC_DUMPER, std::make_shared<TrafficDumperFactory>()));
117 ptrExecutorFactoryMap_->insert(
118 std::make_pair(DumperConstant::IPC_STAT_DUMPER, std::make_shared<IPCStatDumperFactory>()));
119 }
120
Main(int argc,char * argv[],const std::shared_ptr<RawParam> & reqCtl)121 DumpStatus DumpImplement::Main(int argc, char *argv[], const std::shared_ptr<RawParam> &reqCtl)
122 {
123 std::shared_ptr<DumperParameter> ptrDumperParameter = std::make_shared<DumperParameter>();
124 DumpStatus ret = InitHandle(argc, argv, reqCtl, ptrDumperParameter);
125 if (ret != DumpStatus::DUMP_OK) {
126 return ret;
127 }
128 std::vector<std::shared_ptr<DumpCfg>> &configs = ptrDumperParameter->GetExecutorConfigList();
129 DUMPER_HILOGD(MODULE_COMMON, "debug|Main configs size is %{public}zu", configs.size());
130 if (configs.size() == 0) {
131 DUMPER_HILOGE(MODULE_COMMON, "Executor config list is empty, so can not dump.");
132 return DumpStatus::DUMP_FAIL;
133 }
134 bool isZip = ptrDumperParameter->GetOpts().IsDumpZip();
135 std::vector<std::shared_ptr<HidumperExecutor>> hidumperExecutors;
136 setExecutorList(hidumperExecutors, configs, isZip);
137 if (hidumperExecutors.empty()) {
138 DUMPER_HILOGE(MODULE_COMMON, "Executor list is empty, so dump fail.");
139 return DumpStatus::DUMP_FAIL;
140 }
141
142 reqCtl->SetProgressEnabled(isZip);
143 isZip ? reqCtl->SetTitle(",The result is:" + path_) : reqCtl->SetTitle("");
144 HidumperExecutor::StringMatrix dumpDatas = std::make_shared<std::vector<std::vector<std::string>>>();
145 ret = DumpDatas(hidumperExecutors, ptrDumperParameter, dumpDatas);
146 std::lock_guard<std::mutex> lock(mutexCmdLock_); // lock for dumperSysEventParams_
147 if (ret != DumpStatus::DUMP_OK) {
148 DUMPER_HILOGE(MODULE_COMMON, "DUMP FAIL!!!");
149 dumperSysEventParams_->errorCode = static_cast<int32_t>(ret);
150 dumperSysEventParams_->errorMsg = "dump fail";
151 DumpCommonUtils::ReportCmdUsage(dumperSysEventParams_);
152 return ret;
153 }
154 DumpCommonUtils::ReportCmdUsage(dumperSysEventParams_);
155 return DumpStatus::DUMP_OK;
156 }
157
InitHandle(int argc,char * argv[],const std::shared_ptr<RawParam> & reqCtl,std::shared_ptr<DumperParameter> & ptrDumperParameter)158 DumpStatus DumpImplement::InitHandle(int argc, char *argv[], const std::shared_ptr<RawParam> &reqCtl,
159 std::shared_ptr<DumperParameter>& ptrDumperParameter)
160 {
161 ptrDumperParameter->setClientCallback(reqCtl);
162 ptrDumperParameter->SetPid(reqCtl->GetPid());
163 ptrDumperParameter->SetUid(reqCtl->GetUid());
164 std::lock_guard<std::mutex> lock(mutexCmdLock_); // lock for optind value safe
165 dumperSysEventParams_ = std::make_unique<DumperSysEventParams>();
166 dumperSysEventParams_->errorCode = 0;
167 dumperSysEventParams_->callerPpid = -1;
168 DumpStatus ret = CmdParse(argc, argv, ptrDumperParameter);
169 if (ret != DumpStatus::DUMP_OK) {
170 DUMPER_HILOGE(MODULE_COMMON, "Parse cmd FAIL!!!");
171 dumperSysEventParams_->errorCode = static_cast<int32_t>(ret);
172 dumperSysEventParams_->errorMsg = "parse cmd fail";
173 DumpCommonUtils::ReportCmdUsage(dumperSysEventParams_);
174 return ret;
175 }
176 ConfigUtils::GetDumperConfigs(ptrDumperParameter);
177 return DumpStatus::DUMP_OK;
178 }
179
ProcessDumpOptions(int clientPid,std::shared_ptr<DumperParameter> & dumpParameter,DumperOpts & opts)180 void DumpImplement::ProcessDumpOptions(int clientPid, std::shared_ptr<DumperParameter> &dumpParameter, DumperOpts &opts)
181 {
182 if (IsHidumperClientProcess(clientPid)) {
183 opts.AddSelectAll();
184 opts.isAppendix_ = true;
185 } else {
186 opts.isDumpCpuFreq_ = true;
187 #ifdef HIDUMPER_HIVIEWDFX_HIVIEW_ENABLE
188 opts.isDumpCpuUsage_ = true;
189 opts.cpuUsagePid_ = clientPid;
190 #endif
191 opts.isDumpMem_ = true;
192 opts.memPid_ = clientPid;
193 }
194 dumpParameter->SetPid(clientPid);
195 }
196
CheckArgs(int argc,char * argv[])197 DumpStatus DumpImplement::CheckArgs(int argc, char* argv[])
198 {
199 std::stringstream dumpCmdSs;
200 if (argc > ARG_MAX_COUNT) {
201 DUMPER_HILOGE(MODULE_COMMON, "too many arguments(%{public}d), limit size %{public}d.", argc, ARG_MAX_COUNT);
202 return DumpStatus::DUMP_FAIL;
203 }
204 for (int i = 0; i < argc; i++) {
205 if (argv[i] == nullptr) {
206 DUMPER_HILOGE(MODULE_COMMON, "argument(%{public}d) is null.", i);
207 return DumpStatus::DUMP_FAIL;
208 }
209 size_t len = strlen(argv[i]);
210 if (len == 0) {
211 DUMPER_HILOGE(MODULE_COMMON, "argument(%{public}d) is empty.", i);
212 return DumpStatus::DUMP_FAIL;
213 }
214 if (len > SINGLE_ARG_MAXLEN) {
215 DUMPER_HILOGE(MODULE_COMMON, "too long args:%{public}zu, limit size:%{public}d.", len, SINGLE_ARG_MAXLEN);
216 return DumpStatus::DUMP_FAIL;
217 }
218 dumpCmdSs << argv[i] << " ";
219 }
220 if (dumpCmdSs.str().length() > 0) {
221 dumperSysEventParams_->arguments = dumpCmdSs.str().substr(0, dumpCmdSs.str().length() - 1);
222 }
223 return DumpStatus::DUMP_OK;
224 }
225
CmdParse(int argc,char * argv[],std::shared_ptr<DumperParameter> & dumpParameter)226 DumpStatus DumpImplement::CmdParse(int argc, char *argv[], std::shared_ptr<DumperParameter> &dumpParameter)
227 {
228 if (CheckArgs(argc, argv) != DumpStatus::DUMP_OK)
229 return DumpStatus::DUMP_FAIL;
230 DumperOpts opts;
231 DumpStatus status = CmdParseWithParameter(dumpParameter, argc, argv, opts);
232 if (status != DumpStatus::DUMP_OK)
233 return status;
234 if (!opts.IsSelectAny()) { // 注:hidumper不添加任何参数时,dump全部内容;IPC方式dump时,仅dump 当前进程的CPU和memory情况
235 int clientPid = dumpParameter->GetPid(); // to be set value
236 ProcessDumpOptions(clientPid, dumpParameter, opts);
237 }
238 ReportJsheap(opts);
239 ReportCjheap(opts);
240 dumpParameter->SetOpts(opts);
241 return DumpStatus::DUMP_OK;
242 }
243
IsHidumperClientProcess(int pid)244 bool DumpImplement::IsHidumperClientProcess(int pid)
245 {
246 bool ret = false;
247 std::string procName;
248 if (DumpCommonUtils::GetProcessNameByPid(pid, procName)) {
249 ret = (procName.find("hidumper") != std::string::npos);
250 }
251 DUMPER_HILOGD(
252 MODULE_COMMON, "debug|ret=%{public}d, pid=%{public}d, procName=%{public}s", ret, pid, procName.c_str());
253 return ret;
254 }
255
CmdParseWithParameter(int argc,char * argv[],DumperOpts & opts_)256 DumpStatus DumpImplement::CmdParseWithParameter(int argc, char *argv[], DumperOpts &opts_)
257 {
258 optind = 0; // reset getopt_long
259 opterr = 0; // getopt not show error info
260 const char optStr[] = "-hlcsa:epvT:t:";
261 bool loop = true;
262 while (loop) {
263 int optionIndex = 0;
264 int c = getopt_long(argc, argv, optStr, LONG_OPTIONS, &optionIndex);
265 if (c == -1) {
266 break;
267 } else if (c == 0) {
268 DumpStatus status = ParseLongCmdOption(argc, opts_, LONG_OPTIONS, optionIndex, argv);
269 if (status != DumpStatus::DUMP_OK) {
270 return status;
271 }
272 } else if (c == 'h') {
273 CmdHelp();
274 return DumpStatus::DUMP_HELP;
275 } else if (c == '?') {
276 CheckIncorrectCmdOption(optStr, argv);
277 return DumpStatus::DUMP_INVALID_ARG;
278 } else {
279 DumpStatus status = ParseShortCmdOption(c, opts_, argc, argv);
280 if (status != DumpStatus::DUMP_OK) {
281 return status;
282 }
283 }
284 }
285 DumpStatus status = CheckProcessAlive(opts_);
286 if (status != DumpStatus::DUMP_OK) {
287 return status;
288 }
289 if (!CheckDumpPermission(opts_)) {
290 if (!opts_.isShowSmaps_ || !opts_.isDumpMem_) {
291 CmdHelp();
292 }
293 return DumpStatus::DUMP_HELP;
294 }
295 if (!opts_.IsSelectAny() && argc != 1) {
296 CmdHelp();
297 return DumpStatus::DUMP_HELP;
298 }
299 RemoveDuplicateString(opts_);
300 return DumpStatus::DUMP_OK;
301 }
302
CmdParseWithParameter(std::shared_ptr<DumperParameter> & dumpParameter,int argc,char * argv[],DumperOpts & opts)303 DumpStatus DumpImplement::CmdParseWithParameter(std::shared_ptr<DumperParameter> &dumpParameter, int argc, char *argv[],
304 DumperOpts &opts)
305 {
306 DUMPER_HILOGD(MODULE_COMMON, "enter|");
307 ptrReqCtl_ = dumpParameter->getClientCallback();
308 dumperSysEventParams_->callerPpid = ptrReqCtl_->GetCallerPpid();
309 DumpStatus ret = CmdParseWithParameter(argc, argv, opts);
310 if (ret == DumpStatus::DUMP_OK) {
311 std::string errorStr;
312 if (!opts.CheckOptions(errorStr)) {
313 SendErrorMessage(invalidError_ + errorStr);
314 ret = DumpStatus::DUMP_INVALID_ARG;
315 }
316 }
317 ptrReqCtl_ = nullptr;
318 DUMPER_HILOGD(MODULE_COMMON, "leave|ret=%{public}d", ret);
319 return ret;
320 }
321
SetCmdParameter(int argc,char * argv[],DumperOpts & opts_)322 DumpStatus DumpImplement::SetCmdParameter(int argc, char *argv[], DumperOpts &opts_)
323 {
324 DumpStatus status = DumpStatus::DUMP_OK;
325 DUMPER_HILOGD(MODULE_COMMON,
326 "debug|SetCmdParameter optind is %{public}d"
327 " argc is %{public}d",
328 optind,
329 argc);
330 if (optind > 1 && optind <= argc) {
331 bool hiviewEnable = false;
332 #ifdef HIDUMPER_HIVIEWDFX_HIVIEW_ENABLE
333 hiviewEnable = true;
334 #endif
335 if (hiviewEnable &&
336 StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--cpuusage")) {
337 status = SetCmdIntegerParameter(argv[optind - 1], opts_.cpuUsagePid_);
338 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--mem")) {
339 std::string optionParam = argv[optind - 1];
340 if (optionParam == "SIGINT") {
341 opts_.isReceivedSigInt_ = true;
342 } else {
343 status = SetCmdIntegerParameter(optionParam, opts_.memPid_);
344 }
345 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--net")) {
346 status = SetCmdIntegerParameter(argv[optind - 1], opts_.netPid_);
347 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--storage")) {
348 status = SetCmdIntegerParameter(argv[optind - 1], opts_.storagePid_);
349 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "-c")) {
350 opts_.systemArgs_.push_back(argv[optind - 1]);
351 dumperSysEventParams_->subOpt = argv[optind - 1];
352 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "-p")) {
353 status = SetCmdIntegerParameter(argv[optind - 1], opts_.processPid_);
354 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "-T")) {
355 status = SetCmdIntegerParameter(argv[optind - 1], opts_.threadId_);
356 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "-t")) {
357 status = SetCmdIntegerParameter(argv[optind - 1], opts_.timeInterval_);
358 } else if (IsSADumperOption(argv)) {
359 opts_.abilitieNames_.push_back(argv[optind - 1]);
360 dumperSysEventParams_->target += argv[optind - 1];
361 } else if (StringUtils::GetInstance().IsSameStr(argv[optind - ARG_INDEX_OFFSET_LAST_OPTION], "--ipc")) {
362 status = SetCmdIntegerParameter(argv[optind - 1], opts_.ipcStatPid_);
363 } else {
364 std::string optionName = RemoveCharacterFromStr(argv[optind - 1], '-');
365 std::string errorStr = unrecognizedError_ + optionName;
366 SendErrorMessage(errorStr);
367 return DumpStatus::DUMP_FAIL;
368 }
369 }
370 return status;
371 }
372
GetTime()373 std::string DumpImplement::GetTime()
374 {
375 struct timeval curTime;
376 gettimeofday(&curTime, nullptr);
377 int milli = curTime.tv_usec / 1000;
378
379 char buffer[80] = {0};
380 struct tm nowTime;
381 localtime_r(&curTime.tv_sec, &nowTime);
382 (void)strftime(buffer, sizeof(buffer), "%Y%m%d-%H%M%S", &nowTime);
383
384 char currentTime[84] = {0};
385 if (sprintf_s(currentTime, sizeof(currentTime), "%s-%03d", buffer, milli) < 0) {
386 return "";
387 };
388
389 return currentTime;
390 }
391
ParseSubLongCmdOption(int argc,DumperOpts & opts_,const struct option longOptions[],const int & optionIndex,char * argv[])392 bool DumpImplement::ParseSubLongCmdOption(int argc, DumperOpts &opts_, const struct option longOptions[],
393 const int &optionIndex, char *argv[])
394 {
395 bool hiviewEnable = false;
396 #ifdef HIDUMPER_HIVIEWDFX_HIVIEW_ENABLE
397 hiviewEnable = true;
398 #endif
399 if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "cpufreq")) {
400 opts_.isDumpCpuFreq_ = true;
401 dumperSysEventParams_->opt = "cpufreq";
402 } else if (hiviewEnable && StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "cpuusage")) {
403 opts_.isDumpCpuUsage_ = true;
404 dumperSysEventParams_->opt = "cpuusage";
405 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "mem")) {
406 opts_.isDumpMem_ = true;
407 dumperSysEventParams_->opt = "mem";
408 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "net")) {
409 opts_.isDumpNet_ = true;
410 dumperSysEventParams_->opt = "net";
411 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "storage")) {
412 opts_.isDumpStorage_ = true;
413 dumperSysEventParams_->opt = "storage";
414 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "zip")) {
415 path_ = ZIP_FOLDER + GetTime() + ".zip";
416 opts_.path_ = path_;
417 } else {
418 return false;
419 }
420
421 return true;
422 }
423
ParseLongCmdOption(int argc,DumperOpts & opts_,const struct option longOptions[],const int & optionIndex,char * argv[])424 DumpStatus DumpImplement::ParseLongCmdOption(int argc, DumperOpts &opts_, const struct option longOptions[],
425 const int &optionIndex, char *argv[])
426 {
427 if (ParseSubLongCmdOption(argc, opts_, longOptions, optionIndex, argv)) {
428 return DumpStatus::DUMP_OK;
429 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "mem-smaps")) {
430 DumpStatus status = SetMemSmapsParam(opts_, argc, argv);
431 if (status != DumpStatus::DUMP_OK) {
432 return status;
433 }
434 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "show-ashmem")) {
435 opts_.showAshmem_ = true;
436 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "show-dmabuf")) {
437 opts_.showDmaBuf_ = true;
438 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "mem-jsheap")) {
439 return SetMemJsheapParam(opts_);
440 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "mem-cjheap")) {
441 return SetMemCjheapParam(opts_);
442 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "raw")) {
443 return SetRawParam(opts_);
444 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "prune")) {
445 return SetMemPruneParam(opts_);
446 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "gc")) {
447 return SetGCParam(opts_);
448 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "leakobj")) {
449 opts_.isDumpJsHeapLeakobj_ = true;
450 } else if (StringUtils::GetInstance().IsSameStr(longOptions[optionIndex].name, "ipc")) {
451 opts_.isDumpIpc_ = true;
452 dumperSysEventParams_->opt = "ipc";
453 if (IPC_STAT_ARG_NUMS != argc) {
454 DUMPER_HILOGE(MODULE_COMMON, "ipc stat cmd args invalid");
455 SendErrorMessage("ipc stat cmd args invalid\n");
456 CmdHelp();
457 return DumpStatus::DUMP_HELP;
458 }
459 } else if (SetIpcStatParam(opts_, longOptions[optionIndex].name)) {
460 if (!opts_.isDumpIpc_) {
461 DUMPER_HILOGE(MODULE_COMMON, "ipc stat param invalid");
462 SendErrorMessage("ipc stat cmd args invalid\n");
463 CmdHelp();
464 return DumpStatus::DUMP_HELP;
465 }
466 } else {
467 DUMPER_HILOGE(MODULE_COMMON, "ParseLongCmdOption %{public}s", longOptions[optionIndex].name);
468 }
469 return DumpStatus::DUMP_OK;
470 }
471
SetMemSmapsParam(DumperOpts & opt,int argc,char * argv[])472 DumpStatus DumpImplement::SetMemSmapsParam(DumperOpts &opt, int argc, char *argv[])
473 {
474 opt.isShowSmaps_ = true;
475 dumperSysEventParams_->opt = "mem-smaps";
476 DumpStatus status;
477 if (ARG_INDEX_OFFSET_LAST_OPTION < 0 || ARG_INDEX_OFFSET_LAST_OPTION >= argc) {
478 status = DumpStatus::DUMP_FAIL;
479 } else {
480 status = SetCmdIntegerParameter(argv[ARG_INDEX_OFFSET_LAST_OPTION], opt.memPid_);
481 }
482 return status;
483 }
484
SetMemJsheapParam(DumperOpts & opt)485 DumpStatus DumpImplement::SetMemJsheapParam(DumperOpts &opt)
486 {
487 opt.isDumpJsHeapMem_ = true;
488 dumperSysEventParams_->opt = "mem-jsheap";
489 if (optarg == nullptr) {
490 DUMPER_HILOGE(MODULE_COMMON, "mem-jsheap nullptr");
491 return DumpStatus::DUMP_FAIL;
492 }
493 return SetCmdIntegerParameter(optarg, opt.dumpJsHeapMemPid_);
494 }
495
SetMemCjheapParam(DumperOpts & opt)496 DumpStatus DumpImplement::SetMemCjheapParam(DumperOpts &opt)
497 {
498 opt.isDumpCjHeapMem_ = true;
499 dumperSysEventParams_->opt = "mem-cjheap";
500 if (optarg == nullptr) {
501 DUMPER_HILOGE(MODULE_COMMON, "mem-cjheap nullptr");
502 return DumpStatus::DUMP_FAIL;
503 }
504 return SetCmdIntegerParameter(optarg, opt.dumpCjHeapMemPid_);
505 }
506
SetRawParam(DumperOpts & opt)507 DumpStatus DumpImplement::SetRawParam(DumperOpts &opt)
508 {
509 DumpStatus status = DumpStatus::DUMP_FAIL;
510 if (opt.isDumpJsHeapMem_) {
511 opt.dumpJsRawHeap_ = true;
512 dumperSysEventParams_->opt = "mem-jsrawheap";
513 status = DumpStatus::DUMP_OK;
514 }
515
516 return status;
517 }
518
SetMemPruneParam(DumperOpts & opt)519 DumpStatus DumpImplement::SetMemPruneParam(DumperOpts &opt)
520 {
521 DumpStatus status = DumpStatus::DUMP_FAIL;
522 if (opt.isDumpMem_) {
523 opt.dumpMemPrune_ = true;
524 dumperSysEventParams_->opt = "mem";
525 status = DumpStatus::DUMP_OK;
526 }
527 return status;
528 }
529
SetGCParam(DumperOpts & opt)530 DumpStatus DumpImplement::SetGCParam(DumperOpts &opt)
531 {
532 DumpStatus status = DumpStatus::DUMP_FAIL;
533 if (opt.isDumpJsHeapMem_) {
534 opt.isDumpJsHeapMemGC_ = true;
535 status = DumpStatus::DUMP_OK;
536 } else if (opt.isDumpCjHeapMem_) {
537 opt.isDumpCjHeapMemGC_ = true;
538 status = DumpStatus::DUMP_OK;
539 }
540 return status;
541 }
542
SetIpcStatParam(DumperOpts & opts_,const std::string & param)543 bool DumpImplement::SetIpcStatParam(DumperOpts &opts_, const std::string& param)
544 {
545 if (StringUtils::GetInstance().IsSameStr(param, "start-stat")) {
546 opts_.isDumpIpcStartStat_ = true;
547 dumperSysEventParams_->subOpt = "start-stat";
548 } else if (StringUtils::GetInstance().IsSameStr(param, "stop-stat")) {
549 opts_.isDumpIpcStopStat_ = true;
550 dumperSysEventParams_->subOpt = "stop-stat";
551 } else if (StringUtils::GetInstance().IsSameStr(param, "stat")) {
552 opts_.isDumpIpcStat_ = true;
553 dumperSysEventParams_->subOpt = "stat";
554 } else {
555 return false;
556 }
557 return true;
558 }
559
ParseCmdOptionForA(DumperOpts & opts_,char * argv[])560 DumpStatus DumpImplement::ParseCmdOptionForA(DumperOpts &opts_, char *argv[])
561 {
562 if (opts_.isDumpSystemAbility_) {
563 SplitStr(optarg, " ", opts_.abilitieArgs_);
564 dumperSysEventParams_->subOpt = "a";
565 } else if (opts_.isDumpIpc_) {
566 opts_.isDumpAllIpc_ = true;
567 dumperSysEventParams_->target = "allPid";
568 if (optarg != nullptr) {
569 std::vector<std::string> ipcStatParams;
570 SplitStr(optarg, "--", ipcStatParams);
571 if (ipcStatParams.empty()) {
572 SendErrorMessage(invalidError_);
573 return DumpStatus::DUMP_INVALID_ARG;
574 }
575 if (!SetIpcStatParam(opts_, ipcStatParams[0])) {
576 SendErrorMessage(invalidError_ + ":" + ipcStatParams[0]);
577 return DumpStatus::DUMP_INVALID_ARG;
578 }
579 }
580 } else {
581 std::string optionName = RemoveCharacterFromStr(argv[optind - 1], '-');
582 std::string errorStr = unrecognizedError_ + optionName;
583 SendErrorMessage(errorStr);
584 return DumpStatus::DUMP_INVALID_ARG;
585 }
586 return DumpStatus::DUMP_OK;
587 }
588
ParseShortCmdOption(int c,DumperOpts & opts_,int argc,char * argv[])589 DumpStatus DumpImplement::ParseShortCmdOption(int c, DumperOpts &opts_, int argc, char *argv[])
590 {
591 switch (c) {
592 case 'a': {
593 DumpStatus status = ParseCmdOptionForA(opts_, argv);
594 if (status != DumpStatus::DUMP_OK) {
595 return status;
596 }
597 break;
598 }
599 case 'c':
600 opts_.isDumpSystem_ = true;
601 dumperSysEventParams_->opt += "c";
602 break;
603 case 'e':
604 opts_.isFaultLog_ = true;
605 dumperSysEventParams_->opt = "e";
606 break;
607 case 'l':
608 opts_.isDumpList_ = true;
609 dumperSysEventParams_->opt += "l";
610 break;
611 case 's':
612 opts_.isDumpSystemAbility_ = true;
613 dumperSysEventParams_->opt += "s";
614 break;
615 case 'p':
616 opts_.isDumpProcesses_ = true;
617 dumperSysEventParams_->opt = "p";
618 break;
619 case 'v':
620 opts_.isShowSmapsInfo_ = true;
621 dumperSysEventParams_->subOpt = "v";
622 break;
623 default: {
624 DumpStatus status = SetCmdParameter(argc, argv, opts_);
625 if (status != DumpStatus::DUMP_OK) {
626 return status;
627 }
628 break;
629 }
630 }
631 return DumpStatus::DUMP_OK;
632 }
633
SetCmdIntegerParameter(const std::string & str,int & value)634 DumpStatus DumpImplement::SetCmdIntegerParameter(const std::string &str, int &value)
635 {
636 if (!IsNumericStr(str)) {
637 DUMPER_HILOGE(MODULE_COMMON, "Invalid string arg %{public}s", str.c_str());
638 std::string errorStr = invalidError_ + str;
639 SendErrorMessage(errorStr);
640 return DumpStatus::DUMP_INVALID_ARG;
641 }
642 if (!StrToInt(str, value)) {
643 DUMPER_HILOGE(MODULE_COMMON, "StrToInt error, str=%{public}s", str.c_str());
644 return DumpStatus::DUMP_FAIL;
645 }
646 dumperSysEventParams_->target = str;
647 return DumpStatus::DUMP_OK;
648 }
649
PrintCommonUsage(std::string & str)650 void DumpImplement::PrintCommonUsage(std::string& str)
651 {
652 if (DumpUtils::IsUserMode()) {
653 std::string substr = " --mem [pid] -t [timeInterval] |dump process memory change information,"
654 " press Ctrl+C to stop the export. detail information is stored in /data/log/hidumper/record_mem.txt.\n";
655
656 size_t pos = str.find(substr);
657 if (pos != std::string::npos) {
658 str.erase(pos, substr.length());
659 }
660 }
661
662 if (ptrReqCtl_ == nullptr) {
663 return;
664 }
665 int rawParamFd = ptrReqCtl_->GetOutputFd();
666 if (rawParamFd < 0) {
667 return;
668 }
669 SaveStringToFd(rawParamFd, str.c_str());
670 }
671
CmdHelp()672 void DumpImplement::CmdHelp()
673 {
674 const std::string commonUsageStr =
675 "usage:\n"
676 " -h |help text for the tool\n"
677 " -lc |a list of system information clusters\n"
678 " -ls |a list of system abilities\n"
679 " -c |all system information clusters\n"
680 " -c [base system] |system information clusters labeled \"base\" and \"system\"\n"
681 " -s |all system abilities\n"
682 " -s [SA0 SA1] |system abilities labeled \"SA0\" and \"SA1\"\n"
683 " -s [SA] -a ['-h'] |system ability labeled \"SA\" with arguments \"-h\" specified\n"
684 " -e |faultlogs of crash history\n"
685 " --net [pid] |dump network information; if pid is specified,"
686 " dump traffic usage of specified pid\n"
687 " --storage [pid] |dump storage information; if pid is specified, dump /proc/pid/io\n"
688 " -p |processes information, include list and infromation of processes"
689 " and threads\n"
690 " -p [pid] |dump threads under pid, includes smap, block channel,"
691 " execute time, mountinfo\n"
692 " --cpufreq |dump real CPU frequency of each core\n"
693 " --mem [pid] [--prune] |dump memory usage of total; dump memory usage of specified"
694 " pid if pid was specified; dump simplified memory infomation if prune is specified and not support"
695 " dumped simplified memory infomation of specified pid\n"
696 " --mem [pid] [--show-ashmem] |show ashmem info when dumping memory of specified pid\n"
697 " --mem [pid] [--show-dmabuf] |show dmabuf info when dumping memory of specified pid\n"
698 " --mem [pid] -t [timeInterval] |dump process memory change information, press Ctrl+C to stop the export."
699 " detail information is stored in /data/log/hidumper/record_mem.txt.\n"
700 " --zip |compress output to /data/log/hidumper\n"
701 " --mem-smaps pid [-v] |display statistic in /proc/pid/smaps, use -v specify more details\n"
702 " --mem-jsheap pid [-T tid] [--gc] [--leakobj] [--raw] |triggerGC, dumpHeapSnapshot, dumpRawHeap"
703 " and dumpLeakList under pid and tid\n"
704 " --mem-cjheap pid [--gc] |the pid should belong to the Cangjie process; triggerGC and"
705 " dumpHeapSnapshot under pid\n"
706 " --ipc pid ARG |ipc load statistic; pid must be specified or set to -a dump all"
707 " processes. ARG must be one of --start-stat | --stop-stat | --stat\n";
708
709 #ifdef HIDUMPER_HIVIEWDFX_HIVIEW_ENABLE
710 const std::string extendedUsageStr =
711 " --cpuusage [pid] |dump cpu usage by processes and category; if PID is specified,"
712 " dump category usage of specified pid\n";
713
714 std::string str = commonUsageStr + extendedUsageStr;
715 #else
716 std::string str = commonUsageStr;
717 #endif
718 PrintCommonUsage(str);
719 }
720
setExecutorList(std::vector<std::shared_ptr<HidumperExecutor>> & executors,const std::vector<std::shared_ptr<DumpCfg>> & configs,bool isZip)721 void DumpImplement::setExecutorList(std::vector<std::shared_ptr<HidumperExecutor>> &executors,
722 const std::vector<std::shared_ptr<DumpCfg>> &configs, bool isZip)
723 {
724 std::shared_ptr<HidumperExecutor> ptrOutput;
725
726 for (size_t i = 0; i < configs.size(); i++) {
727 std::shared_ptr<ExecutorFactory> ptrExecutorFactory;
728 if ((configs[i]->class_) == DumperConstant::FD_OUTPUT) {
729 if (isZip) {
730 ptrExecutorFactory = std::make_shared<ZipOutputFactory>();
731 } else {
732 ptrExecutorFactory = std::make_shared<FDOutputFactory>();
733 }
734
735 if (ptrOutput.get() == nullptr) {
736 ptrOutput = ptrExecutorFactory->CreateExecutor();
737 }
738 ptrOutput->SetDumpConfig(configs[i]);
739 executors.push_back(ptrOutput);
740 continue;
741 } else {
742 ExecutorFactoryMap::iterator it = ptrExecutorFactoryMap_->find(configs[i]->class_);
743 if (it != ptrExecutorFactoryMap_->end()) {
744 ptrExecutorFactory = it->second;
745 }
746 }
747
748 if (ptrExecutorFactory.get() == nullptr) {
749 DUMPER_HILOGE(MODULE_COMMON, "configs[%{public}zu].class_ is %{public}d", i, configs[i]->class_);
750 continue;
751 }
752 std::shared_ptr<HidumperExecutor> ptrExecutor = ptrExecutorFactory->CreateExecutor();
753 if (ptrExecutor != nullptr) {
754 configs[i]->executor_ = ptrExecutor;
755 ptrExecutor->SetDumpConfig(configs[i]);
756 }
757 executors.push_back(ptrExecutor);
758 }
759
760 // must clear.
761 for (auto cfg : configs) {
762 cfg->executor_ = nullptr;
763 }
764 }
765
DumpDatas(const std::vector<std::shared_ptr<HidumperExecutor>> & executors,const std::shared_ptr<DumperParameter> & dumpParameter,HidumperExecutor::StringMatrix dumpDatas)766 DumpStatus DumpImplement::DumpDatas(const std::vector<std::shared_ptr<HidumperExecutor>> &executors,
767 const std::shared_ptr<DumperParameter> &dumpParameter,
768 HidumperExecutor::StringMatrix dumpDatas)
769 {
770 auto callback = dumpParameter->getClientCallback();
771
772 std::string groupName = "";
773 std::vector<size_t> loopStack;
774 const size_t executorSum = executors.size();
775 for (size_t index = 0; index < executorSum; index++) {
776 callback->UpdateProgress(executors.size(), index);
777 if (callback->IsCanceled()) {
778 break;
779 }
780
781 auto dumpCfg = executors[index]->GetDumpConfig();
782 if (dumpCfg->IsDumper() && CheckGroupName(groupName, dumpCfg->section_)) {
783 AddGroupTitle(groupName, dumpDatas, dumpParameter);
784 }
785
786 DumpStatus ret = DumpStatus::DUMP_FAIL;
787 ret = executors[index]->DoPreExecute(dumpParameter, dumpDatas);
788 if (ret != DumpStatus::DUMP_OK) {
789 continue;
790 }
791
792 ret = executors[index]->DoExecute();
793 if ((ret != DumpStatus::DUMP_OK) && (ret != DumpStatus::DUMP_MORE_DATA)) {
794 continue;
795 }
796
797 ret = executors[index]->DoAfterExecute();
798 if (dumpCfg->IsDumper() && dumpCfg->CanLoop() && (ret == DumpStatus::DUMP_MORE_DATA)) {
799 loopStack.push_back(index);
800 }
801
802 if (dumpCfg->IsOutput() || dumpCfg->IsGroup()) {
803 if (!loopStack.empty()) {
804 index = loopStack.back() - 1; // the 1 will add back by end for.
805 }
806 loopStack.clear(); // clear now.
807 }
808 }
809 for (auto executor : executors) {
810 executor->Reset();
811 }
812 callback->UpdateProgress(executors.size(), executors.size());
813 return DumpStatus::DUMP_OK;
814 }
815
AddGroupTitle(const std::string & groupName,HidumperExecutor::StringMatrix dumpDatas,const std::shared_ptr<DumperParameter> & dumpParameter)816 void DumpImplement::AddGroupTitle(const std::string &groupName, HidumperExecutor::StringMatrix dumpDatas,
817 const std::shared_ptr<DumperParameter>& dumpParameter)
818 {
819 /**
820 * @brief The group title is followed
821 * '
822 * -------------------------------[groupName]-------------------------------
823 * '
824 */
825 if (StringUtils::GetInstance().IsSameStr(groupName, "ipc")) {
826 DUMPER_HILOGI(MODULE_COMMON, "ipc statistic cmd, do not need title.");
827 return;
828 }
829 if (StringUtils::GetInstance().IsSameStr(groupName, "memory") && dumpParameter->GetOpts().memPid_ <= 0) {
830 DUMPER_HILOGI(MODULE_COMMON, "hidumper --mem cmd, do not need title.");
831 return;
832 }
833 if (StringUtils::GetInstance().IsSameStr(groupName, "memory") && dumpParameter->GetOpts().timeInterval_ > 0) {
834 DUMPER_HILOGI(MODULE_COMMON, "hidumper --mem pid -t timeinterval cmd, do not need title.");
835 return;
836 }
837 if (StringUtils::GetInstance().IsSameStr(groupName, "ability")) {
838 return;
839 }
840 std::vector<std::string> lineData;
841 lineData.push_back("");
842 dumpDatas->push_back(lineData);
843 std::vector<std::string>().swap(lineData);
844 lineData.push_back("-------------------------------[");
845 lineData.push_back(groupName);
846 lineData.push_back("]-------------------------------");
847 dumpDatas->push_back(lineData);
848 std::vector<std::string>().swap(lineData);
849 lineData.push_back("");
850 dumpDatas->push_back(lineData);
851 std::vector<std::string>().swap(lineData);
852 }
853
CheckGroupName(std::string & lastName,const std::string & curName)854 bool DumpImplement::CheckGroupName(std::string &lastName, const std::string &curName)
855 {
856 if (curName.compare("") == 0) {
857 return false;
858 }
859
860 if (lastName.compare(curName) == 0) {
861 return false;
862 }
863
864 lastName.assign(curName);
865 return true;
866 }
867
GetSystemAbilityManager()868 const sptr<ISystemAbilityManager> DumpImplement::GetSystemAbilityManager()
869 {
870 sam_ = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
871 if (sam_ == nullptr) {
872 DUMPER_HILOGE(MODULE_COMMON, "SystemAbilityManager not found.");
873 }
874 return sam_;
875 }
876
CheckIncorrectCmdOption(const char * optStr,char * argv[])877 void DumpImplement::CheckIncorrectCmdOption(const char *optStr, char *argv[])
878 {
879 if (optopt == 0) {
880 SendErrorMessage(unrecognizedError_ + RemoveCharacterFromStr(argv[optind - 1], '-'));
881 } else if (!IsShortOptionReqArg(optStr)) {
882 std::string errorStr = unrecognizedError_;
883 errorStr += optopt;
884 SendErrorMessage(errorStr);
885 }
886 }
887
IsShortOptionReqArg(const char * optStr)888 bool DumpImplement::IsShortOptionReqArg(const char *optStr)
889 {
890 int len = strlen(optStr);
891 for (int i = 0; i < len; i++) {
892 if (optStr[i] == optopt) {
893 SendErrorMessage(requireError_ + optStr[i]);
894 return true;
895 }
896 }
897 return false;
898 }
899
SendErrorMessage(const std::string & errorStr)900 void DumpImplement::SendErrorMessage(const std::string &errorStr)
901 {
902 if (ptrReqCtl_ == nullptr) {
903 return;
904 }
905 int rawParamFd = ptrReqCtl_->GetOutputFd();
906 if (rawParamFd < 0) {
907 return;
908 }
909 SaveStringToFd(rawParamFd, errorStr + "\n");
910 }
911
SendPidErrorMessage(int pid)912 void DumpImplement::SendPidErrorMessage(int pid)
913 {
914 if (ptrReqCtl_ == nullptr) {
915 return;
916 }
917 int rawParamFd = ptrReqCtl_->GetOutputFd();
918 if (rawParamFd < 0) {
919 return;
920 }
921 dprintf(rawParamFd, pidError_.c_str(), pid);
922 }
923
SendReleaseAppErrorMessage(const std::string & opt)924 void DumpImplement::SendReleaseAppErrorMessage(const std::string& opt)
925 {
926 if (ptrReqCtl_ == nullptr) {
927 DUMPER_HILOGE(MODULE_COMMON, "ptrReqCtl_ == nullptr");
928 return;
929 }
930 int rawParamFd = ptrReqCtl_->GetOutputFd();
931 if (rawParamFd < 0) {
932 DUMPER_HILOGE(MODULE_COMMON, "rawParamFd < 0");
933 return;
934 }
935 std::string onlySupportDebugSignedAppMessage_;
936 onlySupportDebugSignedAppMessage_ += "[ERROR]: The %s option is only supported for debug-signed application [ ";
937 onlySupportDebugSignedAppMessage_ += "\"appProvisionType\": \"debug\"].\n";
938 dprintf(rawParamFd, onlySupportDebugSignedAppMessage_.c_str(), opt.c_str());
939 }
940
SendReleaseVersionErrorMessage(const std::string & opt)941 void DumpImplement::SendReleaseVersionErrorMessage(const std::string& opt)
942 {
943 if (ptrReqCtl_ == nullptr) {
944 DUMPER_HILOGE(MODULE_COMMON, "ptrReqCtl_ == nullptr");
945 return;
946 }
947 int rawParamFd = ptrReqCtl_->GetOutputFd();
948 if (rawParamFd < 0) {
949 DUMPER_HILOGE(MODULE_COMMON, "rawParamFd < 0");
950 return;
951 }
952 std::string onlySupportDebugVersionAppMessage;
953 onlySupportDebugVersionAppMessage += "[ERROR]: The %s option is not supported in user privilege.\n";
954 dprintf(rawParamFd, onlySupportDebugVersionAppMessage.c_str(), opt.c_str());
955 }
956
RemoveCharacterFromStr(const std::string & str,const char character)957 std::string DumpImplement::RemoveCharacterFromStr(const std::string &str, const char character)
958 {
959 std::string strTmp = str;
960 while (strTmp.find(character) != std::string::npos) {
961 strTmp.erase(strTmp.find(character), 1);
962 }
963 return strTmp;
964 }
965
IsSADumperOption(char * argv[])966 bool DumpImplement::IsSADumperOption(char *argv[])
967 {
968 for (int i = optind - 2; i > 0; i--) {
969 if (IsSubStr(argv[i], "-")) {
970 return StringUtils::GetInstance().IsSameStr(argv[i], "-s")
971 || StringUtils::GetInstance().IsSameStr(argv[i], "-a");
972 }
973 }
974 return false;
975 }
976
CheckProcessAlive(const DumperOpts & opts_)977 DumpStatus DumpImplement::CheckProcessAlive(const DumperOpts &opts_)
978 {
979 if ((opts_.cpuUsagePid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.cpuUsagePid_)) {
980 SendPidErrorMessage(opts_.cpuUsagePid_);
981 return DumpStatus::DUMP_FAIL;
982 }
983 if ((opts_.memPid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.memPid_)) {
984 SendPidErrorMessage(opts_.memPid_);
985 return DumpStatus::DUMP_FAIL;
986 }
987 if ((opts_.processPid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.processPid_)) {
988 SendPidErrorMessage(opts_.processPid_);
989 return DumpStatus::DUMP_FAIL;
990 }
991 if ((opts_.storagePid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.storagePid_)) {
992 SendPidErrorMessage(opts_.storagePid_);
993 return DumpStatus::DUMP_FAIL;
994 }
995 if ((opts_.netPid_ > -1) && !DumpUtils::CheckProcessAlive(opts_.netPid_)) {
996 SendPidErrorMessage(opts_.netPid_);
997 return DumpStatus::DUMP_FAIL;
998 }
999 if ((opts_.dumpJsHeapMemPid_ > 0) && !DumpUtils::CheckProcessAlive(opts_.dumpJsHeapMemPid_)) {
1000 SendPidErrorMessage(opts_.dumpJsHeapMemPid_);
1001 return DumpStatus::DUMP_FAIL;
1002 }
1003 if ((opts_.dumpCjHeapMemPid_ > 0) && !DumpUtils::CheckProcessAlive(opts_.dumpCjHeapMemPid_)) {
1004 SendPidErrorMessage(opts_.dumpCjHeapMemPid_);
1005 return DumpStatus::DUMP_FAIL;
1006 }
1007 if ((opts_.ipcStatPid_ > 0) && !DumpUtils::CheckProcessAlive(opts_.ipcStatPid_)) {
1008 SendPidErrorMessage(opts_.ipcStatPid_);
1009 return DumpStatus::DUMP_FAIL;
1010 }
1011 return DumpStatus::DUMP_OK;
1012 }
1013
RemoveDuplicateString(DumperOpts & opts_)1014 void DumpImplement::RemoveDuplicateString(DumperOpts &opts_)
1015 {
1016 DumpUtils::RemoveDuplicateString(opts_.logArgs_); // remove duplicate log names
1017 DumpUtils::RemoveDuplicateString(opts_.systemArgs_); // remove duplicate system names
1018 DumpUtils::RemoveDuplicateString(opts_.abilitieNames_); // remove duplicate ability names
1019 }
1020
1021 #ifdef HIDUMPER_HIVIEWDFX_HISYSEVENT_ENABLE
ReportJsheap(const DumperOpts & opts)1022 void DumpImplement::ReportJsheap(const DumperOpts &opts)
1023 {
1024 if (!opts.isDumpJsHeapMem_) {
1025 return;
1026 }
1027 std::string strType = "hidumper";
1028 if (opts.dumpJsRawHeap_) {
1029 strType = "hidumperRawHeap";
1030 }
1031 int memJsheapRet = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::FRAMEWORK, "ARK_STATS_DUMP",
1032 OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
1033 "PID", std::to_string(opts.dumpJsHeapMemPid_),
1034 "TYPE", strType);
1035 if (memJsheapRet != 0) {
1036 DUMPER_HILOGE(MODULE_COMMON, "hisysevent report mem jsheap failed! ret %{public}d.", memJsheapRet);
1037 }
1038 }
1039
ReportCjheap(const DumperOpts & opts)1040 void DumpImplement::ReportCjheap(const DumperOpts &opts)
1041 {
1042 if (!opts.isDumpCjHeapMem_) {
1043 return;
1044 }
1045 std::string strType = "hidumper";
1046 int memCjheapRet = HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::FRAMEWORK, "ARK_STATS_DUMP",
1047 OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
1048 "PID", std::to_string(opts.dumpCjHeapMemPid_),
1049 "TYPE", strType);
1050 if (memCjheapRet != 0) {
1051 DUMPER_HILOGE(MODULE_COMMON, "hisysevent report mem cjheap failed! ret %{public}d.", memCjheapRet);
1052 }
1053 }
1054 #endif
1055
CheckDumpPermission(DumperOpts & opt)1056 bool DumpImplement::CheckDumpPermission(DumperOpts& opt)
1057 {
1058 bool isUserMode = DumpUtils::IsUserMode();
1059 DUMPER_HILOGD(MODULE_COMMON, "debug|isUserMode %{public}d", isUserMode);
1060 if (!isUserMode) {
1061 return true;
1062 }
1063 // mem-smaps [-v] + releaseApp
1064 int uid = ptrReqCtl_->GetUid();
1065 if (opt.isShowSmaps_ && uid != HIVIEW_UID && !DumpUtils::CheckAppDebugVersion(opt.memPid_)) {
1066 SendReleaseAppErrorMessage("--mem-smaps");
1067 DUMPER_HILOGE(MODULE_COMMON, "ShowSmaps false, isUserMode:%{public}d, pid:%{public}d", isUserMode, opt.memPid_);
1068 return false;
1069 }
1070 // mem-jsheap + releaseApp
1071 if (opt.isDumpJsHeapMem_ && !DumpUtils::CheckAppDebugVersion(opt.dumpJsHeapMemPid_)) {
1072 DUMPER_HILOGE(MODULE_COMMON, "DumpJsHeapMem false isUserMode %{public}d", isUserMode);
1073 return false;
1074 }
1075 // mem-cjheap + releaseApp
1076 if (opt.isDumpCjHeapMem_ && !DumpUtils::CheckAppDebugVersion(opt.dumpCjHeapMemPid_)) {
1077 DUMPER_HILOGE(MODULE_COMMON, "DumpCjHeapMem false isUserMode %{public}d", isUserMode);
1078 return false;
1079 }
1080 if (opt.isDumpMem_ && opt.timeInterval_ > 0) {
1081 SendReleaseVersionErrorMessage("-t");
1082 DUMPER_HILOGE(MODULE_COMMON, "Show mem false, isUserMode:%{public}d, pid:%{public}d, timeInterval_:%{public}d",
1083 isUserMode, opt.memPid_, opt.timeInterval_);
1084 return false;
1085 }
1086 return true;
1087 }
1088 } // namespace HiviewDFX
1089 } // namespace OHOS
1090