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