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_, ×tamp, 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