148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci#define HILOG_TAG "PerfRecord"
1648f512ceSopenharmony_ci
1748f512ceSopenharmony_ci#include "perf_event_record.h"
1848f512ceSopenharmony_ci#include "spe_decoder.h"
1948f512ceSopenharmony_ci#include <cinttypes>
2048f512ceSopenharmony_ci
2148f512ceSopenharmony_ci#include "utilities.h"
2248f512ceSopenharmony_ci
2348f512ceSopenharmony_ciusing namespace OHOS::HiviewDFX;
2448f512ceSopenharmony_ciusing namespace std;
2548f512ceSopenharmony_cinamespace OHOS {
2648f512ceSopenharmony_cinamespace Developtools {
2748f512ceSopenharmony_cinamespace HiPerf {
2848f512ceSopenharmony_ci
2948f512ceSopenharmony_civoid *g_sampleMemCache = nullptr; // for read record from buf thread
3048f512ceSopenharmony_civoid *g_sampleMemCacheMain = nullptr; // for main thread:collecttionsymbol
3148f512ceSopenharmony_ciconstexpr size_t SAMPLE_CACHE_SIZE = 4 * 1024;
3248f512ceSopenharmony_ci
3348f512ceSopenharmony_cistd::unique_ptr<PerfEventRecord> GetPerfEventRecord(const int type, uint8_t *p,
3448f512ceSopenharmony_ci                                                    const perf_event_attr &attr)
3548f512ceSopenharmony_ci{
3648f512ceSopenharmony_ci    HLOG_ASSERT(p);
3748f512ceSopenharmony_ci    uint8_t *data = p;
3848f512ceSopenharmony_ci
3948f512ceSopenharmony_ci    // check kernel
4048f512ceSopenharmony_ci    switch (type) {
4148f512ceSopenharmony_ci        case PERF_RECORD_SAMPLE:
4248f512ceSopenharmony_ci            return std::make_unique<PerfRecordSample>(data, attr);
4348f512ceSopenharmony_ci        case PERF_RECORD_MMAP:
4448f512ceSopenharmony_ci            return std::make_unique<PerfRecordMmap>(data);
4548f512ceSopenharmony_ci        case PERF_RECORD_MMAP2:
4648f512ceSopenharmony_ci            return std::make_unique<PerfRecordMmap2>(data);
4748f512ceSopenharmony_ci        case PERF_RECORD_LOST:
4848f512ceSopenharmony_ci            return std::make_unique<PerfRecordLost>(data);
4948f512ceSopenharmony_ci        case PERF_RECORD_COMM:
5048f512ceSopenharmony_ci            return std::make_unique<PerfRecordComm>(data);
5148f512ceSopenharmony_ci        case PERF_RECORD_EXIT:
5248f512ceSopenharmony_ci            return std::make_unique<PerfRecordExit>(data);
5348f512ceSopenharmony_ci        case PERF_RECORD_THROTTLE:
5448f512ceSopenharmony_ci            return std::make_unique<PerfRecordThrottle>(data);
5548f512ceSopenharmony_ci        case PERF_RECORD_UNTHROTTLE:
5648f512ceSopenharmony_ci            return std::make_unique<PerfRecordUnthrottle>(data);
5748f512ceSopenharmony_ci        case PERF_RECORD_FORK:
5848f512ceSopenharmony_ci            return std::make_unique<PerfRecordFork>(data);
5948f512ceSopenharmony_ci        case PERF_RECORD_READ:
6048f512ceSopenharmony_ci            return std::make_unique<PerfRecordRead>(data);
6148f512ceSopenharmony_ci        case PERF_RECORD_AUX:
6248f512ceSopenharmony_ci            return std::make_unique<PerfRecordAux>(data);
6348f512ceSopenharmony_ci        case PERF_RECORD_AUXTRACE:
6448f512ceSopenharmony_ci            return std::make_unique<PerfRecordAuxtrace>(data);
6548f512ceSopenharmony_ci        case PERF_RECORD_ITRACE_START:
6648f512ceSopenharmony_ci            return std::make_unique<PerfRecordItraceStart>(data);
6748f512ceSopenharmony_ci        case PERF_RECORD_LOST_SAMPLES:
6848f512ceSopenharmony_ci            return std::make_unique<PerfRecordLostSamples>(data);
6948f512ceSopenharmony_ci        case PERF_RECORD_SWITCH:
7048f512ceSopenharmony_ci            return std::make_unique<PerfRecordSwitch>(data);
7148f512ceSopenharmony_ci        case PERF_RECORD_SWITCH_CPU_WIDE:
7248f512ceSopenharmony_ci            return std::make_unique<PerfRecordSwitchCpuWide>(data);
7348f512ceSopenharmony_ci        default:
7448f512ceSopenharmony_ci            HLOGE("unknown record type %d\n", type);
7548f512ceSopenharmony_ci            return nullptr;
7648f512ceSopenharmony_ci    }
7748f512ceSopenharmony_ci}
7848f512ceSopenharmony_ci
7948f512ceSopenharmony_cistd::unique_ptr<PerfEventRecord> GetPerfSampleFromCache(const int type, uint8_t *p,
8048f512ceSopenharmony_ci                                                        const perf_event_attr &attr)
8148f512ceSopenharmony_ci{
8248f512ceSopenharmony_ci    HLOG_ASSERT(p);
8348f512ceSopenharmony_ci    uint8_t *data = p;
8448f512ceSopenharmony_ci
8548f512ceSopenharmony_ci    if (type == PERF_RECORD_SAMPLE) {
8648f512ceSopenharmony_ci        if (g_sampleMemCache != nullptr) {
8748f512ceSopenharmony_ci            memset_s(g_sampleMemCache, SAMPLE_CACHE_SIZE, 0, SAMPLE_CACHE_SIZE);
8848f512ceSopenharmony_ci            return std::unique_ptr<PerfEventRecord>(new (g_sampleMemCache) PerfRecordSample(data, attr));
8948f512ceSopenharmony_ci        } else {
9048f512ceSopenharmony_ci            g_sampleMemCache = std::malloc(SAMPLE_CACHE_SIZE);
9148f512ceSopenharmony_ci            memset_s(g_sampleMemCache, SAMPLE_CACHE_SIZE, 0, SAMPLE_CACHE_SIZE);
9248f512ceSopenharmony_ci            return std::unique_ptr<PerfEventRecord>(new (g_sampleMemCache) PerfRecordSample(data, attr));
9348f512ceSopenharmony_ci        }
9448f512ceSopenharmony_ci    }
9548f512ceSopenharmony_ci    return GetPerfEventRecord(type, p, attr);
9648f512ceSopenharmony_ci}
9748f512ceSopenharmony_ci
9848f512ceSopenharmony_cistd::unique_ptr<PerfEventRecord> GetPerfSampleFromCacheMain(const int type, uint8_t *p,
9948f512ceSopenharmony_ci                                                            const perf_event_attr &attr)
10048f512ceSopenharmony_ci{
10148f512ceSopenharmony_ci    HLOG_ASSERT(p);
10248f512ceSopenharmony_ci    uint8_t *data = p;
10348f512ceSopenharmony_ci
10448f512ceSopenharmony_ci    if (type == PERF_RECORD_SAMPLE) {
10548f512ceSopenharmony_ci        if (g_sampleMemCacheMain != nullptr) {
10648f512ceSopenharmony_ci            memset_s(g_sampleMemCacheMain, SAMPLE_CACHE_SIZE, 0, SAMPLE_CACHE_SIZE);
10748f512ceSopenharmony_ci            return std::unique_ptr<PerfEventRecord>(new (g_sampleMemCacheMain) PerfRecordSample(data, attr));
10848f512ceSopenharmony_ci        } else {
10948f512ceSopenharmony_ci            g_sampleMemCacheMain = std::malloc(SAMPLE_CACHE_SIZE);
11048f512ceSopenharmony_ci            memset_s(g_sampleMemCacheMain, SAMPLE_CACHE_SIZE, 0, SAMPLE_CACHE_SIZE);
11148f512ceSopenharmony_ci            return std::unique_ptr<PerfEventRecord>(new (g_sampleMemCacheMain) PerfRecordSample(data, attr));
11248f512ceSopenharmony_ci        }
11348f512ceSopenharmony_ci    }
11448f512ceSopenharmony_ci    return GetPerfEventRecord(type, p, attr);
11548f512ceSopenharmony_ci}
11648f512ceSopenharmony_ci
11748f512ceSopenharmony_citemplate<typename T>
11848f512ceSopenharmony_ciinline void PushToBinary(bool condition, uint8_t *&p, const T &v)
11948f512ceSopenharmony_ci{
12048f512ceSopenharmony_ci    if (condition) {
12148f512ceSopenharmony_ci        *(reinterpret_cast<T *>(p)) = v;
12248f512ceSopenharmony_ci        p += sizeof(T);
12348f512ceSopenharmony_ci    }
12448f512ceSopenharmony_ci}
12548f512ceSopenharmony_ci
12648f512ceSopenharmony_citemplate<typename T1, typename T2>
12748f512ceSopenharmony_ciinline void PushToBinary2(bool condition, uint8_t *&p, const T1 &v1, const T2 &v2)
12848f512ceSopenharmony_ci{
12948f512ceSopenharmony_ci    if (condition) {
13048f512ceSopenharmony_ci        *(reinterpret_cast<T1 *>(p)) = v1;
13148f512ceSopenharmony_ci        p += sizeof(T1);
13248f512ceSopenharmony_ci        *(reinterpret_cast<T2 *>(p)) = v2;
13348f512ceSopenharmony_ci        p += sizeof(T2);
13448f512ceSopenharmony_ci    }
13548f512ceSopenharmony_ci}
13648f512ceSopenharmony_ci
13748f512ceSopenharmony_citemplate<typename T>
13848f512ceSopenharmony_ciinline void PopFromBinary(bool condition, uint8_t *&p, T &v)
13948f512ceSopenharmony_ci{
14048f512ceSopenharmony_ci    if (condition) {
14148f512ceSopenharmony_ci        v = *(reinterpret_cast<const T *>(p));
14248f512ceSopenharmony_ci        p += sizeof(T);
14348f512ceSopenharmony_ci    }
14448f512ceSopenharmony_ci}
14548f512ceSopenharmony_ci
14648f512ceSopenharmony_citemplate<typename T1, typename T2>
14748f512ceSopenharmony_ciinline void PopFromBinary2(bool condition, uint8_t *&p, T1 &v1, T2 &v2)
14848f512ceSopenharmony_ci{
14948f512ceSopenharmony_ci    if (condition) {
15048f512ceSopenharmony_ci        v1 = *(reinterpret_cast<const T1 *>(p));
15148f512ceSopenharmony_ci        p += sizeof(T1);
15248f512ceSopenharmony_ci        v2 = *(reinterpret_cast<const T2 *>(p));
15348f512ceSopenharmony_ci        p += sizeof(T2);
15448f512ceSopenharmony_ci    }
15548f512ceSopenharmony_ci}
15648f512ceSopenharmony_ci
15748f512ceSopenharmony_ci// PerfEventRecord
15848f512ceSopenharmony_ciPerfEventRecord::PerfEventRecord(perf_event_type type, bool inKernel, const std::string &name)
15948f512ceSopenharmony_ci    : name_(name)
16048f512ceSopenharmony_ci{
16148f512ceSopenharmony_ci    header.type = type;
16248f512ceSopenharmony_ci    header.misc = inKernel ? PERF_RECORD_MISC_KERNEL : PERF_RECORD_MISC_USER;
16348f512ceSopenharmony_ci    header.size = sizeof(header);
16448f512ceSopenharmony_ci}
16548f512ceSopenharmony_ci
16648f512ceSopenharmony_ciPerfEventRecord::PerfEventRecord(perf_event_hiperf_ext_type type, const std::string &name)
16748f512ceSopenharmony_ci    : name_(name)
16848f512ceSopenharmony_ci{
16948f512ceSopenharmony_ci    header.type = type;
17048f512ceSopenharmony_ci    header.misc = PERF_RECORD_MISC_USER;
17148f512ceSopenharmony_ci    header.size = sizeof(header);
17248f512ceSopenharmony_ci}
17348f512ceSopenharmony_ci
17448f512ceSopenharmony_ciPerfEventRecord::PerfEventRecord(uint8_t *p, const std::string &name) : name_(name)
17548f512ceSopenharmony_ci{
17648f512ceSopenharmony_ci    if (p == nullptr) {
17748f512ceSopenharmony_ci        header.type = PERF_RECORD_MMAP;
17848f512ceSopenharmony_ci        header.misc = PERF_RECORD_MISC_USER;
17948f512ceSopenharmony_ci        header.size = 0;
18048f512ceSopenharmony_ci        return;
18148f512ceSopenharmony_ci    }
18248f512ceSopenharmony_ci    header = *(reinterpret_cast<perf_event_header *>(p));
18348f512ceSopenharmony_ci}
18448f512ceSopenharmony_ci
18548f512ceSopenharmony_civoid PerfEventRecord::GetHeaderBinary(std::vector<uint8_t> &buf) const
18648f512ceSopenharmony_ci{
18748f512ceSopenharmony_ci    if (buf.size() < GetHeaderSize()) {
18848f512ceSopenharmony_ci        buf.resize(GetHeaderSize());
18948f512ceSopenharmony_ci    }
19048f512ceSopenharmony_ci    uint8_t *p = buf.data();
19148f512ceSopenharmony_ci    *(reinterpret_cast<perf_event_header *>(p)) = header;
19248f512ceSopenharmony_ci}
19348f512ceSopenharmony_ci
19448f512ceSopenharmony_civoid PerfEventRecord::Dump(int indent, std::string outputFilename, FILE *outputDump) const
19548f512ceSopenharmony_ci{
19648f512ceSopenharmony_ci    if (outputDump != nullptr) {
19748f512ceSopenharmony_ci        g_outputDump = outputDump;
19848f512ceSopenharmony_ci    } else if (!outputFilename.empty() && g_outputDump == nullptr) {
19948f512ceSopenharmony_ci        std::string resolvedPath = CanonicalizeSpecPath(outputFilename.c_str());
20048f512ceSopenharmony_ci        g_outputDump = fopen(resolvedPath.c_str(), "w");
20148f512ceSopenharmony_ci        if (g_outputDump == nullptr) {
20248f512ceSopenharmony_ci            printf("unable open file to '%s' because '%d'\n", outputFilename.c_str(), errno);
20348f512ceSopenharmony_ci            return;
20448f512ceSopenharmony_ci        }
20548f512ceSopenharmony_ci    }
20648f512ceSopenharmony_ci    PRINT_INDENT(indent, "\n");
20748f512ceSopenharmony_ci    PRINT_INDENT(indent, "record %s: type %u, misc %u, size %zu\n", GetName().c_str(), GetType(),
20848f512ceSopenharmony_ci                 GetMisc(), GetSize());
20948f512ceSopenharmony_ci    DumpData(indent + 1);
21048f512ceSopenharmony_ci}
21148f512ceSopenharmony_ci
21248f512ceSopenharmony_civoid PerfEventRecord::DumpLog(const std::string &prefix) const
21348f512ceSopenharmony_ci{
21448f512ceSopenharmony_ci    HLOGV("%s: record %s: type %u, misc %u, size %zu\n", prefix.c_str(), GetName().c_str(),
21548f512ceSopenharmony_ci          GetType(), GetMisc(), GetSize());
21648f512ceSopenharmony_ci}
21748f512ceSopenharmony_ci
21848f512ceSopenharmony_cistd::vector<u64> PerfRecordSample::ips_ = {};
21948f512ceSopenharmony_cistd::vector<DfxFrame> PerfRecordSample::callFrames_ = {};
22048f512ceSopenharmony_cistd::vector<pid_t> PerfRecordSample::serverPidMap_ = {};
22148f512ceSopenharmony_ci
22248f512ceSopenharmony_ciPerfRecordAuxtrace::PerfRecordAuxtrace(uint8_t *p) : PerfEventRecord(p, "auxtrace")
22348f512ceSopenharmony_ci{
22448f512ceSopenharmony_ci    if (header.size >= sizeof(header)) {
22548f512ceSopenharmony_ci        size_t copySize = header.size - sizeof(header);
22648f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
22748f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
22848f512ceSopenharmony_ci        }
22948f512ceSopenharmony_ci    } else {
23048f512ceSopenharmony_ci        HLOGE("PerfRecordAuxtrace retren failed !!!");
23148f512ceSopenharmony_ci    }
23248f512ceSopenharmony_ci    rawData_ = p + header.size;
23348f512ceSopenharmony_ci}
23448f512ceSopenharmony_ci
23548f512ceSopenharmony_ciPerfRecordAuxtrace::PerfRecordAuxtrace(u64 size, u64 offset, u64 reference, u32 idx, u32 tid, u32 cpu, u32 pid)
23648f512ceSopenharmony_ci    : PerfEventRecord(PERF_RECORD_AUXTRACE, "auxtrace")
23748f512ceSopenharmony_ci{
23848f512ceSopenharmony_ci    data_.size = size;
23948f512ceSopenharmony_ci    data_.offset = offset;
24048f512ceSopenharmony_ci    data_.reference = reference;
24148f512ceSopenharmony_ci    data_.idx = idx;
24248f512ceSopenharmony_ci    data_.tid = tid;
24348f512ceSopenharmony_ci    data_.cpu = cpu;
24448f512ceSopenharmony_ci    data_.reserved__ = pid;
24548f512ceSopenharmony_ci
24648f512ceSopenharmony_ci    header.size = sizeof(header) + sizeof(data_);
24748f512ceSopenharmony_ci}
24848f512ceSopenharmony_ci
24948f512ceSopenharmony_cibool PerfRecordAuxtrace::GetBinary1(std::vector<uint8_t> &buf) const
25048f512ceSopenharmony_ci{
25148f512ceSopenharmony_ci    if (buf.size() < header.size) {
25248f512ceSopenharmony_ci        buf.resize(header.size);
25348f512ceSopenharmony_ci    }
25448f512ceSopenharmony_ci
25548f512ceSopenharmony_ci    GetHeaderBinary(buf);
25648f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
25748f512ceSopenharmony_ci
25848f512ceSopenharmony_ci    size_t copySize = header.size - GetHeaderSize();
25948f512ceSopenharmony_ci    if (memcpy_s(p, sizeof(data_), reinterpret_cast<const uint8_t *>(&data_), copySize) != 0) {
26048f512ceSopenharmony_ci        HLOGE("memcpy_s return failed");
26148f512ceSopenharmony_ci        return false;
26248f512ceSopenharmony_ci    }
26348f512ceSopenharmony_ci    return true;
26448f512ceSopenharmony_ci}
26548f512ceSopenharmony_ci
26648f512ceSopenharmony_cibool PerfRecordAuxtrace::GetBinary(std::vector<uint8_t> &buf) const
26748f512ceSopenharmony_ci{
26848f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
26948f512ceSopenharmony_ci        buf.resize(GetSize());
27048f512ceSopenharmony_ci    }
27148f512ceSopenharmony_ci
27248f512ceSopenharmony_ci    GetHeaderBinary(buf);
27348f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
27448f512ceSopenharmony_ci
27548f512ceSopenharmony_ci    size_t copySize = header.size - GetHeaderSize();
27648f512ceSopenharmony_ci    if (memcpy_s(p, sizeof(data_), reinterpret_cast<const uint8_t *>(&data_), copySize) != 0) {
27748f512ceSopenharmony_ci        HLOGE("memcpy_s return failed");
27848f512ceSopenharmony_ci        return false;
27948f512ceSopenharmony_ci    }
28048f512ceSopenharmony_ci    p += header.size - GetHeaderSize();
28148f512ceSopenharmony_ci    if (memcpy_s(p, data_.size, static_cast<uint8_t *>(rawData_), data_.size) != 0) {
28248f512ceSopenharmony_ci        HLOGE("memcpy_s return failed");
28348f512ceSopenharmony_ci        return false;
28448f512ceSopenharmony_ci    }
28548f512ceSopenharmony_ci    return true;
28648f512ceSopenharmony_ci}
28748f512ceSopenharmony_ci
28848f512ceSopenharmony_civoid PerfRecordAuxtrace::DumpData(int indent) const
28948f512ceSopenharmony_ci{
29048f512ceSopenharmony_ci    PRINT_INDENT(indent, "size 0x%llx, offset 0x%llx, reference 0x%llx, idx %u, tid %u, cpu %u, pid %u\n",
29148f512ceSopenharmony_ci                 data_.size, data_.offset, data_.reference, data_.idx, data_.tid, data_.cpu, data_.reserved__);
29248f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos
29348f512ceSopenharmony_ci    if (!SpeDumpRawData(rawData_, data_.size, indent, g_outputDump)) {
29448f512ceSopenharmony_ci        HLOGE("SpeDumpRawData failed");
29548f512ceSopenharmony_ci    }
29648f512ceSopenharmony_ci#endif
29748f512ceSopenharmony_ci}
29848f512ceSopenharmony_ci
29948f512ceSopenharmony_civoid PerfRecordAuxtrace::DumpLog(const std::string &prefix) const
30048f512ceSopenharmony_ci{
30148f512ceSopenharmony_ci    HLOGV("size %llu, offset 0x%llx, reference 0x%llx, idx %u, tid %u, cpu %u\n",
30248f512ceSopenharmony_ci          data_.size, data_.offset, data_.reference, data_.idx, data_.tid, data_.cpu);
30348f512ceSopenharmony_ci}
30448f512ceSopenharmony_ci
30548f512ceSopenharmony_cisize_t PerfRecordAuxtrace::GetSize() const
30648f512ceSopenharmony_ci{
30748f512ceSopenharmony_ci    return header.size + data_.size;
30848f512ceSopenharmony_ci}
30948f512ceSopenharmony_ci
31048f512ceSopenharmony_civoid PerfRecordSample::DumpLog(const std::string &prefix) const
31148f512ceSopenharmony_ci{
31248f512ceSopenharmony_ci    HLOGV("%s: SAMPLE: id= %llu size %d pid %u tid %u ips %llu regs %llu, stacks %llu time %llu",
31348f512ceSopenharmony_ci          prefix.c_str(), data_.sample_id, header.size, data_.pid, data_.tid, data_.nr,
31448f512ceSopenharmony_ci          data_.reg_nr, data_.dyn_size, data_.time);
31548f512ceSopenharmony_ci}
31648f512ceSopenharmony_ci
31748f512ceSopenharmony_civoid PerfRecordSample::RecoverCallStack()
31848f512ceSopenharmony_ci{
31948f512ceSopenharmony_ci    data_.ips = ips_.data();
32048f512ceSopenharmony_ci    data_.nr = ips_.size();
32148f512ceSopenharmony_ci    removeStack_ = true;
32248f512ceSopenharmony_ci}
32348f512ceSopenharmony_ci
32448f512ceSopenharmony_civoid PerfRecordSample::ReplaceWithCallStack(size_t originalSize)
32548f512ceSopenharmony_ci{
32648f512ceSopenharmony_ci    // first we check if we have some user unwind stack need to merge ?
32748f512ceSopenharmony_ci    if (callFrames_.size() != 0) {
32848f512ceSopenharmony_ci        // when we have some kernel ips , we cp it first
32948f512ceSopenharmony_ci        // new size is user call frames + kernel call frames
33048f512ceSopenharmony_ci        // + PERF_CONTEXT_USER(last + 1) + expand mark(also PERF_CONTEXT_USER)
33148f512ceSopenharmony_ci        const unsigned int perfContextSize = 2;
33248f512ceSopenharmony_ci        ips_.reserve(data_.nr + callFrames_.size() + perfContextSize);
33348f512ceSopenharmony_ci        if (data_.nr > 0) {
33448f512ceSopenharmony_ci            ips_.assign(data_.ips, data_.ips + data_.nr);
33548f512ceSopenharmony_ci        }
33648f512ceSopenharmony_ci        // add user context mark
33748f512ceSopenharmony_ci        ips_.emplace_back(PERF_CONTEXT_USER);
33848f512ceSopenharmony_ci        // we also need make a expand mark just for debug only
33948f512ceSopenharmony_ci        const size_t beginIpsSize = ips_.size();
34048f512ceSopenharmony_ci        bool ret = std::all_of(callFrames_.begin(), callFrames_.end(), [&](const DfxFrame &frame) {
34148f512ceSopenharmony_ci            ips_.emplace_back(frame.pc);
34248f512ceSopenharmony_ci            if (originalSize != 0 and (originalSize != callFrames_.size()) and
34348f512ceSopenharmony_ci                ips_.size() == (originalSize + beginIpsSize)) {
34448f512ceSopenharmony_ci                // just for debug
34548f512ceSopenharmony_ci                // so we can see which frame begin is expand call frames
34648f512ceSopenharmony_ci                ips_.emplace_back(PERF_CONTEXT_USER);
34748f512ceSopenharmony_ci            }
34848f512ceSopenharmony_ci            return true;
34948f512ceSopenharmony_ci        });
35048f512ceSopenharmony_ci        if (ret) {
35148f512ceSopenharmony_ci            HLOGV("combed %zu", callFrames_.size());
35248f512ceSopenharmony_ci        } else {
35348f512ceSopenharmony_ci            HLOGV("failed to combed %zu", callFrames_.size());
35448f512ceSopenharmony_ci        }
35548f512ceSopenharmony_ci
35648f512ceSopenharmony_ci        if (sampleType_ & PERF_SAMPLE_REGS_USER) {
35748f512ceSopenharmony_ci            header.size -= data_.reg_nr * sizeof(u64);
35848f512ceSopenharmony_ci            data_.reg_nr = 0;
35948f512ceSopenharmony_ci            data_.user_abi = 0;
36048f512ceSopenharmony_ci        }
36148f512ceSopenharmony_ci
36248f512ceSopenharmony_ci        if (sampleType_ & PERF_SAMPLE_STACK_USER) {
36348f512ceSopenharmony_ci            // 1. remove the user stack
36448f512ceSopenharmony_ci            header.size -= data_.stack_size;
36548f512ceSopenharmony_ci            header.size -= sizeof(data_.dyn_size);
36648f512ceSopenharmony_ci
36748f512ceSopenharmony_ci            // 2. clean the size
36848f512ceSopenharmony_ci            data_.stack_size = 0;
36948f512ceSopenharmony_ci            data_.dyn_size = 0;
37048f512ceSopenharmony_ci        }
37148f512ceSopenharmony_ci
37248f512ceSopenharmony_ci        if (sampleType_ & PERF_SAMPLE_CALLCHAIN) {
37348f512ceSopenharmony_ci            HLOGV("ips change from %llu -> %zu", data_.nr, ips_.size());
37448f512ceSopenharmony_ci
37548f512ceSopenharmony_ci            // 3. remove the nr size
37648f512ceSopenharmony_ci            header.size -= data_.nr * sizeof(u64);
37748f512ceSopenharmony_ci
37848f512ceSopenharmony_ci            // 4. add new nr size
37948f512ceSopenharmony_ci            data_.nr = ips_.size();
38048f512ceSopenharmony_ci            header.size += data_.nr * sizeof(u64);
38148f512ceSopenharmony_ci
38248f512ceSopenharmony_ci            // 5. change ips potin to our ips array and hold it.
38348f512ceSopenharmony_ci            data_.ips = ips_.data();
38448f512ceSopenharmony_ci        }
38548f512ceSopenharmony_ci    } else {
38648f512ceSopenharmony_ci        // nothing need change
38748f512ceSopenharmony_ci        return;
38848f512ceSopenharmony_ci    }
38948f512ceSopenharmony_ci}
39048f512ceSopenharmony_ci
39148f512ceSopenharmony_ciPerfRecordSample::PerfRecordSample(uint8_t *p, const perf_event_attr &attr)
39248f512ceSopenharmony_ci    : PerfEventRecord(p, "sample")
39348f512ceSopenharmony_ci{
39448f512ceSopenharmony_ci    if (p == nullptr) {
39548f512ceSopenharmony_ci        HLOG_ASSERT(p);
39648f512ceSopenharmony_ci        return;
39748f512ceSopenharmony_ci    }
39848f512ceSopenharmony_ci    // clear the static vector data
39948f512ceSopenharmony_ci    Clean();
40048f512ceSopenharmony_ci    sampleType_ = attr.sample_type;
40148f512ceSopenharmony_ci
40248f512ceSopenharmony_ci    uint8_t *start = p;
40348f512ceSopenharmony_ci
40448f512ceSopenharmony_ci    p += sizeof(header);
40548f512ceSopenharmony_ci
40648f512ceSopenharmony_ci    // parse record according SAMPLE_TYPE
40748f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_IDENTIFIER, p, data_.sample_id);
40848f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_IP, p, data_.ip);
40948f512ceSopenharmony_ci    PopFromBinary2(sampleType_ & PERF_SAMPLE_TID, p, data_.pid, data_.tid);
41048f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_TIME, p, data_.time);
41148f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_ADDR, p, data_.addr);
41248f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_ID, p, data_.id);
41348f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_STREAM_ID, p, data_.stream_id);
41448f512ceSopenharmony_ci    PopFromBinary2(sampleType_ & PERF_SAMPLE_CPU, p, data_.cpu, data_.res);
41548f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_PERIOD, p, data_.period);
41648f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_CALLCHAIN, p, data_.nr);
41748f512ceSopenharmony_ci    if (data_.nr > 0) {
41848f512ceSopenharmony_ci        // the pointer is from input(p), require caller keep input(p) with *this together
41948f512ceSopenharmony_ci        // think it in next time
42048f512ceSopenharmony_ci        data_.ips = reinterpret_cast<u64 *>(p);
42148f512ceSopenharmony_ci        p += data_.nr * sizeof(u64);
42248f512ceSopenharmony_ci    }
42348f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_RAW, p, data_.raw_size);
42448f512ceSopenharmony_ci    if (data_.raw_size > 0) {
42548f512ceSopenharmony_ci        data_.raw_data = p;
42648f512ceSopenharmony_ci        p += data_.raw_size * sizeof(u8);
42748f512ceSopenharmony_ci    }
42848f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_BRANCH_STACK, p, data_.bnr);
42948f512ceSopenharmony_ci    if (data_.bnr > 0) {
43048f512ceSopenharmony_ci        data_.lbr = reinterpret_cast<PerfBranchEntry *>(p);
43148f512ceSopenharmony_ci        p += data_.bnr * sizeof(PerfBranchEntry);
43248f512ceSopenharmony_ci    }
43348f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_REGS_USER, p, data_.user_abi);
43448f512ceSopenharmony_ci    if (data_.user_abi > 0) {
43548f512ceSopenharmony_ci        data_.reg_mask = attr.sample_regs_user;
43648f512ceSopenharmony_ci        data_.reg_nr = __builtin_popcountll(data_.reg_mask);
43748f512ceSopenharmony_ci        data_.user_regs = reinterpret_cast<u64 *>(p);
43848f512ceSopenharmony_ci        p += data_.reg_nr * sizeof(u64);
43948f512ceSopenharmony_ci    }
44048f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_SERVER_PID, p, data_.server_nr);
44148f512ceSopenharmony_ci    if (data_.server_nr > 0) {
44248f512ceSopenharmony_ci        data_.server_pids = reinterpret_cast<u64 *>(p);
44348f512ceSopenharmony_ci        p += data_.server_nr * sizeof(u64);
44448f512ceSopenharmony_ci    }
44548f512ceSopenharmony_ci    PopFromBinary(sampleType_ & PERF_SAMPLE_STACK_USER, p, data_.stack_size);
44648f512ceSopenharmony_ci    if (data_.stack_size > 0) {
44748f512ceSopenharmony_ci        data_.stack_data = p;
44848f512ceSopenharmony_ci        p += data_.stack_size;
44948f512ceSopenharmony_ci        PopFromBinary(true, p, data_.dyn_size);
45048f512ceSopenharmony_ci    }
45148f512ceSopenharmony_ci    uint32_t remain = header.size - (p - start);
45248f512ceSopenharmony_ci    if (data_.nr == 0 && dumpRemoveStack_ && remain == sizeof(stackId_)) {
45348f512ceSopenharmony_ci        PopFromBinary(true, p, stackId_.value);
45448f512ceSopenharmony_ci    }
45548f512ceSopenharmony_ci}
45648f512ceSopenharmony_ci
45748f512ceSopenharmony_cibool PerfRecordSample::GetBinary(std::vector<uint8_t> &buf) const
45848f512ceSopenharmony_ci{
45948f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
46048f512ceSopenharmony_ci        buf.resize(GetSize());
46148f512ceSopenharmony_ci    }
46248f512ceSopenharmony_ci
46348f512ceSopenharmony_ci    GetHeaderBinary(buf);
46448f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
46548f512ceSopenharmony_ci
46648f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_IDENTIFIER, p, data_.sample_id);
46748f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_IP, p, data_.ip);
46848f512ceSopenharmony_ci    PushToBinary2(sampleType_ & PERF_SAMPLE_TID, p, data_.pid, data_.tid);
46948f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_TIME, p, data_.time);
47048f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_ADDR, p, data_.addr);
47148f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_ID, p, data_.id);
47248f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_STREAM_ID, p, data_.stream_id);
47348f512ceSopenharmony_ci    PushToBinary2(sampleType_ & PERF_SAMPLE_CPU, p, data_.cpu, data_.res);
47448f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_PERIOD, p, data_.period);
47548f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_CALLCHAIN, p, data_.nr);
47648f512ceSopenharmony_ci    if (data_.nr > 0 && !removeStack_) {
47748f512ceSopenharmony_ci        std::copy(data_.ips + skipKernel_, data_.ips + data_.nr + skipKernel_,
47848f512ceSopenharmony_ci                  reinterpret_cast<u64 *>(p));
47948f512ceSopenharmony_ci        p += data_.nr * sizeof(u64);
48048f512ceSopenharmony_ci    }
48148f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_RAW, p, data_.raw_size);
48248f512ceSopenharmony_ci    if (data_.raw_size > 0) {
48348f512ceSopenharmony_ci        std::copy(data_.raw_data, data_.raw_data + data_.raw_size, p);
48448f512ceSopenharmony_ci        p += data_.raw_size * sizeof(u8);
48548f512ceSopenharmony_ci    }
48648f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_BRANCH_STACK, p, data_.bnr);
48748f512ceSopenharmony_ci    if (data_.bnr > 0) {
48848f512ceSopenharmony_ci        std::copy(data_.lbr, data_.lbr + data_.bnr, reinterpret_cast<PerfBranchEntry *>(p));
48948f512ceSopenharmony_ci        p += data_.bnr * sizeof(PerfBranchEntry);
49048f512ceSopenharmony_ci    }
49148f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_REGS_USER, p, data_.user_abi);
49248f512ceSopenharmony_ci    if (data_.user_abi > 0 && data_.reg_nr > 0) {
49348f512ceSopenharmony_ci        std::copy(data_.user_regs, data_.user_regs + data_.reg_nr, reinterpret_cast<u64 *>(p));
49448f512ceSopenharmony_ci        p += data_.reg_nr * sizeof(u64);
49548f512ceSopenharmony_ci    }
49648f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_SERVER_PID, p, data_.server_nr);
49748f512ceSopenharmony_ci    if (data_.server_nr > 0) {
49848f512ceSopenharmony_ci        std::copy(data_.server_pids + skipPid_, data_.server_pids + data_.server_nr + skipPid_,
49948f512ceSopenharmony_ci                  reinterpret_cast<u64 *>(p));
50048f512ceSopenharmony_ci        p += data_.server_nr * sizeof(u64);
50148f512ceSopenharmony_ci    }
50248f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_STACK_USER, p, data_.stack_size);
50348f512ceSopenharmony_ci    if (data_.stack_size > 0) {
50448f512ceSopenharmony_ci        std::copy(data_.stack_data, data_.stack_data + data_.stack_size, p);
50548f512ceSopenharmony_ci        p += data_.stack_size * sizeof(u8);
50648f512ceSopenharmony_ci        PushToBinary(true, p, data_.dyn_size);
50748f512ceSopenharmony_ci    }
50848f512ceSopenharmony_ci    PushToBinary(removeStack_, p, stackId_.value);
50948f512ceSopenharmony_ci    return true;
51048f512ceSopenharmony_ci}
51148f512ceSopenharmony_ci
51248f512ceSopenharmony_civoid PerfRecordSample::DumpData(int indent) const
51348f512ceSopenharmony_ci{
51448f512ceSopenharmony_ci    PRINT_INDENT(indent, "sample_type: 0x%" PRIx64 "\n", sampleType_);
51548f512ceSopenharmony_ci
51648f512ceSopenharmony_ci    // dump record according sampleType
51748f512ceSopenharmony_ci    if (sampleType_ & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) {
51848f512ceSopenharmony_ci        PRINT_INDENT(indent, "ID %" PRIu64 "\n", static_cast<uint64_t>(data_.sample_id));
51948f512ceSopenharmony_ci    }
52048f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_IP) {
52148f512ceSopenharmony_ci        PRINT_INDENT(indent, "ip %llx\n", data_.ip);
52248f512ceSopenharmony_ci    }
52348f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_TID) {
52448f512ceSopenharmony_ci        PRINT_INDENT(indent, "pid %u, tid %u\n", data_.pid, data_.tid);
52548f512ceSopenharmony_ci    }
52648f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_TIME) {
52748f512ceSopenharmony_ci        PRINT_INDENT(indent, "time %llu\n", data_.time);
52848f512ceSopenharmony_ci    }
52948f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_ADDR) {
53048f512ceSopenharmony_ci        PRINT_INDENT(indent, "addr %p\n", reinterpret_cast<void *>(data_.addr));
53148f512ceSopenharmony_ci    }
53248f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_STREAM_ID) {
53348f512ceSopenharmony_ci        PRINT_INDENT(indent, "stream_id %" PRIu64 "\n", static_cast<uint64_t>(data_.stream_id));
53448f512ceSopenharmony_ci    }
53548f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_CPU) {
53648f512ceSopenharmony_ci        PRINT_INDENT(indent, "cpu %u, res %u\n", data_.cpu, data_.res);
53748f512ceSopenharmony_ci    }
53848f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_PERIOD) {
53948f512ceSopenharmony_ci        PRINT_INDENT(indent, "period %" PRIu64 "\n", static_cast<uint64_t>(data_.period));
54048f512ceSopenharmony_ci    }
54148f512ceSopenharmony_ci    if (stackId_.section.id > 0) {
54248f512ceSopenharmony_ci        PRINT_INDENT(indent, "stackid %" PRIu64 "\n", static_cast<uint64_t>(stackId_.section.id));
54348f512ceSopenharmony_ci    }
54448f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_CALLCHAIN) {
54548f512ceSopenharmony_ci        bool userContext = false;
54648f512ceSopenharmony_ci        PRINT_INDENT(indent, "callchain nr=%lld\n", data_.nr);
54748f512ceSopenharmony_ci        for (uint64_t i = 0; i < data_.nr; ++i) {
54848f512ceSopenharmony_ci            std::string_view supplement = "";
54948f512ceSopenharmony_ci            if ((sampleType_ & PERF_SAMPLE_STACK_USER) == 0 || data_.ips[i] != PERF_CONTEXT_USER) {
55048f512ceSopenharmony_ci                PRINT_INDENT(indent + 1, "0x%llx%s\n", data_.ips[i], supplement.data());
55148f512ceSopenharmony_ci                continue;
55248f512ceSopenharmony_ci            }
55348f512ceSopenharmony_ci            // is PERF_SAMPLE_STACK_USER type and is PERF_CONTEXT_USER
55448f512ceSopenharmony_ci            if (!userContext) {
55548f512ceSopenharmony_ci                userContext = true;
55648f512ceSopenharmony_ci                supplement = " <unwind callstack>";
55748f512ceSopenharmony_ci            } else {
55848f512ceSopenharmony_ci                supplement = " <expand callstack>";
55948f512ceSopenharmony_ci            }
56048f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "0x%llx%s\n", data_.ips[i], supplement.data());
56148f512ceSopenharmony_ci        }
56248f512ceSopenharmony_ci    }
56348f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_RAW) {
56448f512ceSopenharmony_ci        PRINT_INDENT(indent, "raw size=%u\n", data_.raw_size);
56548f512ceSopenharmony_ci        const uint32_t *data = reinterpret_cast<const uint32_t *>(data_.raw_data);
56648f512ceSopenharmony_ci        size_t size = data_.raw_size / sizeof(uint32_t);
56748f512ceSopenharmony_ci        for (size_t i = 0; i < size; ++i) {
56848f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "0x%08x (%x)\n", data[i], data[i]);
56948f512ceSopenharmony_ci        }
57048f512ceSopenharmony_ci    }
57148f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_BRANCH_STACK) {
57248f512ceSopenharmony_ci        PRINT_INDENT(indent, "branch_stack nr=%lld\n", data_.bnr);
57348f512ceSopenharmony_ci        for (uint64_t i = 0; i < data_.bnr; ++i) {
57448f512ceSopenharmony_ci            auto &item = data_.lbr[i];
57548f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "from 0x%llx, to 0x%llx, flags 0x%llx\n", item.from, item.to, item.flags);
57648f512ceSopenharmony_ci        }
57748f512ceSopenharmony_ci    }
57848f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_REGS_USER) {
57948f512ceSopenharmony_ci        PRINT_INDENT(indent, "user regs: abi=%lld, reg_nr=%lld\n", data_.user_abi, data_.reg_nr);
58048f512ceSopenharmony_ci        for (uint64_t i = 0; i < data_.reg_nr; ++i) {
58148f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "0x%llx\n", data_.user_regs[i]);
58248f512ceSopenharmony_ci        }
58348f512ceSopenharmony_ci    }
58448f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_SERVER_PID) {
58548f512ceSopenharmony_ci        PRINT_INDENT(indent, "server nr=%lld\n", data_.server_nr);
58648f512ceSopenharmony_ci        for (uint64_t i = 0; i < data_.server_nr; ++i) {
58748f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "pid: %llu\n", data_.server_pids[i]);
58848f512ceSopenharmony_ci        }
58948f512ceSopenharmony_ci    }
59048f512ceSopenharmony_ci    if (sampleType_ & PERF_SAMPLE_STACK_USER) {
59148f512ceSopenharmony_ci        PRINT_INDENT(indent, "user stack: size %llu dyn_size %lld\n", data_.stack_size,
59248f512ceSopenharmony_ci                     data_.dyn_size);
59348f512ceSopenharmony_ci    }
59448f512ceSopenharmony_ci}
59548f512ceSopenharmony_ci
59648f512ceSopenharmony_ciinline pid_t PerfRecordSample::GetPid() const
59748f512ceSopenharmony_ci{
59848f512ceSopenharmony_ci    return data_.pid;
59948f512ceSopenharmony_ci}
60048f512ceSopenharmony_ci
60148f512ceSopenharmony_civoid PerfRecordSample::Clean()
60248f512ceSopenharmony_ci{
60348f512ceSopenharmony_ci    ips_.clear();
60448f512ceSopenharmony_ci    callFrames_.clear();
60548f512ceSopenharmony_ci    serverPidMap_.clear();
60648f512ceSopenharmony_ci}
60748f512ceSopenharmony_ci
60848f512ceSopenharmony_ciPerfRecordMmap::PerfRecordMmap(uint8_t *p) : PerfEventRecord(p, "mmap")
60948f512ceSopenharmony_ci{
61048f512ceSopenharmony_ci    size_t dataSize = GetSize();
61148f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
61248f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
61348f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
61448f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
61548f512ceSopenharmony_ci        }
61648f512ceSopenharmony_ci    } else {
61748f512ceSopenharmony_ci        HLOGE("PerfRecordMmap retren failed !!!");
61848f512ceSopenharmony_ci    }
61948f512ceSopenharmony_ci}
62048f512ceSopenharmony_ci
62148f512ceSopenharmony_ciPerfRecordMmap::PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff,
62248f512ceSopenharmony_ci                               const std::string &filename)
62348f512ceSopenharmony_ci    : PerfEventRecord(PERF_RECORD_MMAP, inKernel, "mmap")
62448f512ceSopenharmony_ci{
62548f512ceSopenharmony_ci    data_.pid = pid;
62648f512ceSopenharmony_ci    data_.tid = tid;
62748f512ceSopenharmony_ci    data_.addr = addr;
62848f512ceSopenharmony_ci    data_.len = len;
62948f512ceSopenharmony_ci    data_.pgoff = pgoff;
63048f512ceSopenharmony_ci    if (strncpy_s(data_.filename, KILO, filename.c_str(), filename.size()) != 0) {
63148f512ceSopenharmony_ci        HLOGE("strncpy_s failed");
63248f512ceSopenharmony_ci    }
63348f512ceSopenharmony_ci
63448f512ceSopenharmony_ci    header.size = sizeof(header) + sizeof(data_) - KILO + filename.size() + 1;
63548f512ceSopenharmony_ci}
63648f512ceSopenharmony_ci
63748f512ceSopenharmony_cibool PerfRecordMmap::GetBinary(std::vector<uint8_t> &buf) const
63848f512ceSopenharmony_ci{
63948f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
64048f512ceSopenharmony_ci        buf.resize(GetSize());
64148f512ceSopenharmony_ci    }
64248f512ceSopenharmony_ci
64348f512ceSopenharmony_ci    GetHeaderBinary(buf);
64448f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
64548f512ceSopenharmony_ci
64648f512ceSopenharmony_ci    // data_.filename[] is variable-length
64748f512ceSopenharmony_ci    std::copy(reinterpret_cast<const uint8_t *>(&data_),
64848f512ceSopenharmony_ci              reinterpret_cast<const uint8_t *>(&data_) + GetSize() - GetHeaderSize(), p);
64948f512ceSopenharmony_ci    return true;
65048f512ceSopenharmony_ci}
65148f512ceSopenharmony_ci
65248f512ceSopenharmony_civoid PerfRecordMmap::DumpData(int indent) const
65348f512ceSopenharmony_ci{
65448f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos
65548f512ceSopenharmony_ci    if (IsRoot()) {
65648f512ceSopenharmony_ci        PRINT_INDENT(indent, "pid %u, tid %u, addr 0x%llx, len 0x%llx\n", data_.pid, data_.tid,
65748f512ceSopenharmony_ci                     data_.addr, data_.len);
65848f512ceSopenharmony_ci        PRINT_INDENT(indent, "pgoff 0x%llx, filename %s\n", data_.pgoff, data_.filename);
65948f512ceSopenharmony_ci    }
66048f512ceSopenharmony_ci#endif
66148f512ceSopenharmony_ci}
66248f512ceSopenharmony_ci
66348f512ceSopenharmony_civoid PerfRecordMmap::DumpLog(const std::string &prefix) const
66448f512ceSopenharmony_ci{
66548f512ceSopenharmony_ci    HLOGV("%s:  MMAP: size %d pid %u tid %u dso '%s' (0x%llx-0x%llx)@0x%llx", prefix.c_str(),
66648f512ceSopenharmony_ci          header.size, data_.pid, data_.tid, data_.filename, data_.addr, data_.addr + data_.len, data_.pgoff);
66748f512ceSopenharmony_ci}
66848f512ceSopenharmony_ci
66948f512ceSopenharmony_ciPerfRecordMmap2::PerfRecordMmap2(uint8_t *p) : PerfEventRecord(p, "mmap2")
67048f512ceSopenharmony_ci{
67148f512ceSopenharmony_ci    size_t dataSize = GetSize();
67248f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
67348f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
67448f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
67548f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
67648f512ceSopenharmony_ci        }
67748f512ceSopenharmony_ci    } else {
67848f512ceSopenharmony_ci        HLOGE("PerfRecordMmap2 retren failed !!!");
67948f512ceSopenharmony_ci    }
68048f512ceSopenharmony_ci}
68148f512ceSopenharmony_ci
68248f512ceSopenharmony_ciPerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff,
68348f512ceSopenharmony_ci                                 u32 maj, u32 min, u64 ino, u32 prot, u32 flags,
68448f512ceSopenharmony_ci                                 const std::string &filename)
68548f512ceSopenharmony_ci    : PerfEventRecord(PERF_RECORD_MMAP2, inKernel, "mmap2")
68648f512ceSopenharmony_ci{
68748f512ceSopenharmony_ci    data_.pid = pid;
68848f512ceSopenharmony_ci    data_.tid = tid;
68948f512ceSopenharmony_ci    data_.addr = addr;
69048f512ceSopenharmony_ci    data_.len = len;
69148f512ceSopenharmony_ci    data_.pgoff = pgoff;
69248f512ceSopenharmony_ci    data_.maj = maj;
69348f512ceSopenharmony_ci    data_.min = min;
69448f512ceSopenharmony_ci    data_.ino = ino;
69548f512ceSopenharmony_ci    data_.ino_generation = 0;
69648f512ceSopenharmony_ci    data_.prot = prot;
69748f512ceSopenharmony_ci    data_.flags = flags;
69848f512ceSopenharmony_ci    if (strncpy_s(data_.filename, KILO, filename.c_str(), filename.size()) != 0) {
69948f512ceSopenharmony_ci        HLOGE("strncpy_s failed");
70048f512ceSopenharmony_ci    }
70148f512ceSopenharmony_ci
70248f512ceSopenharmony_ci    header.size = sizeof(header) + sizeof(data_) - KILO + filename.size() + 1;
70348f512ceSopenharmony_ci}
70448f512ceSopenharmony_ci
70548f512ceSopenharmony_ciPerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, std::shared_ptr<DfxMap> item)
70648f512ceSopenharmony_ci    : PerfEventRecord(PERF_RECORD_MMAP2, inKernel, "mmap2")
70748f512ceSopenharmony_ci{
70848f512ceSopenharmony_ci    data_.pid = pid;
70948f512ceSopenharmony_ci    data_.tid = tid;
71048f512ceSopenharmony_ci    if (item != nullptr) {
71148f512ceSopenharmony_ci        data_.addr = item->begin;
71248f512ceSopenharmony_ci        data_.len = item->end - item->begin;
71348f512ceSopenharmony_ci        data_.pgoff = item->offset;
71448f512ceSopenharmony_ci        data_.maj = item->major;
71548f512ceSopenharmony_ci        data_.min = item->minor;
71648f512ceSopenharmony_ci        data_.ino = item->inode;
71748f512ceSopenharmony_ci        data_.ino_generation = 0;
71848f512ceSopenharmony_ci        // r--p 00000000 103:3e 12307                         /data/storage/el1/bundle/entry.hap
71948f512ceSopenharmony_ci        // why prot get from this is 7. rwxp
72048f512ceSopenharmony_ci        DfxMap::PermsToProts(item->perms, data_.prot, data_.flags);
72148f512ceSopenharmony_ci        if (strncpy_s(data_.filename, KILO, item->name.c_str(), item->name.size()) != 0) {
72248f512ceSopenharmony_ci            HLOGE("strncpy_s failed");
72348f512ceSopenharmony_ci        }
72448f512ceSopenharmony_ci
72548f512ceSopenharmony_ci        header.size = sizeof(header) + sizeof(data_) - KILO + item->name.size() + 1;
72648f512ceSopenharmony_ci    } else {
72748f512ceSopenharmony_ci        data_.addr = 0;
72848f512ceSopenharmony_ci        data_.len = 0;
72948f512ceSopenharmony_ci        data_.pgoff = 0;
73048f512ceSopenharmony_ci        data_.maj = 0;
73148f512ceSopenharmony_ci        data_.min = 0;
73248f512ceSopenharmony_ci        data_.ino = 0;
73348f512ceSopenharmony_ci        data_.ino_generation = 0;
73448f512ceSopenharmony_ci        if (memset_s(data_.filename, KILO, 0, KILO) != EOK) {
73548f512ceSopenharmony_ci            HLOGE("memset_s failed");
73648f512ceSopenharmony_ci        }
73748f512ceSopenharmony_ci    }
73848f512ceSopenharmony_ci}
73948f512ceSopenharmony_ci
74048f512ceSopenharmony_cibool PerfRecordMmap2::GetBinary(std::vector<uint8_t> &buf) const
74148f512ceSopenharmony_ci{
74248f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
74348f512ceSopenharmony_ci        buf.resize(GetSize());
74448f512ceSopenharmony_ci    }
74548f512ceSopenharmony_ci
74648f512ceSopenharmony_ci    GetHeaderBinary(buf);
74748f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
74848f512ceSopenharmony_ci
74948f512ceSopenharmony_ci    // data_.filename[] is variable-length
75048f512ceSopenharmony_ci    std::copy(reinterpret_cast<const uint8_t *>(&data_),
75148f512ceSopenharmony_ci              reinterpret_cast<const uint8_t *>(&data_) + GetSize() - GetHeaderSize(), p);
75248f512ceSopenharmony_ci    return true;
75348f512ceSopenharmony_ci}
75448f512ceSopenharmony_ci
75548f512ceSopenharmony_civoid PerfRecordMmap2::DumpData(int indent) const
75648f512ceSopenharmony_ci{
75748f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos
75848f512ceSopenharmony_ci    if (IsRoot()) {
75948f512ceSopenharmony_ci        PRINT_INDENT(indent, "pid %u, tid %u, addr 0x%llx, len 0x%llx\n", data_.pid, data_.tid,
76048f512ceSopenharmony_ci                     data_.addr, data_.len);
76148f512ceSopenharmony_ci        PRINT_INDENT(indent, "pgoff 0x%llx, maj %u, min %u, ino %llu, ino_generation %llu\n",
76248f512ceSopenharmony_ci                     data_.pgoff, data_.maj, data_.min, data_.ino, data_.ino_generation);
76348f512ceSopenharmony_ci        PRINT_INDENT(indent, "prot %u, flags %u, filename %s\n", data_.prot, data_.flags,
76448f512ceSopenharmony_ci                     data_.filename);
76548f512ceSopenharmony_ci    }
76648f512ceSopenharmony_ci#endif
76748f512ceSopenharmony_ci}
76848f512ceSopenharmony_civoid PerfRecordMmap2::DumpLog(const std::string &prefix) const
76948f512ceSopenharmony_ci{
77048f512ceSopenharmony_ci    HLOGV("%s:  MMAP2: size %d pid %u tid %u dso '%s' (0x%llx-0x%llx)@0x%llx", prefix.c_str(),
77148f512ceSopenharmony_ci          header.size, data_.pid, data_.tid, data_.filename, data_.addr, data_.addr + data_.len,
77248f512ceSopenharmony_ci          data_.pgoff);
77348f512ceSopenharmony_ci}
77448f512ceSopenharmony_ci
77548f512ceSopenharmony_ciPerfRecordLost::PerfRecordLost(uint8_t *p) : PerfEventRecord(p, "lost")
77648f512ceSopenharmony_ci{
77748f512ceSopenharmony_ci    size_t dataSize = GetSize();
77848f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
77948f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
78048f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
78148f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
78248f512ceSopenharmony_ci        }
78348f512ceSopenharmony_ci    } else {
78448f512ceSopenharmony_ci        HLOGE("PerfRecordLost retren failed !!!");
78548f512ceSopenharmony_ci    }
78648f512ceSopenharmony_ci}
78748f512ceSopenharmony_ci
78848f512ceSopenharmony_cibool PerfRecordLost::GetBinary(std::vector<uint8_t> &buf) const
78948f512ceSopenharmony_ci{
79048f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
79148f512ceSopenharmony_ci        buf.resize(GetSize());
79248f512ceSopenharmony_ci    }
79348f512ceSopenharmony_ci
79448f512ceSopenharmony_ci    GetHeaderBinary(buf);
79548f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
79648f512ceSopenharmony_ci
79748f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordLostData *>(p);
79848f512ceSopenharmony_ci    *pDest = data_;
79948f512ceSopenharmony_ci
80048f512ceSopenharmony_ci    return true;
80148f512ceSopenharmony_ci}
80248f512ceSopenharmony_ci
80348f512ceSopenharmony_civoid PerfRecordLost::DumpData(int indent) const
80448f512ceSopenharmony_ci{
80548f512ceSopenharmony_ci    PRINT_INDENT(indent, "id %llu, lost %llu\n", data_.id, data_.lost);
80648f512ceSopenharmony_ci}
80748f512ceSopenharmony_ci
80848f512ceSopenharmony_ciPerfRecordComm::PerfRecordComm(uint8_t *p) : PerfEventRecord(p, "comm")
80948f512ceSopenharmony_ci{
81048f512ceSopenharmony_ci    size_t dataSize = GetSize();
81148f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
81248f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
81348f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
81448f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
81548f512ceSopenharmony_ci        }
81648f512ceSopenharmony_ci    } else {
81748f512ceSopenharmony_ci        HLOGE("PerfRecordComm retren failed !!!");
81848f512ceSopenharmony_ci    }
81948f512ceSopenharmony_ci}
82048f512ceSopenharmony_ci
82148f512ceSopenharmony_ciPerfRecordComm::PerfRecordComm(bool inKernel, u32 pid, u32 tid, const std::string &comm)
82248f512ceSopenharmony_ci    : PerfEventRecord(PERF_RECORD_COMM, inKernel, "comm")
82348f512ceSopenharmony_ci{
82448f512ceSopenharmony_ci    data_.pid = pid;
82548f512ceSopenharmony_ci    data_.tid = tid;
82648f512ceSopenharmony_ci    if (strncpy_s(data_.comm, KILO, comm.c_str(), comm.size()) != 0) {
82748f512ceSopenharmony_ci        HLOGE("strncpy_s failed !!!");
82848f512ceSopenharmony_ci    }
82948f512ceSopenharmony_ci
83048f512ceSopenharmony_ci    header.size = sizeof(header) + sizeof(data_) - KILO + comm.size() + 1;
83148f512ceSopenharmony_ci}
83248f512ceSopenharmony_ci
83348f512ceSopenharmony_cibool PerfRecordComm::GetBinary(std::vector<uint8_t> &buf) const
83448f512ceSopenharmony_ci{
83548f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
83648f512ceSopenharmony_ci        buf.resize(GetSize());
83748f512ceSopenharmony_ci    }
83848f512ceSopenharmony_ci
83948f512ceSopenharmony_ci    GetHeaderBinary(buf);
84048f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
84148f512ceSopenharmony_ci
84248f512ceSopenharmony_ci    // data_.comm[] is variable-length
84348f512ceSopenharmony_ci    std::copy(reinterpret_cast<const uint8_t *>(&data_),
84448f512ceSopenharmony_ci              reinterpret_cast<const uint8_t *>(&data_) + GetSize() - GetHeaderSize(), p);
84548f512ceSopenharmony_ci
84648f512ceSopenharmony_ci    return true;
84748f512ceSopenharmony_ci}
84848f512ceSopenharmony_ci
84948f512ceSopenharmony_civoid PerfRecordComm::DumpData(int indent) const
85048f512ceSopenharmony_ci{
85148f512ceSopenharmony_ci    PRINT_INDENT(indent, "pid %u, tid %u, comm %s\n", data_.pid, data_.tid, data_.comm);
85248f512ceSopenharmony_ci}
85348f512ceSopenharmony_ci
85448f512ceSopenharmony_civoid PerfRecordComm::DumpLog(const std::string &prefix) const
85548f512ceSopenharmony_ci{
85648f512ceSopenharmony_ci    HLOGV("pid %u, tid %u, comm %s\n", data_.pid, data_.tid, data_.comm);
85748f512ceSopenharmony_ci}
85848f512ceSopenharmony_ci
85948f512ceSopenharmony_ciPerfRecordExit::PerfRecordExit(uint8_t *p) : PerfEventRecord(p, "exit")
86048f512ceSopenharmony_ci{
86148f512ceSopenharmony_ci    size_t dataSize = GetSize();
86248f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
86348f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
86448f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
86548f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
86648f512ceSopenharmony_ci        }
86748f512ceSopenharmony_ci    } else {
86848f512ceSopenharmony_ci        HLOGE("PerfRecordExit retren failed !!!");
86948f512ceSopenharmony_ci    }
87048f512ceSopenharmony_ci}
87148f512ceSopenharmony_ci
87248f512ceSopenharmony_cibool PerfRecordExit::GetBinary(std::vector<uint8_t> &buf) const
87348f512ceSopenharmony_ci{
87448f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
87548f512ceSopenharmony_ci        buf.resize(GetSize());
87648f512ceSopenharmony_ci    }
87748f512ceSopenharmony_ci
87848f512ceSopenharmony_ci    GetHeaderBinary(buf);
87948f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
88048f512ceSopenharmony_ci
88148f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordExitData *>(p);
88248f512ceSopenharmony_ci    *pDest = data_;
88348f512ceSopenharmony_ci    return true;
88448f512ceSopenharmony_ci}
88548f512ceSopenharmony_ci
88648f512ceSopenharmony_civoid PerfRecordExit::DumpData(int indent) const
88748f512ceSopenharmony_ci{
88848f512ceSopenharmony_ci    PRINT_INDENT(indent, "pid %u, ppid %u, tid %u, ptid %u time 0x%llx\n", data_.pid, data_.ppid,
88948f512ceSopenharmony_ci                 data_.tid, data_.ptid, data_.time);
89048f512ceSopenharmony_ci}
89148f512ceSopenharmony_ci
89248f512ceSopenharmony_ciPerfRecordThrottle::PerfRecordThrottle(uint8_t *p) : PerfEventRecord(p, "throttle")
89348f512ceSopenharmony_ci{
89448f512ceSopenharmony_ci    size_t dataSize = GetSize();
89548f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
89648f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
89748f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
89848f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
89948f512ceSopenharmony_ci        }
90048f512ceSopenharmony_ci    } else {
90148f512ceSopenharmony_ci        HLOGE("PerfRecordThrottle retren failed !!!");
90248f512ceSopenharmony_ci    }
90348f512ceSopenharmony_ci}
90448f512ceSopenharmony_ci
90548f512ceSopenharmony_cibool PerfRecordThrottle::GetBinary(std::vector<uint8_t> &buf) const
90648f512ceSopenharmony_ci{
90748f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
90848f512ceSopenharmony_ci        buf.resize(GetSize());
90948f512ceSopenharmony_ci    }
91048f512ceSopenharmony_ci
91148f512ceSopenharmony_ci    GetHeaderBinary(buf);
91248f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
91348f512ceSopenharmony_ci
91448f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordThrottleData *>(p);
91548f512ceSopenharmony_ci    *pDest = data_;
91648f512ceSopenharmony_ci    return true;
91748f512ceSopenharmony_ci}
91848f512ceSopenharmony_ci
91948f512ceSopenharmony_civoid PerfRecordThrottle::DumpData(int indent) const
92048f512ceSopenharmony_ci{
92148f512ceSopenharmony_ci    PRINT_INDENT(indent, "time 0x%llx, id %llx, stream_id %llx\n", data_.time, data_.id,
92248f512ceSopenharmony_ci                 data_.stream_id);
92348f512ceSopenharmony_ci}
92448f512ceSopenharmony_ci
92548f512ceSopenharmony_ciPerfRecordUnthrottle::PerfRecordUnthrottle(uint8_t *p) : PerfEventRecord(p, "unthrottle")
92648f512ceSopenharmony_ci{
92748f512ceSopenharmony_ci    size_t dataSize = GetSize();
92848f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
92948f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
93048f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
93148f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
93248f512ceSopenharmony_ci        }
93348f512ceSopenharmony_ci    } else {
93448f512ceSopenharmony_ci        HLOGE("PerfRecordUnthrottle retren failed !!!");
93548f512ceSopenharmony_ci    }
93648f512ceSopenharmony_ci}
93748f512ceSopenharmony_ci
93848f512ceSopenharmony_cibool PerfRecordUnthrottle::GetBinary(std::vector<uint8_t> &buf) const
93948f512ceSopenharmony_ci{
94048f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
94148f512ceSopenharmony_ci        buf.resize(GetSize());
94248f512ceSopenharmony_ci    }
94348f512ceSopenharmony_ci
94448f512ceSopenharmony_ci    GetHeaderBinary(buf);
94548f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
94648f512ceSopenharmony_ci
94748f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordThrottleData *>(p);
94848f512ceSopenharmony_ci    *pDest = data_;
94948f512ceSopenharmony_ci    return true;
95048f512ceSopenharmony_ci}
95148f512ceSopenharmony_civoid PerfRecordUnthrottle::DumpData(int indent) const
95248f512ceSopenharmony_ci{
95348f512ceSopenharmony_ci    PRINT_INDENT(indent, "time 0x%llx, id %llx, stream_id %llx\n", data_.time, data_.id,
95448f512ceSopenharmony_ci                 data_.stream_id);
95548f512ceSopenharmony_ci}
95648f512ceSopenharmony_ci
95748f512ceSopenharmony_ciPerfRecordFork::PerfRecordFork(uint8_t *p) : PerfEventRecord(p, "fork")
95848f512ceSopenharmony_ci{
95948f512ceSopenharmony_ci    size_t dataSize = GetSize();
96048f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
96148f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
96248f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
96348f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
96448f512ceSopenharmony_ci        }
96548f512ceSopenharmony_ci    } else {
96648f512ceSopenharmony_ci        HLOGE("PerfRecordFork retren failed !!!");
96748f512ceSopenharmony_ci    }
96848f512ceSopenharmony_ci}
96948f512ceSopenharmony_ci
97048f512ceSopenharmony_cibool PerfRecordFork::GetBinary(std::vector<uint8_t> &buf) const
97148f512ceSopenharmony_ci{
97248f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
97348f512ceSopenharmony_ci        buf.resize(GetSize());
97448f512ceSopenharmony_ci    }
97548f512ceSopenharmony_ci
97648f512ceSopenharmony_ci    GetHeaderBinary(buf);
97748f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
97848f512ceSopenharmony_ci
97948f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordForkData *>(p);
98048f512ceSopenharmony_ci    *pDest = data_;
98148f512ceSopenharmony_ci    return true;
98248f512ceSopenharmony_ci}
98348f512ceSopenharmony_ci
98448f512ceSopenharmony_civoid PerfRecordFork::DumpData(int indent) const
98548f512ceSopenharmony_ci{
98648f512ceSopenharmony_ci    PRINT_INDENT(indent, "pid %u, ppid %u, tid %u, ptid %u\n", data_.pid, data_.ppid, data_.tid,
98748f512ceSopenharmony_ci                 data_.ptid);
98848f512ceSopenharmony_ci}
98948f512ceSopenharmony_ci
99048f512ceSopenharmony_ciPerfRecordRead::PerfRecordRead(uint8_t *p) : PerfEventRecord(p, "read")
99148f512ceSopenharmony_ci{
99248f512ceSopenharmony_ci    size_t dataSize = GetSize();
99348f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
99448f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
99548f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
99648f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
99748f512ceSopenharmony_ci        }
99848f512ceSopenharmony_ci    } else {
99948f512ceSopenharmony_ci        HLOGE("PerfRecordRead retren failed !!!");
100048f512ceSopenharmony_ci    }
100148f512ceSopenharmony_ci}
100248f512ceSopenharmony_ci
100348f512ceSopenharmony_cibool PerfRecordRead::GetBinary(std::vector<uint8_t> &buf) const
100448f512ceSopenharmony_ci{
100548f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
100648f512ceSopenharmony_ci        buf.resize(GetSize());
100748f512ceSopenharmony_ci    }
100848f512ceSopenharmony_ci
100948f512ceSopenharmony_ci    GetHeaderBinary(buf);
101048f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
101148f512ceSopenharmony_ci
101248f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordReadData *>(p);
101348f512ceSopenharmony_ci    *pDest = data_;
101448f512ceSopenharmony_ci    return true;
101548f512ceSopenharmony_ci}
101648f512ceSopenharmony_ci
101748f512ceSopenharmony_civoid PerfRecordRead::DumpData(int indent) const
101848f512ceSopenharmony_ci{
101948f512ceSopenharmony_ci    PRINT_INDENT(indent, "pid %u, tid %u\n", data_.pid, data_.tid);
102048f512ceSopenharmony_ci    PRINT_INDENT(indent, "values: value %llx, timeEnabled %llx, timeRunning %llx, id %llx\n",
102148f512ceSopenharmony_ci                 data_.values.value, data_.values.timeEnabled, data_.values.timeRunning, data_.values.id);
102248f512ceSopenharmony_ci}
102348f512ceSopenharmony_ci
102448f512ceSopenharmony_ciPerfRecordAux::PerfRecordAux(uint8_t *p) : PerfEventRecord(p, "aux")
102548f512ceSopenharmony_ci{
102648f512ceSopenharmony_ci    size_t dataSize = GetSize();
102748f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
102848f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
102948f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
103048f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
103148f512ceSopenharmony_ci        }
103248f512ceSopenharmony_ci    } else {
103348f512ceSopenharmony_ci        HLOGE("PerfRecordAux retren failed !!!");
103448f512ceSopenharmony_ci    }
103548f512ceSopenharmony_ci}
103648f512ceSopenharmony_ci
103748f512ceSopenharmony_cibool PerfRecordAux::GetBinary(std::vector<uint8_t> &buf) const
103848f512ceSopenharmony_ci{
103948f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
104048f512ceSopenharmony_ci        buf.resize(GetSize());
104148f512ceSopenharmony_ci    }
104248f512ceSopenharmony_ci
104348f512ceSopenharmony_ci    GetHeaderBinary(buf);
104448f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
104548f512ceSopenharmony_ci
104648f512ceSopenharmony_ci    PushToBinary(true, p, data_.aux_offset);
104748f512ceSopenharmony_ci    PushToBinary(true, p, data_.aux_size);
104848f512ceSopenharmony_ci    PushToBinary(true, p, data_.flags);
104948f512ceSopenharmony_ci    PushToBinary2(sampleType_ & PERF_SAMPLE_TID, p, data_.sample_id.pid, data_.sample_id.tid);
105048f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_TIME, p, data_.sample_id.time);
105148f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_ID, p, data_.sample_id.id);
105248f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_STREAM_ID, p, data_.sample_id.stream_id);
105348f512ceSopenharmony_ci
105448f512ceSopenharmony_ci    PushToBinary2(sampleType_ & PERF_SAMPLE_CPU, p, data_.sample_id.cpu, data_.sample_id.res);
105548f512ceSopenharmony_ci    PushToBinary(sampleType_ & PERF_SAMPLE_IDENTIFIER, p, data_.sample_id.id2);
105648f512ceSopenharmony_ci    return true;
105748f512ceSopenharmony_ci}
105848f512ceSopenharmony_ci
105948f512ceSopenharmony_civoid PerfRecordAux::DumpData(int indent) const
106048f512ceSopenharmony_ci{
106148f512ceSopenharmony_ci    PRINT_INDENT(indent, "aux_offset 0x%llx aux_size 0x%llx flags 0x%llx pid %u tid %u time %llu",
106248f512ceSopenharmony_ci                 data_.aux_offset, data_.aux_size, data_.flags, data_.sample_id.pid, data_.sample_id.tid,
106348f512ceSopenharmony_ci                 data_.sample_id.time);
106448f512ceSopenharmony_ci}
106548f512ceSopenharmony_ci
106648f512ceSopenharmony_ciPerfRecordItraceStart::PerfRecordItraceStart(uint8_t *p) : PerfEventRecord(p, "itraceStart")
106748f512ceSopenharmony_ci{
106848f512ceSopenharmony_ci    size_t dataSize = GetSize();
106948f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
107048f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
107148f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
107248f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
107348f512ceSopenharmony_ci        }
107448f512ceSopenharmony_ci    } else {
107548f512ceSopenharmony_ci        HLOGE("PerfRecordItraceStart retren failed !!!");
107648f512ceSopenharmony_ci    }
107748f512ceSopenharmony_ci}
107848f512ceSopenharmony_ci
107948f512ceSopenharmony_cibool PerfRecordItraceStart::GetBinary(std::vector<uint8_t> &buf) const
108048f512ceSopenharmony_ci{
108148f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
108248f512ceSopenharmony_ci        buf.resize(GetSize());
108348f512ceSopenharmony_ci    }
108448f512ceSopenharmony_ci
108548f512ceSopenharmony_ci    GetHeaderBinary(buf);
108648f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
108748f512ceSopenharmony_ci
108848f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordItraceStartData *>(p);
108948f512ceSopenharmony_ci    *pDest = data_;
109048f512ceSopenharmony_ci    return true;
109148f512ceSopenharmony_ci}
109248f512ceSopenharmony_ci
109348f512ceSopenharmony_civoid PerfRecordItraceStart::DumpData(int indent) const
109448f512ceSopenharmony_ci{
109548f512ceSopenharmony_ci    PRINT_INDENT(indent, "pid %u, tid %u\n", data_.pid, data_.tid);
109648f512ceSopenharmony_ci}
109748f512ceSopenharmony_ci
109848f512ceSopenharmony_ciPerfRecordLostSamples::PerfRecordLostSamples(uint8_t *p) : PerfEventRecord(p, "lostSamples")
109948f512ceSopenharmony_ci{
110048f512ceSopenharmony_ci    size_t dataSize = GetSize();
110148f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
110248f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
110348f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
110448f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
110548f512ceSopenharmony_ci        }
110648f512ceSopenharmony_ci    } else {
110748f512ceSopenharmony_ci        HLOGE("PerfRecordLostSamples retren failed !!!");
110848f512ceSopenharmony_ci    }
110948f512ceSopenharmony_ci}
111048f512ceSopenharmony_ci
111148f512ceSopenharmony_cibool PerfRecordLostSamples::GetBinary(std::vector<uint8_t> &buf) const
111248f512ceSopenharmony_ci{
111348f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
111448f512ceSopenharmony_ci        buf.resize(GetSize());
111548f512ceSopenharmony_ci    }
111648f512ceSopenharmony_ci
111748f512ceSopenharmony_ci    GetHeaderBinary(buf);
111848f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
111948f512ceSopenharmony_ci
112048f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordLostSamplesData *>(p);
112148f512ceSopenharmony_ci    *pDest = data_;
112248f512ceSopenharmony_ci    return true;
112348f512ceSopenharmony_ci}
112448f512ceSopenharmony_ci
112548f512ceSopenharmony_civoid PerfRecordLostSamples::DumpData(int indent) const
112648f512ceSopenharmony_ci{
112748f512ceSopenharmony_ci    PRINT_INDENT(indent, "lost %llu\n", data_.lost);
112848f512ceSopenharmony_ci}
112948f512ceSopenharmony_ci
113048f512ceSopenharmony_ciPerfRecordSwitch::PerfRecordSwitch(uint8_t *p) : PerfEventRecord(p, "switch")
113148f512ceSopenharmony_ci{
113248f512ceSopenharmony_ci    size_t dataSize = GetSize();
113348f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
113448f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
113548f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
113648f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
113748f512ceSopenharmony_ci        }
113848f512ceSopenharmony_ci    } else {
113948f512ceSopenharmony_ci        HLOGE("PerfRecordSwitch retren failed !!!");
114048f512ceSopenharmony_ci    }
114148f512ceSopenharmony_ci}
114248f512ceSopenharmony_ci
114348f512ceSopenharmony_cibool PerfRecordSwitch::GetBinary(std::vector<uint8_t> &buf) const
114448f512ceSopenharmony_ci{
114548f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
114648f512ceSopenharmony_ci        buf.resize(GetSize());
114748f512ceSopenharmony_ci    }
114848f512ceSopenharmony_ci
114948f512ceSopenharmony_ci    GetHeaderBinary(buf);
115048f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
115148f512ceSopenharmony_ci
115248f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordSwitchData *>(p);
115348f512ceSopenharmony_ci    *pDest = data_;
115448f512ceSopenharmony_ci    return true;
115548f512ceSopenharmony_ci}
115648f512ceSopenharmony_ci
115748f512ceSopenharmony_ciPerfRecordSwitchCpuWide::PerfRecordSwitchCpuWide(uint8_t *p) : PerfEventRecord(p, "switchCpuWide")
115848f512ceSopenharmony_ci{
115948f512ceSopenharmony_ci    size_t dataSize = GetSize();
116048f512ceSopenharmony_ci    if (dataSize >= sizeof(header)) {
116148f512ceSopenharmony_ci        size_t copySize = dataSize - sizeof(header);
116248f512ceSopenharmony_ci        if (memcpy_s(reinterpret_cast<uint8_t *>(&data_), sizeof(data_), p + sizeof(header), copySize) != 0) {
116348f512ceSopenharmony_ci            HLOGE("memcpy_s retren failed !!!");
116448f512ceSopenharmony_ci        }
116548f512ceSopenharmony_ci    } else {
116648f512ceSopenharmony_ci        HLOGE("PerfRecordSwitchCpuWide retren failed !!!");
116748f512ceSopenharmony_ci    }
116848f512ceSopenharmony_ci}
116948f512ceSopenharmony_ci
117048f512ceSopenharmony_cibool PerfRecordSwitchCpuWide::GetBinary(std::vector<uint8_t> &buf) const
117148f512ceSopenharmony_ci{
117248f512ceSopenharmony_ci    if (buf.size() < GetSize()) {
117348f512ceSopenharmony_ci        buf.resize(GetSize());
117448f512ceSopenharmony_ci    }
117548f512ceSopenharmony_ci
117648f512ceSopenharmony_ci    GetHeaderBinary(buf);
117748f512ceSopenharmony_ci    uint8_t *p = buf.data() + GetHeaderSize();
117848f512ceSopenharmony_ci
117948f512ceSopenharmony_ci    auto pDest = reinterpret_cast<PerfRecordSwitchCpuWideData *>(p);
118048f512ceSopenharmony_ci    *pDest = data_;
118148f512ceSopenharmony_ci    return true;
118248f512ceSopenharmony_ci}
118348f512ceSopenharmony_ci
118448f512ceSopenharmony_civoid PerfRecordSwitchCpuWide::DumpData(int indent) const
118548f512ceSopenharmony_ci{
118648f512ceSopenharmony_ci    PRINT_INDENT(indent, "next_prev_pid %u, next_prev_tid %u\n", data_.next_prev_pid,
118748f512ceSopenharmony_ci                 data_.next_prev_tid);
118848f512ceSopenharmony_ci}
118948f512ceSopenharmony_ci
119048f512ceSopenharmony_cipid_t PerfRecordSample::GetUstackServerPid()
119148f512ceSopenharmony_ci{
119248f512ceSopenharmony_ci    if (!data_.server_nr) {
119348f512ceSopenharmony_ci        return data_.pid;
119448f512ceSopenharmony_ci    }
119548f512ceSopenharmony_ci
119648f512ceSopenharmony_ci    size_t currServer = 0;
119748f512ceSopenharmony_ci    // ipNr == 1...nr: server_pid of data_.ips[nr]
119848f512ceSopenharmony_ci    for (size_t i = 0; i < data_.nr; i++) {
119948f512ceSopenharmony_ci        // context change, use next server pid
120048f512ceSopenharmony_ci        if (data_.ips[i] >= PERF_CONTEXT_MAX) {
120148f512ceSopenharmony_ci            currServer++;
120248f512ceSopenharmony_ci        }
120348f512ceSopenharmony_ci    }
120448f512ceSopenharmony_ci    // ipNr == nr + 1: server_pid of ustack
120548f512ceSopenharmony_ci    if (currServer > 0) {
120648f512ceSopenharmony_ci        currServer++;
120748f512ceSopenharmony_ci    }
120848f512ceSopenharmony_ci    if (currServer >= data_.server_nr) {
120948f512ceSopenharmony_ci        HLOGE("ustack server pid nr %zu out of range", currServer);
121048f512ceSopenharmony_ci        return data_.pid;
121148f512ceSopenharmony_ci    }
121248f512ceSopenharmony_ci
121348f512ceSopenharmony_ci    // return server pid
121448f512ceSopenharmony_ci    return data_.server_pids[currServer];
121548f512ceSopenharmony_ci}
121648f512ceSopenharmony_ci
121748f512ceSopenharmony_cipid_t PerfRecordSample::GetServerPidof(unsigned int ipNr)
121848f512ceSopenharmony_ci{
121948f512ceSopenharmony_ci    if (!data_.server_nr) {
122048f512ceSopenharmony_ci        return data_.pid;
122148f512ceSopenharmony_ci    }
122248f512ceSopenharmony_ci
122348f512ceSopenharmony_ci    // init serverPidMap_
122448f512ceSopenharmony_ci    if (!serverPidMap_.size()) {
122548f512ceSopenharmony_ci        size_t currServer = 0;
122648f512ceSopenharmony_ci        // ipNr == 0: server_pid of data_.ip
122748f512ceSopenharmony_ci        serverPidMap_.emplace_back(data_.server_pids[currServer]);
122848f512ceSopenharmony_ci        // ipNr == 1...nr: server_pid of data_.ips[nr]
122948f512ceSopenharmony_ci        for (size_t i = 1; i < data_.nr; i++) {
123048f512ceSopenharmony_ci            // context change, use next server pid
123148f512ceSopenharmony_ci            if (data_.ips[i] >= PERF_CONTEXT_MAX) {
123248f512ceSopenharmony_ci                currServer++;
123348f512ceSopenharmony_ci            }
123448f512ceSopenharmony_ci            if (currServer >= data_.server_nr) {
123548f512ceSopenharmony_ci                HLOGE("callchain server pid nr %zu out of range", currServer);
123648f512ceSopenharmony_ci                break;
123748f512ceSopenharmony_ci            }
123848f512ceSopenharmony_ci            serverPidMap_.emplace_back(data_.server_pids[currServer]);
123948f512ceSopenharmony_ci        }
124048f512ceSopenharmony_ci    }
124148f512ceSopenharmony_ci
124248f512ceSopenharmony_ci    // return server pid
124348f512ceSopenharmony_ci    if (ipNr >= serverPidMap_.size()) {
124448f512ceSopenharmony_ci        return data_.pid;
124548f512ceSopenharmony_ci    } else {
124648f512ceSopenharmony_ci        return serverPidMap_[ipNr];
124748f512ceSopenharmony_ci    }
124848f512ceSopenharmony_ci}
124948f512ceSopenharmony_ci} // namespace HiPerf
125048f512ceSopenharmony_ci} // namespace Developtools
125148f512ceSopenharmony_ci} // namespace OHOS
1252