148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021-2024 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
1648f512ceSopenharmony_ci#include "spe_decoder.h"
1748f512ceSopenharmony_ci#include "hiperf_hilog.h"
1848f512ceSopenharmony_ci
1948f512ceSopenharmony_ci#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
2048f512ceSopenharmony_ci#define LE16_TO_CPU bswap_16
2148f512ceSopenharmony_ci#define LE32_TO_CPU bswap_32
2248f512ceSopenharmony_ci#define LE64_TO_CPU bswap_64
2348f512ceSopenharmony_ci#else
2448f512ceSopenharmony_ci#define LE16_TO_CPU
2548f512ceSopenharmony_ci#define LE32_TO_CPU
2648f512ceSopenharmony_ci#define LE64_TO_CPU
2748f512ceSopenharmony_ci#endif
2848f512ceSopenharmony_ci
2948f512ceSopenharmony_cinamespace OHOS {
3048f512ceSopenharmony_cinamespace Developtools {
3148f512ceSopenharmony_cinamespace HiPerf {
3248f512ceSopenharmony_ciconstexpr const int UN_PRMT = -1;
3348f512ceSopenharmony_ci
3448f512ceSopenharmony_ciconst char *SpePktName(enum SpePktType type)
3548f512ceSopenharmony_ci{
3648f512ceSopenharmony_ci    const char* spePacketName;
3748f512ceSopenharmony_ci    switch (type) {
3848f512ceSopenharmony_ci        case PERF_SPE_PAD:         spePacketName = "PAD"; break;
3948f512ceSopenharmony_ci        case PERF_SPE_END:         spePacketName = "END"; break;
4048f512ceSopenharmony_ci        case PERF_SPE_TIMESTAMP:   spePacketName = "TS"; break;
4148f512ceSopenharmony_ci        case PERF_SPE_ADDRESS:     spePacketName = "ADDR"; break;
4248f512ceSopenharmony_ci        case PERF_SPE_COUNTER:     spePacketName = "LAT"; break;
4348f512ceSopenharmony_ci        case PERF_SPE_CONTEXT:     spePacketName = "CONTEXT"; break;
4448f512ceSopenharmony_ci        case PERF_SPE_OP_TYPE:     spePacketName = "OP-TYPE"; break;
4548f512ceSopenharmony_ci        case PERF_SPE_EVENTS:      spePacketName = "EVENTS"; break;
4648f512ceSopenharmony_ci        case PERF_SPE_DATA_SOURCE: spePacketName = "DATA-SOURCE"; break;
4748f512ceSopenharmony_ci        default:                   spePacketName = "INVALID"; break;
4848f512ceSopenharmony_ci    }
4948f512ceSopenharmony_ci    return spePacketName;
5048f512ceSopenharmony_ci}
5148f512ceSopenharmony_ci
5248f512ceSopenharmony_cistatic unsigned int SpePayloadLen(unsigned char hdr)
5348f512ceSopenharmony_ci{
5448f512ceSopenharmony_ci    return 1U << PERF_SPE_HDR_GET_BYTES_5_4(hdr);
5548f512ceSopenharmony_ci}
5648f512ceSopenharmony_ci
5748f512ceSopenharmony_cistatic int SpeGetPayload(const unsigned char *buf, size_t len,
5848f512ceSopenharmony_ci                         unsigned char extHdr, struct SpePkt *packet)
5948f512ceSopenharmony_ci{
6048f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
6148f512ceSopenharmony_ci    size_t payloadLen = SpePayloadLen(buf[extHdr]);
6248f512ceSopenharmony_ci    if (len < 1 + extHdr + payloadLen) {
6348f512ceSopenharmony_ci        return PERF_SPE_NEED_MORE_BYTES;
6448f512ceSopenharmony_ci    }
6548f512ceSopenharmony_ci    buf += 1 + extHdr;
6648f512ceSopenharmony_ci
6748f512ceSopenharmony_ci    switch (payloadLen) {
6848f512ceSopenharmony_ci        case LEN_TYPE_BYTE: packet->payload = *(reinterpret_cast<const uint8_t *>(buf)); break;
6948f512ceSopenharmony_ci        case LEN_TYPE_HLFWRD: packet->payload = LE16_TO_CPU(*reinterpret_cast<const uint16_t *>(buf)); break;
7048f512ceSopenharmony_ci        case LEN_TYPE_WORD: packet->payload = LE32_TO_CPU(*reinterpret_cast<const uint32_t *>(buf)); break;
7148f512ceSopenharmony_ci        case LEN_TYPE_DBLEWRD: packet->payload = LE64_TO_CPU(*reinterpret_cast<const uint64_t *>(buf)); break;
7248f512ceSopenharmony_ci        default: return PERF_SPE_BAD_PACKET;
7348f512ceSopenharmony_ci    }
7448f512ceSopenharmony_ci
7548f512ceSopenharmony_ci    return 1 + extHdr + payloadLen;
7648f512ceSopenharmony_ci}
7748f512ceSopenharmony_ci
7848f512ceSopenharmony_cistatic int SpeGetPad(struct SpePkt *packet)
7948f512ceSopenharmony_ci{
8048f512ceSopenharmony_ci    CHECK_TRUE(packet == nullptr, -1, 1, "Invalid pointer!");
8148f512ceSopenharmony_ci    packet->type = PERF_SPE_PAD;
8248f512ceSopenharmony_ci    return 1;
8348f512ceSopenharmony_ci}
8448f512ceSopenharmony_ci
8548f512ceSopenharmony_cistatic int SpeGetAlignment(const unsigned char *buf, size_t len,
8648f512ceSopenharmony_ci                           struct SpePkt *packet)
8748f512ceSopenharmony_ci{
8848f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
8948f512ceSopenharmony_ci    unsigned int alignment = 1 << ((buf[0] & 0xf) + 1);
9048f512ceSopenharmony_ci
9148f512ceSopenharmony_ci    if (len < alignment)
9248f512ceSopenharmony_ci        return PERF_SPE_NEED_MORE_BYTES;
9348f512ceSopenharmony_ci
9448f512ceSopenharmony_ci    packet->type = PERF_SPE_PAD;
9548f512ceSopenharmony_ci    return alignment - (((uintptr_t)buf) & (alignment - 1));
9648f512ceSopenharmony_ci}
9748f512ceSopenharmony_ci
9848f512ceSopenharmony_cistatic int SpeGetEnd(struct SpePkt *packet)
9948f512ceSopenharmony_ci{
10048f512ceSopenharmony_ci    CHECK_TRUE(packet == nullptr, -1, 1, "Invalid pointer!");
10148f512ceSopenharmony_ci    packet->type = PERF_SPE_END;
10248f512ceSopenharmony_ci    return 1;
10348f512ceSopenharmony_ci}
10448f512ceSopenharmony_ci
10548f512ceSopenharmony_cistatic int SpeGetTimestamp(const unsigned char *buf, size_t len,
10648f512ceSopenharmony_ci                           struct SpePkt *packet)
10748f512ceSopenharmony_ci{
10848f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
10948f512ceSopenharmony_ci    packet->type = PERF_SPE_TIMESTAMP;
11048f512ceSopenharmony_ci    return SpeGetPayload(buf, len, 0, packet);
11148f512ceSopenharmony_ci}
11248f512ceSopenharmony_ci
11348f512ceSopenharmony_cistatic int SpeGetEvents(const unsigned char *buf, size_t len,
11448f512ceSopenharmony_ci                        struct SpePkt *packet)
11548f512ceSopenharmony_ci{
11648f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
11748f512ceSopenharmony_ci    packet->type = PERF_SPE_EVENTS;
11848f512ceSopenharmony_ci    packet->index = SpePayloadLen(buf[0]);
11948f512ceSopenharmony_ci    return SpeGetPayload(buf, len, 0, packet);
12048f512ceSopenharmony_ci}
12148f512ceSopenharmony_ci
12248f512ceSopenharmony_cistatic int SpeGetDataSource(const unsigned char *buf, size_t len,
12348f512ceSopenharmony_ci                            struct SpePkt *packet)
12448f512ceSopenharmony_ci{
12548f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
12648f512ceSopenharmony_ci    packet->type = PERF_SPE_DATA_SOURCE;
12748f512ceSopenharmony_ci    return SpeGetPayload(buf, len, 0, packet);
12848f512ceSopenharmony_ci}
12948f512ceSopenharmony_ci
13048f512ceSopenharmony_cistatic int SpeGetContext(const unsigned char *buf, size_t len,
13148f512ceSopenharmony_ci                         struct SpePkt *packet)
13248f512ceSopenharmony_ci{
13348f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
13448f512ceSopenharmony_ci    packet->type = PERF_SPE_CONTEXT;
13548f512ceSopenharmony_ci    packet->index = PERF_SPE_CTX_PKT_HDR_INDEX(buf[0]);
13648f512ceSopenharmony_ci    return SpeGetPayload(buf, len, 0, packet);
13748f512ceSopenharmony_ci}
13848f512ceSopenharmony_ci
13948f512ceSopenharmony_cistatic int SpeGetOpType(const unsigned char *buf, size_t len,
14048f512ceSopenharmony_ci                        struct SpePkt *packet)
14148f512ceSopenharmony_ci{
14248f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
14348f512ceSopenharmony_ci    packet->type = PERF_SPE_OP_TYPE;
14448f512ceSopenharmony_ci    packet->index = PERF_SPE_OP_PKT_HDR_CLASS(buf[0]);
14548f512ceSopenharmony_ci    return SpeGetPayload(buf, len, 0, packet);
14648f512ceSopenharmony_ci}
14748f512ceSopenharmony_ci
14848f512ceSopenharmony_cistatic int SpeGetCounter(const unsigned char *buf, size_t len,
14948f512ceSopenharmony_ci                         const unsigned char extHdr, struct SpePkt *packet)
15048f512ceSopenharmony_ci{
15148f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
15248f512ceSopenharmony_ci    packet->type = PERF_SPE_COUNTER;
15348f512ceSopenharmony_ci    if (extHdr) {
15448f512ceSopenharmony_ci        packet->index = PERF_SPE_HDR_EXTENDED_INDEX(buf[0], buf[1]);
15548f512ceSopenharmony_ci    } else {
15648f512ceSopenharmony_ci        packet->index = PERF_SPE_HDR_SHORT_INDEX(buf[0]);
15748f512ceSopenharmony_ci    }
15848f512ceSopenharmony_ci
15948f512ceSopenharmony_ci    return SpeGetPayload(buf, len, extHdr, packet);
16048f512ceSopenharmony_ci}
16148f512ceSopenharmony_ci
16248f512ceSopenharmony_cistatic int SpeGetAddr(const unsigned char *buf, size_t len,
16348f512ceSopenharmony_ci                      const unsigned char extHdr, struct SpePkt *packet)
16448f512ceSopenharmony_ci{
16548f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
16648f512ceSopenharmony_ci    packet->type = PERF_SPE_ADDRESS;
16748f512ceSopenharmony_ci    if (extHdr) {
16848f512ceSopenharmony_ci        packet->index = PERF_SPE_HDR_EXTENDED_INDEX(buf[0], buf[1]);
16948f512ceSopenharmony_ci    } else {
17048f512ceSopenharmony_ci        packet->index = PERF_SPE_HDR_SHORT_INDEX(buf[0]);
17148f512ceSopenharmony_ci    }
17248f512ceSopenharmony_ci
17348f512ceSopenharmony_ci    return SpeGetPayload(buf, len, extHdr, packet);
17448f512ceSopenharmony_ci}
17548f512ceSopenharmony_ci
17648f512ceSopenharmony_cistatic int SpeDoGetPacket(const unsigned char *buf, size_t len,
17748f512ceSopenharmony_ci                          struct SpePkt *packet)
17848f512ceSopenharmony_ci{
17948f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
18048f512ceSopenharmony_ci    unsigned int hdr;
18148f512ceSopenharmony_ci    unsigned char extHdr = 0;
18248f512ceSopenharmony_ci
18348f512ceSopenharmony_ci    memset_s(packet, sizeof(struct SpePkt), 0, sizeof(struct SpePkt));
18448f512ceSopenharmony_ci
18548f512ceSopenharmony_ci    if (!len) {
18648f512ceSopenharmony_ci        return PERF_SPE_NEED_MORE_BYTES;
18748f512ceSopenharmony_ci    }
18848f512ceSopenharmony_ci
18948f512ceSopenharmony_ci    hdr = buf[0];
19048f512ceSopenharmony_ci    if (hdr == PERF_SPE_HEADER0_PAD) {
19148f512ceSopenharmony_ci        return SpeGetPad(packet);
19248f512ceSopenharmony_ci    } else if (hdr == PERF_SPE_HEADER0_END) {      /* no timestamp at end of record */
19348f512ceSopenharmony_ci        return SpeGetEnd(packet);
19448f512ceSopenharmony_ci    }
19548f512ceSopenharmony_ci    if (hdr == PERF_SPE_HEADER0_TIMESTAMP) {
19648f512ceSopenharmony_ci        return SpeGetTimestamp(buf, len, packet);
19748f512ceSopenharmony_ci    } else if ((hdr & PERF_SPE_HEADER0_MASK1) == PERF_SPE_HEADER0_EVENTS) {
19848f512ceSopenharmony_ci        return SpeGetEvents(buf, len, packet);
19948f512ceSopenharmony_ci    } else if ((hdr & PERF_SPE_HEADER0_MASK1) == PERF_SPE_HEADER0_SOURCE) {
20048f512ceSopenharmony_ci        return SpeGetDataSource(buf, len, packet);
20148f512ceSopenharmony_ci    } else if ((hdr & PERF_SPE_HEADER0_MASK2) == PERF_SPE_HEADER0_CONTEXT) {
20248f512ceSopenharmony_ci        return SpeGetContext(buf, len, packet);
20348f512ceSopenharmony_ci    } else if ((hdr & PERF_SPE_HEADER0_MASK2) == PERF_SPE_HEADER0_OP_TYPE) {
20448f512ceSopenharmony_ci        return SpeGetOpType(buf, len, packet);
20548f512ceSopenharmony_ci    }
20648f512ceSopenharmony_ci    if ((hdr & PERF_SPE_HEADER0_MASK2) == PERF_SPE_HEADER0_EXTENDED) {
20748f512ceSopenharmony_ci        /* 16-bit extended format header */
20848f512ceSopenharmony_ci        if (len == 1) {
20948f512ceSopenharmony_ci            return PERF_SPE_BAD_PACKET;
21048f512ceSopenharmony_ci        }
21148f512ceSopenharmony_ci
21248f512ceSopenharmony_ci        extHdr = 1;
21348f512ceSopenharmony_ci        hdr = buf[1];
21448f512ceSopenharmony_ci        if (hdr == PERF_SPE_HEADER1_ALIGNMENT) {
21548f512ceSopenharmony_ci            return SpeGetAlignment(buf, len, packet);
21648f512ceSopenharmony_ci        }
21748f512ceSopenharmony_ci    }
21848f512ceSopenharmony_ci
21948f512ceSopenharmony_ci    /*
22048f512ceSopenharmony_ci     * The short format header's byte 0 or the extended format header's
22148f512ceSopenharmony_ci     * byte 1 has been assigned to 'hdr', which uses the same encoding for
22248f512ceSopenharmony_ci     * address packet and counter packet, so don't need to distinguish if
22348f512ceSopenharmony_ci     * it's short format or extended format and handle in once.
22448f512ceSopenharmony_ci     */
22548f512ceSopenharmony_ci    if ((hdr & PERF_SPE_HEADER0_MASK3) == PERF_SPE_HEADER0_ADDRESS) {
22648f512ceSopenharmony_ci        return SpeGetAddr(buf, len, extHdr, packet);
22748f512ceSopenharmony_ci    }
22848f512ceSopenharmony_ci
22948f512ceSopenharmony_ci    if ((hdr & PERF_SPE_HEADER0_MASK3) == PERF_SPE_HEADER0_COUNTER) {
23048f512ceSopenharmony_ci        return SpeGetCounter(buf, len, extHdr, packet);
23148f512ceSopenharmony_ci    }
23248f512ceSopenharmony_ci    return PERF_SPE_BAD_PACKET;
23348f512ceSopenharmony_ci}
23448f512ceSopenharmony_ci
23548f512ceSopenharmony_ciint SpeGetPacket(const unsigned char *buf, size_t len,
23648f512ceSopenharmony_ci                 struct SpePkt *packet)
23748f512ceSopenharmony_ci{
23848f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
23948f512ceSopenharmony_ci    int ret = SpeDoGetPacket(buf, len, packet);
24048f512ceSopenharmony_ci    /* put multiple consecutive PADs on the same line, up to
24148f512ceSopenharmony_ci     * the fixed-width output format of 16 bytes per line.
24248f512ceSopenharmony_ci     */
24348f512ceSopenharmony_ci    if (ret > 0 && packet->type == PERF_SPE_PAD) {
24448f512ceSopenharmony_ci        while (ret < BYTE_WIDTH && len > (size_t)ret && !buf[ret]) {
24548f512ceSopenharmony_ci            ret += 1;
24648f512ceSopenharmony_ci        }
24748f512ceSopenharmony_ci    }
24848f512ceSopenharmony_ci    return ret;
24948f512ceSopenharmony_ci}
25048f512ceSopenharmony_ci
25148f512ceSopenharmony_cistatic int SpePktOutString(int *err, char **bufPtr, size_t *bufLen,
25248f512ceSopenharmony_ci                           const char *fmt, ...)
25348f512ceSopenharmony_ci{
25448f512ceSopenharmony_ci    CHECK_TRUE(*bufPtr == nullptr || bufLen == nullptr || fmt == nullptr, -1, 1, "Invalid pointer!");
25548f512ceSopenharmony_ci    va_list args;
25648f512ceSopenharmony_ci    int ret = 0;
25748f512ceSopenharmony_ci
25848f512ceSopenharmony_ci    /* If any errors occur, exit */
25948f512ceSopenharmony_ci    if (err && *err) {
26048f512ceSopenharmony_ci        return *err;
26148f512ceSopenharmony_ci    }
26248f512ceSopenharmony_ci
26348f512ceSopenharmony_ci    va_start(args, fmt);
26448f512ceSopenharmony_ci    ret = vsnprintf_s(*bufPtr, *bufLen, *bufLen - 1, fmt, args);
26548f512ceSopenharmony_ci    va_end(args);
26648f512ceSopenharmony_ci
26748f512ceSopenharmony_ci    if (ret < 0) {
26848f512ceSopenharmony_ci        if (err && !*err) {
26948f512ceSopenharmony_ci            *err = ret;
27048f512ceSopenharmony_ci        }
27148f512ceSopenharmony_ci
27248f512ceSopenharmony_ci    /*
27348f512ceSopenharmony_ci     * If the return value is *bufLen or greater, the output was
27448f512ceSopenharmony_ci     * truncated and the buffer overflowed.
27548f512ceSopenharmony_ci     */
27648f512ceSopenharmony_ci    } else if ((size_t)ret >= *bufLen) {
27748f512ceSopenharmony_ci        (*bufPtr)[*bufLen - 1] = '\0';
27848f512ceSopenharmony_ci
27948f512ceSopenharmony_ci        /*
28048f512ceSopenharmony_ci         * Set *err to 'ret' to avoid overflow if tries to
28148f512ceSopenharmony_ci         * fill this buffer sequentially.
28248f512ceSopenharmony_ci         */
28348f512ceSopenharmony_ci        if (err && !*err) {
28448f512ceSopenharmony_ci            *err = ret;
28548f512ceSopenharmony_ci        }
28648f512ceSopenharmony_ci    } else {
28748f512ceSopenharmony_ci        *bufPtr += ret;
28848f512ceSopenharmony_ci        *bufLen -= ret;
28948f512ceSopenharmony_ci    }
29048f512ceSopenharmony_ci
29148f512ceSopenharmony_ci    return ret;
29248f512ceSopenharmony_ci}
29348f512ceSopenharmony_ci
29448f512ceSopenharmony_cistatic int SpePktDescEvent(const struct SpePkt *packet,
29548f512ceSopenharmony_ci                           char *buf, size_t bufLen)
29648f512ceSopenharmony_ci{
29748f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
29848f512ceSopenharmony_ci    u64 payload = packet->payload;
29948f512ceSopenharmony_ci    int err = 0;
30048f512ceSopenharmony_ci
30148f512ceSopenharmony_ci    SpePktOutString(&err, &buf, &bufLen, "EV");
30248f512ceSopenharmony_ci    if (payload & BIT(EVENT_EXCEPTION_GEN)) {
30348f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " EXCEPTION-GEN");
30448f512ceSopenharmony_ci    }
30548f512ceSopenharmony_ci    if (payload & BIT(EVENT_RETIRED)) {
30648f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " RETIRED");
30748f512ceSopenharmony_ci    }
30848f512ceSopenharmony_ci    if (payload & BIT(EVENT_L1D_ACCESS)) {
30948f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " L1D-ACCESS");
31048f512ceSopenharmony_ci    }
31148f512ceSopenharmony_ci    if (payload & BIT(EVENT_L1D_REFILL)) {
31248f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " L1D-REFILL");
31348f512ceSopenharmony_ci    }
31448f512ceSopenharmony_ci    if (payload & BIT(EVENT_TLB_ACCESS)) {
31548f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " TLB-ACCESS");
31648f512ceSopenharmony_ci    }
31748f512ceSopenharmony_ci    if (payload & BIT(EVENT_TLB_WALK)) {
31848f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " TLB-REFILL");
31948f512ceSopenharmony_ci    }
32048f512ceSopenharmony_ci    if (payload & BIT(EVENT_NOT_TAKEN)) {
32148f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " NOT-TAKEN");
32248f512ceSopenharmony_ci    }
32348f512ceSopenharmony_ci    if (payload & BIT(EVENT_MISPRED)) {
32448f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " MISPRED");
32548f512ceSopenharmony_ci    }
32648f512ceSopenharmony_ci    if (payload & BIT(EVENT_LLC_ACCESS)) {
32748f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " LLC-ACCESS");
32848f512ceSopenharmony_ci    }
32948f512ceSopenharmony_ci    if (payload & BIT(EVENT_LLC_MISS)) {
33048f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " LLC-REFILL");
33148f512ceSopenharmony_ci    }
33248f512ceSopenharmony_ci    if (payload & BIT(EVENT_REMOTE_ACCESS)) {
33348f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " REMOTE-ACCESS");
33448f512ceSopenharmony_ci    }
33548f512ceSopenharmony_ci    if (payload & BIT(EVENT_ALIGNMENT)) {
33648f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " ALIGNMENT");
33748f512ceSopenharmony_ci    }
33848f512ceSopenharmony_ci    if (payload & BIT(EVENT_PARTIAL_PREDICATE)) {
33948f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " SVE-PARTIAL-PRED");
34048f512ceSopenharmony_ci    }
34148f512ceSopenharmony_ci    if (payload & BIT(EVENT_EMPTY_PREDICATE)) {
34248f512ceSopenharmony_ci        SpePktOutString(&err, &buf, &bufLen, " SVE-EMPTY-PRED");
34348f512ceSopenharmony_ci    }
34448f512ceSopenharmony_ci
34548f512ceSopenharmony_ci    return err;
34648f512ceSopenharmony_ci}
34748f512ceSopenharmony_ci
34848f512ceSopenharmony_cistatic int SpePktDescOpType(const struct SpePkt *packet,
34948f512ceSopenharmony_ci                            char *buf, size_t bufLen)
35048f512ceSopenharmony_ci{
35148f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
35248f512ceSopenharmony_ci    u64 payload = packet->payload;
35348f512ceSopenharmony_ci    int err = 0;
35448f512ceSopenharmony_ci
35548f512ceSopenharmony_ci    switch (packet->index) {
35648f512ceSopenharmony_ci        case PERF_SPE_OP_PKT_HDR_CLASS_OTHER:
35748f512ceSopenharmony_ci            if (PERF_SPE_OP_PKT_IS_OTHER_SVE_OP(payload)) {
35848f512ceSopenharmony_ci                SpePktOutString(&err, &buf, &bufLen, "SVE-OTHER");
35948f512ceSopenharmony_ci
36048f512ceSopenharmony_ci                /* SVE effective vector length */
36148f512ceSopenharmony_ci                SpePktOutString(&err, &buf, &bufLen, " EVLEN %d",
36248f512ceSopenharmony_ci                                PERF_SPE_OP_PKG_SVE_EVL(payload));
36348f512ceSopenharmony_ci
36448f512ceSopenharmony_ci                if (payload & PERF_SPE_OP_PKT_SVE_FP)
36548f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " FP");
36648f512ceSopenharmony_ci                if (payload & PERF_SPE_OP_PKT_SVE_PRED)
36748f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " PRED");
36848f512ceSopenharmony_ci            } else {
36948f512ceSopenharmony_ci                SpePktOutString(&err, &buf, &bufLen, "OTHER");
37048f512ceSopenharmony_ci                SpePktOutString(&err, &buf, &bufLen, " %s",
37148f512ceSopenharmony_ci                                payload & PERF_SPE_OP_PKT_COND ?
37248f512ceSopenharmony_ci                                "COND-SELECT" : "INSN-OTHER");
37348f512ceSopenharmony_ci            }
37448f512ceSopenharmony_ci            break;
37548f512ceSopenharmony_ci        case PERF_SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC:
37648f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &bufLen,
37748f512ceSopenharmony_ci                            payload & 0x1 ? "ST" : "LD");
37848f512ceSopenharmony_ci
37948f512ceSopenharmony_ci            if (PERF_SPE_OP_PKT_IS_LDST_ATOMIC(payload)) {
38048f512ceSopenharmony_ci                if (payload & PERF_SPE_OP_PKT_AT)
38148f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " AT");
38248f512ceSopenharmony_ci                if (payload & PERF_SPE_OP_PKT_EXCL)
38348f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " EXCL");
38448f512ceSopenharmony_ci                if (payload & PERF_SPE_OP_PKT_AR)
38548f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " AR");
38648f512ceSopenharmony_ci            }
38748f512ceSopenharmony_ci
38848f512ceSopenharmony_ci            switch (PERF_SPE_OP_PKT_LDST_SUBCLASS_GET(payload)) {
38948f512ceSopenharmony_ci                case PERF_SPE_OP_PKT_LDST_SUBCLASS_SIMD_FP:
39048f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " SIMD-FP");
39148f512ceSopenharmony_ci                    break;
39248f512ceSopenharmony_ci                case PERF_SPE_OP_PKT_LDST_SUBCLASS_GP_REG:
39348f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " GP-REG");
39448f512ceSopenharmony_ci                    break;
39548f512ceSopenharmony_ci                case PERF_SPE_OP_PKT_LDST_SUBCLASS_UNSPEC_REG:
39648f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " UNSPEC-REG");
39748f512ceSopenharmony_ci                    break;
39848f512ceSopenharmony_ci                case PERF_SPE_OP_PKT_LDST_SUBCLASS_NV_SYSREG:
39948f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " NV-SYSREG");
40048f512ceSopenharmony_ci                    break;
40148f512ceSopenharmony_ci                case PERF_SPE_OP_PKT_LDST_SUBCLASS_MTE_TAG:
40248f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " MTE-TAG");
40348f512ceSopenharmony_ci                    break;
40448f512ceSopenharmony_ci                case PERF_SPE_OP_PKT_LDST_SUBCLASS_MEMCPY:
40548f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " MEMCPY");
40648f512ceSopenharmony_ci                    break;
40748f512ceSopenharmony_ci                case PERF_SPE_OP_PKT_LDST_SUBCLASS_MEMSET:
40848f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " MEMSET");
40948f512ceSopenharmony_ci                    break;
41048f512ceSopenharmony_ci                default:
41148f512ceSopenharmony_ci                    break;
41248f512ceSopenharmony_ci            }
41348f512ceSopenharmony_ci
41448f512ceSopenharmony_ci            if (PERF_SPE_OP_PKT_IS_LDST_SVE(payload)) {
41548f512ceSopenharmony_ci                /* SVE effective vector length */
41648f512ceSopenharmony_ci                SpePktOutString(&err, &buf, &bufLen, " EVLEN %d",
41748f512ceSopenharmony_ci                                PERF_SPE_OP_PKG_SVE_EVL(payload));
41848f512ceSopenharmony_ci
41948f512ceSopenharmony_ci                if (payload & PERF_SPE_OP_PKT_SVE_PRED)
42048f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " PRED");
42148f512ceSopenharmony_ci                if (payload & PERF_SPE_OP_PKT_SVE_SG)
42248f512ceSopenharmony_ci                    SpePktOutString(&err, &buf, &bufLen, " SG");
42348f512ceSopenharmony_ci            }
42448f512ceSopenharmony_ci            break;
42548f512ceSopenharmony_ci        case PERF_SPE_OP_PKT_HDR_CLASS_BR_ERET:
42648f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &bufLen, "B");
42748f512ceSopenharmony_ci
42848f512ceSopenharmony_ci            if (payload & PERF_SPE_OP_PKT_COND)
42948f512ceSopenharmony_ci                SpePktOutString(&err, &buf, &bufLen, " COND");
43048f512ceSopenharmony_ci
43148f512ceSopenharmony_ci            if (PERF_SPE_OP_PKT_IS_INDIRECT_BRANCH(payload))
43248f512ceSopenharmony_ci                SpePktOutString(&err, &buf, &bufLen, " IND");
43348f512ceSopenharmony_ci
43448f512ceSopenharmony_ci            break;
43548f512ceSopenharmony_ci        default:
43648f512ceSopenharmony_ci            /* Unknown packet index */
43748f512ceSopenharmony_ci            err = UN_PRMT;
43848f512ceSopenharmony_ci            break;
43948f512ceSopenharmony_ci    }
44048f512ceSopenharmony_ci
44148f512ceSopenharmony_ci    return err;
44248f512ceSopenharmony_ci}
44348f512ceSopenharmony_ci
44448f512ceSopenharmony_cistatic int SpePktDescAddr(const struct SpePkt *packet,
44548f512ceSopenharmony_ci                          char *buf, size_t bufLen)
44648f512ceSopenharmony_ci{
44748f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
44848f512ceSopenharmony_ci    int ns;
44948f512ceSopenharmony_ci    int el;
45048f512ceSopenharmony_ci    int idx = packet->index;
45148f512ceSopenharmony_ci    int ch;
45248f512ceSopenharmony_ci    int pat;
45348f512ceSopenharmony_ci    u64 payload = packet->payload;
45448f512ceSopenharmony_ci    int err = 0;
45548f512ceSopenharmony_ci    static const char *idxName[] = {"PC", "TGT", "VA", "PA", "PBT"};
45648f512ceSopenharmony_ci
45748f512ceSopenharmony_ci    switch (idx) {
45848f512ceSopenharmony_ci        case PERF_SPE_ADDR_PKT_HDR_INDEX_INS:
45948f512ceSopenharmony_ci        case PERF_SPE_ADDR_PKT_HDR_INDEX_BRANCH:
46048f512ceSopenharmony_ci        case PERF_SPE_ADDR_PKT_HDR_INDEX_PREV_BRANCH:
46148f512ceSopenharmony_ci            ns = !!PERF_SPE_ADDR_PKT_GET_NS(payload);
46248f512ceSopenharmony_ci            el = PERF_SPE_ADDR_PKT_GET_EL(payload);
46348f512ceSopenharmony_ci            payload = PERF_SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
46448f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &bufLen,
46548f512ceSopenharmony_ci                            "%s 0x%llx el%d ns=%d",
46648f512ceSopenharmony_ci                            idxName[idx], payload, el, ns);
46748f512ceSopenharmony_ci            break;
46848f512ceSopenharmony_ci        case PERF_SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT:
46948f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &bufLen,
47048f512ceSopenharmony_ci                            "VA 0x%llx", payload);
47148f512ceSopenharmony_ci            break;
47248f512ceSopenharmony_ci        case PERF_SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS:
47348f512ceSopenharmony_ci            ns = !!PERF_SPE_ADDR_PKT_GET_NS(payload);
47448f512ceSopenharmony_ci            ch = !!PERF_SPE_ADDR_PKT_GET_CH(payload);
47548f512ceSopenharmony_ci            pat = PERF_SPE_ADDR_PKT_GET_PAT(payload);
47648f512ceSopenharmony_ci            payload = PERF_SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
47748f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &bufLen,
47848f512ceSopenharmony_ci                            "PA 0x%llx ns=%d ch=%d pat=%x",
47948f512ceSopenharmony_ci                            payload, ns, ch, pat);
48048f512ceSopenharmony_ci            break;
48148f512ceSopenharmony_ci        default:
48248f512ceSopenharmony_ci            /* Unknown packet index */
48348f512ceSopenharmony_ci            err = UN_PRMT;
48448f512ceSopenharmony_ci            break;
48548f512ceSopenharmony_ci    }
48648f512ceSopenharmony_ci
48748f512ceSopenharmony_ci    return err;
48848f512ceSopenharmony_ci}
48948f512ceSopenharmony_ci
49048f512ceSopenharmony_cistatic int SpePktDesCont(const struct SpePkt *packet,
49148f512ceSopenharmony_ci                         char *buf, size_t bufLen)
49248f512ceSopenharmony_ci{
49348f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
49448f512ceSopenharmony_ci    u64 payload = packet->payload;
49548f512ceSopenharmony_ci    const char *name = SpePktName(packet->type);
49648f512ceSopenharmony_ci    int err = 0;
49748f512ceSopenharmony_ci
49848f512ceSopenharmony_ci    SpePktOutString(&err, &buf, &bufLen, "%s %d ", name,
49948f512ceSopenharmony_ci                    (unsigned short)payload);
50048f512ceSopenharmony_ci
50148f512ceSopenharmony_ci    switch (packet->index) {
50248f512ceSopenharmony_ci        case PERF_SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT:
50348f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &bufLen, "TOT");
50448f512ceSopenharmony_ci            break;
50548f512ceSopenharmony_ci        case PERF_SPE_CNT_PKT_HDR_INDEX_ISSUE_LAT:
50648f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &bufLen, "ISSUE");
50748f512ceSopenharmony_ci            break;
50848f512ceSopenharmony_ci        case PERF_SPE_CNT_PKT_HDR_INDEX_TRANS_LAT:
50948f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &bufLen, "XLAT");
51048f512ceSopenharmony_ci            break;
51148f512ceSopenharmony_ci        default:
51248f512ceSopenharmony_ci            break;
51348f512ceSopenharmony_ci    }
51448f512ceSopenharmony_ci
51548f512ceSopenharmony_ci    return err;
51648f512ceSopenharmony_ci}
51748f512ceSopenharmony_ci
51848f512ceSopenharmony_ciint SpePktDesc(const struct SpePkt *packet, char *buf,
51948f512ceSopenharmony_ci               size_t bufLen)
52048f512ceSopenharmony_ci{
52148f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr || packet == nullptr, -1, 1, "Invalid pointer!");
52248f512ceSopenharmony_ci    int idx = packet->index;
52348f512ceSopenharmony_ci    unsigned long long payload = packet->payload;
52448f512ceSopenharmony_ci    const char *name = SpePktName(packet->type);
52548f512ceSopenharmony_ci    char *bufOrig = buf;
52648f512ceSopenharmony_ci    size_t blen = bufLen;
52748f512ceSopenharmony_ci    int err = 0;
52848f512ceSopenharmony_ci
52948f512ceSopenharmony_ci    switch (packet->type) {
53048f512ceSopenharmony_ci        case PERF_SPE_BAD:
53148f512ceSopenharmony_ci        case PERF_SPE_PAD:
53248f512ceSopenharmony_ci        case PERF_SPE_END:
53348f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &blen, "%s", name);
53448f512ceSopenharmony_ci            break;
53548f512ceSopenharmony_ci        case PERF_SPE_EVENTS:
53648f512ceSopenharmony_ci            err = SpePktDescEvent(packet, buf, bufLen);
53748f512ceSopenharmony_ci            break;
53848f512ceSopenharmony_ci        case PERF_SPE_OP_TYPE:
53948f512ceSopenharmony_ci            err = SpePktDescOpType(packet, buf, bufLen);
54048f512ceSopenharmony_ci            break;
54148f512ceSopenharmony_ci        case PERF_SPE_DATA_SOURCE:
54248f512ceSopenharmony_ci        case PERF_SPE_TIMESTAMP:
54348f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &blen, "%s %lld", name, payload);
54448f512ceSopenharmony_ci            break;
54548f512ceSopenharmony_ci        case PERF_SPE_ADDRESS:
54648f512ceSopenharmony_ci            err = SpePktDescAddr(packet, buf, bufLen);
54748f512ceSopenharmony_ci            break;
54848f512ceSopenharmony_ci        case PERF_SPE_CONTEXT:
54948f512ceSopenharmony_ci            SpePktOutString(&err, &buf, &blen, "%s 0x%lx el%d",
55048f512ceSopenharmony_ci                            name, (unsigned long)payload, idx + 1);
55148f512ceSopenharmony_ci            break;
55248f512ceSopenharmony_ci        case PERF_SPE_COUNTER:
55348f512ceSopenharmony_ci            err = SpePktDesCont(packet, buf, bufLen);
55448f512ceSopenharmony_ci            break;
55548f512ceSopenharmony_ci        default:
55648f512ceSopenharmony_ci            /* Unknown packet type */
55748f512ceSopenharmony_ci            err = UN_PRMT;
55848f512ceSopenharmony_ci            break;
55948f512ceSopenharmony_ci    }
56048f512ceSopenharmony_ci
56148f512ceSopenharmony_ci    /* If any errors are detected, the raw data is output*/
56248f512ceSopenharmony_ci    if (err) {
56348f512ceSopenharmony_ci        err = 0;
56448f512ceSopenharmony_ci        SpePktOutString(&err, &bufOrig, &bufLen, "%s 0x%llx (%d)",
56548f512ceSopenharmony_ci                        name, payload, packet->index);
56648f512ceSopenharmony_ci    }
56748f512ceSopenharmony_ci
56848f512ceSopenharmony_ci    return err;
56948f512ceSopenharmony_ci}
57048f512ceSopenharmony_ci
57148f512ceSopenharmony_cistatic u64 SpeCalcIp(int index, u64 payload)
57248f512ceSopenharmony_ci{
57348f512ceSopenharmony_ci    u64 ns;
57448f512ceSopenharmony_ci    u64 el;
57548f512ceSopenharmony_ci    u64 val;
57648f512ceSopenharmony_ci
57748f512ceSopenharmony_ci    /* Instruction virtual address or Branch target address */
57848f512ceSopenharmony_ci    if (index == PERF_SPE_ADDR_PKT_HDR_INDEX_INS ||
57948f512ceSopenharmony_ci        index == PERF_SPE_ADDR_PKT_HDR_INDEX_BRANCH) {
58048f512ceSopenharmony_ci        ns = PERF_SPE_ADDR_PKT_GET_NS(payload);
58148f512ceSopenharmony_ci        el = PERF_SPE_ADDR_PKT_GET_EL(payload);
58248f512ceSopenharmony_ci
58348f512ceSopenharmony_ci        /* Clean highest byte */
58448f512ceSopenharmony_ci        payload = PERF_SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
58548f512ceSopenharmony_ci
58648f512ceSopenharmony_ci        /* Fill highest byte for EL1 or EL2 (VHE) mode */
58748f512ceSopenharmony_ci        if (ns && (el == PERF_SPE_ADDR_PKT_EL1 || el == PERF_SPE_ADDR_PKT_EL2)) {
58848f512ceSopenharmony_ci            payload |= 0xffULL << PERF_SPE_ADDR_PKT_ADDR_BYTE7_SHIFT;
58948f512ceSopenharmony_ci        }
59048f512ceSopenharmony_ci
59148f512ceSopenharmony_ci    /* Data access virtual address */
59248f512ceSopenharmony_ci    } else if (index == PERF_SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT) {
59348f512ceSopenharmony_ci        /* Clean tags */
59448f512ceSopenharmony_ci        payload = PERF_SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
59548f512ceSopenharmony_ci
59648f512ceSopenharmony_ci        /*
59748f512ceSopenharmony_ci         * Armv8 ARM (ARM DDI 0487F.c), chapter "D10.2.1 Address packet"
59848f512ceSopenharmony_ci         * defines the data virtual address payload format, the top byte
59948f512ceSopenharmony_ci         * (bits [63:56]) is assigned as top-byte tag; so we only can
60048f512ceSopenharmony_ci         * retrieve address value from bits [55:0].
60148f512ceSopenharmony_ci         *
60248f512ceSopenharmony_ci         * According to Documentation/arch/arm64/memory.rst, if detects the
60348f512ceSopenharmony_ci         * specific pattern in bits [55:52] of payload which falls in
60448f512ceSopenharmony_ci         * the kernel space, should fixup the top byte and this allows
60548f512ceSopenharmony_ci         * perf tool to parse DSO symbol for data address correctly.
60648f512ceSopenharmony_ci         *
60748f512ceSopenharmony_ci         * For this reason, if detects the bits [55:52] is 0xf, will
60848f512ceSopenharmony_ci         * fill 0xff into the top byte.
60948f512ceSopenharmony_ci         */
61048f512ceSopenharmony_ci        val = PERF_SPE_ADDR_PKT_ADDR_GET_BYTE_6(payload);
61148f512ceSopenharmony_ci        if ((val & 0xf0ULL) == 0xf0ULL) {
61248f512ceSopenharmony_ci            payload |= 0xffULL << PERF_SPE_ADDR_PKT_ADDR_BYTE7_SHIFT;
61348f512ceSopenharmony_ci        }
61448f512ceSopenharmony_ci
61548f512ceSopenharmony_ci        /* Data access physical address */
61648f512ceSopenharmony_ci    } else if (index == PERF_SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS) {
61748f512ceSopenharmony_ci        /* Clean highest byte */
61848f512ceSopenharmony_ci        payload = PERF_SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);
61948f512ceSopenharmony_ci    } else {
62048f512ceSopenharmony_ci        static u32 seen_idx = 0;
62148f512ceSopenharmony_ci        if (!(seen_idx & BIT(index))) {
62248f512ceSopenharmony_ci            seen_idx |= BIT(index);
62348f512ceSopenharmony_ci            HLOGV("ignoring address packet index: 0x%x\n", index);
62448f512ceSopenharmony_ci        }
62548f512ceSopenharmony_ci    }
62648f512ceSopenharmony_ci
62748f512ceSopenharmony_ci    return payload;
62848f512ceSopenharmony_ci}
62948f512ceSopenharmony_ci
63048f512ceSopenharmony_cistruct SpeDecoder *SpeDecoderNew(struct SpeParams *params)
63148f512ceSopenharmony_ci{
63248f512ceSopenharmony_ci    CHECK_TRUE(params == nullptr, nullptr, 1, "Invalid pointer!");
63348f512ceSopenharmony_ci    struct SpeDecoder *decoder;
63448f512ceSopenharmony_ci
63548f512ceSopenharmony_ci    decoder = static_cast<struct SpeDecoder*>(malloc(sizeof(struct SpeDecoder)));
63648f512ceSopenharmony_ci    if (!decoder) {
63748f512ceSopenharmony_ci        return NULL;
63848f512ceSopenharmony_ci    }
63948f512ceSopenharmony_ci
64048f512ceSopenharmony_ci    decoder->data = params->data;
64148f512ceSopenharmony_ci
64248f512ceSopenharmony_ci    return decoder;
64348f512ceSopenharmony_ci}
64448f512ceSopenharmony_ci
64548f512ceSopenharmony_civoid SpeDecoderFree(struct SpeDecoder *decoder)
64648f512ceSopenharmony_ci{
64748f512ceSopenharmony_ci    CHECK_TRUE(decoder == nullptr, NO_RETVAL, 1, "Invalid pointer!");
64848f512ceSopenharmony_ci    free(decoder);
64948f512ceSopenharmony_ci}
65048f512ceSopenharmony_ci
65148f512ceSopenharmony_cistatic int SpeGetNextPacket(struct SpeDecoder *decoder)
65248f512ceSopenharmony_ci{
65348f512ceSopenharmony_ci    CHECK_TRUE(decoder == nullptr, -1, 1, "Invalid pointer!");
65448f512ceSopenharmony_ci    int ret = 1;
65548f512ceSopenharmony_ci
65648f512ceSopenharmony_ci    do {
65748f512ceSopenharmony_ci        if (!decoder->len) {
65848f512ceSopenharmony_ci            /* Failed to read out trace data */
65948f512ceSopenharmony_ci            if (ret <= 0) {
66048f512ceSopenharmony_ci                return ret;
66148f512ceSopenharmony_ci            }
66248f512ceSopenharmony_ci        }
66348f512ceSopenharmony_ci
66448f512ceSopenharmony_ci        ret = SpeGetPacket(decoder->buf, decoder->len,
66548f512ceSopenharmony_ci                           &decoder->packet);
66648f512ceSopenharmony_ci        if (ret <= 0) {
66748f512ceSopenharmony_ci            /* Move forward for 1 byte */
66848f512ceSopenharmony_ci            decoder->buf += 1;
66948f512ceSopenharmony_ci            decoder->len -= 1;
67048f512ceSopenharmony_ci            return -EBADMSG;
67148f512ceSopenharmony_ci        }
67248f512ceSopenharmony_ci
67348f512ceSopenharmony_ci        decoder->buf += ret;
67448f512ceSopenharmony_ci        decoder->len -= static_cast<size_t>(ret);
67548f512ceSopenharmony_ci    } while (decoder->packet.type == PERF_SPE_PAD);
67648f512ceSopenharmony_ci    return 1;
67748f512ceSopenharmony_ci}
67848f512ceSopenharmony_ci
67948f512ceSopenharmony_cistatic int SpeReadRecord(struct SpeDecoder *decoder)
68048f512ceSopenharmony_ci{
68148f512ceSopenharmony_ci    u64 payload;
68248f512ceSopenharmony_ci    u64 ip;
68348f512ceSopenharmony_ci    CHECK_TRUE(decoder == nullptr, -1, 1, "Invalid pointer!");
68448f512ceSopenharmony_ci    memset_s(&decoder->record, sizeof(decoder->record), 0, sizeof(decoder->record));
68548f512ceSopenharmony_ci    decoder->record.context_id = (u64)-1;
68648f512ceSopenharmony_ci
68748f512ceSopenharmony_ci    while (true) {
68848f512ceSopenharmony_ci        int err = SpeGetNextPacket(decoder);
68948f512ceSopenharmony_ci        if (err <= 0) {
69048f512ceSopenharmony_ci            return err;
69148f512ceSopenharmony_ci        }
69248f512ceSopenharmony_ci
69348f512ceSopenharmony_ci        int idx = decoder->packet.index;
69448f512ceSopenharmony_ci        payload = decoder->packet.payload;
69548f512ceSopenharmony_ci
69648f512ceSopenharmony_ci        switch (decoder->packet.type) {
69748f512ceSopenharmony_ci            case PERF_SPE_TIMESTAMP:
69848f512ceSopenharmony_ci                decoder->record.timestamp = payload;
69948f512ceSopenharmony_ci                return 1;
70048f512ceSopenharmony_ci            case PERF_SPE_END:
70148f512ceSopenharmony_ci                return 1;
70248f512ceSopenharmony_ci            case PERF_SPE_ADDRESS:
70348f512ceSopenharmony_ci                ip = SpeCalcIp(idx, payload);
70448f512ceSopenharmony_ci                if (idx == PERF_SPE_ADDR_PKT_HDR_INDEX_INS) {
70548f512ceSopenharmony_ci                    decoder->record.from_ip = ip;
70648f512ceSopenharmony_ci                } else if (idx == PERF_SPE_ADDR_PKT_HDR_INDEX_BRANCH) {
70748f512ceSopenharmony_ci                    decoder->record.to_ip = ip;
70848f512ceSopenharmony_ci                } else if (idx == PERF_SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT) {
70948f512ceSopenharmony_ci                    decoder->record.virt_addr = ip;
71048f512ceSopenharmony_ci                } else if (idx == PERF_SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS) {
71148f512ceSopenharmony_ci                    decoder->record.phys_addr = ip;
71248f512ceSopenharmony_ci                }
71348f512ceSopenharmony_ci                break;
71448f512ceSopenharmony_ci            case PERF_SPE_COUNTER:
71548f512ceSopenharmony_ci                if (idx == PERF_SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT) {
71648f512ceSopenharmony_ci                    decoder->record.latency = payload;
71748f512ceSopenharmony_ci                }
71848f512ceSopenharmony_ci                break;
71948f512ceSopenharmony_ci            case PERF_SPE_CONTEXT:
72048f512ceSopenharmony_ci                decoder->record.context_id = payload;
72148f512ceSopenharmony_ci                break;
72248f512ceSopenharmony_ci            case PERF_SPE_OP_TYPE:
72348f512ceSopenharmony_ci                switch (idx) {
72448f512ceSopenharmony_ci                    case PERF_SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC:
72548f512ceSopenharmony_ci                        decoder->record.op |= PERF_SPE_OP_LDST;
72648f512ceSopenharmony_ci                        if (payload & PERF_SPE_OP_PKT_ST) {
72748f512ceSopenharmony_ci                            decoder->record.op |= PERF_SPE_OP_ST;
72848f512ceSopenharmony_ci                        } else {
72948f512ceSopenharmony_ci                            decoder->record.op |= PERF_SPE_OP_LD;
73048f512ceSopenharmony_ci                        }
73148f512ceSopenharmony_ci
73248f512ceSopenharmony_ci                        if (PERF_SPE_OP_PKT_IS_LDST_SVE(payload)) {
73348f512ceSopenharmony_ci                            decoder->record.op |= PERF_SPE_OP_SVE_LDST;
73448f512ceSopenharmony_ci                        }
73548f512ceSopenharmony_ci                        break;
73648f512ceSopenharmony_ci                    case PERF_SPE_OP_PKT_HDR_CLASS_OTHER:
73748f512ceSopenharmony_ci                        decoder->record.op |= PERF_SPE_OP_OTHER;
73848f512ceSopenharmony_ci                        if (PERF_SPE_OP_PKT_IS_OTHER_SVE_OP(payload)) {
73948f512ceSopenharmony_ci                            decoder->record.op |= PERF_SPE_OP_SVE_OTHER;
74048f512ceSopenharmony_ci                        }
74148f512ceSopenharmony_ci                        break;
74248f512ceSopenharmony_ci                    case PERF_SPE_OP_PKT_HDR_CLASS_BR_ERET:
74348f512ceSopenharmony_ci                        decoder->record.op |= PERF_SPE_OP_BRANCH_ERET;
74448f512ceSopenharmony_ci                        break;
74548f512ceSopenharmony_ci                    default:
74648f512ceSopenharmony_ci                        HLOGV("Get packet error!");
74748f512ceSopenharmony_ci                }
74848f512ceSopenharmony_ci                break;
74948f512ceSopenharmony_ci            case PERF_SPE_EVENTS:
75048f512ceSopenharmony_ci                if (payload & BIT(EVENT_L1D_REFILL)) {
75148f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_L1D_MISS;
75248f512ceSopenharmony_ci                }
75348f512ceSopenharmony_ci
75448f512ceSopenharmony_ci                if (payload & BIT(EVENT_L1D_ACCESS)) {
75548f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_L1D_ACCESS;
75648f512ceSopenharmony_ci                }
75748f512ceSopenharmony_ci
75848f512ceSopenharmony_ci                if (payload & BIT(EVENT_TLB_WALK)) {
75948f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_TLB_MISS;
76048f512ceSopenharmony_ci                }
76148f512ceSopenharmony_ci
76248f512ceSopenharmony_ci                if (payload & BIT(EVENT_TLB_ACCESS)) {
76348f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_TLB_ACCESS;
76448f512ceSopenharmony_ci                }
76548f512ceSopenharmony_ci
76648f512ceSopenharmony_ci                if (payload & BIT(EVENT_LLC_MISS)) {
76748f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_LLC_MISS;
76848f512ceSopenharmony_ci                }
76948f512ceSopenharmony_ci
77048f512ceSopenharmony_ci                if (payload & BIT(EVENT_LLC_ACCESS)) {
77148f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_LLC_ACCESS;
77248f512ceSopenharmony_ci                }
77348f512ceSopenharmony_ci
77448f512ceSopenharmony_ci                if (payload & BIT(EVENT_REMOTE_ACCESS)) {
77548f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_REMOTE_ACCESS;
77648f512ceSopenharmony_ci                }
77748f512ceSopenharmony_ci
77848f512ceSopenharmony_ci                if (payload & BIT(EVENT_MISPRED)) {
77948f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_BRANCH_MISS;
78048f512ceSopenharmony_ci                }
78148f512ceSopenharmony_ci
78248f512ceSopenharmony_ci                if (payload & BIT(EVENT_PARTIAL_PREDICATE)) {
78348f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_SVE_PARTIAL_PRED;
78448f512ceSopenharmony_ci                }
78548f512ceSopenharmony_ci
78648f512ceSopenharmony_ci                if (payload & BIT(EVENT_EMPTY_PREDICATE)) {
78748f512ceSopenharmony_ci                    decoder->record.type |= PERF_SPE_SVE_EMPTY_PRED;
78848f512ceSopenharmony_ci                }
78948f512ceSopenharmony_ci                break;
79048f512ceSopenharmony_ci            case PERF_SPE_DATA_SOURCE:
79148f512ceSopenharmony_ci                decoder->record.source = payload;
79248f512ceSopenharmony_ci                break;
79348f512ceSopenharmony_ci            case PERF_SPE_BAD:
79448f512ceSopenharmony_ci                break;
79548f512ceSopenharmony_ci            case PERF_SPE_PAD:
79648f512ceSopenharmony_ci                break;
79748f512ceSopenharmony_ci            default:
79848f512ceSopenharmony_ci                printf("Get packet error!\n");
79948f512ceSopenharmony_ci                return -1;
80048f512ceSopenharmony_ci        }
80148f512ceSopenharmony_ci    }
80248f512ceSopenharmony_ci    return 0;
80348f512ceSopenharmony_ci}
80448f512ceSopenharmony_ci
80548f512ceSopenharmony_ciint SpeDecode(struct SpeDecoder *decoder)
80648f512ceSopenharmony_ci{
80748f512ceSopenharmony_ci    CHECK_TRUE(decoder == nullptr, -1, 1, "Invalid pointer!");
80848f512ceSopenharmony_ci    return SpeReadRecord(decoder);
80948f512ceSopenharmony_ci}
81048f512ceSopenharmony_ci
81148f512ceSopenharmony_cistruct SpeDecoder *SpeDecoderDataNew(const unsigned char *speBuf, size_t speLen)
81248f512ceSopenharmony_ci{
81348f512ceSopenharmony_ci    CHECK_TRUE(speBuf == nullptr, nullptr, 1, "Invalid pointer!");
81448f512ceSopenharmony_ci    struct SpeDecoder *decoder;
81548f512ceSopenharmony_ci
81648f512ceSopenharmony_ci    decoder = reinterpret_cast<SpeDecoder *>(malloc(sizeof(struct SpeDecoder)));
81748f512ceSopenharmony_ci    if (!decoder) {
81848f512ceSopenharmony_ci        return NULL;
81948f512ceSopenharmony_ci    }
82048f512ceSopenharmony_ci    memset_s(decoder, sizeof(struct SpeDecoder), 0, sizeof(struct SpeDecoder));
82148f512ceSopenharmony_ci
82248f512ceSopenharmony_ci    decoder->buf = speBuf;
82348f512ceSopenharmony_ci    decoder->len = speLen;
82448f512ceSopenharmony_ci
82548f512ceSopenharmony_ci    return decoder;
82648f512ceSopenharmony_ci}
82748f512ceSopenharmony_ci
82848f512ceSopenharmony_cibool SpeDumpRawData(unsigned char *buf, size_t len, int indent, FILE *outputDump)
82948f512ceSopenharmony_ci{
83048f512ceSopenharmony_ci    CHECK_TRUE(buf == nullptr, false, 1, "Invalid pointer!");
83148f512ceSopenharmony_ci    if (outputDump != nullptr) {
83248f512ceSopenharmony_ci        g_outputDump = outputDump;
83348f512ceSopenharmony_ci    }
83448f512ceSopenharmony_ci    struct SpePkt packet;
83548f512ceSopenharmony_ci    size_t pos = 0;
83648f512ceSopenharmony_ci    int pktLen;
83748f512ceSopenharmony_ci    int i;
83848f512ceSopenharmony_ci    char desc[PERF_SPE_PKT_DESC_MAX];
83948f512ceSopenharmony_ci
84048f512ceSopenharmony_ci    PRINT_INDENT(indent, ". ... ARM SPE data: size %#zx bytes\n", len);
84148f512ceSopenharmony_ci    while (len) {
84248f512ceSopenharmony_ci        int ret = SpeGetPacket(buf, len, &packet);
84348f512ceSopenharmony_ci        if (ret > 0) {
84448f512ceSopenharmony_ci            pktLen = ret;
84548f512ceSopenharmony_ci        } else {
84648f512ceSopenharmony_ci            pktLen = 1;
84748f512ceSopenharmony_ci        }
84848f512ceSopenharmony_ci        PRINT_INDENT(indent, ".");
84948f512ceSopenharmony_ci        PRINT_INDENT(indent, "  %08zx: ", pos);
85048f512ceSopenharmony_ci        for (i = 0; i < pktLen; i++) {
85148f512ceSopenharmony_ci            PRINT_INDENT(indent, " %02x", buf[i]);
85248f512ceSopenharmony_ci        }
85348f512ceSopenharmony_ci        for (; i < 16; i++) { // 16 : space
85448f512ceSopenharmony_ci            PRINT_INDENT(indent, "   ");
85548f512ceSopenharmony_ci        }
85648f512ceSopenharmony_ci        if (ret > 0) {
85748f512ceSopenharmony_ci            ret = SpePktDesc(&packet, desc,
85848f512ceSopenharmony_ci                             PERF_SPE_PKT_DESC_MAX);
85948f512ceSopenharmony_ci            if (!ret) {
86048f512ceSopenharmony_ci                PRINT_INDENT(indent, " %s\n", desc);
86148f512ceSopenharmony_ci            }
86248f512ceSopenharmony_ci        } else {
86348f512ceSopenharmony_ci            PRINT_INDENT(indent, " Bad packet!\n");
86448f512ceSopenharmony_ci        }
86548f512ceSopenharmony_ci        pos += static_cast<size_t>(pktLen);
86648f512ceSopenharmony_ci        buf += pktLen;
86748f512ceSopenharmony_ci        if (len >= static_cast<size_t>(pktLen)) {
86848f512ceSopenharmony_ci            len -= static_cast<size_t>(pktLen);
86948f512ceSopenharmony_ci        } else {
87048f512ceSopenharmony_ci            break;
87148f512ceSopenharmony_ci        }
87248f512ceSopenharmony_ci    }
87348f512ceSopenharmony_ci    return true;
87448f512ceSopenharmony_ci}
87548f512ceSopenharmony_ci
87648f512ceSopenharmony_cistd::map<u32, std::map<u64, ReportItemAuxRawData>> AuxRawDataMap_;
87748f512ceSopenharmony_cistd::map<u32, u64> typeCount;
87848f512ceSopenharmony_ci
87948f512ceSopenharmony_ciconst std::vector<u32> DEFAULT_SPE_EVENT_TYPE = {
88048f512ceSopenharmony_ci    PERF_SPE_L1D_ACCESS,
88148f512ceSopenharmony_ci    PERF_SPE_L1D_MISS,
88248f512ceSopenharmony_ci    PERF_SPE_LLC_ACCESS,
88348f512ceSopenharmony_ci    PERF_SPE_LLC_MISS,
88448f512ceSopenharmony_ci    PERF_SPE_TLB_ACCESS,
88548f512ceSopenharmony_ci    PERF_SPE_TLB_MISS,
88648f512ceSopenharmony_ci    PERF_SPE_BRANCH_MISS,
88748f512ceSopenharmony_ci    PERF_SPE_REMOTE_ACCESS,
88848f512ceSopenharmony_ci    PERF_SPE_SVE_PARTIAL_PRED,
88948f512ceSopenharmony_ci    PERF_SPE_SVE_EMPTY_PRED,
89048f512ceSopenharmony_ci};
89148f512ceSopenharmony_ci
89248f512ceSopenharmony_ciconstexpr const int SPE_PERCENTAGE_COMM_LEN = 40;
89348f512ceSopenharmony_ciconstexpr const int SPE_PERCENTAGE_PC_LEN = 18;
89448f512ceSopenharmony_ciconstexpr const int SPE_PERCENTAGE_DSO_LEN = 50;
89548f512ceSopenharmony_ciconstexpr const int SPE_PERCENTAGE_FUNC_LEN = 60;
89648f512ceSopenharmony_ciconstexpr const int SPE_PERCENTAGE_OFFSET_LEN = 20;
89748f512ceSopenharmony_ci
89848f512ceSopenharmony_civoid AddReportItems(const std::vector<ReportItemAuxRawData>& auxRawData)
89948f512ceSopenharmony_ci{
90048f512ceSopenharmony_ci    for (const auto& data : auxRawData) {
90148f512ceSopenharmony_ci        for (auto type : DEFAULT_SPE_EVENT_TYPE) {
90248f512ceSopenharmony_ci            if (data.type & type) {
90348f512ceSopenharmony_ci                if (typeCount.count(type) == 0) {
90448f512ceSopenharmony_ci                    typeCount[type] = 1;
90548f512ceSopenharmony_ci                } else {
90648f512ceSopenharmony_ci                    typeCount[type]++;
90748f512ceSopenharmony_ci                }
90848f512ceSopenharmony_ci                std::map<u64, ReportItemAuxRawData>& map = AuxRawDataMap_[type];
90948f512ceSopenharmony_ci
91048f512ceSopenharmony_ci                auto data1 = map.find(data.pc);
91148f512ceSopenharmony_ci                if (data1 == map.end()) {
91248f512ceSopenharmony_ci                    HLOGV("add %llx", data.pc);
91348f512ceSopenharmony_ci                    map[data.pc] = {type, 0.0f, 1, data.comm, data.pc, data.SharedObject, data.Symbol, data.offset};
91448f512ceSopenharmony_ci                } else {
91548f512ceSopenharmony_ci                    HLOGV("add pc: %llx", data.pc);
91648f512ceSopenharmony_ci                    data1->second.count++;
91748f512ceSopenharmony_ci                    HLOGV("add pc: %llx count: %llu", data.pc, data1->second.count);
91848f512ceSopenharmony_ci                }
91948f512ceSopenharmony_ci            }
92048f512ceSopenharmony_ci        }
92148f512ceSopenharmony_ci    }
92248f512ceSopenharmony_ci}
92348f512ceSopenharmony_ci
92448f512ceSopenharmony_civoid UpdateHeating()
92548f512ceSopenharmony_ci{
92648f512ceSopenharmony_ci    for (auto it = AuxRawDataMap_.begin(); it != AuxRawDataMap_.end(); it++) {
92748f512ceSopenharmony_ci        u64 cc = typeCount[it->first];
92848f512ceSopenharmony_ci        for (auto& it2 : it->second) {
92948f512ceSopenharmony_ci            float heating = (float)it2.second.count / cc * FULL_PERCENTAGE;
93048f512ceSopenharmony_ci            HLOGV("heating %llu/%llu %f", it2.second.count, cc, heating);
93148f512ceSopenharmony_ci            it2.second.heating = heating;
93248f512ceSopenharmony_ci        }
93348f512ceSopenharmony_ci    }
93448f512ceSopenharmony_ci}
93548f512ceSopenharmony_ci
93648f512ceSopenharmony_civoid GetSpeEventNameByType(uint32_t type, std::string& eventName)
93748f512ceSopenharmony_ci{
93848f512ceSopenharmony_ci    switch (type) {
93948f512ceSopenharmony_ci        case PERF_SPE_L1D_ACCESS:
94048f512ceSopenharmony_ci            eventName = "l1d-access";
94148f512ceSopenharmony_ci            break;
94248f512ceSopenharmony_ci        case PERF_SPE_L1D_MISS:
94348f512ceSopenharmony_ci            eventName = "l1d-miss";
94448f512ceSopenharmony_ci            break;
94548f512ceSopenharmony_ci        case PERF_SPE_LLC_ACCESS:
94648f512ceSopenharmony_ci            eventName = "llc-access";
94748f512ceSopenharmony_ci            break;
94848f512ceSopenharmony_ci        case PERF_SPE_LLC_MISS:
94948f512ceSopenharmony_ci            eventName = "llc-miss";
95048f512ceSopenharmony_ci            break;
95148f512ceSopenharmony_ci        case PERF_SPE_TLB_ACCESS:
95248f512ceSopenharmony_ci            eventName = "tlb-access";
95348f512ceSopenharmony_ci            break;
95448f512ceSopenharmony_ci        case PERF_SPE_TLB_MISS:
95548f512ceSopenharmony_ci            eventName = "tlb-miss";
95648f512ceSopenharmony_ci            break;
95748f512ceSopenharmony_ci        case PERF_SPE_BRANCH_MISS:
95848f512ceSopenharmony_ci            eventName = "branch-miss";
95948f512ceSopenharmony_ci            break;
96048f512ceSopenharmony_ci        case PERF_SPE_REMOTE_ACCESS:
96148f512ceSopenharmony_ci            eventName = "remote-access";
96248f512ceSopenharmony_ci            break;
96348f512ceSopenharmony_ci        case PERF_SPE_SVE_PARTIAL_PRED:
96448f512ceSopenharmony_ci            eventName = "paritial_read";
96548f512ceSopenharmony_ci            break;
96648f512ceSopenharmony_ci        case PERF_SPE_SVE_EMPTY_PRED:
96748f512ceSopenharmony_ci            eventName = "empty_read";
96848f512ceSopenharmony_ci            break;
96948f512ceSopenharmony_ci        default:
97048f512ceSopenharmony_ci            eventName = "unknow";
97148f512ceSopenharmony_ci            return;
97248f512ceSopenharmony_ci        }
97348f512ceSopenharmony_ci}
97448f512ceSopenharmony_ci
97548f512ceSopenharmony_civoid DumpSpeReportHead(int indent, uint32_t type, uint64_t count)
97648f512ceSopenharmony_ci{
97748f512ceSopenharmony_ci    std::string eventName = "";
97848f512ceSopenharmony_ci    GetSpeEventNameByType(type, eventName);
97948f512ceSopenharmony_ci    PRINT_INDENT(indent, "\nEvent :%s\n", eventName.c_str());
98048f512ceSopenharmony_ci    PRINT_INDENT(indent, "Samples Count: %" PRIu64 "\n", count);
98148f512ceSopenharmony_ci
98248f512ceSopenharmony_ci    // head print
98348f512ceSopenharmony_ci    const std::string head = "Heating";
98448f512ceSopenharmony_ci    PRINT_INDENT(indent, "%-*s ", FULL_PERCENTAGE_LEN, head.c_str());
98548f512ceSopenharmony_ci    const std::string eventCount = "   count";
98648f512ceSopenharmony_ci    PRINT_INDENT(indent, "%-*s ", FULL_PERCENTAGE_LEN, eventCount.c_str());
98748f512ceSopenharmony_ci    const std::string comm = "    comm";
98848f512ceSopenharmony_ci    PRINT_INDENT(indent, "%-*s ", SPE_PERCENTAGE_COMM_LEN, comm.c_str());
98948f512ceSopenharmony_ci    const std::string pc = "      PC";
99048f512ceSopenharmony_ci    PRINT_INDENT(indent, "%-*s ", SPE_PERCENTAGE_PC_LEN, pc.c_str());
99148f512ceSopenharmony_ci    const std::string dso = "          dso";
99248f512ceSopenharmony_ci    PRINT_INDENT(indent, "%-*s ", SPE_PERCENTAGE_DSO_LEN, dso.c_str());
99348f512ceSopenharmony_ci    const std::string func = "            func";
99448f512ceSopenharmony_ci    PRINT_INDENT(indent, "%-*s", SPE_PERCENTAGE_FUNC_LEN, func.c_str());
99548f512ceSopenharmony_ci    const std::string offset = "              offset";
99648f512ceSopenharmony_ci    PRINT_INDENT(indent, "%-*s\n", SPE_PERCENTAGE_OFFSET_LEN, offset.c_str());
99748f512ceSopenharmony_ci    return;
99848f512ceSopenharmony_ci}
99948f512ceSopenharmony_ci
100048f512ceSopenharmony_civoid DumpSpeReportData(int indent, FILE *outputDump)
100148f512ceSopenharmony_ci{
100248f512ceSopenharmony_ci    if (outputDump != nullptr) {
100348f512ceSopenharmony_ci        g_outputDump = outputDump;
100448f512ceSopenharmony_ci    }
100548f512ceSopenharmony_ci    if (AuxRawDataMap_.empty()) {
100648f512ceSopenharmony_ci        return;
100748f512ceSopenharmony_ci    }
100848f512ceSopenharmony_ci    PRINT_INDENT(indent, "\n ==== Spe Report Data ====\n");
100948f512ceSopenharmony_ci    for (auto it = AuxRawDataMap_.begin(); it != AuxRawDataMap_.end(); it++) {
101048f512ceSopenharmony_ci        u64 count = typeCount[it->first];
101148f512ceSopenharmony_ci        DumpSpeReportHead(indent, it->first, count);
101248f512ceSopenharmony_ci        for (auto& it2 : it->second) {
101348f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "%*.2f%% ", FULL_PERCENTAGE_LEN, it2.second.heating);
101448f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "%-*llu ", FULL_PERCENTAGE_LEN, it2.second.count);
101548f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "%-*s ", SPE_PERCENTAGE_COMM_LEN, it2.second.comm.c_str());
101648f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "0x%-*llx ", SPE_PERCENTAGE_PC_LEN, it2.second.pc);
101748f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "%-*s ", SPE_PERCENTAGE_DSO_LEN, it2.second.SharedObject.c_str());
101848f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "%-*s", SPE_PERCENTAGE_FUNC_LEN, it2.second.Symbol.c_str());
101948f512ceSopenharmony_ci            PRINT_INDENT(indent + 1, "0x%llx\n", it2.second.offset);
102048f512ceSopenharmony_ci        }
102148f512ceSopenharmony_ci    }
102248f512ceSopenharmony_ci}
102348f512ceSopenharmony_ci} // namespace HiPerf
102448f512ceSopenharmony_ci} // namespace Developtools
102548f512ceSopenharmony_ci} // namespace OHOS
1026