106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci * 1506f6ba60Sopenharmony_ci * Description: FtraceParser class define 1606f6ba60Sopenharmony_ci */ 1706f6ba60Sopenharmony_ci#ifndef FTRACE_EVENT_CONTAINER_H 1806f6ba60Sopenharmony_ci#define FTRACE_EVENT_CONTAINER_H 1906f6ba60Sopenharmony_ci#include <cinttypes> 2006f6ba60Sopenharmony_ci#include <memory> 2106f6ba60Sopenharmony_ci#include <regex> 2206f6ba60Sopenharmony_ci#include <string> 2306f6ba60Sopenharmony_ci#include <vector> 2406f6ba60Sopenharmony_ci 2506f6ba60Sopenharmony_ci#include "logging.h" 2606f6ba60Sopenharmony_ci#include "ftrace_common_type.h" 2706f6ba60Sopenharmony_ci#include "ftrace_field_parser.h" 2806f6ba60Sopenharmony_ci#include "ftrace_fs_ops.h" 2906f6ba60Sopenharmony_ci#include "printk_formats_parser.h" 3006f6ba60Sopenharmony_ci#include "sub_event_parser.h" 3106f6ba60Sopenharmony_ci 3206f6ba60Sopenharmony_ciFTRACE_NS_BEGIN 3306f6ba60Sopenharmony_ciclass FtraceParser { 3406f6ba60Sopenharmony_cipublic: 3506f6ba60Sopenharmony_ci FtraceParser(); 3606f6ba60Sopenharmony_ci ~FtraceParser(); 3706f6ba60Sopenharmony_ci 3806f6ba60Sopenharmony_ci bool Init(); 3906f6ba60Sopenharmony_ci bool SetupEvent(const std::string& type, const std::string& name); 4006f6ba60Sopenharmony_ci 4106f6ba60Sopenharmony_ci bool ParsePerCpuStatus(PerCpuStats& stats, const std::string& perCpuStats); 4206f6ba60Sopenharmony_ci 4306f6ba60Sopenharmony_ci template <typename T, typename E> bool ParsePage(T& ftraceCpuDetailMsg, uint8_t page[], size_t size, E* ftraceEvent) 4406f6ba60Sopenharmony_ci { 4506f6ba60Sopenharmony_ci cur_ = page; 4606f6ba60Sopenharmony_ci page_ = page; 4706f6ba60Sopenharmony_ci endOfPage_ = page + size; 4806f6ba60Sopenharmony_ci 4906f6ba60Sopenharmony_ci CHECK_TRUE(ParsePageHeader(), false, "parse page header fail!"); 5006f6ba60Sopenharmony_ci ftraceCpuDetailMsg.set_overwrite(pageHeader_.overwrite); 5106f6ba60Sopenharmony_ci 5206f6ba60Sopenharmony_ci timestamp_ = pageHeader_.timestamp; 5306f6ba60Sopenharmony_ci endOfData_ = pageHeader_.endpos; 5406f6ba60Sopenharmony_ci while (cur_ < pageHeader_.endpos) { 5506f6ba60Sopenharmony_ci FtraceEventHeader eventHeader = {}; 5606f6ba60Sopenharmony_ci CHECK_TRUE(ReadInc(&cur_, endOfData_, &eventHeader, sizeof(FtraceEventHeader)), false, 5706f6ba60Sopenharmony_ci "read EventHeader fail!"); 5806f6ba60Sopenharmony_ci 5906f6ba60Sopenharmony_ci timestamp_ += eventHeader.timeDelta; 6006f6ba60Sopenharmony_ci 6106f6ba60Sopenharmony_ci bool retval = false; 6206f6ba60Sopenharmony_ci switch (eventHeader.typeLen) { 6306f6ba60Sopenharmony_ci case BUFFER_TYPE_PADDING: 6406f6ba60Sopenharmony_ci retval = ParsePaddingData(eventHeader); 6506f6ba60Sopenharmony_ci CHECK_TRUE(retval, false, "parse PADDING data failed!"); 6606f6ba60Sopenharmony_ci break; 6706f6ba60Sopenharmony_ci case BUFFER_TYPE_TIME_EXTEND: 6806f6ba60Sopenharmony_ci retval = ParseTimeExtend(eventHeader); 6906f6ba60Sopenharmony_ci CHECK_TRUE(retval, false, "parse TIME_EXTEND failed!"); 7006f6ba60Sopenharmony_ci break; 7106f6ba60Sopenharmony_ci case BUFFER_TYPE_TIME_STAMP: 7206f6ba60Sopenharmony_ci retval = ParseTimeStamp(eventHeader); 7306f6ba60Sopenharmony_ci CHECK_TRUE(retval, false, "parse TIME_STAMP failed!"); 7406f6ba60Sopenharmony_ci break; 7506f6ba60Sopenharmony_ci default: 7606f6ba60Sopenharmony_ci retval = ParseDataRecord(eventHeader, ftraceCpuDetailMsg, ftraceEvent); 7706f6ba60Sopenharmony_ci CHECK_TRUE(retval, false, "parse record data failed!"); 7806f6ba60Sopenharmony_ci break; 7906f6ba60Sopenharmony_ci } 8006f6ba60Sopenharmony_ci } 8106f6ba60Sopenharmony_ci return true; 8206f6ba60Sopenharmony_ci } 8306f6ba60Sopenharmony_ci 8406f6ba60Sopenharmony_ci bool ParseSavedTgid(const std::string& savedTgid); 8506f6ba60Sopenharmony_ci bool ParseSavedCmdlines(const std::string& savedCmdlines); 8606f6ba60Sopenharmony_ci 8706f6ba60Sopenharmony_ci void SetDebugOn(bool value); 8806f6ba60Sopenharmony_ci 8906f6ba60Sopenharmony_ci template <typename T, typename P> bool HmParseFtraceEvent(T& ftraceEvent, uint8_t data[], 9006f6ba60Sopenharmony_ci size_t dataSize, P& parseEventCtx) 9106f6ba60Sopenharmony_ci { 9206f6ba60Sopenharmony_ci return ParseFtraceEvent(ftraceEvent, data, dataSize, parseEventCtx); 9306f6ba60Sopenharmony_ci } 9406f6ba60Sopenharmony_ci 9506f6ba60Sopenharmony_ciprivate: 9606f6ba60Sopenharmony_ci int GetHeaderPageCommitSize(void); 9706f6ba60Sopenharmony_ci bool ParseHeaderPageFormat(const std::string& formatDesc); 9806f6ba60Sopenharmony_ci bool ParseEventFormat(const std::string& formatDesc, EventFormat& format); 9906f6ba60Sopenharmony_ci bool ParseFieldFormat(const std::string& fieldLine, EventFormat& format); 10006f6ba60Sopenharmony_ci bool ParseFieldType(const std::string& type, FieldFormat& field); 10106f6ba60Sopenharmony_ci static void ParseProtoType(FieldFormat& field); 10206f6ba60Sopenharmony_ci 10306f6ba60Sopenharmony_ci bool ParsePageHeader(); 10406f6ba60Sopenharmony_ci 10506f6ba60Sopenharmony_ci // parse different page types 10606f6ba60Sopenharmony_ci bool ParsePaddingData(const FtraceEventHeader& eventHeader); 10706f6ba60Sopenharmony_ci bool ParseTimeExtend(const FtraceEventHeader& eventHeader); 10806f6ba60Sopenharmony_ci bool ParseTimeStamp(const FtraceEventHeader& eventHeader); 10906f6ba60Sopenharmony_ci 11006f6ba60Sopenharmony_ci template <typename T, typename E> 11106f6ba60Sopenharmony_ci bool ParseDataRecord(const FtraceEventHeader& eventHeader, T& ftraceCpuDetailMsg, E* event) 11206f6ba60Sopenharmony_ci { 11306f6ba60Sopenharmony_ci uint32_t evtSize = 0; 11406f6ba60Sopenharmony_ci // refers comments of kernel function rb_event_data_length: 11506f6ba60Sopenharmony_ci if (eventHeader.typeLen) { 11606f6ba60Sopenharmony_ci evtSize = sizeof(eventHeader.array[0]) * eventHeader.typeLen; 11706f6ba60Sopenharmony_ci } else { 11806f6ba60Sopenharmony_ci CHECK_TRUE(ReadInc(&cur_, endOfData_, &evtSize, sizeof(evtSize)), false, "read event size failed!"); 11906f6ba60Sopenharmony_ci if (evtSize < sizeof(uint32_t)) { 12006f6ba60Sopenharmony_ci return false; 12106f6ba60Sopenharmony_ci } 12206f6ba60Sopenharmony_ci evtSize -= sizeof(uint32_t); // array[0] is length, array[1...array[0]] is event data 12306f6ba60Sopenharmony_ci } 12406f6ba60Sopenharmony_ci 12506f6ba60Sopenharmony_ci uint8_t* evStart = cur_; 12606f6ba60Sopenharmony_ci uint8_t* evEnd = cur_ + evtSize; 12706f6ba60Sopenharmony_ci uint16_t evId = 0; 12806f6ba60Sopenharmony_ci CHECK_TRUE(ReadInc(&cur_, evEnd, &evId, sizeof(evId)), false, "read event ID failed!"); 12906f6ba60Sopenharmony_ci 13006f6ba60Sopenharmony_ci uint32_t eventId = evId; 13106f6ba60Sopenharmony_ci auto* parseEventCtx = SubEventParser<E>::GetInstance().GetParseEventCtx(eventId); 13206f6ba60Sopenharmony_ci if (parseEventCtx != nullptr) { 13306f6ba60Sopenharmony_ci auto* ftraceEvent = ftraceCpuDetailMsg.add_event(); 13406f6ba60Sopenharmony_ci ftraceEvent->set_timestamp(timestamp_); 13506f6ba60Sopenharmony_ci ParseFtraceEvent(*ftraceEvent, evStart, evtSize, parseEventCtx); 13606f6ba60Sopenharmony_ci } 13706f6ba60Sopenharmony_ci 13806f6ba60Sopenharmony_ci cur_ = evEnd; 13906f6ba60Sopenharmony_ci return true; 14006f6ba60Sopenharmony_ci } 14106f6ba60Sopenharmony_ci 14206f6ba60Sopenharmony_ci template <typename T, typename P> // P: SubEventParser<FtraceEvent>::ParseEventCtx 14306f6ba60Sopenharmony_ci bool ParseFtraceEvent(T& ftraceEvent, uint8_t data[], size_t dataSize, P& parseEventCtx) 14406f6ba60Sopenharmony_ci { 14506f6ba60Sopenharmony_ci CHECK_TRUE( 14606f6ba60Sopenharmony_ci dataSize >= parseEventCtx->format.eventSize, false, 14706f6ba60Sopenharmony_ci "FtraceParser::ParseFtraceEvent, dataSize not enough! event name is %s,eventSize is %u, dataSize is %zd", 14806f6ba60Sopenharmony_ci parseEventCtx->format.eventName.c_str(), parseEventCtx->format.eventSize, dataSize); 14906f6ba60Sopenharmony_ci 15006f6ba60Sopenharmony_ci int pid = 0; 15106f6ba60Sopenharmony_ci CHECK_TRUE(ParseFtraceCommonFields(ftraceEvent, data, dataSize, parseEventCtx->format, pid), 15206f6ba60Sopenharmony_ci false, "parse common fields failed!"); 15306f6ba60Sopenharmony_ci if (pid != 0) { 15406f6ba60Sopenharmony_ci int tgid = 0; 15506f6ba60Sopenharmony_ci if (auto it = tgidDict_.find(pid); it != tgidDict_.end()) { 15606f6ba60Sopenharmony_ci tgid = it->second; 15706f6ba60Sopenharmony_ci ftraceEvent.set_tgid(tgid); 15806f6ba60Sopenharmony_ci } else { 15906f6ba60Sopenharmony_ci ParseSavedTgid(FtraceFsOps::GetInstance().GetSavedTgids()); 16006f6ba60Sopenharmony_ci if (auto itm = tgidDict_.find(pid); itm != tgidDict_.end()) { 16106f6ba60Sopenharmony_ci tgid = itm->second; 16206f6ba60Sopenharmony_ci ftraceEvent.set_tgid(tgid); 16306f6ba60Sopenharmony_ci } 16406f6ba60Sopenharmony_ci } 16506f6ba60Sopenharmony_ci 16606f6ba60Sopenharmony_ci std::string comm; 16706f6ba60Sopenharmony_ci if (auto it = commDict_.find(pid); it != commDict_.end()) { 16806f6ba60Sopenharmony_ci comm = it->second; 16906f6ba60Sopenharmony_ci } else { 17006f6ba60Sopenharmony_ci if (tgid != 0) { 17106f6ba60Sopenharmony_ci comm = FtraceFsOps::GetInstance().GetThreadComm(tgid, pid); 17206f6ba60Sopenharmony_ci } else { 17306f6ba60Sopenharmony_ci comm = FtraceFsOps::GetInstance().GetProcessComm(pid); 17406f6ba60Sopenharmony_ci } 17506f6ba60Sopenharmony_ci if (comm.size() > 0) { 17606f6ba60Sopenharmony_ci comm.pop_back(); // /proc/xxx/comm end with `\n` 17706f6ba60Sopenharmony_ci commDict_.insert(std::pair<int32_t, std::string>(pid, comm)); 17806f6ba60Sopenharmony_ci } 17906f6ba60Sopenharmony_ci } 18006f6ba60Sopenharmony_ci if (comm.size() > 0) { 18106f6ba60Sopenharmony_ci ftraceEvent.set_comm(comm); 18206f6ba60Sopenharmony_ci } 18306f6ba60Sopenharmony_ci } 18406f6ba60Sopenharmony_ci 18506f6ba60Sopenharmony_ci SubEventParser<T>::GetInstance().ParseEvent(ftraceEvent, data, dataSize, parseEventCtx); 18606f6ba60Sopenharmony_ci return true; 18706f6ba60Sopenharmony_ci } 18806f6ba60Sopenharmony_ci 18906f6ba60Sopenharmony_ci template <typename T> 19006f6ba60Sopenharmony_ci bool ParseFtraceCommonFields(T& ftraceEvent, uint8_t data[], size_t dataSize, const EventFormat& format, int& pid) 19106f6ba60Sopenharmony_ci { 19206f6ba60Sopenharmony_ci auto& index = format.commonIndex; 19306f6ba60Sopenharmony_ci 19406f6ba60Sopenharmony_ci CHECK_TRUE(IsValidIndex(index.pid), false, "pid index %d invalid!", index.pid); 19506f6ba60Sopenharmony_ci CHECK_TRUE(IsValidIndex(index.type), false, "type index %d invalid!", index.type); 19606f6ba60Sopenharmony_ci CHECK_TRUE(IsValidIndex(index.flags), false, "flags index %d invalid!", index.flags); 19706f6ba60Sopenharmony_ci CHECK_TRUE(IsValidIndex(index.preemt), false, "preemt index %d invalid!", index.preemt); 19806f6ba60Sopenharmony_ci 19906f6ba60Sopenharmony_ci auto& fields = format.commonFields; 20006f6ba60Sopenharmony_ci auto commonFields = ftraceEvent.mutable_common_fields(); 20106f6ba60Sopenharmony_ci pid = FtraceFieldParser::ParseIntField<int32_t>(fields, index.pid, data, dataSize); 20206f6ba60Sopenharmony_ci commonFields->set_pid(pid); 20306f6ba60Sopenharmony_ci commonFields->set_type(FtraceFieldParser::ParseIntField<uint32_t>(fields, index.type, data, dataSize)); 20406f6ba60Sopenharmony_ci commonFields->set_flags(FtraceFieldParser::ParseIntField<uint32_t>(fields, index.flags, data, dataSize)); 20506f6ba60Sopenharmony_ci commonFields->set_preempt_count(FtraceFieldParser::ParseIntField<uint32_t>(fields, index.preemt, 20606f6ba60Sopenharmony_ci data, dataSize)); 20706f6ba60Sopenharmony_ci return true; 20806f6ba60Sopenharmony_ci } 20906f6ba60Sopenharmony_ci 21006f6ba60Sopenharmony_ci bool ReadInc(uint8_t* start[], uint8_t end[], void* outData, size_t outSize); 21106f6ba60Sopenharmony_ci bool IsValidIndex(int idx); 21206f6ba60Sopenharmony_ci 21306f6ba60Sopenharmony_ciprivate: 21406f6ba60Sopenharmony_ci DISALLOW_COPY_AND_MOVE(FtraceParser); 21506f6ba60Sopenharmony_ci bool debugOn_ = false; 21606f6ba60Sopenharmony_ci std::regex fixedCharArrayRegex_; 21706f6ba60Sopenharmony_ci std::regex flexDataLocArrayRegex_; 21806f6ba60Sopenharmony_ci PageHeaderFormat pageHeaderFormat_ = {}; 21906f6ba60Sopenharmony_ci std::string savedTgidPath_ = ""; 22006f6ba60Sopenharmony_ci std::string savedCmdlines_ = ""; 22106f6ba60Sopenharmony_ci 22206f6ba60Sopenharmony_ci uint8_t* cur_ = nullptr; 22306f6ba60Sopenharmony_ci uint8_t* page_ = nullptr; // page start 22406f6ba60Sopenharmony_ci uint8_t* endOfData_ = nullptr; // end of event data 22506f6ba60Sopenharmony_ci uint8_t* endOfPage_ = nullptr; // end of full page 22606f6ba60Sopenharmony_ci uint64_t timestamp_ = 0; 22706f6ba60Sopenharmony_ci PageHeader pageHeader_ = {}; 22806f6ba60Sopenharmony_ci 22906f6ba60Sopenharmony_ci std::unordered_map<int32_t, int32_t> tgidDict_ = {}; 23006f6ba60Sopenharmony_ci std::unordered_map<int32_t, std::string> commDict_ = {}; 23106f6ba60Sopenharmony_ci}; 23206f6ba60Sopenharmony_ciFTRACE_NS_END 23306f6ba60Sopenharmony_ci#endif 234