• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cinttypes>
17 #include <csignal>
18 #include <cstdio>
19 #include <ctime>
20 #include <fstream>
21 #include <regex>
22 #include <sstream>
23 #include <string>
24 #include <vector>
25 #include <map>
26 #include <fcntl.h>
27 #include <getopt.h>
28 #include <sys/stat.h>
29 #include <thread>
30 #include <unistd.h>
31 #include <zlib.h>
32 #include "hitrace_meter.h"
33 #include "bytrace_osal.h"
34 #include "securec.h"
35 
36 using namespace std;
37 using namespace OHOS::Developtools::BytraceOsal;
38 
39 namespace {
40 struct option g_longOptions[] = {
41     { "buffer_size",       required_argument, nullptr, 0 },
42     { "trace_clock",       required_argument, nullptr, 0 },
43     { "help",              no_argument,       nullptr, 0 },
44     { "output",            required_argument, nullptr, 0 },
45     { "time",              required_argument, nullptr, 0 }, // used to specify the time (in seconds) for trace to run.
46     { "trace_begin",       no_argument,       nullptr, 0 },
47     { "trace_finish",      no_argument,       nullptr, 0 },
48     { "trace_dump",        no_argument,       nullptr, 0 },
49     { "list_categories",   no_argument,       nullptr, 0 },
50     { "overwrite",         no_argument,       nullptr, 0 },
51     { nullptr,             0,                 nullptr, 0 },
52 };
53 // char range
54 const unsigned int CHUNK_SIZE = 65536;
55 const int BLOCK_SIZE = 4096;
56 const int SHELL_UID = 2000;
57 const int WAIT_MILLISECONDS = 10;
58 
59 const string TRACE_TAG_PROPERTY = "debug.hitrace.tags.enableflags";
60 
61 // various operating paths of ftrace
62 const string TRACING_ON_PATH = "tracing_on";
63 const string TRACE_PATH = "trace";
64 const string TRACE_MARKER_PATH = "trace_marker";
65 const string BUFFER_SIZE_PATH = "buffer_size_kb";
66 const string CURRENT_TRACER_PATH = "current_tracer";
67 const string TRACE_CLOCK_PATH = "trace_clock";
68 const string OVER_WRITE_PATH = "options/overwrite";
69 const string RECORD_TGID_PATH = "options/record-tgid";
70 
71 // support customization of some parameters
72 
73 const int MIN_BUFFER_SIZE = 256;
74 const int MAX_BUFFER_SIZE = 307200; // 300 MB
75 constexpr unsigned int MAX_OUTPUT_LEN = 255;
76 const int PAGE_SIZE_KB = 4; // 4 KB
77 int g_traceDuration = 5; // g_traceDuration
78 int g_bufferSizeKB = 2048;
79 string g_clock = "boot";
80 bool g_overwrite = true;
81 string g_outputFile;
82 bool g_compress = false;
83 
84 string g_traceRootPath; // g_traceRootPath
85 
86 const unsigned int START_NONE = 0;
87 const unsigned int START_NORMAL = 1;
88 const unsigned int START_ASYNC = 2;
89 unsigned int g_traceStart = START_NORMAL;
90 bool g_traceStop = true;
91 bool g_traceDump = true;
92 
93 map<string, TagCategory> g_tagMap; // stored tags
94 vector<uint64_t> g_userEnabledTags;
95 vector<string> g_kernelEnabledPaths;
96 }
97 
IsTraceMounted()98 static bool IsTraceMounted()
99 {
100     const string debugfsPath = "/sys/kernel/debug/tracing/";
101     const string tracefsPath = "/sys/kernel/tracing/";
102     // find debugfsPath first
103     if (access((debugfsPath + TRACE_MARKER_PATH).c_str(), F_OK) != -1) {
104         g_traceRootPath = debugfsPath;
105         return true;
106     }
107     if (access((tracefsPath + TRACE_MARKER_PATH).c_str(), F_OK) != -1) {
108         g_traceRootPath = tracefsPath;
109         return true;
110     }
111 
112     (void)fprintf(stderr, "Error: Did not find trace folder.\n"); // can't find trace folder
113     return false;
114 }
115 
IsFileExit(const string & filename)116 static bool IsFileExit(const string& filename)
117 {
118     return access((g_traceRootPath + filename).c_str(), F_OK) != -1; // verify if the file exists
119 }
120 
IsWritableFile(const string & filename)121 static bool IsWritableFile(const string& filename)
122 {
123     return access((g_traceRootPath + filename).c_str(), W_OK) != -1; // verify if the file writable
124 }
125 
WriteStrToFile(const string & filename,const std::string & str)126 static bool WriteStrToFile(const string& filename, const std::string& str)
127 {
128     ofstream out;
129     out.open(g_traceRootPath + filename, ios::out);
130     if (out.fail()) {
131         // can't open the file
132         fprintf(stderr, "Error: Did not open %s\n", filename.c_str());
133         return false;
134     }
135     out << str;
136     if (out.bad()) {
137         fprintf(stderr, "Error: Did not write %s\n", filename.c_str());
138         out.close();
139         return false;
140     }
141     // release resources
142     out.flush();
143     out.close();
144     return true;
145 }
146 
SetFtraceEnabled(const string & path,bool enabled)147 static bool SetFtraceEnabled(const string& path, bool enabled)
148 {
149     return WriteStrToFile(path, enabled ? "1" : "0"); // write 1 or 0 to file
150 }
151 
IsTagSupported(const string & name)152 static bool IsTagSupported(const string& name)
153 {
154     auto it = g_tagMap.find(name);
155     if (it == g_tagMap.end()) {
156         // can't find item from map
157         return false;
158     }
159 
160     TagCategory tagCategory = it->second;
161     if (tagCategory.type != KERNEL) {
162         g_userEnabledTags.push_back(tagCategory.tag);
163         return true;
164     }
165 
166     bool findPath = false;
167     for (int i = 0; i < MAX_SYS_FILES; i++) {
168         const string path = tagCategory.sysfiles[i].path;
169         if (path.size() == 0) {
170             continue;
171         }
172         if (IsWritableFile(path)) {
173             g_kernelEnabledPaths.push_back(path);
174             findPath = true;
175         } else if (IsFileExit(path)) {
176             fprintf(stderr, "Warning: category \"%s\" requires root privileges.\n", name.c_str());
177         }
178     }
179     return findPath;
180 }
181 
CanonicalizeSpecPath(const char * src)182 static string CanonicalizeSpecPath(const char* src)
183 {
184     // PATH_MAX is 4096, defined in linux/limits.h
185     if (src == nullptr || strlen(src) >= PATH_MAX) {
186         fprintf(stderr, "Error: CanonicalizeSpecPath %s failed\n", src);
187         return "";
188     }
189     char resolvedPath[PATH_MAX] = { 0 };
190 #if defined(_WIN32)
191     if (!_fullpath(resolvedPath, src, PATH_MAX)) {
192         fprintf(stderr, "Error: _fullpath %s failed\n", src);
193         return "";
194     }
195 #else
196     if (access(src, F_OK) == 0) {
197         // function to find the absolute path of a file in the directory
198         if (realpath(src, resolvedPath) == nullptr) {
199             fprintf(stderr, "Error: realpath %s failed\n", src);
200             return "";
201         }
202     } else {
203         // trace_clock file doesn't exist
204         string fileName(src);
205         if (fileName.find("..") == string::npos) {
206             if (sprintf_s(resolvedPath, PATH_MAX, "%s", src) == -1) {
207                 fprintf(stderr, "Error: sprintf_s %s failed\n", src);
208                 return "";
209             }
210         } else {
211             // find file failed
212             fprintf(stderr, "Error: find .. %s failed\n", src);
213             return "";
214         }
215     }
216 #endif
217     string res(resolvedPath);
218     return res; // return the string
219 }
220 
ReadFile(const string & filename)221 static string ReadFile(const string& filename)
222 {
223     // standardize file paths
224     string resolvedPath = CanonicalizeSpecPath((g_traceRootPath + filename).c_str());
225     ifstream fin(resolvedPath.c_str());
226     if (!fin.is_open()) {
227         fprintf(stderr, "open file: %s failed!\n", (g_traceRootPath + filename).c_str());
228         return "";
229     }
230 
231     string str((istreambuf_iterator<char>(fin)), istreambuf_iterator<char>());
232     // close a file handle
233     fin.close();
234     return str;
235 }
236 
SetBufferSize(int bufferSize)237 static bool SetBufferSize(int bufferSize)
238 {
239     if (!WriteStrToFile(CURRENT_TRACER_PATH, "nop")) {
240         // process for current_tracer file does not have permission
241         fprintf(stderr, "Error: write \"nop\" to %s\n", CURRENT_TRACER_PATH.c_str());
242     }
243     return WriteStrToFile(BUFFER_SIZE_PATH, to_string(bufferSize));
244 }
245 
SetClock(const string & timeclock)246 static bool SetClock(const string& timeclock)
247 {
248     string allClocks = ReadFile(TRACE_CLOCK_PATH);
249     size_t begin = allClocks.find("[");
250     size_t end = allClocks.find("]");
251     string newClock;
252     // if the clock to be set is the same as the existing clock, it will not be set
253     if (begin != string::npos && end != string::npos &&
254         timeclock.compare(0, timeclock.size(), allClocks, begin + 1, end - begin - 1) == 0) {
255         return true;
256     } else if (allClocks.find(timeclock) != string::npos) {
257         newClock = timeclock;
258     } else if (allClocks.find("boot") != string::npos) {
259         // boot: This is the boot clock (CLOCK_BOOTTIME) and is based on the fast monotonic clock,
260         newClock = "boot";
261     } else if (allClocks.find("mono") != string::npos) {
262         // mono: uses the fast monotonic clock (CLOCK_MONOTONIC)
263         // which is monotonic and is subject to NTP rate adjustments.
264         newClock = "mono";
265     } else if (allClocks.find("global") != string::npos) {
266         newClock = "global";
267     } else {
268         fprintf(stderr, "You can set trace clock in %s\n", allClocks.c_str());
269         return false;
270     }
271     if (newClock.size() != 0) {
272         return WriteStrToFile(TRACE_CLOCK_PATH, newClock);
273     }
274     return true;
275 }
276 
SetOverWriteEnable(bool enabled)277 static bool SetOverWriteEnable(bool enabled)
278 {
279     return SetFtraceEnabled(OVER_WRITE_PATH, enabled);
280 }
281 
SetTgidEnable(bool enabled)282 static bool SetTgidEnable(bool enabled)
283 {
284     return SetFtraceEnabled(RECORD_TGID_PATH, enabled);
285 }
286 
DisableAllFtraceEvents()287 static bool DisableAllFtraceEvents()
288 {
289     bool isTrue = true;
290     // DisableAllFtraceEvents
291     for (auto it = g_tagMap.begin(); it != g_tagMap.end(); ++it) {
292         TagCategory tag = it->second;
293         if (tag.type != KERNEL) {
294             continue;
295         }
296         for (int i = 0; i < MAX_SYS_FILES; i++) {
297             const string path = tag.sysfiles[i].path;
298             if ((path.size() > 0) && IsWritableFile(path)) {
299                 isTrue = isTrue && SetFtraceEnabled(path, false); // set false to ftraceEnabled
300             }
301         }
302     }
303     return isTrue;
304 }
305 
SetProperty(const string & property,const string & value)306 static bool SetProperty(const string& property, const string& value)
307 {
308     // set the system property
309     return SetPropertyInner(property, value);
310 }
311 
SetTraceTagsEnabled(uint64_t tags)312 static bool SetTraceTagsEnabled(uint64_t tags)
313 {
314     string value = to_string(tags);
315     return SetProperty(TRACE_TAG_PROPERTY, value);
316 }
317 
RefreshServices()318 static bool RefreshServices()
319 {
320     bool res = false;
321     // refresh binderServices
322     res = RefreshBinderServices();
323     if (!res) {
324         return res;
325     }
326     res = RefreshHalServices();
327     return res;
328 }
329 
SetUserSpaceSettings()330 static bool SetUserSpaceSettings()
331 {
332     // set userSpace settings
333     uint64_t enabledTags = 0;
334     for (auto tag: g_userEnabledTags) {
335         enabledTags |= tag;
336     }
337     return SetTraceTagsEnabled(enabledTags) && RefreshServices();
338 }
339 
ClearUserSpaceSettings()340 static bool ClearUserSpaceSettings()
341 {
342     // clear userSpace settings
343     return SetTraceTagsEnabled(0) && RefreshServices();
344 }
345 
SetKernelSpaceSettings()346 static bool SetKernelSpaceSettings()
347 {
348     // set kernelSpace settings
349     if (!(SetBufferSize(g_bufferSizeKB) && SetClock(g_clock) &&
350         SetOverWriteEnable(g_overwrite) && SetTgidEnable(true))) {
351         fprintf(stderr, "Set trace kernel settings failed.\n");
352         return false;
353     }
354     if (DisableAllFtraceEvents() == false) {
355         fprintf(stderr, "Pre-clear kernel tracers failed.\n");
356         return false; // pre-clear kernel tracers failed
357     }
358     for (const auto& path : g_kernelEnabledPaths) {
359         SetFtraceEnabled(path, true);
360     }
361     return true;
362 }
363 
ClearKernelSpaceSettings()364 static bool ClearKernelSpaceSettings()
365 {
366     // clear kernelSpace settings
367     return DisableAllFtraceEvents() && SetOverWriteEnable(true) && SetBufferSize(1) && SetClock("boot");
368 }
369 
ShowListCategory()370 static void ShowListCategory()
371 {
372     printf("  %18s   description:\n", "tagName:");
373     for (auto it = g_tagMap.begin(); it != g_tagMap.end(); ++it) {
374         string key = it->first; // show categorys
375         TagCategory tag = it->second;
376         if (IsTagSupported(key)) {
377             printf("  %18s - %s\n", tag.name.c_str(), tag.description.c_str());
378         }
379     }
380 }
381 
ShowHelp(const string & cmd)382 static void ShowHelp(const string& cmd)
383 {
384     printf("usage: %s [options] [categories...]\n", cmd.c_str());
385     printf("options include:\n"
386            "  -b N               Sets the size of the buffer (KB) for storing and reading traces. The default \n"
387            "                     buffer size is 2048 KB.\n"
388            "  --buffer_size N    Like \"-b N\".\n"
389            "  -l                 Lists available bytrace categories.\n"
390            "  --list_categories  Like \"-l\".\n"
391            "  -t N               Sets the bytrace running duration in seconds (5s by default), which depends on \n"
392            "                     the time required for analysis.\n"
393            "  --time N           Like \"-t N\".\n"
394            "  --trace_clock clock\n"
395            "                     Sets the type of the clock for adding a timestamp to a trace, which can be\n"
396            "                     boot (default), global, mono, uptime, or perf.\n"
397            "  --trace_begin      Starts capturing traces.\n"
398            "  --trace_dump       Dumps traces to a specified path (stdout by default).\n"
399            "  --trace_finish     Stops capturing traces and dumps traces to a specified path (stdout by default).\n"
400            "  --overwrite        Sets the action to take when the buffer is full. If this option is used,\n"
401            "                     the latest traces are discarded; if this option is not used (default setting),\n"
402            "                     the earliest traces are discarded.\n"
403            "  -o filename        Specifies the name of the target file (stdout by default).\n"
404            "  --output filename\n"
405            "                     Like \"-o filename\".\n"
406            "  -z                 Compresses a captured trace.\n"
407     );
408 }
409 
410 template <typename T>
StrToNum(const std::string & sString,T & tX)411 inline bool StrToNum(const std::string& sString, T &tX)
412 {
413     // str to num
414     std::istringstream iStream(sString);
415     return (iStream >> tX) ? true : false;
416 }
417 
ParseControlOpt(int optionIndex,bool & isTrue)418 static bool ParseControlOpt(int optionIndex, bool& isTrue)
419 {
420     if (!strcmp(g_longOptions[optionIndex].name, "trace_begin")) {
421         g_traceStart = START_ASYNC;
422         g_traceStop = false;
423         g_traceDump = false;
424         return true;
425     } else if (!strcmp(g_longOptions[optionIndex].name, "trace_finish")) {
426         g_traceStart = START_NONE;
427         g_traceStop = true;
428         g_traceDump = true;
429         return true;
430     } else if (!strcmp(g_longOptions[optionIndex].name, "trace_dump")) {
431         g_traceStart = START_NONE;
432         g_traceStop = false;
433         g_traceDump = true;
434         return true;
435     } else if (!strcmp(g_longOptions[optionIndex].name, "list_categories")) {
436         ShowListCategory();
437         isTrue = false;
438         return true;
439     }
440     return false;
441 }
442 
ParseBufferSizeOpt(int optionIndex,bool & isTrue)443 static bool ParseBufferSizeOpt(int optionIndex, bool& isTrue)
444 {
445     if (!strcmp(g_longOptions[optionIndex].name, "buffer_size")) {
446         if (!StrToNum(optarg, g_bufferSizeKB)) {
447             fprintf(stderr, "Error: buffer size is illegal input. eg: \"--buffer_size 1024\"\n");
448             isTrue = false;
449         } else if (g_bufferSizeKB < MIN_BUFFER_SIZE || g_bufferSizeKB > MAX_BUFFER_SIZE) {
450             fprintf(stderr, "Error: buffer size must be from 256 KB to 300 MB. eg: \"--buffer_size 1024\"\n");
451             isTrue = false;
452         }
453         g_bufferSizeKB = g_bufferSizeKB / PAGE_SIZE_KB * PAGE_SIZE_KB;
454         return true;
455     }
456     return false;
457 }
458 
ParseTraceClockOpt(int optionIndex,bool & isTrue)459 static bool ParseTraceClockOpt(int optionIndex, bool& isTrue)
460 {
461     if (!strcmp(g_longOptions[optionIndex].name, "trace_clock")) {
462         regex re("[a-zA-Z]{4,6}");
463         if (regex_match(optarg, re)) {
464             g_clock = optarg;
465         } else {
466             fprintf(stderr, "Error: \"--trace_clock\" is illegal input. eg: \"--trace_clock boot\"\n");
467             isTrue = false;
468         }
469         return true;
470     } else if (!strcmp(g_longOptions[optionIndex].name, "overwrite")) {
471         g_overwrite = false;
472         return true;
473     }
474     return false;
475 }
476 
ParseOutputOpt(int optionIndex,bool & isTrue)477 static bool ParseOutputOpt(int optionIndex, bool& isTrue)
478 {
479     if (!strcmp(g_longOptions[optionIndex].name, "output")) {
480         struct stat buf;
481         size_t len = strnlen(optarg, MAX_OUTPUT_LEN);
482         if (len == MAX_OUTPUT_LEN || len < 1 || (stat(optarg, &buf) == 0 && (buf.st_mode & S_IFDIR))) {
483             fprintf(stderr, "Error: output file is illegal\n");
484             isTrue = false;
485         } else {
486             g_outputFile = optarg;
487         }
488         return true;
489     }
490     return false;
491 }
492 
ParseHelpTimeOpt(const string & cmd,int optionIndex,bool & isTrue)493 static void ParseHelpTimeOpt(const string& cmd, int optionIndex, bool& isTrue)
494 {
495     if (!strcmp(g_longOptions[optionIndex].name, "help")) {
496         ShowHelp(cmd);
497         isTrue = false;
498     } else if (!strcmp(g_longOptions[optionIndex].name, "time")) {
499         if (!StrToNum(optarg, g_traceDuration)) {
500             fprintf(stderr, "Error: the time is illegal input. eg: \"--time 5\"\n");
501             isTrue = false;
502         } else if (g_traceDuration < 1) {
503             fprintf(stderr, "Error: \"-t %s\" to be greater than zero. eg: \"--time 5\"\n", optarg);
504             isTrue = false;
505         }
506     }
507 }
508 
ParseLongOpt(const string & cmd,int optionIndex,bool & isTrue)509 static void ParseLongOpt(const string& cmd, int optionIndex, bool& isTrue)
510 {
511     bool isFinish = ParseControlOpt(optionIndex, isTrue);
512     if (isFinish) {
513         return;
514     }
515     isFinish = ParseBufferSizeOpt(optionIndex, isTrue);
516     if (isFinish) {
517         return;
518     }
519     isFinish = ParseTraceClockOpt(optionIndex, isTrue);
520     if (isFinish) {
521         return;
522     }
523     isFinish = ParseOutputOpt(optionIndex, isTrue);
524     if (isFinish) {
525         return;
526     }
527     ParseHelpTimeOpt(cmd, optionIndex, isTrue);
528 }
529 
ParseBOpt(int opt,bool & isTrue)530 static bool ParseBOpt(int opt, bool& isTrue)
531 {
532     if (opt == 'b') {
533         if (!StrToNum(optarg, g_bufferSizeKB)) {
534             fprintf(stderr, "Error: buffer size is illegal input. eg: \"--buffer_size 1024\"\n");
535             isTrue = false;
536         } else if (g_bufferSizeKB < MIN_BUFFER_SIZE || g_bufferSizeKB > MAX_BUFFER_SIZE) {
537             fprintf(stderr, "Error: buffer size must be from 256 KB to 300 MB. eg: \"--buffer_size 1024\"\n");
538             isTrue = false;
539         }
540         g_bufferSizeKB = g_bufferSizeKB / PAGE_SIZE_KB * PAGE_SIZE_KB;
541         return true;
542     }
543     return false;
544 }
545 
ParseHltOpt(int opt,char ** argv,bool & isTrue)546 static bool ParseHltOpt(int opt, char** argv, bool& isTrue)
547 {
548     if (opt == 'h') {
549         ShowHelp(argv[0]);
550         isTrue = false;
551         return true;
552     } else if (opt == 'l') {
553         ShowListCategory();
554         isTrue = false;
555         return true;
556     } else if (opt == 't') {
557         if (!StrToNum(optarg, g_traceDuration)) {
558             fprintf(stderr, "Error: the time is illegal input. eg: \"--time 5\"\n");
559             isTrue = false;
560         } else if (g_traceDuration < 1) {
561             fprintf(stderr, "Error: \"-t %s\" to be greater than zero. eg: \"--time 5\"\n", optarg);
562             isTrue = false;
563         }
564         return true;
565     }
566     return false;
567 }
568 
ParseOzOpt(int opt,char ** argv,bool & isTrue)569 static bool ParseOzOpt(int opt, char** argv, bool& isTrue)
570 {
571     if (opt == 'o') {
572         struct stat buf;
573         size_t len = strnlen(optarg, MAX_OUTPUT_LEN);
574         if (len == MAX_OUTPUT_LEN || len < 1 || (stat(optarg, &buf) == 0 && (buf.st_mode & S_IFDIR))) {
575             fprintf(stderr, "Error: output file is illegal\n");
576             isTrue = false;
577         } else {
578             g_outputFile = optarg;
579         }
580         return true;
581     } else if (opt == 'z') {
582         g_compress = true;
583         return true;
584     }
585     return false;
586 }
587 
ParseDefaultOpt(int opt,char ** argv,int optIndex,bool & isTrue)588 static void ParseDefaultOpt(int opt, char** argv, int optIndex, bool& isTrue)
589 {
590     if (opt == 0) {
591         ParseLongOpt(argv[0], optIndex, isTrue);
592     } else {
593         ShowHelp(argv[0]);
594         isTrue = false;
595     }
596 }
597 
ParseOpt(int opt,char ** argv,int optIndex)598 static bool ParseOpt(int opt, char** argv, int optIndex)
599 {
600     bool isTrue = true;
601     bool isFinish = ParseBOpt(opt, isTrue);
602     if (isFinish) {
603         return isTrue;
604     }
605     isFinish = ParseHltOpt(opt, argv, isTrue);
606     if (isFinish) {
607         return isTrue;
608     }
609     isFinish = ParseOzOpt(opt, argv, isTrue);
610     if (isFinish) {
611         return isTrue;
612     }
613     ParseDefaultOpt(opt, argv, optIndex, isTrue);
614     return isTrue;
615 }
616 
IsInvalidOpt(int argc,char ** argv)617 static void IsInvalidOpt(int argc, char** argv)
618 {
619     for (int i = optind; i < argc; i++) {
620         if (!IsTagSupported(argv[i])) {
621             fprintf(stderr, "Error: \"%s\" is not support category on this device\n", argv[i]);
622             // tag is not support, exit
623             exit(-1);
624         }
625     }
626 }
627 
HandleOpt(int argc,char ** argv)628 static bool HandleOpt(int argc, char** argv)
629 {
630     // handle opt
631     bool isTrue = true;
632     int opt = 0;
633     int optionIndex = 0;
634     string shortOption = "b:c:hlo:t:z";
635     int argcSize = argc;
636     while (isTrue && argcSize-- > 0) {
637         opt = getopt_long(argc, argv, shortOption.c_str(), g_longOptions, &optionIndex);
638         if (opt < 0) {
639             IsInvalidOpt(argc, argv);
640             break;
641         }
642         isTrue = ParseOpt(opt, argv, optionIndex); // parse Opt
643     }
644     return isTrue;
645 }
646 
TruncateFile(const string & path)647 static bool TruncateFile(const string& path)
648 {
649     // rebuild file
650     int fd = creat((g_traceRootPath + path).c_str(), 0);
651     if (fd == -1) {
652         fprintf(stderr, "Error: clear %s, errno: %d\n", (g_traceRootPath + path).c_str(), errno);
653         return false;
654     }
655     close(fd);
656     fd = -1;
657     return true;
658 }
659 
ClearTrace()660 static bool ClearTrace()
661 {
662     // truncate file
663     return TruncateFile(TRACE_PATH);
664 }
665 
StartTrace()666 static bool StartTrace()
667 {
668     // set trace_on 1
669     if (!SetFtraceEnabled(TRACING_ON_PATH, true)) {
670         return false;
671     }
672     ClearTrace();
673     printf("capturing trace...\n");
674     fflush(stdout);
675     return true;
676 }
677 
WaitForTraceDone(void)678 static void WaitForTraceDone(void)
679 {
680     // wait for traceDone
681     struct timespec ts = {0, 0};
682     ts.tv_sec = g_traceDuration;
683     ts.tv_nsec = 0;
684     while ((nanosleep(&ts, &ts) == -1) && (errno == EINTR)) {}
685 }
686 
StopTrace()687 static bool StopTrace()
688 {
689     return SetFtraceEnabled(TRACING_ON_PATH, false);
690 }
691 
DumpCompressedTrace(int traceFd,int outFd)692 static void DumpCompressedTrace(int traceFd, int outFd)
693 {
694     // dump compressedTrace
695     z_stream zs { nullptr };
696     int flush = Z_NO_FLUSH;
697     ssize_t bytesWritten;
698     ssize_t bytesRead;
699     if (memset_s(&zs, sizeof(zs), 0, sizeof(zs)) != 0) {
700         fprintf(stderr, "Error: zip stream buffer init failed\n");
701         return;
702     }
703     // begin deflate init
704     int ret = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
705     if (ret != Z_OK) {
706         fprintf(stderr, "Error: initializing zlib: %d\n", ret);
707         return;
708     }
709     std::unique_ptr<uint8_t[]>  in = std::make_unique<uint8_t[]>(CHUNK_SIZE);
710     std::unique_ptr<uint8_t[]>  out = std::make_unique<uint8_t[]>(CHUNK_SIZE);
711     if (!in || !out) {
712         fprintf(stderr, "Error: couldn't allocate buffers\n");
713         return;
714     }
715     zs.next_out = reinterpret_cast<Bytef*>(out.get());
716     zs.avail_out = CHUNK_SIZE;
717 
718     do {
719         // no flush
720         if (zs.avail_in == 0 && flush == Z_NO_FLUSH) {
721             bytesRead = TEMP_FAILURE_RETRY(read(traceFd, in.get(), CHUNK_SIZE));
722             if (bytesRead == 0) {
723                 flush = Z_FINISH;
724             } else if (bytesRead == -1) {
725                 fprintf(stderr, "Error: reading trace, errno: %d\n", errno);
726                 break;
727             } else {
728                 zs.next_in = reinterpret_cast<Bytef*>(in.get());
729                 zs.avail_in = bytesRead;
730             }
731         }
732         if (zs.avail_out == 0) {
733             bytesWritten = TEMP_FAILURE_RETRY(write(outFd, out.get(), CHUNK_SIZE));
734             if (bytesWritten < CHUNK_SIZE) {
735                 fprintf(stderr, "Error: writing deflated trace, errno: %d\n", errno);
736                 break;
737             }
738             zs.next_out = reinterpret_cast<Bytef*>(out.get());
739             zs.avail_out = CHUNK_SIZE;
740         }
741         // deflate
742         ret = deflate(&zs, flush);
743         if (flush == Z_FINISH && ret == Z_STREAM_END) {
744             size_t have = CHUNK_SIZE - zs.avail_out;
745             bytesWritten = TEMP_FAILURE_RETRY(write(outFd, out.get(), have));
746             if (static_cast<size_t>(bytesWritten) < have) {
747                 fprintf(stderr, "Error: writing deflated trace, errno: %d\n", errno);
748             }
749             break;
750         } else if (ret != Z_OK) {
751             if (ret == Z_ERRNO) {
752                 fprintf(stderr, "Error: deflate failed with errno %d\n", errno);
753             } else {
754                 fprintf(stderr, "Error: deflate failed return %d\n", ret);
755             }
756             break;
757         }
758     } while (ret == Z_OK);
759 
760     // deflate end
761     ret = deflateEnd(&zs);
762     if (ret != Z_OK) {
763         fprintf(stderr, "error cleaning up zlib: %d\n", ret);
764     }
765 }
766 
DumpTrace(int outFd,const string & path)767 static void DumpTrace(int outFd, const string& path)
768 {
769     // standardize file paths
770     string resolvedPath = CanonicalizeSpecPath((g_traceRootPath + path).c_str());
771     int traceFd = open(resolvedPath.c_str(), O_RDWR);
772     if (traceFd == -1) {
773         fprintf(stderr, "error opening %s, errno: %d\n", path.c_str(), errno);
774         return;
775     }
776     ssize_t bytesWritten;
777     ssize_t bytesRead;
778     if (g_compress) {
779         // dump and compress trace
780         DumpCompressedTrace(traceFd, outFd);
781     } else {
782         char buffer[BLOCK_SIZE];
783         do {
784             bytesRead = TEMP_FAILURE_RETRY(read(traceFd, buffer, BLOCK_SIZE));
785             if ((bytesRead == 0) || (bytesRead == -1)) {
786                 break;
787             }
788             bytesWritten = TEMP_FAILURE_RETRY(write(outFd, buffer, bytesRead));
789         } while (bytesWritten > 0);
790     }
791     // close fd
792     close(traceFd);
793 }
794 
MarkOthersClockSync()795 static bool MarkOthersClockSync()
796 {
797     constexpr unsigned int bufferSize = 128; // buffer size
798     char buffer[bufferSize] = { 0 };
799     // standardize file paths
800     string resolvedPath = CanonicalizeSpecPath((g_traceRootPath + TRACE_MARKER_PATH).c_str());
801     int fd = open(resolvedPath.c_str(), O_WRONLY);
802     if (fd == -1) {
803         fprintf(stderr, "Error: opening %s, errno: %d\n", TRACE_MARKER_PATH.c_str(), errno);
804         return false;
805     }
806 
807     struct timespec mts = {0, 0};
808     struct timespec rts = {0, 0};
809     if (clock_gettime(CLOCK_REALTIME, &rts) == -1) { // get timestamp from 1970s
810         fprintf(stderr, "Error: get realtime, errno: %d\n", errno);
811         close(fd);
812         return false;
813     } else if (clock_gettime(CLOCK_MONOTONIC, &mts) == -1) { // get timestamp from machine startup
814         fprintf(stderr, "Error: get parent_ts, errno: %d\n", errno);
815         close(fd);
816         return false;
817     }
818     constexpr unsigned int nanoSeconds = 1000000000; // seconds converted to nanoseconds
819     constexpr unsigned int nanoToMill = 1000000; // millisecond converted to nanoseconds
820     constexpr float nanoToSecond = 1000000000.0f; // consistent with the ftrace timestamp format
821     int len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1,
822         "trace_event_clock_sync: realtime_ts=%" PRId64 "\n",
823         static_cast<int64_t>((rts.tv_sec * nanoSeconds + rts.tv_nsec) / nanoToMill));
824     if (len < 0) { // entering data into buffer error
825         fprintf(stderr, "Error: entering data into buffer, errno: %d\n", errno);
826         close(fd);
827         return false;
828     }
829     if (write(fd, buffer, len) < 0) {
830         fprintf(stderr, "Warning: writing clock sync marker, errno: %d\n", errno);
831         fprintf(stderr, "the buffer is not enough, please increase the buffer\n");
832     }
833     len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "trace_event_clock_sync: parent_ts=%f\n",
834         static_cast<float>(((static_cast<float>(mts.tv_sec)) * nanoSeconds + mts.tv_nsec) / nanoToSecond));
835     if (len < 0) { // entering data into buffer error
836         fprintf(stderr, "Error: entering data into buffer, errno: %d\n", errno);
837         close(fd);
838         return false;
839     }
840     if (write(fd, buffer, len) < 0) {
841         fprintf(stderr, "Warning: writing clock sync marker, errno: %d\n", errno);
842         fprintf(stderr, "the buffer is not enough, please increase the buffer\n");
843     }
844     close(fd);
845     return true;
846 }
847 
InitDiskSupportTags()848 static void InitDiskSupportTags()
849 {
850     // disk support tags
851     g_tagMap["disk"] = { "disk", "Disk I/O", 0, KERNEL, {
852         { "events/f2fs/f2fs_sync_file_enter/enable" },
853         { "events/f2fs/f2fs_sync_file_exit/enable" },
854         { "events/f2fs/f2fs_write_begin/enable" },
855         { "events/f2fs/f2fs_write_end/enable" },
856         { "events/ext4/ext4_da_write_begin/enable" },
857         { "events/ext4/ext4_da_write_end/enable" },
858         { "events/ext4/ext4_sync_file_enter/enable" },
859         { "events/ext4/ext4_sync_file_exit/enable" },
860         { "events/block/block_rq_issue/enable" },
861         { "events/block/block_rq_complete/enable" },
862     }};
863     g_tagMap["mmc"] = { "mmc", "eMMC commands", 0, KERNEL, {
864         { "events/mmc/enable" },
865     }};
866     g_tagMap["ufs"] = { "ufs", "UFS commands", 0, KERNEL, {
867         { "events/ufs/enable" },
868     }};
869 }
870 
InitHardwareSupportTags()871 static void InitHardwareSupportTags()
872 {
873     // hardware support tags
874     g_tagMap["irq"] = { "irq", "IRQ Events", 0, KERNEL, {
875         { "events/irq/enable" },
876         { "events/ipi/enable" },
877     }};
878     g_tagMap["irqoff"] = { "irqoff", "IRQ-disabled code section tracing", 0, KERNEL, {
879         { "events/preemptirq/irq_enable/enable" },
880         { "events/preemptirq/irq_disable/enable" },
881     }};
882     InitDiskSupportTags();
883     g_tagMap["i2c"] = { "i2c", "I2C Events", 0, KERNEL, {
884         { "events/i2c/enable" },
885         { "events/i2c/i2c_read/enable" },
886         { "events/i2c/i2c_write/enable" },
887         { "events/i2c/i2c_result/enable" },
888         { "events/i2c/i2c_reply/enable" },
889         { "events/i2c/smbus_read/enable" },
890         { "events/i2c/smbus_write/enable" },
891         { "events/i2c/smbus_result/enable" },
892         { "events/i2c/smbus_reply/enable" },
893     }};
894     g_tagMap["regulators"] = { "regulators", "Voltage and Current Regulators", 0, KERNEL, {
895         { "events/regulator/enable" },
896     }};
897     g_tagMap["membus"] = { "membus", "Memory Bus Utilization", 0, KERNEL, {
898         { "events/memory_bus/enable" },
899     }};
900 }
901 
InitCpuSupportTags()902 static void InitCpuSupportTags()
903 {
904     // cpu support tags
905     g_tagMap["freq"] = { "freq", "CPU Frequency", 0, KERNEL, {
906         { "events/power/cpu_frequency/enable" },
907         { "events/power/clock_set_rate/enable" },
908         { "events/power/clock_disable/enable" },
909         { "events/power/clock_enable/enable" },
910         { "events/clk/clk_set_rate/enable" },
911         { "events/clk/clk_disable/enable" },
912         { "events/clk/clk_enable/enable" },
913         { "events/power/cpu_frequency_limits/enable" },
914     }};
915     g_tagMap["idle"] = { "idle", "CPU Idle", 0, KERNEL, {
916         { "events/power/cpu_idle/enable" },
917     }};
918     g_tagMap["load"] = { "load", "CPU Load", 0, KERNEL, {
919         { "events/cpufreq_interactive/enable" },
920     }};
921 }
922 
InitKernelSupportTags()923 static void InitKernelSupportTags()
924 {
925     // kernel support tags
926     g_tagMap["sched"] = { "sched", "CPU Scheduling", 0, KERNEL, {
927         { "events/sched/sched_switch/enable" },
928         { "events/sched/sched_wakeup/enable" },
929         { "events/sched/sched_wakeup_new/enable" },
930         { "events/sched/sched_waking/enable" },
931         { "events/sched/sched_blocked_reason/enable" },
932         { "events/sched/sched_pi_setprio/enable" },
933         { "events/sched/sched_process_exit/enable" },
934         { "events/cgroup/enable" },
935         { "events/oom/oom_score_adj_update/enable" },
936         { "events/task/task_newtask/enable" },
937         { "events/task/task_rename/enable" },
938     }};
939     g_tagMap["preemptoff"] = { "preemptoff", "Preempt-disabled code section tracing", 0, KERNEL, {
940         { "events/preemptirq/preempt_enable/enable" },
941         { "events/preemptirq/preempt_disable/enable" },
942     }};
943 
944     g_tagMap["binder"] = { "binder", "Binder kernel Info", 0, KERNEL, {
945         { "events/binder/binder_transaction/enable" },
946         { "events/binder/binder_transaction_received/enable" },
947         { "events/binder/binder_transaction_alloc_buf/enable" },
948         { "events/binder/binder_set_priority/enable" },
949         { "events/binder/binder_lock/enable" },
950         { "events/binder/binder_unlock/enable" },
951         { "events/binder/binder_locked/enable" },
952     }};
953 
954     g_tagMap["sync"] = { "sync", "Synchronization", 0, KERNEL, {
955         // linux kernel > 4.9
956         { "events/dma_fence/enable" },
957     }};
958     g_tagMap["workq"] = { "workq", "Kernel Workqueues", 0, KERNEL, {
959         { "events/workqueue/enable" },
960     }};
961     g_tagMap["memreclaim"] = { "memreclaim", "Kernel Memory Reclaim", 0, KERNEL, {
962         { "events/vmscan/mm_vmscan_direct_reclaim_end/enable" },
963         { "events/vmscan/mm_vmscan_direct_reclaim_begin/enable" },
964         { "events/vmscan/mm_vmscan_kswapd_wake/enable" },
965         { "events/vmscan/mm_vmscan_kswapd_sleep/enable" },
966         { "events/lowmemorykiller/enable" },
967     }};
968     g_tagMap["pagecache"] = { "pagecache", "Page cache", 0, KERNEL, {
969         { "events/filemap/enable" },
970     }};
971     g_tagMap["memory"] = { "memory", "Memory", 0, KERNEL, {
972         { "events/kmem/rss_stat/enable" },
973         { "events/kmem/ion_heap_shrink/enable" },
974         { "events/kmem/ion_heap_grow/enable" },
975     }};
976     InitCpuSupportTags();
977     InitHardwareSupportTags();
978 }
979 
InitAllSupportTags()980 static void InitAllSupportTags()
981 {
982     // OHOS
983     g_tagMap["ability"] = { "ability", "Ability Manager", HITRACE_TAG_ABILITY_MANAGER, USER, {}};
984     g_tagMap["ohos"] = { "ohos", "OpenHarmony", HITRACE_TAG_OHOS, USER, {}};
985     g_tagMap["zcamera"] = { "zcamera", "OpenHarmony Camera Module", HITRACE_TAG_ZCAMERA, USER, {}};
986     g_tagMap["zmedia"] = { "zmedia", "OpenHarmony Media Module", HITRACE_TAG_ZMEDIA, USER, {}};
987     g_tagMap["zimage"] = { "zimage", "OpenHarmony Image Module", HITRACE_TAG_ZIMAGE, USER, {}};
988     g_tagMap["zaudio"] = { "zaudio", "OpenHarmony Audio Module", HITRACE_TAG_ZAUDIO, USER, {}};
989     g_tagMap["distributeddatamgr"] = { "distributeddatamgr", "Distributed Data Manager",
990         HITRACE_TAG_DISTRIBUTEDDATA, USER, {}};
991     g_tagMap["mdfs"] = { "mdfs", "Mobile Distributed File System", HITRACE_TAG_MDFS, USER, {}};
992     g_tagMap["graphic"] = { "graphic", "Graphic Module", HITRACE_TAG_GRAPHIC_AGP, USER, {}};
993     g_tagMap["ace"] = { "ace", "ACE development framework", HITRACE_TAG_ACE, USER, {}};
994     g_tagMap["notification"] = { "notification", "Notification Module", HITRACE_TAG_NOTIFICATION, USER, {}};
995     g_tagMap["multimodalinput"] = { "multimodalinput", "Multimodal Input Module",
996         HITRACE_TAG_MULTIMODALINPUT, USER, {}};
997     g_tagMap["misc"] = { "misc", "Misc Module", HITRACE_TAG_MISC, USER, {}};
998     g_tagMap["sensors"] = { "sensors", "Sensors Module", HITRACE_TAG_SENSORS, USER, {}};
999     g_tagMap["msdp"] = { "msdp", "Multimodal Sensor Data Platform", HITRACE_TAG_MSDP, USER, {}};
1000     g_tagMap["dsoftbus"] = { "dsoftbus", "Distributed Softbus", HITRACE_TAG_DSOFTBUS, USER, {}};
1001     g_tagMap["rpc"] = { "rpc", "RPC and IPC", HITRACE_TAG_RPC, USER, {}};
1002     g_tagMap["ark"] = { "ark", "ARK Module", HITRACE_TAG_ARK, USER, {}};
1003     g_tagMap["window"] = { "window", "Window Manager", HITRACE_TAG_WINDOW_MANAGER, USER, {}};
1004     g_tagMap["accessibility"] = { "accessibility", "Accessibility Manager",
1005         HITRACE_TAG_ACCESSIBILITY_MANAGER, USER, {}};
1006     g_tagMap["dhfwk"] = { "dhfwk", "Distributed Hardware FWK", HITRACE_TAG_DISTRIBUTED_HARDWARE_FWK, USER, {}};
1007     g_tagMap["account"] = { "account", "Account Manager", HITRACE_TAG_ACCOUNT_MANAGER, USER, {}};
1008     g_tagMap["daudio"] = { "daudio", "Distributed Audio", HITRACE_TAG_DISTRIBUTED_AUDIO, USER, {}};
1009     g_tagMap["dscreen"] = { "dscreen", "Distributed Screen", HITRACE_TAG_DISTRIBUTED_SCREEN, USER, {}};
1010     g_tagMap["dcamera"] = { "dcamera", "Distributed Camera", HITRACE_TAG_DISTRIBUTED_CAMERA, USER, {}};
1011     g_tagMap["dinput"] = { "dinput", "Distributed Input", HITRACE_TAG_DISTRIBUTED_INPUT, USER, {}};
1012     g_tagMap["devicemanager"] = { "devicemanager", "Device Manager", HITRACE_TAG_DEVICE_MANAGER, USER, {}};
1013     g_tagMap["deviceprofile"] = { "deviceprofile", "Device Profile", HITRACE_TAG_DEVICE_PROFILE, USER, {}};
1014     g_tagMap["dsched"] = { "dsched", "Distributed Schedule", HITRACE_TAG_DISTRIBUTED_SCHEDULE, USER, {}};
1015     g_tagMap["huks"] = { "huks", "Universal KeyStore", HITRACE_TAG_HUKS, USER, {}};
1016     g_tagMap["dlpcre"] = { "dlpcre", "Dlp Credential Service", HITRACE_TAG_DLP_CREDENTIAL, USER, {}};
1017     g_tagMap["app"] = { "app", "APP Module", HITRACE_TAG_APP, USER, {}};
1018     g_tagMap["samgr"] = { "samgr", "samgr", HITRACE_TAG_SAMGR, USER, {}};
1019     g_tagMap["zbinder"] = { "zbinder", "OpenHarmony binder communication", 0, KERNEL, {
1020         { "events/zbinder/enable" },
1021     }};
1022     g_tagMap["gresource"] = { "gresource", "Global Resource Manager", HITRACE_TAG_GLOBAL_RESMGR, USER, {}};
1023     g_tagMap["power"] = { "power", "Power Manager", HITRACE_TAG_POWER, USER, {}};
1024     g_tagMap["filemanagement"] = { "filemanagement", "filemanagement", HITRACE_TAG_FILEMANAGEMENT, USER, {}};
1025     g_tagMap["dslm"] = {"dslm", "device security level", HITRACE_TAG_DLSM, USER, {}};
1026     g_tagMap["nweb"] = {"nweb", "NWEB Module", HITRACE_TAG_NWEB, USER, {}};
1027     g_tagMap["useriam"] = {"useriam", "useriam", HITRACE_TAG_USERIAM, USER, {}};
1028     g_tagMap["net"] = {"net", "net", HITRACE_TAG_NET, USER, {}};
1029     g_tagMap["accesscontrol"] = {"accesscontrol", "Access Control Module", HITRACE_TAG_ACCESS_CONTROL, USER, {}};
1030     g_tagMap["interconn"] = {"interconn", "Interconnection subsystem", HITRACE_TAG_INTERCONNECTION, USER, {}};
1031     g_tagMap["commonlibrary"] = {"commonlibrary", "Commonlibrary subsystem", HITRACE_TAG_COMMONLIBRARY, USER, {}};
1032 
1033     // Kernel os
1034     InitKernelSupportTags();
1035 }
1036 
InterruptExit(int signo)1037 static void InterruptExit(int signo)
1038 {
1039     _exit(-1);
1040 }
1041 
main(int argc,char ** argv)1042 int main(int argc, char **argv)
1043 {
1044     setgid(SHELL_UID);
1045     (void)signal(SIGKILL, InterruptExit);
1046     (void)signal(SIGINT, InterruptExit);
1047 
1048     if (!IsTraceMounted()) {
1049         exit(-1);
1050     }
1051 
1052     InitAllSupportTags();
1053 
1054     if (!HandleOpt(argc, argv)) {
1055         exit(-1);
1056     }
1057 
1058     if (g_traceStart != START_NONE) {
1059         if (!SetKernelSpaceSettings()) {
1060             ClearKernelSpaceSettings();
1061             exit(-1);
1062         }
1063     }
1064 
1065     bool isTrue = true;
1066     if (g_traceStart != START_NONE) {
1067         isTrue = isTrue && StartTrace();
1068         if (!SetUserSpaceSettings()) {
1069             ClearKernelSpaceSettings();
1070             ClearUserSpaceSettings();
1071             exit(-1);
1072         }
1073         if (g_traceStart == START_ASYNC) {
1074             return isTrue ? 0 : -1;
1075         }
1076         WaitForTraceDone();
1077     }
1078 
1079     // following is dump and stop handling
1080     isTrue = isTrue && MarkOthersClockSync();
1081 
1082     if (g_traceStop) {
1083         // clear user tags first and sleep a little to let apps already be notified.
1084         ClearUserSpaceSettings();
1085         std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_MILLISECONDS));
1086         isTrue = isTrue && StopTrace();
1087     }
1088 
1089     if (isTrue && g_traceDump) {
1090         int outFd = STDOUT_FILENO;
1091         if (g_outputFile.size() > 0) {
1092             printf("write trace to %s\n", g_outputFile.c_str());
1093             string resolvedPath = CanonicalizeSpecPath(g_outputFile.c_str());
1094             outFd = open(resolvedPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
1095         }
1096         if (outFd == -1) {
1097             fprintf(stderr, "Failed to open file '%s', err=%d", g_outputFile.c_str(), errno);
1098             isTrue = false;
1099         } else {
1100             dprintf(outFd, "TRACE:\n");
1101             DumpTrace(outFd, TRACE_PATH);
1102             if (outFd != STDOUT_FILENO) {
1103                 close(outFd);
1104                 outFd = -1;
1105             }
1106         }
1107         ClearTrace();
1108     }
1109 
1110     if (g_traceStop) {
1111         // clear kernel setting including clock type after dump(MUST) and tracing_on is off.
1112         ClearKernelSpaceSettings();
1113     }
1114     return isTrue ? 0 : -1;
1115 }
1116