• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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