• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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  * Description: FtraceParser class implements
16  */
17 #include "ftrace_parser.h"
18 
19 #include <algorithm>
20 #include <cerrno>
21 #include <cstring>
22 #include <fcntl.h>
23 #include <fstream>
24 #include <regex>
25 #include <sstream>
26 #include <unistd.h>
27 
28 #include "file_utils.h"
29 #include "securec.h"
30 #include "string_utils.h"
31 
32 #ifdef HILOG_DEBUG
33 #undef HILOG_DEBUG
34 #endif
35 
36 #define HILOG_DEBUG(LOG_CORE, fmt, ...) \
37     if (debugOn_) { \
38         PROFILER_LOG_INFO(LOG_CORE, ":DEBUG: " fmt, ##__VA_ARGS__); \
39     }
40 
41 namespace {
42 using namespace OHOS::Developtools::Profiler;
43 constexpr unsigned RB_MISSED_EVENTS = (1uL << 31); // Flag when events were overwritten
44 constexpr unsigned RB_MISSED_STORED = (1 << 30);   // Missed count stored at end
45 constexpr unsigned RB_MISSED_FLAGS = (RB_MISSED_EVENTS | RB_MISSED_STORED);
46 
47 constexpr unsigned COL_IDX_NAME = 0;
48 constexpr unsigned COL_IDX_VALUE = 1;
49 
50 constexpr unsigned TS_EXT_SHIFT = 27;
51 
GetTimestampIncrements(uint64_t ext)52 inline uint64_t GetTimestampIncrements(uint64_t ext)
53 {
54     return ext << TS_EXT_SHIFT;
55 }
56 } // namespace
57 
58 FTRACE_NS_BEGIN
FtraceParser()59 FtraceParser::FtraceParser()
60 {
61     PROFILER_LOG_INFO(LOG_CORE, "FtraceParser create!");
62 }
63 
Init()64 bool FtraceParser::Init()
65 {
66     fixedCharArrayRegex_ = std::regex(R"(char \w+\[\d+\])");
67     flexDataLocArrayRegex_ = std::regex(R"(__data_loc [a-zA-Z_0-9 ]+\[\] \w+)");
68     if (FtraceFsOps::GetInstance().IsHmKernel()) {
69         return true;
70     }
71     std::string printkFormats = FtraceFsOps::GetInstance().GetPrintkFormats();
72     CHECK_TRUE(printkFormats.size() > 0, false, "read printk_formats failed!");
73     CHECK_TRUE(PrintkFormatsParser::GetInstance().Parse(printkFormats), false, "parse printk_formats failed");
74 
75     std::string formatDesc = FtraceFsOps::GetInstance().GetPageHeaderFormat();
76     CHECK_TRUE(formatDesc.size() > 0, false, "read header_page failed!");
77     return ParseHeaderPageFormat(formatDesc);
78 }
79 
~FtraceParser()80 FtraceParser::~FtraceParser()
81 {
82     PROFILER_LOG_INFO(LOG_CORE, "FtraceParser destroy!");
83 }
84 
SetupEvent(const std::string & type,const std::string & name)85 bool FtraceParser::SetupEvent(const std::string& type, const std::string& name)
86 {
87     if (!SubEventParser<FtraceEvent>::GetInstance().IsSupport(name)) {
88         // no sub event parser found for event, so no need to parse format file
89         return false;
90     }
91 
92     EventFormat format;
93     format.eventType = type;
94     format.eventName = name;
95     std::string desc = FtraceFsOps::GetInstance().GetEventDataFormat(type, name);
96     if (desc != "") {
97         CHECK_TRUE(ParseEventFormat(desc.data(), format), false, "parse %s/%s/format failed!",
98             type.c_str(), name.c_str());
99         CHECK_TRUE(SubEventParser<FtraceEvent>::GetInstance().SetupEvent(format),
100             false, "setup %s/%s failed!", type.c_str(), name.c_str());
101         CHECK_TRUE(SubEventParser<ProtoEncoder::FtraceEvent>::GetInstance().SetupEvent(format),
102             false, "setup pbzero %s/%s failed!", type.c_str(), name.c_str());
103     }
104     return true;
105 }
106 
ParseHeaderPageFormat(const std::string & formatDesc)107 bool FtraceParser::ParseHeaderPageFormat(const std::string& formatDesc)
108 {
109     EventFormat format = {};
110     CHECK_TRUE(ParseEventFormat(formatDesc, format), false, "parse events/header_page failed!");
111 
112     bool commitFound = false;
113     for (auto& field : format.fields) {
114         if (field.name == "timestamp") {
115             pageHeaderFormat_.timestamp = field;
116         } else if (field.name == "commit") {
117             pageHeaderFormat_.commit = field;
118             commitFound = true;
119         } else if (field.name == "overwrite") {
120             pageHeaderFormat_.overwrite = field;
121         }
122     }
123 
124     PROFILER_LOG_INFO(LOG_CORE, "page header info:");
125     PrintFieldInfo(pageHeaderFormat_.timestamp);
126     PrintFieldInfo(pageHeaderFormat_.commit);
127     PrintFieldInfo(pageHeaderFormat_.overwrite);
128     CHECK_TRUE(commitFound, false, "commit field not found!");
129     return true;
130 }
131 
GetHeaderPageCommitSize(void)132 int FtraceParser::GetHeaderPageCommitSize(void)
133 {
134     // return the size value of commit field read from events/header_page
135     return pageHeaderFormat_.commit.size;
136 }
137 
ParseEventFormat(const std::string & formatDesc,EventFormat & format)138 bool FtraceParser::ParseEventFormat(const std::string& formatDesc, EventFormat& format)
139 {
140     std::string idLinePrefix = "ID:";
141     std::string fieldLinePrefix = "field:";
142     std::string printFmtLinePrefix = "print fmt:";
143 
144     std::string line;
145     std::stringstream sin(formatDesc);
146     while (getline(sin, line)) {
147         line = StringUtils::Strip(line);
148         if (line.empty()) {
149             continue;
150         } else if (StringUtils::StartsWith(line, fieldLinePrefix)) {
151             ParseFieldFormat(line, format);
152         } else if (StringUtils::StartsWith(line, idLinePrefix)) {
153             auto idStr = line.substr(idLinePrefix.size() + 1);
154             format.eventId = static_cast<uint32_t>(atoi(idStr.c_str()));
155         }
156     }
157     CHECK_TRUE(format.fields.size() > 0, false, "ParseEventFormat from %s failed!", formatDesc.c_str());
158     size_t lastFiledIndex = format.fields.size() > 1 ? format.fields.size() - 1 : 0;
159     format.eventSize = format.fields[lastFiledIndex].offset + format.fields[lastFiledIndex].size;
160     return true;
161 }
162 
GetName(const std::map<int,std::string> & nameMap,int type)163 static std::string GetName(const std::map<int, std::string>& nameMap, int type)
164 {
165     auto it = nameMap.find(type);
166     if (it != nameMap.end()) {
167         return it->second;
168     }
169     return "";
170 }
171 
GetFieldTypeName(EventFieldType type)172 static std::string GetFieldTypeName(EventFieldType type)
173 {
174     static std::map<int, std::string> toNames = {
175 #define VALUE_NAME(x) {x, #x}
176         VALUE_NAME(FIELD_TYPE_INVALID),   VALUE_NAME(FIELD_TYPE_BOOL),         VALUE_NAME(FIELD_TYPE_INT8),
177         VALUE_NAME(FIELD_TYPE_UINT8),     VALUE_NAME(FIELD_TYPE_INT16),        VALUE_NAME(FIELD_TYPE_UINT16),
178         VALUE_NAME(FIELD_TYPE_INT32),     VALUE_NAME(FIELD_TYPE_UINT32),       VALUE_NAME(FIELD_TYPE_INT64),
179         VALUE_NAME(FIELD_TYPE_UINT64),    VALUE_NAME(FIELD_TYPE_FIXEDCSTRING), VALUE_NAME(FIELD_TYPE_CSTRING),
180         VALUE_NAME(FIELD_TYPE_STRINGPTR), VALUE_NAME(FIELD_TYPE_INODE32),      VALUE_NAME(FIELD_TYPE_INODE64),
181         VALUE_NAME(FIELD_TYPE_PID32),     VALUE_NAME(FIELD_TYPE_COMMONPID32),  VALUE_NAME(FIELD_TYPE_DEVID32),
182         VALUE_NAME(FIELD_TYPE_DEVID64),   VALUE_NAME(FIELD_TYPE_DATALOC),      VALUE_NAME(FIELD_TYPE_SYMADDR32),
183         VALUE_NAME(FIELD_TYPE_SYMADDR64),
184 #undef VALUE_NAME
185     };
186     return GetName(toNames, type);
187 }
188 
GetProtoTypeName(ProtoFieldType type)189 static std::string GetProtoTypeName(ProtoFieldType type)
190 {
191     static std::map<int, std::string> toNames = {
192 #define VALUE_NAME(x) {x, #x}
193         VALUE_NAME(PROTO_TYPE_UNKNOWN),  VALUE_NAME(PROTO_TYPE_DOUBLE),   VALUE_NAME(PROTO_TYPE_FLOAT),
194         VALUE_NAME(PROTO_TYPE_INT64),    VALUE_NAME(PROTO_TYPE_UINT64),   VALUE_NAME(PROTO_TYPE_INT32),
195         VALUE_NAME(PROTO_TYPE_FIXED64),  VALUE_NAME(PROTO_TYPE_FIXED32),  VALUE_NAME(PROTO_TYPE_BOOL),
196         VALUE_NAME(PROTO_TYPE_STRING),   VALUE_NAME(PROTO_TYPE_GROUP),    VALUE_NAME(PROTO_TYPE_MESSAGE),
197         VALUE_NAME(PROTO_TYPE_BYTES),    VALUE_NAME(PROTO_TYPE_UINT32),   VALUE_NAME(PROTO_TYPE_ENUM),
198         VALUE_NAME(PROTO_TYPE_SFIXED32), VALUE_NAME(PROTO_TYPE_SFIXED64), VALUE_NAME(PROTO_TYPE_SINT32),
199         VALUE_NAME(PROTO_TYPE_SINT64),   VALUE_NAME(PROTO_TYPE_MAX),
200 #undef VALUE_NAME
201     };
202     return GetName(toNames, type);
203 }
204 
PrintFieldInfo(const FieldFormat & info)205 void FtraceParser::PrintFieldInfo(const FieldFormat& info)
206 {
207     UNUSED_PARAMETER(GetProtoTypeName);
208     UNUSED_PARAMETER(GetFieldTypeName);
209     PROFILER_LOG_INFO(LOG_CORE,
210         "FieldFormat { offset: %u, size:%u, sign: %u fieldType: %s, protoType:%s, typeName: %s, name: %s}",
211         info.offset, info.size, info.isSigned, GetFieldTypeName(info.filedType).c_str(),
212         GetProtoTypeName(info.protoType).c_str(), info.typeName.c_str(), info.name.c_str());
213 }
214 
SplitNameFromTypeName(const std::string & typeName)215 static std::string SplitNameFromTypeName(const std::string& typeName)
216 {
217     std::string name;
218     if (typeName.size() > 0) { // split type and name
219         auto posT0 = typeName.rfind(" ");
220         std::string rightHalf = typeName.substr(posT0 + 1);
221         size_t dataIndex = rightHalf.size() > 1 ? rightHalf.size() - 1 : 0;
222         if (rightHalf[dataIndex] != ']') {
223             name = rightHalf;
224         } else {
225             std::string::size_type postT1 = rightHalf.rfind('[');
226             if (postT1 == std::string::npos) {
227                 return "";
228             }
229             name = rightHalf.substr(0, postT1);
230         }
231     }
232     return name;
233 }
234 
EraseNameFromTypeName(const std::string & typeName,const std::string & name)235 static std::string EraseNameFromTypeName(const std::string& typeName, const std::string& name)
236 {
237     std::string type;
238     if (name.size() > 0) { // erase name part from typeName
239         type = typeName;
240         auto pos = type.find(name);
241         type.replace(pos, name.size(), "");
242         type = StringUtils::Strip(type);
243     }
244     return type;
245 }
246 
ParseCommonFiledIndex(CommonFiledIndex & commonIndex,const std::string & name,int index)247 static void ParseCommonFiledIndex(CommonFiledIndex& commonIndex, const std::string& name, int index)
248 {
249     if (name == "common_type") {
250         commonIndex.type = index;
251     } else if (name == "common_flags") {
252         commonIndex.flags = index;
253     } else if (name == "common_preempt_count") {
254         commonIndex.preemt = index;
255     } else if (name == "common_pid") {
256         commonIndex.pid = index;
257     }
258 }
259 
ParseFieldFormat(const std::string & fieldLine,EventFormat & format)260 bool FtraceParser::ParseFieldFormat(const std::string& fieldLine, EventFormat& format)
261 {
262     FieldFormat fieldInfo;
263     std::string typeName;
264     std::string offsetStr;
265     std::string sizeStr;
266     std::string signedStr;
267 
268     for (auto& part : StringUtils::Split(fieldLine, ";")) {
269         auto cols = StringUtils::Split(StringUtils::Strip(part), ":");
270         if (cols.size() < COL_IDX_VALUE) {
271             continue;
272         }
273         const auto& key = cols[COL_IDX_NAME];
274         if (key == "field") {
275             typeName = cols[COL_IDX_VALUE];
276         } else if (key == "offset") {
277             offsetStr = cols[COL_IDX_VALUE];
278         } else if (key == "size") {
279             sizeStr = cols[COL_IDX_VALUE];
280         } else if (key == "signed") {
281             signedStr = cols[COL_IDX_VALUE];
282         }
283     }
284 
285     std::string name = SplitNameFromTypeName(typeName);
286     std::string type = EraseNameFromTypeName(typeName, name); // for field type
287     fieldInfo.name = name;
288     fieldInfo.typeName = typeName;
289     fieldInfo.offset = atoi(offsetStr.c_str());
290     fieldInfo.size = atoi(sizeStr.c_str());
291     fieldInfo.isSigned = atoi(signedStr.c_str());
292 
293     ParseFieldType(type, fieldInfo);
294     ParseProtoType(fieldInfo);
295 
296     if (StringUtils::StartsWith(name, "common_")) {
297         ParseCommonFiledIndex(format.commonIndex, name, static_cast<int>(format.commonFields.size()));
298         format.commonFields.push_back(fieldInfo);
299     } else {
300         format.fields.push_back(fieldInfo);
301     }
302     return true;
303 }
304 
ParseSepcialIntType(FieldFormat & field,const std::string & type,const std::string & typeName)305 static bool ParseSepcialIntType(FieldFormat& field, const std::string& type, const std::string& typeName)
306 {
307     if (type == "bool") {
308         field.filedType = FIELD_TYPE_BOOL;
309         return true;
310     }
311 
312     if (type == "ino_t" || type == "i_ino") {
313         if (field.size == sizeof(uint32_t)) {
314             field.filedType = FIELD_TYPE_INODE32;
315             return true;
316         } else if (field.size == sizeof(uint64_t)) {
317             field.filedType = FIELD_TYPE_INODE64;
318             return true;
319         }
320     }
321 
322     if (type == "dev_t") {
323         if (field.size == sizeof(uint32_t)) {
324             field.filedType = FIELD_TYPE_DEVID32;
325             return true;
326         } else if (field.size == sizeof(uint64_t)) {
327             field.filedType = FIELD_TYPE_DEVID64;
328             return true;
329         }
330     }
331 
332     // Pids (as in 'sched_switch').
333     if (type == "pid_t") {
334         field.filedType = FIELD_TYPE_PID32;
335         return true;
336     }
337 
338     if ((typeName.find("common_pid") != std::string::npos)) {
339         field.filedType = FIELD_TYPE_COMMONPID32;
340         return true;
341     }
342     return false;
343 }
344 
ParseCommonIntType(FieldFormat & field,bool sign)345 static bool ParseCommonIntType(FieldFormat& field, bool sign)
346 {
347     switch (field.size) {
348         case sizeof(int8_t):
349             field.filedType = sign ? FIELD_TYPE_INT8 : FIELD_TYPE_UINT8;
350             return true;
351         case sizeof(int16_t):
352             field.filedType = sign ? FIELD_TYPE_INT16 : FIELD_TYPE_UINT16;
353             return true;
354         case sizeof(int32_t):
355             field.filedType = sign ? FIELD_TYPE_INT32 : FIELD_TYPE_UINT32;
356             return true;
357         case sizeof(int64_t):
358             field.filedType = sign ? FIELD_TYPE_INT64 : FIELD_TYPE_UINT64;
359             return true;
360         default:
361             break;
362     }
363     return false;
364 }
365 
ParseKernelAddrField(FieldFormat & field,const std::string & type)366 static bool ParseKernelAddrField(FieldFormat& field, const std::string& type)
367 {
368     if (type == "void*" || type == "void *") {
369         if (field.size == sizeof(uint64_t)) { // 64-bit kernel addresses
370             field.filedType = FIELD_TYPE_SYMADDR64;
371             return true;
372         } else if (field.size == sizeof(uint32_t)) { // 32-bit kernel addresses
373             field.filedType = FIELD_TYPE_SYMADDR32;
374             return true;
375         }
376     }
377     return false;
378 }
379 
ParseFieldType(const std::string & type,FieldFormat & field)380 bool FtraceParser::ParseFieldType(const std::string& type, FieldFormat& field)
381 {
382     const std::string& typeName = field.typeName;
383     // Fixed size C char arrary, likes "char a[LEN]"
384     if (std::regex_match(typeName, fixedCharArrayRegex_)) {
385         field.filedType = FIELD_TYPE_FIXEDCSTRING;
386         return true;
387     }
388 
389     // for flex array with __data_loc mark, likes: __data_loc char[] name; __data_loc __u8[] buf;
390     if (std::regex_match(typeName, flexDataLocArrayRegex_)) {
391         CHECK_TRUE(field.size == sizeof(uint32_t), false, "__data_loc %s, size: %hu", typeName.c_str(), field.size);
392         field.filedType = FIELD_TYPE_DATALOC;
393         return true;
394     }
395 
396     if ((typeName.find("char[]") != std::string::npos) || (typeName.find("char *") != std::string::npos)) {
397         field.filedType = FIELD_TYPE_STRINGPTR;
398         return true;
399     }
400 
401     // Variable length strings: "char foo" + size: 0 (as in 'print').
402     if ((type == "char" || type == "char []") && field.size == 0) {
403         field.filedType = FIELD_TYPE_CSTRING;
404         return true;
405     }
406 
407     // 64-bit kernel addresses
408     if (ParseKernelAddrField(field, type)) {
409         return true;
410     }
411 
412     if (ParseSepcialIntType(field, type, typeName)) {
413         return true;
414     }
415 
416     // int uint:
417     if (ParseCommonIntType(field, field.isSigned)) {
418         return true;
419     }
420     return false;
421 }
422 
ParseProtoType(FieldFormat & field)423 void FtraceParser::ParseProtoType(FieldFormat& field)
424 {
425     switch (field.filedType) {
426         case FIELD_TYPE_CSTRING:
427         case FIELD_TYPE_FIXEDCSTRING:
428         case FIELD_TYPE_STRINGPTR:
429         case FIELD_TYPE_DATALOC:
430             field.protoType = PROTO_TYPE_STRING;
431             break;
432         case FIELD_TYPE_INT8:
433         case FIELD_TYPE_INT16:
434         case FIELD_TYPE_INT32:
435         case FIELD_TYPE_PID32:
436         case FIELD_TYPE_COMMONPID32:
437             field.protoType = PROTO_TYPE_INT32;
438             break;
439         case FIELD_TYPE_INT64:
440             field.protoType = PROTO_TYPE_INT64;
441             break;
442         case FIELD_TYPE_UINT8:
443         case FIELD_TYPE_UINT16:
444         case FIELD_TYPE_UINT32:
445         case FIELD_TYPE_BOOL:
446         case FIELD_TYPE_DEVID32:
447         case FIELD_TYPE_SYMADDR32:
448             field.protoType = PROTO_TYPE_UINT32;
449             break;
450         case FIELD_TYPE_DEVID64:
451         case FIELD_TYPE_UINT64:
452         case FIELD_TYPE_INODE32:
453         case FIELD_TYPE_INODE64:
454         case FIELD_TYPE_SYMADDR64:
455             field.protoType = PROTO_TYPE_UINT64;
456             break;
457         case FIELD_TYPE_INVALID:
458             field.protoType = PROTO_TYPE_UNKNOWN;
459             break;
460         default:
461             break;
462     }
463 }
464 
ParsePerCpuStatus(PerCpuStats & stats,const std::string & perCpuStats)465 bool FtraceParser::ParsePerCpuStatus(PerCpuStats& stats, const std::string& perCpuStats)
466 {
467     std::string line;
468     std::stringstream input(perCpuStats);
469 
470     int count = 0;
471     while (getline(input, line, '\n')) {
472         std::string sep = ": ";
473         size_t pos = line.rfind(sep);
474         if (pos == std::string::npos) {
475             continue;
476         }
477         std::stringstream ss(line.substr(pos + sep.size()));
478         std::string name = line.substr(0, pos);
479         if (name == "entries") {
480             ss >> stats.entries;
481             count++;
482         } else if (name == "overrun") {
483             ss >> stats.overrun;
484             count++;
485         } else if (name == "commit overrun") {
486             ss >> stats.commitOverrun;
487             count++;
488         } else if (name == "bytes") {
489             ss >> stats.bytes;
490             count++;
491         } else if (name == "oldest event ts") {
492             ss >> stats.oldestEventTs;
493             count++;
494         } else if (name == "now ts") {
495             ss >> stats.nowTs;
496             count++;
497         } else if (name == "dropped events") {
498             ss >> stats.droppedEvents;
499             count++;
500         } else if (name == "read events") {
501             ss >> stats.readEvents;
502             count++;
503         }
504     }
505     return count > 0;
506 }
507 
508 // parse kernel ring buffer page header data
ParsePageHeader()509 bool FtraceParser::ParsePageHeader()
510 {
511     // read time stamp
512     uint64_t timestamp = 0;
513     CHECK_TRUE(ReadInc(&cur_, endOfPage_, &timestamp, sizeof(timestamp)), false, "read timestamp from page failed!");
514     pageHeader_.timestamp = timestamp;
515 
516     // read data size and overwriten flags
517     uint64_t commit = 0;
518     const int commitSize = GetHeaderPageCommitSize(); // 8B on 64bit device, 4B on 32bit device
519     CHECK_TRUE(ReadInc(&cur_, endOfPage_, &commit, commitSize), false, "read commit to page header failed!");
520 
521     // refers kernel function ring_buffer_page_len:
522     pageHeader_.size = (commit & ~RB_MISSED_FLAGS);
523     pageHeader_.overwrite = (commit & RB_MISSED_EVENTS);
524 
525     pageHeader_.startpos = cur_;
526     pageHeader_.endpos = cur_ + pageHeader_.size;
527     return true;
528 }
529 
530 // parse /sys/kernel/debug/tracing/saved_tgids
531 // refers kernel function saved_tgids_show
ParseSavedTgid(const std::string & savedTgid)532 bool FtraceParser::ParseSavedTgid(const std::string& savedTgid)
533 {
534     int32_t pid = 0;
535     int32_t tgid = 0;
536     std::stringstream sin(savedTgid);
537     // kernel format code with: "%d %d\n"
538     while (sin >> pid >> tgid) {
539         tgidDict_[pid] = tgid;
540     }
541 
542     if (tgidDict_.size() == 0) {
543         PROFILER_LOG_WARN(LOG_CORE, "ParseSavedTgid: parsed tigds: %zu", tgidDict_.size());
544     }
545     return true;
546 }
547 
548 // parse /sys/kernel/debug/tracing/saved_cmdlines
549 // refers kernel function saved_cmdlines_show
ParseSavedCmdlines(const std::string & savedCmdlines)550 bool FtraceParser::ParseSavedCmdlines(const std::string& savedCmdlines)
551 {
552     bool retval = false;
553     int32_t pid;
554     std::string comm;
555     std::string line;
556     std::stringstream sin(savedCmdlines);
557     while (std::getline(sin, line)) {
558         // kernel format with: "%d %s\n"
559         auto pos = line.find(' ');
560         if (pos != std::string::npos) {
561             pid = std::stoi(line.substr(0, pos));
562             comm = line.substr(pos + 1);
563             commDict_[pid] = comm;
564             retval = true;
565         }
566     }
567 
568     if (commDict_.size() == 0) {
569         PROFILER_LOG_WARN(LOG_CORE, "ParseSavedCmdlines: parsed cmdlines: %zu", commDict_.size());
570     }
571     return retval;
572 }
573 
ParsePaddingData(const FtraceEventHeader & eventHeader)574 bool FtraceParser::ParsePaddingData(const FtraceEventHeader& eventHeader)
575 {
576     if (eventHeader.timeDelta == 0) {
577         return false;
578     }
579     uint32_t paddingLength;
580     CHECK_TRUE(ReadInc(&cur_, endOfData_, &paddingLength, sizeof(paddingLength)), false, "read padding len failed!");
581 
582     // skip padding data
583     cur_ += paddingLength;
584     return true;
585 }
586 
ParseTimeExtend(const FtraceEventHeader & eventHeader)587 bool FtraceParser::ParseTimeExtend(const FtraceEventHeader& eventHeader)
588 {
589     uint32_t deltaExt = 0;
590     CHECK_TRUE(ReadInc(&cur_, endOfData_, &deltaExt, sizeof(deltaExt)), false, "read time delta failed!");
591 
592     timestamp_ += GetTimestampIncrements(deltaExt);
593     PROFILER_LOG_INFO(LOG_CORE, "ParseTimeExtend: update ts with %u to %" PRIu64, deltaExt, timestamp_);
594     return true;
595 }
596 
ParseTimeStamp(const FtraceEventHeader & eventHeader)597 bool FtraceParser::ParseTimeStamp(const FtraceEventHeader& eventHeader)
598 {
599     uint32_t deltaExt = 0;
600     CHECK_TRUE(ReadInc(&cur_, endOfData_, &deltaExt, sizeof(deltaExt)), false, "read time delta failed!");
601 
602     // refers kernel function rb_update_write_stamp in ring_buffer.c
603     timestamp_ = eventHeader.timeDelta + GetTimestampIncrements(deltaExt);
604     PROFILER_LOG_INFO(LOG_CORE, "ParseTimeStamp: update ts with %u to %" PRIu64, deltaExt, timestamp_);
605     return true;
606 }
607 
ReadInc(uint8_t * start[],uint8_t end[],void * outData,size_t outSize)608 bool FtraceParser::ReadInc(uint8_t* start[], uint8_t end[], void* outData, size_t outSize)
609 {
610     if ((end - *start) < static_cast<ptrdiff_t>(outSize)) {
611         return false;
612     }
613     CHECK_TRUE(memcpy_s(outData, outSize, *start, outSize) == EOK, false,
614                "read %zu bytes from memory region FAILED", outSize);
615     *start += outSize;
616     return true;
617 }
618 
IsValidIndex(int idx)619 bool FtraceParser::IsValidIndex(int idx)
620 {
621     return idx != CommonFiledIndex::INVALID_IDX;
622 }
623 
SetDebugOn(bool value)624 void FtraceParser::SetDebugOn(bool value)
625 {
626     debugOn_ = value;
627     PROFILER_LOG_INFO(LOG_CORE, "debugOption: %s", debugOn_ ? "true" : "false");
628 }
629 FTRACE_NS_END
630