106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include "stack_preprocess.h"
1706f6ba60Sopenharmony_ci
1806f6ba60Sopenharmony_ci#include <elf.h>
1906f6ba60Sopenharmony_ci#include <unistd.h>
2006f6ba60Sopenharmony_ci
2106f6ba60Sopenharmony_ci#include "common.h"
2206f6ba60Sopenharmony_ci#include "logging.h"
2306f6ba60Sopenharmony_ci#include "plugin_service_types.pb.h"
2406f6ba60Sopenharmony_ci#include "dfx_elf.h"
2506f6ba60Sopenharmony_ci#include "utilities.h"
2606f6ba60Sopenharmony_ci#include "native_hook_result_standard.pb.h"
2706f6ba60Sopenharmony_ci#include "native_hook_config_standard.pb.h"
2806f6ba60Sopenharmony_ci#include "google/protobuf/text_format.h"
2906f6ba60Sopenharmony_ci#include "trace_file_writer.h"
3006f6ba60Sopenharmony_ci
3106f6ba60Sopenharmony_ci
3206f6ba60Sopenharmony_ciconstexpr static uint32_t SC_LG_TINY_MIN = 3;
3306f6ba60Sopenharmony_ciconstexpr static uint32_t LG_QUANTUM = 4;
3406f6ba60Sopenharmony_ciconstexpr static uint32_t SC_NTINY = LG_QUANTUM - SC_LG_TINY_MIN;
3506f6ba60Sopenharmony_ciconstexpr static uint32_t SC_LG_TINY_MAXCLASS = (LG_QUANTUM > SC_LG_TINY_MIN ? LG_QUANTUM - 1 : -1);
3606f6ba60Sopenharmony_ciconstexpr static uint32_t SC_LG_NGROUP = 2;
3706f6ba60Sopenharmony_ciconstexpr static uint32_t LG_SIZE_CLASS_GROUP = 2;
3806f6ba60Sopenharmony_ciconstexpr static uint32_t NTBINS = 1;
3906f6ba60Sopenharmony_ciconstexpr static uint32_t LG_TINY_MAXCLASS = 3;
4006f6ba60Sopenharmony_ciconstexpr static uint32_t MAX_MATCH_CNT = 1000;
4106f6ba60Sopenharmony_ciconstexpr static uint32_t MAX_MATCH_INTERVAL = 3600;
4206f6ba60Sopenharmony_ciconstexpr static uint32_t LOG_PRINT_TIMES = 10000;
4306f6ba60Sopenharmony_ciconstexpr static uint32_t WAIT_STOP_TIME = 5000;
4406f6ba60Sopenharmony_ciconstexpr static uint32_t WAIT_TIME_ONCE = 10;
4506f6ba60Sopenharmony_ciconstexpr static uint32_t MAX_BATCH_CNT = 40;
4606f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_1 = 1;
4706f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_2 = 2;
4806f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_4 = 4;
4906f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_8 = 8;
5006f6ba60Sopenharmony_ciconstexpr static uint32_t RIGHT_MOVE_16 = 16;
5106f6ba60Sopenharmony_ciconstexpr static uint64_t SIZE_MASK = 0xFFFFFF0000000000;
5206f6ba60Sopenharmony_ciconstexpr static uint64_t JS_OFFLINE_IP_MASK = 0xFFFFFE0000000000;
5306f6ba60Sopenharmony_ciconstexpr static uint64_t DWARF_ERROR_ID = 999999;
5406f6ba60Sopenharmony_ciconstexpr static uint64_t DWARF_NAPI_CALLBACK = 999999;
5506f6ba60Sopenharmony_cistatic std::string JS_CALL_STACK_DEPTH_SEP = ",";   // ',' is js call stack depth separator
5606f6ba60Sopenharmony_cistatic std::string JS_SYMBOL_FILEPATH_SEP = "|";    // '|' is js symbol and filepath separator
5706f6ba60Sopenharmony_ciconstexpr static int NAPI_CALL_STACK = 2; // just for napi call stack
5806f6ba60Sopenharmony_ciconstexpr static uint32_t FRAME_DEPTH = 2; // add two frames
5906f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG
6006f6ba60Sopenharmony_ciconstexpr static uint32_t LONG_TIME_THRESHOLD = 1000000;
6106f6ba60Sopenharmony_cistatic std::atomic<uint64_t> timeCost = 0;
6206f6ba60Sopenharmony_cistatic std::atomic<uint64_t> unwindTimes = 0;
6306f6ba60Sopenharmony_ci#endif
6406f6ba60Sopenharmony_ci
6506f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::NativeDaemon;
6606f6ba60Sopenharmony_ciusing namespace OHOS::HiviewDFX;
6706f6ba60Sopenharmony_ciusing namespace OHOS::Developtools::Profiler;
6806f6ba60Sopenharmony_ci
6906f6ba60Sopenharmony_ciStackPreprocess::StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const NativeHookConfig& hookConfig,
7006f6ba60Sopenharmony_ci    clockid_t pluginDataClockId, FILE* fpHookData, bool isHookStandalone, bool isSaService, bool isProtobufSerialize)
7106f6ba60Sopenharmony_ci    : dataRepeater_(dataRepeater), hookConfig_(hookConfig), pluginDataClockId_(pluginDataClockId),
7206f6ba60Sopenharmony_ci      fpHookData_(fpHookData), isHookStandaloneSerialize_(isHookStandalone), isSaService_(isSaService),
7306f6ba60Sopenharmony_ci      isProtobufSerialize_(isProtobufSerialize)
7406f6ba60Sopenharmony_ci{
7506f6ba60Sopenharmony_ci    runtime_instance = std::make_shared<VirtualRuntime>(hookConfig_);
7606f6ba60Sopenharmony_ci
7706f6ba60Sopenharmony_ci    if (hookConfig_.malloc_free_matching_interval() > MAX_MATCH_INTERVAL) {
7806f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "Not support set %d", hookConfig_.malloc_free_matching_interval());
7906f6ba60Sopenharmony_ci        hookConfig_.set_malloc_free_matching_interval(MAX_MATCH_INTERVAL);
8006f6ba60Sopenharmony_ci    }
8106f6ba60Sopenharmony_ci
8206f6ba60Sopenharmony_ci    if (hookConfig_.malloc_free_matching_cnt() > MAX_MATCH_CNT) {
8306f6ba60Sopenharmony_ci        PROFILER_LOG_INFO(LOG_CORE, "Not support set %d", hookConfig_.malloc_free_matching_cnt());
8406f6ba60Sopenharmony_ci        hookConfig_.set_malloc_free_matching_cnt(MAX_MATCH_CNT);
8506f6ba60Sopenharmony_ci    }
8606f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "malloc_free_matching_interval = %d malloc_free_matching_cnt = %d\n",
8706f6ba60Sopenharmony_ci        hookConfig_.malloc_free_matching_interval(), hookConfig_.malloc_free_matching_cnt());
8806f6ba60Sopenharmony_ci
8906f6ba60Sopenharmony_ci    if (hookConfig_.statistics_interval() > 0) {
9006f6ba60Sopenharmony_ci        statisticsInterval_ = std::chrono::seconds(hookConfig_.statistics_interval());
9106f6ba60Sopenharmony_ci        recordStatisticsMap_.reserve(STATISTICS_MAP_SZIE);
9206f6ba60Sopenharmony_ci        statisticsPeriodData_.reserve(STATISTICS_PERIOD_DATA_SIZE);
9306f6ba60Sopenharmony_ci        allocAddrMap_.reserve(ALLOC_ADDRMAMP_SIZE);
9406f6ba60Sopenharmony_ci    }
9506f6ba60Sopenharmony_ci    if (hookConfig_.malloc_free_matching_interval() > 0) {
9606f6ba60Sopenharmony_ci        applyAndReleaseMatchInterval_ = std::chrono::seconds(hookConfig_.malloc_free_matching_interval());
9706f6ba60Sopenharmony_ci        applyAndReleaseMatchIntervallMap_.reserve(MATCH_ADDRMAMP_SIZE);
9806f6ba60Sopenharmony_ci    }
9906f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "statistics_interval = %d statisticsInterval_ = %lld \n",
10006f6ba60Sopenharmony_ci        hookConfig_.statistics_interval(), statisticsInterval_.count());
10106f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "applyAndReleaseMatchInterval_ = %lld", applyAndReleaseMatchInterval_.count());
10206f6ba60Sopenharmony_ci    hookDataClockId_ = COMMON::GetClockId(hookConfig_.clock());
10306f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "StackPreprocess(): pluginDataClockId = %d hookDataClockId = %d \n",
10406f6ba60Sopenharmony_ci        pluginDataClockId_, hookDataClockId_);
10506f6ba60Sopenharmony_ci    if (hookConfig_.save_file() && fpHookData_ == nullptr) {
10606f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "If you need to save the file, please set the file_name");
10706f6ba60Sopenharmony_ci    }
10806f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "isHookStandaloneSerialize_ = %d", isHookStandaloneSerialize_);
10906f6ba60Sopenharmony_ci#if defined(__arm__)
11006f6ba60Sopenharmony_ci    u64regs_.resize(PERF_REG_ARM_MAX);
11106f6ba60Sopenharmony_ci#else
11206f6ba60Sopenharmony_ci    u64regs_.resize(PERF_REG_ARM64_MAX);
11306f6ba60Sopenharmony_ci#endif
11406f6ba60Sopenharmony_ci    callFrames_.reserve(hookConfig_.max_stack_depth() + hookConfig_.max_js_stack_depth());
11506f6ba60Sopenharmony_ci    if (hookConfig_.fp_unwind() && hookConfig_.js_stack_report() > 0) {
11606f6ba60Sopenharmony_ci        fpJsCallStacks_.reserve(hookConfig_.max_js_stack_depth());
11706f6ba60Sopenharmony_ci    }
11806f6ba60Sopenharmony_ci}
11906f6ba60Sopenharmony_ci
12006f6ba60Sopenharmony_ciStackPreprocess::~StackPreprocess()
12106f6ba60Sopenharmony_ci{
12206f6ba60Sopenharmony_ci    isStopTakeData_ = true;
12306f6ba60Sopenharmony_ci    if (dataRepeater_) {
12406f6ba60Sopenharmony_ci        dataRepeater_->Close();
12506f6ba60Sopenharmony_ci    }
12606f6ba60Sopenharmony_ci    if (thread_.joinable()) {
12706f6ba60Sopenharmony_ci        thread_.join();
12806f6ba60Sopenharmony_ci    }
12906f6ba60Sopenharmony_ci    runtime_instance = nullptr;
13006f6ba60Sopenharmony_ci    fpHookData_ = nullptr;
13106f6ba60Sopenharmony_ci}
13206f6ba60Sopenharmony_ci
13306f6ba60Sopenharmony_civoid StackPreprocess::FinishTraceFile()
13406f6ba60Sopenharmony_ci{
13506f6ba60Sopenharmony_ci    if (isSaService_) {
13606f6ba60Sopenharmony_ci        std::shared_ptr<TraceFileWriter> tfPtr = std::static_pointer_cast<TraceFileWriter>(writer_);
13706f6ba60Sopenharmony_ci        tfPtr->SetDurationTime();
13806f6ba60Sopenharmony_ci        tfPtr->Finish();
13906f6ba60Sopenharmony_ci    }
14006f6ba60Sopenharmony_ci}
14106f6ba60Sopenharmony_ci
14206f6ba60Sopenharmony_civoid StackPreprocess::SetWriter(const std::shared_ptr<Writer>& writer)
14306f6ba60Sopenharmony_ci{
14406f6ba60Sopenharmony_ci    writer_ = writer;
14506f6ba60Sopenharmony_ci    if (!isSaService_) {
14606f6ba60Sopenharmony_ci        stackData_ = BatchNativeHookData();
14706f6ba60Sopenharmony_ci    }
14806f6ba60Sopenharmony_ci}
14906f6ba60Sopenharmony_ci
15006f6ba60Sopenharmony_civoid StackPreprocess::SetWriter(const WriterStructPtr& writer)
15106f6ba60Sopenharmony_ci{
15206f6ba60Sopenharmony_ci    resultWriter_ = writer;
15306f6ba60Sopenharmony_ci    auto ctx = resultWriter_->startReport(resultWriter_);
15406f6ba60Sopenharmony_ci    if (ctx == nullptr) {
15506f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__);
15606f6ba60Sopenharmony_ci        return;
15706f6ba60Sopenharmony_ci    }
15806f6ba60Sopenharmony_ci    stackData_ = ProtoEncoder::BatchNativeHookData(ctx);
15906f6ba60Sopenharmony_ci}
16006f6ba60Sopenharmony_ci
16106f6ba60Sopenharmony_cibool StackPreprocess::StartTakeResults()
16206f6ba60Sopenharmony_ci{
16306f6ba60Sopenharmony_ci    CHECK_NOTNULL(dataRepeater_, false, "data repeater null");
16406f6ba60Sopenharmony_ci
16506f6ba60Sopenharmony_ci    std::weak_ptr<StackPreprocess> stackPreprocessPtr(shared_from_this());
16606f6ba60Sopenharmony_ci    std::thread demuxer([stackPreprocessPtr] {
16706f6ba60Sopenharmony_ci        if (auto ptr = stackPreprocessPtr.lock(); ptr != nullptr) {
16806f6ba60Sopenharmony_ci            ptr->TakeResults();
16906f6ba60Sopenharmony_ci        }
17006f6ba60Sopenharmony_ci    });
17106f6ba60Sopenharmony_ci    CHECK_TRUE(demuxer.get_id() != std::thread::id(), false, "demuxer thread invalid");
17206f6ba60Sopenharmony_ci
17306f6ba60Sopenharmony_ci    thread_ = std::move(demuxer);
17406f6ba60Sopenharmony_ci    isStopTakeData_ = false;
17506f6ba60Sopenharmony_ci    return true;
17606f6ba60Sopenharmony_ci}
17706f6ba60Sopenharmony_ci
17806f6ba60Sopenharmony_cibool StackPreprocess::StopTakeResults()
17906f6ba60Sopenharmony_ci{
18006f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "start StopTakeResults");
18106f6ba60Sopenharmony_ci    int32_t timerFd = scheduleTaskManager_.ScheduleTask(
18206f6ba60Sopenharmony_ci        std::bind(&StackPreprocess::ForceStop, this), WAIT_STOP_TIME, true, false);
18306f6ba60Sopenharmony_ci    if (timerFd == -1) {
18406f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "StopTakeResults ScheduleTask failed!");
18506f6ba60Sopenharmony_ci        return false;
18606f6ba60Sopenharmony_ci    }
18706f6ba60Sopenharmony_ci    if (!dataRepeater_) {
18806f6ba60Sopenharmony_ci        while (!isStopTakeData_) {
18906f6ba60Sopenharmony_ci            std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME_ONCE));
19006f6ba60Sopenharmony_ci        }
19106f6ba60Sopenharmony_ci        return true;
19206f6ba60Sopenharmony_ci    }
19306f6ba60Sopenharmony_ci    CHECK_NOTNULL(dataRepeater_, false, "data repeater null");
19406f6ba60Sopenharmony_ci    CHECK_TRUE(thread_.get_id() != std::thread::id(), false, "thread invalid");
19506f6ba60Sopenharmony_ci
19606f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "StopTakeResults Wait thread join");
19706f6ba60Sopenharmony_ci
19806f6ba60Sopenharmony_ci    if (thread_.joinable()) {
19906f6ba60Sopenharmony_ci        thread_.join();
20006f6ba60Sopenharmony_ci    }
20106f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "StopTakeResults Wait thread join success");
20206f6ba60Sopenharmony_ci    return true;
20306f6ba60Sopenharmony_ci}
20406f6ba60Sopenharmony_ci
20506f6ba60Sopenharmony_ciinline void StackPreprocess::IntervalFlushRecordStatistics()
20606f6ba60Sopenharmony_ci{
20706f6ba60Sopenharmony_ci    // interval reporting statistics
20806f6ba60Sopenharmony_ci    if (hookConfig_.statistics_interval() > 0) {
20906f6ba60Sopenharmony_ci        auto currentTime = std::chrono::steady_clock::now();
21006f6ba60Sopenharmony_ci        auto elapsedTime = std::chrono::duration_cast<std::chrono::microseconds>(currentTime - lastStatisticsTime_);
21106f6ba60Sopenharmony_ci        if (elapsedTime >= statisticsInterval_) {
21206f6ba60Sopenharmony_ci            lastStatisticsTime_ = currentTime;
21306f6ba60Sopenharmony_ci            FlushRecordStatistics();
21406f6ba60Sopenharmony_ci        }
21506f6ba60Sopenharmony_ci    }
21606f6ba60Sopenharmony_ci}
21706f6ba60Sopenharmony_ci
21806f6ba60Sopenharmony_ciinline void StackPreprocess::IntervalFlushApplyAndReleaseMatchData()
21906f6ba60Sopenharmony_ci{
22006f6ba60Sopenharmony_ci    // interval reporting apply and release match data
22106f6ba60Sopenharmony_ci    if (hookConfig_.malloc_free_matching_interval() > 0) {
22206f6ba60Sopenharmony_ci        static auto lastStatisticsTime = std::chrono::steady_clock::now();
22306f6ba60Sopenharmony_ci        auto currentTime = std::chrono::steady_clock::now();
22406f6ba60Sopenharmony_ci        auto elapsedTime = std::chrono::duration_cast<std::chrono::seconds>(currentTime - lastStatisticsTime);
22506f6ba60Sopenharmony_ci        if (elapsedTime >= applyAndReleaseMatchInterval_) {
22606f6ba60Sopenharmony_ci            lastStatisticsTime = currentTime;
22706f6ba60Sopenharmony_ci            FlushRecordApplyAndReleaseMatchData();
22806f6ba60Sopenharmony_ci        }
22906f6ba60Sopenharmony_ci    }
23006f6ba60Sopenharmony_ci}
23106f6ba60Sopenharmony_ci
23206f6ba60Sopenharmony_cibool StackPreprocess::HandleNoStackEvent(RawStackPtr& rawData)
23306f6ba60Sopenharmony_ci{
23406f6ba60Sopenharmony_ci    if (rawData->stackConext->type == MMAP_FILE_TYPE) {
23506f6ba60Sopenharmony_ci        BaseStackRawData* mmapRawData = rawData->stackConext;
23606f6ba60Sopenharmony_ci        std::string filePath(reinterpret_cast<char *>(rawData->data));
23706f6ba60Sopenharmony_ci        COMMON::AdaptSandboxPath(filePath, rawData->stackConext->pid);
23806f6ba60Sopenharmony_ci        PROFILER_LOG_DEBUG(LOG_CORE, "MMAP_FILE_TYPE curMmapAddr=%p, MAP_FIXED=%d, "
23906f6ba60Sopenharmony_ci                    "PROT_EXEC=%d, offset=%" PRIu64 ", filePath=%s",
24006f6ba60Sopenharmony_ci                    mmapRawData->addr, mmapRawData->mmapArgs.flags & MAP_FIXED,
24106f6ba60Sopenharmony_ci                    mmapRawData->mmapArgs.flags & PROT_EXEC, mmapRawData->mmapArgs.offset, filePath.data());
24206f6ba60Sopenharmony_ci        std::lock_guard<std::mutex> guard(mtx_);
24306f6ba60Sopenharmony_ci        runtime_instance->HandleMapInfo({reinterpret_cast<uint64_t>(mmapRawData->addr),
24406f6ba60Sopenharmony_ci            mmapRawData->mallocSize, mmapRawData->mmapArgs.flags, mmapRawData->mmapArgs.offset}, filePath,
24506f6ba60Sopenharmony_ci            rawData->stackConext->pid, rawData->stackConext->tid);
24606f6ba60Sopenharmony_ci        flushBasicData_ = true;
24706f6ba60Sopenharmony_ci    } else if (rawData->stackConext->type == THREAD_NAME_MSG) {
24806f6ba60Sopenharmony_ci        std::string threadName = reinterpret_cast<char*>(rawData->data);
24906f6ba60Sopenharmony_ci        ReportThreadNameMap(rawData->stackConext->tid, threadName);
25006f6ba60Sopenharmony_ci    } else {
25106f6ba60Sopenharmony_ci        return false;
25206f6ba60Sopenharmony_ci    }
25306f6ba60Sopenharmony_ci    return true;
25406f6ba60Sopenharmony_ci}
25506f6ba60Sopenharmony_ci
25606f6ba60Sopenharmony_civoid StackPreprocess::ForceStop()
25706f6ba60Sopenharmony_ci{
25806f6ba60Sopenharmony_ci    isStopTakeData_ = true;
25906f6ba60Sopenharmony_ci    if (dataRepeater_ != nullptr) {
26006f6ba60Sopenharmony_ci        dataRepeater_->Close();
26106f6ba60Sopenharmony_ci    }
26206f6ba60Sopenharmony_ci}
26306f6ba60Sopenharmony_ci
26406f6ba60Sopenharmony_civoid StackPreprocess::TakeResultsFromShmem(const std::shared_ptr<EventNotifier>& eventNotifier,
26506f6ba60Sopenharmony_ci                                           const std::shared_ptr<ShareMemoryBlock>& shareMemoryBlock)
26606f6ba60Sopenharmony_ci{
26706f6ba60Sopenharmony_ci    eventNotifier->Take();
26806f6ba60Sopenharmony_ci    StackDataRepeater::RawStack rawStack;
26906f6ba60Sopenharmony_ci    RawStackPtr rawData(&rawStack, [](StackDataRepeater::RawStack* del) {});
27006f6ba60Sopenharmony_ci    while (!isStopTakeData_) {
27106f6ba60Sopenharmony_ci        bool ret = shareMemoryBlock->TakeData(
27206f6ba60Sopenharmony_ci            [&](const int8_t data[], uint32_t size) -> bool {
27306f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG
27406f6ba60Sopenharmony_ci            struct timespec start = {};
27506f6ba60Sopenharmony_ci            clock_gettime(CLOCK_REALTIME, &start);
27606f6ba60Sopenharmony_ci#endif
27706f6ba60Sopenharmony_ci            if (size == sizeof(uint64_t)) {
27806f6ba60Sopenharmony_ci                uint64_t addr = *reinterpret_cast<uint64_t *>(const_cast<int8_t *>(data));
27906f6ba60Sopenharmony_ci                SetFreeStatisticsData(addr);
28006f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG
28106f6ba60Sopenharmony_ci                struct timespec end = {};
28206f6ba60Sopenharmony_ci                clock_gettime(CLOCK_REALTIME, &end);
28306f6ba60Sopenharmony_ci                uint64_t curTimeCost = (end.tv_sec - start.tv_sec) * MAX_MATCH_CNT * MAX_MATCH_CNT * MAX_MATCH_CNT +
28406f6ba60Sopenharmony_ci                    (end.tv_nsec - start.tv_nsec);
28506f6ba60Sopenharmony_ci                timeCost += curTimeCost;
28606f6ba60Sopenharmony_ci                unwindTimes++;
28706f6ba60Sopenharmony_ci                if (unwindTimes % LOG_PRINT_TIMES == 0) {
28806f6ba60Sopenharmony_ci                    PROFILER_LOG_ERROR(LOG_CORE,
28906f6ba60Sopenharmony_ci                                       "unwindTimes %" PRIu64" cost time = %" PRIu64" mean cost = %" PRIu64"\n",
29006f6ba60Sopenharmony_ci                                       unwindTimes.load(), timeCost.load(), timeCost.load() / unwindTimes.load());
29106f6ba60Sopenharmony_ci                }
29206f6ba60Sopenharmony_ci#endif
29306f6ba60Sopenharmony_ci                return true;
29406f6ba60Sopenharmony_ci            }
29506f6ba60Sopenharmony_ci            CHECK_TRUE(size >= sizeof(BaseStackRawData), false, "stack data invalid!");
29606f6ba60Sopenharmony_ci            rawData->stackConext = reinterpret_cast<BaseStackRawData *>(const_cast<int8_t *>(data));
29706f6ba60Sopenharmony_ci            rawData->data = reinterpret_cast<uint8_t*>(const_cast<int8_t *>(data)) + sizeof(BaseStackRawData);
29806f6ba60Sopenharmony_ci            rawData->fpDepth = (size - sizeof(BaseStackRawData)) / sizeof(uint64_t);
29906f6ba60Sopenharmony_ci            if (isStopTakeData_) {
30006f6ba60Sopenharmony_ci                return false;
30106f6ba60Sopenharmony_ci            } else if (rawData->stackConext->type == MEMORY_TAG) {
30206f6ba60Sopenharmony_ci                std::string tagName = reinterpret_cast<char*>(rawData->data);
30306f6ba60Sopenharmony_ci                SaveMemTag(rawData->stackConext->tagId, tagName);
30406f6ba60Sopenharmony_ci                return true;
30506f6ba60Sopenharmony_ci            } else if (HandleNoStackEvent(rawData)) {
30606f6ba60Sopenharmony_ci                return true;
30706f6ba60Sopenharmony_ci            } else if (rawData->stackConext->type == MUNMAP_MSG) {
30806f6ba60Sopenharmony_ci                std::lock_guard<std::mutex> guard(mtx_);
30906f6ba60Sopenharmony_ci                runtime_instance->RemoveMaps(reinterpret_cast<uint64_t>(rawData->stackConext->addr));
31006f6ba60Sopenharmony_ci            } else if (rawData->stackConext->type == NMD_MSG) {
31106f6ba60Sopenharmony_ci                const char* nmdResult = reinterpret_cast<const char*>(rawData->data);
31206f6ba60Sopenharmony_ci                lseek(nmdFd_, 0, SEEK_END);
31306f6ba60Sopenharmony_ci                (void)write(nmdFd_, nmdResult, strlen(nmdResult));
31406f6ba60Sopenharmony_ci                return true;
31506f6ba60Sopenharmony_ci            }  else if (rawData->stackConext->type == END_MSG) {
31606f6ba60Sopenharmony_ci                isStopTakeData_ = true;
31706f6ba60Sopenharmony_ci                return true;
31806f6ba60Sopenharmony_ci            }
31906f6ba60Sopenharmony_ci            {
32006f6ba60Sopenharmony_ci                std::lock_guard<std::mutex> guard(mtx_);
32106f6ba60Sopenharmony_ci                runtime_instance->UpdateThread(rawData->stackConext->pid, rawData->stackConext->tid);
32206f6ba60Sopenharmony_ci            }
32306f6ba60Sopenharmony_ci            ReportOfflineSymbolizationData();
32406f6ba60Sopenharmony_ci            std::visit([&](auto& stackData) {
32506f6ba60Sopenharmony_ci                SetHookData(rawData, stackData);
32606f6ba60Sopenharmony_ci                FlushCheck(stackData);
32706f6ba60Sopenharmony_ci                }, stackData_);
32806f6ba60Sopenharmony_ci            IntervalFlushRecordStatistics();
32906f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG
33006f6ba60Sopenharmony_ci            struct timespec end = {};
33106f6ba60Sopenharmony_ci            clock_gettime(CLOCK_REALTIME, &end);
33206f6ba60Sopenharmony_ci            uint64_t curTimeCost = (end.tv_sec - start.tv_sec) * MAX_MATCH_CNT * MAX_MATCH_CNT * MAX_MATCH_CNT +
33306f6ba60Sopenharmony_ci                (end.tv_nsec - start.tv_nsec);
33406f6ba60Sopenharmony_ci            if (curTimeCost >= LONG_TIME_THRESHOLD) {
33506f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "bigTimeCost %" PRIu64 " event=%d fpDepth=%u",
33606f6ba60Sopenharmony_ci                            curTimeCost, rawData->stackConext->type, rawData->fpDepth);
33706f6ba60Sopenharmony_ci            }
33806f6ba60Sopenharmony_ci            timeCost += curTimeCost;
33906f6ba60Sopenharmony_ci            unwindTimes++;
34006f6ba60Sopenharmony_ci            if (unwindTimes % LOG_PRINT_TIMES == 0) {
34106f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "unwindTimes %" PRIu64" cost time = %" PRIu64" mean cost = %" PRIu64"\n",
34206f6ba60Sopenharmony_ci                    unwindTimes.load(), timeCost.load(), timeCost.load() / unwindTimes.load());
34306f6ba60Sopenharmony_ci            }
34406f6ba60Sopenharmony_ci#endif
34506f6ba60Sopenharmony_ci            return true;
34606f6ba60Sopenharmony_ci        });
34706f6ba60Sopenharmony_ci        if (!ret) {
34806f6ba60Sopenharmony_ci            break;
34906f6ba60Sopenharmony_ci        }
35006f6ba60Sopenharmony_ci    }
35106f6ba60Sopenharmony_ci}
35206f6ba60Sopenharmony_ci
35306f6ba60Sopenharmony_civoid StackPreprocess::TakeResults()
35406f6ba60Sopenharmony_ci{
35506f6ba60Sopenharmony_ci    if (!dataRepeater_) {
35606f6ba60Sopenharmony_ci        return;
35706f6ba60Sopenharmony_ci    }
35806f6ba60Sopenharmony_ci
35906f6ba60Sopenharmony_ci    size_t minStackDepth = hookConfig_.max_stack_depth() > MIN_STACK_DEPTH
36006f6ba60Sopenharmony_ci        ? MIN_STACK_DEPTH : hookConfig_.max_stack_depth();
36106f6ba60Sopenharmony_ci    if (hookConfig_.blocked()) {
36206f6ba60Sopenharmony_ci        minStackDepth = static_cast<size_t>(hookConfig_.max_stack_depth());
36306f6ba60Sopenharmony_ci    }
36406f6ba60Sopenharmony_ci    minStackDepth += FILTER_STACK_DEPTH;
36506f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "TakeResults thread %d, start!", gettid());
36606f6ba60Sopenharmony_ci    while (1) {
36706f6ba60Sopenharmony_ci        RawStackPtr batchRawStack[MAX_BATCH_CNT] = {nullptr};
36806f6ba60Sopenharmony_ci        if (isStopTakeData_) {
36906f6ba60Sopenharmony_ci            break;
37006f6ba60Sopenharmony_ci        }
37106f6ba60Sopenharmony_ci        uint32_t during = 0;
37206f6ba60Sopenharmony_ci        if (hookConfig_.statistics_interval() > 0) {
37306f6ba60Sopenharmony_ci            auto currentTime = std::chrono::steady_clock::now();
37406f6ba60Sopenharmony_ci            auto timeDiff = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastStatisticsTime_);
37506f6ba60Sopenharmony_ci            int tempDuring =
37606f6ba60Sopenharmony_ci                std::chrono::duration_cast<std::chrono::milliseconds>(statisticsInterval_).count() - timeDiff.count();
37706f6ba60Sopenharmony_ci            during = tempDuring > 0 ? static_cast<uint32_t>(tempDuring) : 0;
37806f6ba60Sopenharmony_ci        }
37906f6ba60Sopenharmony_ci        bool isTimeOut = false;
38006f6ba60Sopenharmony_ci        auto result = dataRepeater_->TakeRawData(during, hookDataClockId_, MAX_BATCH_CNT, batchRawStack,
38106f6ba60Sopenharmony_ci                                                 hookConfig_.statistics_interval(), isTimeOut);
38206f6ba60Sopenharmony_ci        if (hookConfig_.statistics_interval() > 0 && isTimeOut && result == nullptr) {  // statistics mode
38306f6ba60Sopenharmony_ci            IntervalFlushRecordStatistics();
38406f6ba60Sopenharmony_ci            continue;
38506f6ba60Sopenharmony_ci        }
38606f6ba60Sopenharmony_ci        if (!result) {
38706f6ba60Sopenharmony_ci            break;
38806f6ba60Sopenharmony_ci        }
38906f6ba60Sopenharmony_ci        for (unsigned int i = 0; i < MAX_BATCH_CNT; i++) {
39006f6ba60Sopenharmony_ci            auto rawData = batchRawStack[i];
39106f6ba60Sopenharmony_ci            if (!rawData || isStopTakeData_) {
39206f6ba60Sopenharmony_ci                break;
39306f6ba60Sopenharmony_ci            }
39406f6ba60Sopenharmony_ci            if (rawData->baseStackData == nullptr) {
39506f6ba60Sopenharmony_ci                if (rawData->freeData) {
39606f6ba60Sopenharmony_ci                    SetFreeStatisticsData(rawData->freeData);
39706f6ba60Sopenharmony_ci                }
39806f6ba60Sopenharmony_ci                continue;
39906f6ba60Sopenharmony_ci            }
40006f6ba60Sopenharmony_ci            if (rawData->stackConext == nullptr) {
40106f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "StackPreprocess take results rawData->stackConext is nullptr");
40206f6ba60Sopenharmony_ci                continue;
40306f6ba60Sopenharmony_ci            }
40406f6ba60Sopenharmony_ci            if (rawData->stackConext->type == NMD_MSG) {
40506f6ba60Sopenharmony_ci                continue;
40606f6ba60Sopenharmony_ci            } else if (rawData->stackConext->type == END_MSG) {
40706f6ba60Sopenharmony_ci                isStopTakeData_ = true;
40806f6ba60Sopenharmony_ci                break;
40906f6ba60Sopenharmony_ci            }
41006f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG
41106f6ba60Sopenharmony_ci            struct timespec start = {};
41206f6ba60Sopenharmony_ci            clock_gettime(CLOCK_REALTIME, &start);
41306f6ba60Sopenharmony_ci#endif
41406f6ba60Sopenharmony_ci            if (HandleNoStackEvent(rawData)) {
41506f6ba60Sopenharmony_ci                continue;
41606f6ba60Sopenharmony_ci            } else if (rawData->stackConext->type == MUNMAP_MSG) {
41706f6ba60Sopenharmony_ci                std::lock_guard<std::mutex> guard(mtx_);
41806f6ba60Sopenharmony_ci                runtime_instance->RemoveMaps(reinterpret_cast<uint64_t>(rawData->stackConext->addr));
41906f6ba60Sopenharmony_ci            }
42006f6ba60Sopenharmony_ci
42106f6ba60Sopenharmony_ci            if (!rawData->reportFlag) {
42206f6ba60Sopenharmony_ci                ignoreCnts_++;
42306f6ba60Sopenharmony_ci                if (ignoreCnts_ % LOG_PRINT_TIMES == 0) {
42406f6ba60Sopenharmony_ci                    PROFILER_LOG_INFO(LOG_CORE, "ignoreCnts_ = %d quene size = %zu\n",
42506f6ba60Sopenharmony_ci                                      ignoreCnts_, dataRepeater_->Size());
42606f6ba60Sopenharmony_ci                }
42706f6ba60Sopenharmony_ci                continue;
42806f6ba60Sopenharmony_ci            }
42906f6ba60Sopenharmony_ci            eventCnts_++;
43006f6ba60Sopenharmony_ci            if (eventCnts_ % LOG_PRINT_TIMES == 0) {
43106f6ba60Sopenharmony_ci                PROFILER_LOG_INFO(LOG_CORE, "eventCnts_ = %d quene size = %zu\n", eventCnts_, dataRepeater_->Size());
43206f6ba60Sopenharmony_ci            }
43306f6ba60Sopenharmony_ci            callFrames_.clear();
43406f6ba60Sopenharmony_ci            if (hookConfig_.fp_unwind()) {
43506f6ba60Sopenharmony_ci                FillFpNativeIp(rawData);
43606f6ba60Sopenharmony_ci                if (rawData->stackConext->jsChainId > 0 && rawData->jsStackData && hookConfig_.js_stack_report() > 0) {
43706f6ba60Sopenharmony_ci                    FillFpJsData(rawData);
43806f6ba60Sopenharmony_ci                }
43906f6ba60Sopenharmony_ci            } else if (rawData->stackConext->type != PR_SET_VMA_MSG) {
44006f6ba60Sopenharmony_ci                if (rawData->stackSize == 0) {
44106f6ba60Sopenharmony_ci                    FillDwarfErrorStack();
44206f6ba60Sopenharmony_ci                } else {
44306f6ba60Sopenharmony_ci#if defined(__arm__)
44406f6ba60Sopenharmony_ci                uint32_t *regAddrArm = reinterpret_cast<uint32_t *>(rawData->data);
44506f6ba60Sopenharmony_ci                u64regs_.assign(regAddrArm, regAddrArm + PERF_REG_ARM_MAX);
44606f6ba60Sopenharmony_ci#else
44706f6ba60Sopenharmony_ci                if (memcpy_s(u64regs_.data(), sizeof(uint64_t) * PERF_REG_ARM64_MAX, rawData->data,
44806f6ba60Sopenharmony_ci                    sizeof(uint64_t) * PERF_REG_ARM64_MAX) != EOK) {
44906f6ba60Sopenharmony_ci                    PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s regs failed");
45006f6ba60Sopenharmony_ci                }
45106f6ba60Sopenharmony_ci#endif
45206f6ba60Sopenharmony_ci                }
45306f6ba60Sopenharmony_ci            }
45406f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG
45506f6ba60Sopenharmony_ci            size_t realFrameDepth = callFrames_.size();
45606f6ba60Sopenharmony_ci#endif
45706f6ba60Sopenharmony_ci            size_t stackDepth = ((size_t)hookConfig_.max_stack_depth() > MAX_CALL_FRAME_UNWIND_SIZE)
45806f6ba60Sopenharmony_ci                        ? MAX_CALL_FRAME_UNWIND_SIZE
45906f6ba60Sopenharmony_ci                        : hookConfig_.max_stack_depth() + FILTER_STACK_DEPTH;
46006f6ba60Sopenharmony_ci            if (rawData->reduceStackFlag) {
46106f6ba60Sopenharmony_ci                stackDepth = minStackDepth;
46206f6ba60Sopenharmony_ci            }
46306f6ba60Sopenharmony_ci            if ((hookConfig_.fp_unwind()) || rawData->stackSize > 0) {
46406f6ba60Sopenharmony_ci                std::lock_guard<std::mutex> guard(mtx_);
46506f6ba60Sopenharmony_ci                if (rawData->stackConext->type != PR_SET_VMA_MSG) {
46606f6ba60Sopenharmony_ci                    bool ret = runtime_instance->UnwindStack(u64regs_, rawData->stackData, rawData->stackSize,
46706f6ba60Sopenharmony_ci                    rawData->stackConext->pid, rawData->stackConext->tid, callFrames_, stackDepth);
46806f6ba60Sopenharmony_ci                    if (!ret) {
46906f6ba60Sopenharmony_ci                        PROFILER_LOG_ERROR(LOG_CORE, "unwind fatal error");
47006f6ba60Sopenharmony_ci                        continue;
47106f6ba60Sopenharmony_ci                    }
47206f6ba60Sopenharmony_ci                }
47306f6ba60Sopenharmony_ci            }
47406f6ba60Sopenharmony_ci            if ((hookConfig_.fp_unwind()) || rawData->stackSize > 0) {
47506f6ba60Sopenharmony_ci                ReportOfflineSymbolizationData();
47606f6ba60Sopenharmony_ci            }
47706f6ba60Sopenharmony_ci            std::visit([&](auto& stackData) {
47806f6ba60Sopenharmony_ci                if (hookConfig_.save_file() && hookConfig_.file_name() != "" && isHookStandaloneSerialize_) {
47906f6ba60Sopenharmony_ci                    SetHookData(rawData, callFrames_, stackData);
48006f6ba60Sopenharmony_ci                } else if (hookConfig_.save_file() && hookConfig_.file_name() != "") {
48106f6ba60Sopenharmony_ci                    WriteFrames(rawData, callFrames_);
48206f6ba60Sopenharmony_ci                } else if (!hookConfig_.save_file()) {
48306f6ba60Sopenharmony_ci                    if (hookConfig_.malloc_free_matching_interval() > 0) {
48406f6ba60Sopenharmony_ci                        SetApplyAndReleaseMatchFrame(rawData, callFrames_, stackData);
48506f6ba60Sopenharmony_ci                    } else {
48606f6ba60Sopenharmony_ci                        SetHookData(rawData, callFrames_, stackData);
48706f6ba60Sopenharmony_ci                    }
48806f6ba60Sopenharmony_ci                }
48906f6ba60Sopenharmony_ci                }, stackData_);
49006f6ba60Sopenharmony_ci
49106f6ba60Sopenharmony_ci#ifdef PERFORMANCE_DEBUG
49206f6ba60Sopenharmony_ci            struct timespec end = {};
49306f6ba60Sopenharmony_ci            clock_gettime(CLOCK_REALTIME, &end);
49406f6ba60Sopenharmony_ci            uint64_t curTimeCost = (end.tv_sec - start.tv_sec) * MAX_MATCH_CNT * MAX_MATCH_CNT * MAX_MATCH_CNT +
49506f6ba60Sopenharmony_ci                (end.tv_nsec - start.tv_nsec);
49606f6ba60Sopenharmony_ci            if (curTimeCost >= LONG_TIME_THRESHOLD) {
49706f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "bigTimeCost %" PRIu64 " event=%d, realFrameDepth=%zu, "
49806f6ba60Sopenharmony_ci                    "callFramesDepth=%zu\n",
49906f6ba60Sopenharmony_ci                    curTimeCost, rawData->stackConext->type, realFrameDepth, callFrames_.size());
50006f6ba60Sopenharmony_ci            }
50106f6ba60Sopenharmony_ci            timeCost += curTimeCost;
50206f6ba60Sopenharmony_ci            unwindTimes++;
50306f6ba60Sopenharmony_ci            if (unwindTimes % LOG_PRINT_TIMES == 0) {
50406f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "unwindTimes %" PRIu64" cost time = %" PRIu64" mean cost = %" PRIu64"\n",
50506f6ba60Sopenharmony_ci                    unwindTimes.load(), timeCost.load(), timeCost.load() / unwindTimes.load());
50606f6ba60Sopenharmony_ci            }
50706f6ba60Sopenharmony_ci#endif
50806f6ba60Sopenharmony_ci        } // for
50906f6ba60Sopenharmony_ci        for (unsigned int i = 0; i < MAX_BATCH_CNT; i++) {
51006f6ba60Sopenharmony_ci            if (!batchRawStack[i]) {
51106f6ba60Sopenharmony_ci                break;
51206f6ba60Sopenharmony_ci            }
51306f6ba60Sopenharmony_ci            dataRepeater_->ReturnRawStack(std::move(batchRawStack[i]));
51406f6ba60Sopenharmony_ci        }
51506f6ba60Sopenharmony_ci        if (hookConfig_.save_file() && hookConfig_.file_name() != "" && !isHookStandaloneSerialize_) {
51606f6ba60Sopenharmony_ci            continue;
51706f6ba60Sopenharmony_ci        }
51806f6ba60Sopenharmony_ci        if (hookConfig_.statistics_interval() == 0) {
51906f6ba60Sopenharmony_ci            std::visit([&](auto& stackData) {
52006f6ba60Sopenharmony_ci                FlushCheck(stackData);
52106f6ba60Sopenharmony_ci                }, stackData_);
52206f6ba60Sopenharmony_ci        }
52306f6ba60Sopenharmony_ci        IntervalFlushRecordStatistics();
52406f6ba60Sopenharmony_ci        IntervalFlushApplyAndReleaseMatchData();
52506f6ba60Sopenharmony_ci    } // while
52606f6ba60Sopenharmony_ci    PROFILER_LOG_INFO(LOG_CORE, "TakeResults thread %d, exit!", gettid());
52706f6ba60Sopenharmony_ci}
52806f6ba60Sopenharmony_ci
52906f6ba60Sopenharmony_ciinline void StackPreprocess::ReportThreadNameMap(uint32_t tid, const std::string& tname)
53006f6ba60Sopenharmony_ci{
53106f6ba60Sopenharmony_ci    std::lock_guard<std::mutex> guard(mtx_);
53206f6ba60Sopenharmony_ci    auto it = threadNameMap_.find(tid);
53306f6ba60Sopenharmony_ci    if (it == threadNameMap_.end() || it->second != tname) {
53406f6ba60Sopenharmony_ci        threadNameMap_[tid] = tname;
53506f6ba60Sopenharmony_ci        std::visit([&](auto& stackData) {
53606f6ba60Sopenharmony_ci            auto hookData = stackData.add_events();
53706f6ba60Sopenharmony_ci            auto thread = hookData->mutable_thread_name_map();
53806f6ba60Sopenharmony_ci            thread->set_id(tid);
53906f6ba60Sopenharmony_ci            thread->set_name(tname);
54006f6ba60Sopenharmony_ci            thread->set_pid(pid_);
54106f6ba60Sopenharmony_ci            FlushCheck(stackData);
54206f6ba60Sopenharmony_ci            }, stackData_);
54306f6ba60Sopenharmony_ci    }
54406f6ba60Sopenharmony_ci}
54506f6ba60Sopenharmony_ci
54606f6ba60Sopenharmony_citemplate <typename T>
54706f6ba60Sopenharmony_ciinline void StackPreprocess::FillOfflineCallStack(std::vector<CallFrame>& callFrames, size_t idx, T& stackData)
54806f6ba60Sopenharmony_ci{
54906f6ba60Sopenharmony_ci    for (; idx < callFrames.size(); ++idx) {
55006f6ba60Sopenharmony_ci        if (callFrames[idx].isJsFrame_) {
55106f6ba60Sopenharmony_ci            ReportFrameMap(callFrames[idx], stackData);
55206f6ba60Sopenharmony_ci            callStack_.push_back(callFrames[idx].callFrameId_ | JS_OFFLINE_IP_MASK);
55306f6ba60Sopenharmony_ci            continue;
55406f6ba60Sopenharmony_ci        }
55506f6ba60Sopenharmony_ci        callStack_.push_back(callFrames[idx].ip_);
55606f6ba60Sopenharmony_ci    }
55706f6ba60Sopenharmony_ci}
55806f6ba60Sopenharmony_ci
55906f6ba60Sopenharmony_citemplate <typename T>
56006f6ba60Sopenharmony_ciinline void StackPreprocess::FillCallStack(std::vector<CallFrame>& callFrames, size_t idx, T& stackData)
56106f6ba60Sopenharmony_ci{
56206f6ba60Sopenharmony_ci    for (; idx < callFrames.size(); ++idx) {
56306f6ba60Sopenharmony_ci        ReportFrameMap(callFrames[idx], stackData);
56406f6ba60Sopenharmony_ci        // for call stack id
56506f6ba60Sopenharmony_ci        callStack_.push_back(callFrames[idx].callFrameId_);
56606f6ba60Sopenharmony_ci    }
56706f6ba60Sopenharmony_ci}
56806f6ba60Sopenharmony_ci
56906f6ba60Sopenharmony_ciinline uint32_t StackPreprocess::FindCallStackId(std::vector<uint64_t>& callStack)
57006f6ba60Sopenharmony_ci{
57106f6ba60Sopenharmony_ci    if (hookConfig_.response_library_mode()) {
57206f6ba60Sopenharmony_ci        auto itStack = responseLibraryMap_.find(callStack[0]);
57306f6ba60Sopenharmony_ci        if (itStack != responseLibraryMap_.end()) {
57406f6ba60Sopenharmony_ci            return itStack->second;
57506f6ba60Sopenharmony_ci        }
57606f6ba60Sopenharmony_ci    } else {
57706f6ba60Sopenharmony_ci        auto itStack = callStackMap_.find(callStack);
57806f6ba60Sopenharmony_ci        if (itStack != callStackMap_.end()) {
57906f6ba60Sopenharmony_ci            return itStack->second;
58006f6ba60Sopenharmony_ci        }
58106f6ba60Sopenharmony_ci    }
58206f6ba60Sopenharmony_ci    return 0;
58306f6ba60Sopenharmony_ci}
58406f6ba60Sopenharmony_ci
58506f6ba60Sopenharmony_ci/**
58606f6ba60Sopenharmony_ci * @return '0' is invalid stack id, '> 0' is valid stack id
58706f6ba60Sopenharmony_ci */
58806f6ba60Sopenharmony_citemplate <typename T>
58906f6ba60Sopenharmony_ciinline uint32_t StackPreprocess::SetCallStackMap(T& stackData)
59006f6ba60Sopenharmony_ci{
59106f6ba60Sopenharmony_ci    uint32_t stackId = 0;
59206f6ba60Sopenharmony_ci    auto hookData = stackData.add_events();
59306f6ba60Sopenharmony_ci    auto stackmap = hookData->mutable_stack_map();
59406f6ba60Sopenharmony_ci    if (hookConfig_.response_library_mode()) {
59506f6ba60Sopenharmony_ci        stackId = responseLibraryMap_.size() + 1;
59606f6ba60Sopenharmony_ci    } else {
59706f6ba60Sopenharmony_ci        stackId = callStackMap_.size() + 1;
59806f6ba60Sopenharmony_ci    }
59906f6ba60Sopenharmony_ci    stackmap->set_id(stackId);
60006f6ba60Sopenharmony_ci    // offline symbolization use ip, other use frame_map_id
60106f6ba60Sopenharmony_ci    if (hookConfig_.offline_symbolization()) {
60206f6ba60Sopenharmony_ci        if constexpr (std::is_same<T, ProtoEncoder::BatchNativeHookData>::value) {
60306f6ba60Sopenharmony_ci            stackmap->add_ip(callStack_);
60406f6ba60Sopenharmony_ci        } else {
60506f6ba60Sopenharmony_ci            for (size_t i = 0; i < callStack_.size(); i++) {
60606f6ba60Sopenharmony_ci                stackmap->add_ip(callStack_[i]);
60706f6ba60Sopenharmony_ci            }
60806f6ba60Sopenharmony_ci        }
60906f6ba60Sopenharmony_ci    } else {
61006f6ba60Sopenharmony_ci        if constexpr (std::is_same<T, ProtoEncoder::BatchNativeHookData>::value) {
61106f6ba60Sopenharmony_ci            stackmap->add_frame_map_id(callStack_);
61206f6ba60Sopenharmony_ci        } else {
61306f6ba60Sopenharmony_ci            for (size_t i = 0; i < callStack_.size(); i++) {
61406f6ba60Sopenharmony_ci                stackmap->add_frame_map_id(callStack_[i]);
61506f6ba60Sopenharmony_ci            }
61606f6ba60Sopenharmony_ci        }
61706f6ba60Sopenharmony_ci    }
61806f6ba60Sopenharmony_ci    stackmap->set_pid(pid_);
61906f6ba60Sopenharmony_ci    if (hookConfig_.response_library_mode()) {
62006f6ba60Sopenharmony_ci        responseLibraryMap_[callStack_[0]] = stackId;
62106f6ba60Sopenharmony_ci    } else {
62206f6ba60Sopenharmony_ci        callStackMap_[callStack_] = stackId;
62306f6ba60Sopenharmony_ci    }
62406f6ba60Sopenharmony_ci    return stackId;
62506f6ba60Sopenharmony_ci}
62606f6ba60Sopenharmony_ci
62706f6ba60Sopenharmony_ci/**
62806f6ba60Sopenharmony_ci * @return '0' is invalid stack id, '> 0' is valid stack id
62906f6ba60Sopenharmony_ci */
63006f6ba60Sopenharmony_citemplate <typename T>
63106f6ba60Sopenharmony_ciinline uint32_t StackPreprocess::GetCallStackId(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames,
63206f6ba60Sopenharmony_ci    T& stackData)
63306f6ba60Sopenharmony_ci{
63406f6ba60Sopenharmony_ci    // ignore the first two frame if dwarf unwind
63506f6ba60Sopenharmony_ci    size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH;
63606f6ba60Sopenharmony_ci    // if free_stack_report or munmap_stack_report is false, don't need to record.
63706f6ba60Sopenharmony_ci    if ((rawStack->stackConext->type == FREE_MSG) && !hookConfig_.free_stack_report()) {
63806f6ba60Sopenharmony_ci        return 0;
63906f6ba60Sopenharmony_ci    } else if ((rawStack->stackConext->type == MUNMAP_MSG) && !hookConfig_.munmap_stack_report()) {
64006f6ba60Sopenharmony_ci        return 0;
64106f6ba60Sopenharmony_ci    }
64206f6ba60Sopenharmony_ci    callStack_.clear();
64306f6ba60Sopenharmony_ci    bool isNapi = false;
64406f6ba60Sopenharmony_ci    if (rawStack->stackConext->type == MEMORY_USING_MSG && hookConfig_.js_stack_report() == NAPI_CALL_STACK) {
64506f6ba60Sopenharmony_ci        std::string tagName;
64606f6ba60Sopenharmony_ci        GetMemTag(rawStack->stackConext->tagId, tagName);
64706f6ba60Sopenharmony_ci        if (tagName.find("napi") != std::string::npos) {
64806f6ba60Sopenharmony_ci            callStack_.reserve(callFrames.size() + 1);  // 1 : insert a frame
64906f6ba60Sopenharmony_ci            callStack_.push_back((DWARF_NAPI_CALLBACK + napiIndex_) | JS_OFFLINE_IP_MASK);
65006f6ba60Sopenharmony_ci            isNapi = true;
65106f6ba60Sopenharmony_ci        }
65206f6ba60Sopenharmony_ci    } else {
65306f6ba60Sopenharmony_ci        callStack_.reserve(callFrames.size());
65406f6ba60Sopenharmony_ci    }
65506f6ba60Sopenharmony_ci    if (!hookConfig_.offline_symbolization()) {
65606f6ba60Sopenharmony_ci        FillCallStack(callFrames, idx, stackData);
65706f6ba60Sopenharmony_ci    } else {
65806f6ba60Sopenharmony_ci        if ((!hookConfig_.fp_unwind()) && rawStack->stackSize == 0) {
65906f6ba60Sopenharmony_ci            idx = 0;
66006f6ba60Sopenharmony_ci        }
66106f6ba60Sopenharmony_ci        FillOfflineCallStack(callFrames, idx, stackData);
66206f6ba60Sopenharmony_ci    }
66306f6ba60Sopenharmony_ci    if (isNapi) {
66406f6ba60Sopenharmony_ci        // insert a frame
66506f6ba60Sopenharmony_ci        std::string tagName;
66606f6ba60Sopenharmony_ci        GetMemTag(rawStack->stackConext->tagId, tagName);
66706f6ba60Sopenharmony_ci        FillNapiStack(tagName, callFrames, napiIndex_);
66806f6ba60Sopenharmony_ci        ReportFrameMap(callFrames.back(), stackData);
66906f6ba60Sopenharmony_ci        ++napiIndex_;
67006f6ba60Sopenharmony_ci    }
67106f6ba60Sopenharmony_ci    // return call stack id
67206f6ba60Sopenharmony_ci    std::lock_guard<std::mutex> guard(mtx_);
67306f6ba60Sopenharmony_ci    uint32_t stackId = FindCallStackId(callStack_);
67406f6ba60Sopenharmony_ci    if (stackId > 0) {
67506f6ba60Sopenharmony_ci        return stackId;
67606f6ba60Sopenharmony_ci    } else {
67706f6ba60Sopenharmony_ci        return SetCallStackMap(stackData);
67806f6ba60Sopenharmony_ci    }
67906f6ba60Sopenharmony_ci}
68006f6ba60Sopenharmony_ci
68106f6ba60Sopenharmony_citemplate <typename T>
68206f6ba60Sopenharmony_civoid StackPreprocess::SetEventFrame(const ReportEventBaseData& rawStack,
68306f6ba60Sopenharmony_ci    T* event, uint32_t stackMapId, const std::string& type)
68406f6ba60Sopenharmony_ci{
68506f6ba60Sopenharmony_ci    event->set_pid(pid_);
68606f6ba60Sopenharmony_ci    event->set_tid(rawStack.tid);
68706f6ba60Sopenharmony_ci    event->set_addr(rawStack.addr);
68806f6ba60Sopenharmony_ci    if constexpr (std::is_same<T, ::MmapEvent>::value || std::is_same<T, ProtoEncoder::MmapEvent>::value) {
68906f6ba60Sopenharmony_ci        event->set_type(type);
69006f6ba60Sopenharmony_ci    }
69106f6ba60Sopenharmony_ci
69206f6ba60Sopenharmony_ci    if constexpr (!std::is_same<T, ::FreeEvent>::value && !std::is_same<T, ProtoEncoder::FreeEvent>::value) {
69306f6ba60Sopenharmony_ci        auto size = static_cast<uint64_t>(rawStack.mallocSize);
69406f6ba60Sopenharmony_ci#ifdef USE_JEMALLOC
69506f6ba60Sopenharmony_ci    if constexpr (std::is_same<T, ::AllocEvent>::value || std::is_same<T, ProtoEncoder::AllocEvent>::value) {
69606f6ba60Sopenharmony_ci        size = static_cast<uint64_t>(ComputeAlign(size));
69706f6ba60Sopenharmony_ci    }
69806f6ba60Sopenharmony_ci#endif
69906f6ba60Sopenharmony_ci        event->set_size(size);
70006f6ba60Sopenharmony_ci    }
70106f6ba60Sopenharmony_ci    if (hookConfig_.callframe_compress() && stackMapId != 0) {
70206f6ba60Sopenharmony_ci        event->set_thread_name_id(rawStack.tid);
70306f6ba60Sopenharmony_ci        event->set_stack_id(stackMapId);
70406f6ba60Sopenharmony_ci    }
70506f6ba60Sopenharmony_ci    event->set_thread_name_id(rawStack.tid);
70606f6ba60Sopenharmony_ci}
70706f6ba60Sopenharmony_ci
70806f6ba60Sopenharmony_citemplate <typename T>
70906f6ba60Sopenharmony_civoid StackPreprocess::SetEventFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames,
71006f6ba60Sopenharmony_ci    T* event, uint32_t stackMapId, const std::string& type)
71106f6ba60Sopenharmony_ci{
71206f6ba60Sopenharmony_ci    // ignore the first two frame if dwarf unwind
71306f6ba60Sopenharmony_ci    size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH;
71406f6ba60Sopenharmony_ci    event->set_pid(rawStack->stackConext->pid);
71506f6ba60Sopenharmony_ci    event->set_tid(rawStack->stackConext->tid);
71606f6ba60Sopenharmony_ci    event->set_addr((uint64_t)rawStack->stackConext->addr);
71706f6ba60Sopenharmony_ci
71806f6ba60Sopenharmony_ci    if constexpr (std::is_same<T, ::MmapEvent>::value || std::is_same<T, ProtoEncoder::MmapEvent>::value) {
71906f6ba60Sopenharmony_ci        event->set_type(type);
72006f6ba60Sopenharmony_ci    }
72106f6ba60Sopenharmony_ci
72206f6ba60Sopenharmony_ci    if constexpr (!std::is_same<T, ::FreeEvent>::value && !std::is_same<T, ProtoEncoder::FreeEvent>::value) {
72306f6ba60Sopenharmony_ci        auto size = static_cast<uint64_t>(rawStack->stackConext->mallocSize);
72406f6ba60Sopenharmony_ci#ifdef USE_JEMALLOC
72506f6ba60Sopenharmony_ci    if constexpr (std::is_same<T, ::AllocEvent>::value || std::is_same<T, ProtoEncoder::AllocEvent>::value) {
72606f6ba60Sopenharmony_ci        size = static_cast<uint64_t>(ComputeAlign(size));
72706f6ba60Sopenharmony_ci    }
72806f6ba60Sopenharmony_ci#endif
72906f6ba60Sopenharmony_ci        event->set_size(size);
73006f6ba60Sopenharmony_ci    }
73106f6ba60Sopenharmony_ci
73206f6ba60Sopenharmony_ci    if (hookConfig_.callframe_compress() && stackMapId != 0) {
73306f6ba60Sopenharmony_ci        event->set_thread_name_id(rawStack->stackConext->tid);
73406f6ba60Sopenharmony_ci        event->set_stack_id(stackMapId);
73506f6ba60Sopenharmony_ci    } else {
73606f6ba60Sopenharmony_ci        for (; idx < callFrames.size(); ++idx) {
73706f6ba60Sopenharmony_ci            auto frame = event->add_frame_info();
73806f6ba60Sopenharmony_ci            SetFrameInfo(*frame, callFrames[idx]);
73906f6ba60Sopenharmony_ci        }
74006f6ba60Sopenharmony_ci        event->set_thread_name_id(rawStack->stackConext->tid);
74106f6ba60Sopenharmony_ci    }
74206f6ba60Sopenharmony_ci}
74306f6ba60Sopenharmony_ci
74406f6ba60Sopenharmony_civoid StackPreprocess::FillNapiStack(std::string& tagName, std::vector<CallFrame>& callFrames, uint64_t napiIndex)
74506f6ba60Sopenharmony_ci{
74606f6ba60Sopenharmony_ci    #if defined(__aarch64__)
74706f6ba60Sopenharmony_ci    uintptr_t pacMask = 0xFFFFFF8000000000;
74806f6ba60Sopenharmony_ci#else
74906f6ba60Sopenharmony_ci    uintptr_t pacMask = 0;
75006f6ba60Sopenharmony_ci#endif
75106f6ba60Sopenharmony_ci    CallFrame& jsCallFrame = callFrames_.emplace_back(0 & (~pacMask));
75206f6ba60Sopenharmony_ci    jsCallFrame.symbolName_ = tagName;
75306f6ba60Sopenharmony_ci    jsCallFrame.isJsFrame_ = true;
75406f6ba60Sopenharmony_ci    jsCallFrame.needReport_ |= CALL_FRAME_REPORT;
75506f6ba60Sopenharmony_ci    jsCallFrame.needReport_ |= SYMBOL_NAME_ID_REPORT;
75606f6ba60Sopenharmony_ci    jsCallFrame.needReport_ |= FILE_PATH_ID_REPORT;
75706f6ba60Sopenharmony_ci    jsCallFrame.callFrameId_ = DWARF_NAPI_CALLBACK + napiIndex;
75806f6ba60Sopenharmony_ci    jsCallFrame.symbolNameId_ = DWARF_NAPI_CALLBACK + napiIndex;
75906f6ba60Sopenharmony_ci    jsCallFrame.filePathId_ = DWARF_NAPI_CALLBACK + napiIndex;
76006f6ba60Sopenharmony_ci    jsCallFrame.filePath_ = "no-napi-file-path";
76106f6ba60Sopenharmony_ci}
76206f6ba60Sopenharmony_ci
76306f6ba60Sopenharmony_citemplate <typename T>
76406f6ba60Sopenharmony_civoid StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector<CallFrame>& callFrames,
76506f6ba60Sopenharmony_ci    T& stackData)
76606f6ba60Sopenharmony_ci{
76706f6ba60Sopenharmony_ci    // ignore the first two frame if dwarf unwind
76806f6ba60Sopenharmony_ci    size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH;
76906f6ba60Sopenharmony_ci    callStack_.clear();
77006f6ba60Sopenharmony_ci    bool isNapi = false;
77106f6ba60Sopenharmony_ci    if (hookConfig_.js_stack_report() == NAPI_CALL_STACK) {
77206f6ba60Sopenharmony_ci        std::string tagName;
77306f6ba60Sopenharmony_ci        GetMemTag(rawStack->stackConext->tagId, tagName);
77406f6ba60Sopenharmony_ci        if (tagName.find("napi") != std::string::npos) {
77506f6ba60Sopenharmony_ci            callStack_.reserve(callFrames.size() + FRAME_DEPTH);  // insert a frame
77606f6ba60Sopenharmony_ci            callStack_.push_back((DWARF_NAPI_CALLBACK + napiIndex_) | JS_OFFLINE_IP_MASK);
77706f6ba60Sopenharmony_ci            isNapi = true;
77806f6ba60Sopenharmony_ci        }
77906f6ba60Sopenharmony_ci    } else {
78006f6ba60Sopenharmony_ci        callStack_.reserve(callFrames.size() + 1);
78106f6ba60Sopenharmony_ci    }
78206f6ba60Sopenharmony_ci    callStack_.push_back(rawStack->stackConext->mallocSize | SIZE_MASK);
78306f6ba60Sopenharmony_ci    if (!hookConfig_.offline_symbolization()) {
78406f6ba60Sopenharmony_ci        FillCallStack(callFrames, idx, stackData);
78506f6ba60Sopenharmony_ci    } else {
78606f6ba60Sopenharmony_ci        FillOfflineCallStack(callFrames, idx, stackData);
78706f6ba60Sopenharmony_ci    }
78806f6ba60Sopenharmony_ci    // insert a frame
78906f6ba60Sopenharmony_ci    if (isNapi) {
79006f6ba60Sopenharmony_ci        std::string tagName;
79106f6ba60Sopenharmony_ci        GetMemTag(rawStack->stackConext->tagId, tagName);
79206f6ba60Sopenharmony_ci        FillNapiStack(tagName, callFrames, napiIndex_);
79306f6ba60Sopenharmony_ci        ReportFrameMap(callFrames.back(), stackData);
79406f6ba60Sopenharmony_ci        ++napiIndex_;
79506f6ba60Sopenharmony_ci    }
79606f6ba60Sopenharmony_ci    std::lock_guard<std::mutex> guard(mtx_);
79706f6ba60Sopenharmony_ci    // by call stack id set alloc statistics data.
79806f6ba60Sopenharmony_ci    uint32_t stackId = FindCallStackId(callStack_);
79906f6ba60Sopenharmony_ci    if (stackId > 0) {
80006f6ba60Sopenharmony_ci        SetAllocStatisticsData(rawStack, stackId, true);
80106f6ba60Sopenharmony_ci    } else {
80206f6ba60Sopenharmony_ci        stackId = SetCallStackMap(stackData);
80306f6ba60Sopenharmony_ci        statisticsModelFlushCallstack_ = true;
80406f6ba60Sopenharmony_ci        SetAllocStatisticsData(rawStack, stackId);
80506f6ba60Sopenharmony_ci    }
80606f6ba60Sopenharmony_ci}
80706f6ba60Sopenharmony_ci
80806f6ba60Sopenharmony_citemplate <typename T>
80906f6ba60Sopenharmony_civoid StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack, T& stackData)
81006f6ba60Sopenharmony_ci{
81106f6ba60Sopenharmony_ci    callStack_.resize(rawStack->fpDepth + 1);
81206f6ba60Sopenharmony_ci    callStack_[0] = (rawStack->stackConext->mallocSize | SIZE_MASK);
81306f6ba60Sopenharmony_ci    if (memcpy_s(callStack_.data() + 1, sizeof(uint64_t) * rawStack->fpDepth,
81406f6ba60Sopenharmony_ci                 rawStack->data, sizeof(uint64_t) * rawStack->fpDepth) != EOK) {
81506f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s callStack_ failed");
81606f6ba60Sopenharmony_ci        return;
81706f6ba60Sopenharmony_ci    }
81806f6ba60Sopenharmony_ci    std::lock_guard<std::mutex> guard(mtx_);
81906f6ba60Sopenharmony_ci    // by call stack id set alloc statistics data.
82006f6ba60Sopenharmony_ci    uint32_t stackId = FindCallStackId(callStack_);
82106f6ba60Sopenharmony_ci    if (stackId > 0) {
82206f6ba60Sopenharmony_ci        SetAllocStatisticsData(rawStack, stackId, true);
82306f6ba60Sopenharmony_ci    } else {
82406f6ba60Sopenharmony_ci        stackId = SetCallStackMap(stackData);
82506f6ba60Sopenharmony_ci        statisticsModelFlushCallstack_ = true;
82606f6ba60Sopenharmony_ci        SetAllocStatisticsData(rawStack, stackId);
82706f6ba60Sopenharmony_ci    }
82806f6ba60Sopenharmony_ci}
82906f6ba60Sopenharmony_ci
83006f6ba60Sopenharmony_citemplate <typename T>
83106f6ba60Sopenharmony_civoid StackPreprocess::SetHookData(RawStackPtr rawStack, T& stackData)
83206f6ba60Sopenharmony_ci{
83306f6ba60Sopenharmony_ci    if (hookConfig_.statistics_interval() > 0) {
83406f6ba60Sopenharmony_ci        // statistical reporting must is compressed and accurate.
83506f6ba60Sopenharmony_ci        switch (rawStack->stackConext->type) {
83606f6ba60Sopenharmony_ci            case FREE_MSG:
83706f6ba60Sopenharmony_ci            case MUNMAP_MSG:
83806f6ba60Sopenharmony_ci            case MEMORY_UNUSING_MSG: {
83906f6ba60Sopenharmony_ci                SetFreeStatisticsData((uint64_t)rawStack->stackConext->addr);
84006f6ba60Sopenharmony_ci                break;
84106f6ba60Sopenharmony_ci            }
84206f6ba60Sopenharmony_ci            case MALLOC_MSG:
84306f6ba60Sopenharmony_ci                rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize);
84406f6ba60Sopenharmony_ci            case MMAP_MSG:
84506f6ba60Sopenharmony_ci            case MMAP_FILE_PAGE_MSG:
84606f6ba60Sopenharmony_ci            case MEMORY_USING_MSG: {
84706f6ba60Sopenharmony_ci                SetAllocStatisticsFrame(rawStack, stackData);
84806f6ba60Sopenharmony_ci                break;
84906f6ba60Sopenharmony_ci            }
85006f6ba60Sopenharmony_ci            case PR_SET_VMA_MSG: {
85106f6ba60Sopenharmony_ci                break;
85206f6ba60Sopenharmony_ci            }
85306f6ba60Sopenharmony_ci            default: {
85406f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "statistics event type: error");
85506f6ba60Sopenharmony_ci                break;
85606f6ba60Sopenharmony_ci            }
85706f6ba60Sopenharmony_ci        }
85806f6ba60Sopenharmony_ci        return;
85906f6ba60Sopenharmony_ci    }
86006f6ba60Sopenharmony_ci}
86106f6ba60Sopenharmony_ci
86206f6ba60Sopenharmony_civoid StackPreprocess::ReportOfflineSymbolizationData()
86306f6ba60Sopenharmony_ci{
86406f6ba60Sopenharmony_ci    if (hookConfig_.offline_symbolization() && flushBasicData_) {
86506f6ba60Sopenharmony_ci        SetMapsInfo();
86606f6ba60Sopenharmony_ci        flushBasicData_ = false;
86706f6ba60Sopenharmony_ci    }
86806f6ba60Sopenharmony_ci}
86906f6ba60Sopenharmony_ci
87006f6ba60Sopenharmony_citemplate <typename T>
87106f6ba60Sopenharmony_civoid StackPreprocess::SetApplyAndReleaseMatchFrame(RawStackPtr rawStack, std::vector<CallFrame>& callFrames,
87206f6ba60Sopenharmony_ci                                                   T& stackData)
87306f6ba60Sopenharmony_ci{
87406f6ba60Sopenharmony_ci    uint32_t stackMapId = 0;
87506f6ba60Sopenharmony_ci    if (rawStack->stackConext->type != PR_SET_VMA_MSG) {
87606f6ba60Sopenharmony_ci        stackMapId = GetCallStackId(rawStack, callFrames, stackData);
87706f6ba60Sopenharmony_ci    } else {
87806f6ba60Sopenharmony_ci        rawStack->stackConext->tagId = prctlPeriodTags_.size();
87906f6ba60Sopenharmony_ci        prctlPeriodTags_.emplace_back(reinterpret_cast<char*>(rawStack->data));
88006f6ba60Sopenharmony_ci        applyAndReleaseMatchPeriodListData_.emplace_back(rawStack->stackConext);
88106f6ba60Sopenharmony_ci    }
88206f6ba60Sopenharmony_ci    if (rawStack->stackConext->type == MALLOC_MSG) {
88306f6ba60Sopenharmony_ci        rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize);
88406f6ba60Sopenharmony_ci    } else if (rawStack->stackConext->type == PR_SET_VMA_MSG) {
88506f6ba60Sopenharmony_ci        return;
88606f6ba60Sopenharmony_ci    }
88706f6ba60Sopenharmony_ci    uint64_t addr = reinterpret_cast<uint64_t>(rawStack->stackConext->addr);
88806f6ba60Sopenharmony_ci    auto iter = applyAndReleaseMatchIntervallMap_.find(addr);
88906f6ba60Sopenharmony_ci    if (iter != applyAndReleaseMatchIntervallMap_.end()) {
89006f6ba60Sopenharmony_ci        applyAndReleaseMatchPeriodListData_.erase(iter->second);
89106f6ba60Sopenharmony_ci        applyAndReleaseMatchIntervallMap_.erase(addr);
89206f6ba60Sopenharmony_ci    } else {
89306f6ba60Sopenharmony_ci        applyAndReleaseMatchPeriodListData_.emplace_back(rawStack->stackConext, stackMapId);
89406f6ba60Sopenharmony_ci        applyAndReleaseMatchIntervallMap_.emplace(addr, std::prev(applyAndReleaseMatchPeriodListData_.end()));
89506f6ba60Sopenharmony_ci    }
89606f6ba60Sopenharmony_ci}
89706f6ba60Sopenharmony_ci
89806f6ba60Sopenharmony_citemplate <typename T>
89906f6ba60Sopenharmony_civoid StackPreprocess::SetHookData(RawStackPtr rawStack, std::vector<CallFrame>& callFrames, T& stackData)
90006f6ba60Sopenharmony_ci{
90106f6ba60Sopenharmony_ci    // statistical reporting must is compressed and accurate.
90206f6ba60Sopenharmony_ci    if (hookConfig_.statistics_interval() > 0) {
90306f6ba60Sopenharmony_ci        switch (rawStack->stackConext->type) {
90406f6ba60Sopenharmony_ci            case FREE_MSG:
90506f6ba60Sopenharmony_ci            case MUNMAP_MSG:
90606f6ba60Sopenharmony_ci            case MEMORY_UNUSING_MSG: {
90706f6ba60Sopenharmony_ci                SetFreeStatisticsData((uint64_t)rawStack->stackConext->addr);
90806f6ba60Sopenharmony_ci                break;
90906f6ba60Sopenharmony_ci            }
91006f6ba60Sopenharmony_ci            case MALLOC_MSG:
91106f6ba60Sopenharmony_ci                rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize);
91206f6ba60Sopenharmony_ci            case MMAP_MSG:
91306f6ba60Sopenharmony_ci            case MMAP_FILE_PAGE_MSG:
91406f6ba60Sopenharmony_ci            case MEMORY_USING_MSG: {
91506f6ba60Sopenharmony_ci                SetAllocStatisticsFrame(rawStack, callFrames, stackData);
91606f6ba60Sopenharmony_ci                break;
91706f6ba60Sopenharmony_ci            }
91806f6ba60Sopenharmony_ci            case PR_SET_VMA_MSG: {
91906f6ba60Sopenharmony_ci                break;
92006f6ba60Sopenharmony_ci            }
92106f6ba60Sopenharmony_ci            default: {
92206f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "statistics event type:%d error", rawStack->stackConext->type);
92306f6ba60Sopenharmony_ci                break;
92406f6ba60Sopenharmony_ci            }
92506f6ba60Sopenharmony_ci        }
92606f6ba60Sopenharmony_ci        return;
92706f6ba60Sopenharmony_ci    }
92806f6ba60Sopenharmony_ci
92906f6ba60Sopenharmony_ci    uint32_t stackMapId = 0;
93006f6ba60Sopenharmony_ci    if (hookConfig_.callframe_compress() &&
93106f6ba60Sopenharmony_ci        !(rawStack->stackConext->type == MEMORY_TAG || rawStack->stackConext->type == PR_SET_VMA_MSG)) {
93206f6ba60Sopenharmony_ci        stackMapId = GetCallStackId(rawStack, callFrames, stackData);
93306f6ba60Sopenharmony_ci    }
93406f6ba60Sopenharmony_ci
93506f6ba60Sopenharmony_ci    if ((!hookConfig_.callframe_compress() || stackMapId == 0) && hookConfig_.string_compressed()) {
93606f6ba60Sopenharmony_ci        size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH;
93706f6ba60Sopenharmony_ci        for (; idx < callFrames.size(); ++idx) {
93806f6ba60Sopenharmony_ci            ReportSymbolNameMap(callFrames[idx], stackData);
93906f6ba60Sopenharmony_ci            ReportFilePathMap(callFrames[idx], stackData);
94006f6ba60Sopenharmony_ci        }
94106f6ba60Sopenharmony_ci    }
94206f6ba60Sopenharmony_ci
94306f6ba60Sopenharmony_ci    auto hookData = stackData.add_events();
94406f6ba60Sopenharmony_ci    hookData->set_tv_sec(rawStack->stackConext->ts.tv_sec);
94506f6ba60Sopenharmony_ci    hookData->set_tv_nsec(rawStack->stackConext->ts.tv_nsec);
94606f6ba60Sopenharmony_ci
94706f6ba60Sopenharmony_ci    if (rawStack->stackConext->type == MALLOC_MSG) {
94806f6ba60Sopenharmony_ci        auto allocEvent = hookData->mutable_alloc_event();
94906f6ba60Sopenharmony_ci        SetEventFrame(rawStack, callFrames, allocEvent, stackMapId);
95006f6ba60Sopenharmony_ci    } else if (rawStack->stackConext->type == FREE_MSG) {
95106f6ba60Sopenharmony_ci        auto freeEvent = hookData->mutable_free_event();
95206f6ba60Sopenharmony_ci        SetEventFrame(rawStack, callFrames, freeEvent, stackMapId);
95306f6ba60Sopenharmony_ci    } else if (rawStack->stackConext->type == MMAP_MSG) {
95406f6ba60Sopenharmony_ci        auto mmapEvent = hookData->mutable_mmap_event();
95506f6ba60Sopenharmony_ci        SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId);
95606f6ba60Sopenharmony_ci    } else if (rawStack->stackConext->type == MMAP_FILE_PAGE_MSG) {
95706f6ba60Sopenharmony_ci        auto mmapEvent = hookData->mutable_mmap_event();
95806f6ba60Sopenharmony_ci        const std::string prefix = "FilePage:";
95906f6ba60Sopenharmony_ci        std::string tagName;
96006f6ba60Sopenharmony_ci        if (GetMemTag(rawStack->stackConext->tagId, tagName)) {
96106f6ba60Sopenharmony_ci            tagName = prefix + tagName;
96206f6ba60Sopenharmony_ci        }
96306f6ba60Sopenharmony_ci        SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId, tagName);
96406f6ba60Sopenharmony_ci    } else if (rawStack->stackConext->type == MUNMAP_MSG) {
96506f6ba60Sopenharmony_ci        auto munmapEvent = hookData->mutable_munmap_event();
96606f6ba60Sopenharmony_ci        SetEventFrame(rawStack, callFrames, munmapEvent, stackMapId);
96706f6ba60Sopenharmony_ci    } else if (rawStack->stackConext->type == PR_SET_VMA_MSG) {
96806f6ba60Sopenharmony_ci        auto tagEvent = hookData->mutable_tag_event();
96906f6ba60Sopenharmony_ci        const std::string prefix = "Anonymous:";
97006f6ba60Sopenharmony_ci        std::string tagName(reinterpret_cast<char*>(rawStack->data));
97106f6ba60Sopenharmony_ci        tagEvent->set_addr((uint64_t)rawStack->stackConext->addr);
97206f6ba60Sopenharmony_ci        tagEvent->set_size(rawStack->stackConext->mallocSize);
97306f6ba60Sopenharmony_ci        tagEvent->set_tag(prefix + tagName);
97406f6ba60Sopenharmony_ci        tagEvent->set_pid(pid_);
97506f6ba60Sopenharmony_ci    } else if (rawStack->stackConext->type == MEMORY_USING_MSG) {
97606f6ba60Sopenharmony_ci        auto mmapEvent = hookData->mutable_mmap_event();
97706f6ba60Sopenharmony_ci        std::string tagName;
97806f6ba60Sopenharmony_ci        GetMemTag(rawStack->stackConext->tagId, tagName);
97906f6ba60Sopenharmony_ci        SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId, tagName);
98006f6ba60Sopenharmony_ci    } else if (rawStack->stackConext->type == MEMORY_UNUSING_MSG) {
98106f6ba60Sopenharmony_ci        auto munmapEvent = hookData->mutable_munmap_event();
98206f6ba60Sopenharmony_ci        SetEventFrame(rawStack, callFrames, munmapEvent, stackMapId);
98306f6ba60Sopenharmony_ci    }
98406f6ba60Sopenharmony_ci}
98506f6ba60Sopenharmony_ci
98606f6ba60Sopenharmony_ciinline bool StackPreprocess::SetFreeStatisticsData(uint64_t addr)
98706f6ba60Sopenharmony_ci{
98806f6ba60Sopenharmony_ci    // through the addr lookup record
98906f6ba60Sopenharmony_ci    auto addrIter = allocAddrMap_.find(addr);
99006f6ba60Sopenharmony_ci    if (addrIter != allocAddrMap_.end()) {
99106f6ba60Sopenharmony_ci        auto& record = addrIter->second.second;
99206f6ba60Sopenharmony_ci        ++record->releaseCount;
99306f6ba60Sopenharmony_ci        record->releaseSize += addrIter->second.first;
99406f6ba60Sopenharmony_ci        statisticsPeriodData_[record->callstackId] = record;
99506f6ba60Sopenharmony_ci        allocAddrMap_.erase(addr);
99606f6ba60Sopenharmony_ci        return true;
99706f6ba60Sopenharmony_ci    }
99806f6ba60Sopenharmony_ci    return false;
99906f6ba60Sopenharmony_ci}
100006f6ba60Sopenharmony_ci
100106f6ba60Sopenharmony_ciinline void StackPreprocess::SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists)
100206f6ba60Sopenharmony_ci{
100306f6ba60Sopenharmony_ci    // if the record exists, it is updated.Otherwise Add
100406f6ba60Sopenharmony_ci    if (isExists) {
100506f6ba60Sopenharmony_ci        auto recordIter = recordStatisticsMap_.find(stackId);
100606f6ba60Sopenharmony_ci        if (recordIter != recordStatisticsMap_.end()) {
100706f6ba60Sopenharmony_ci            auto& record = recordIter->second;
100806f6ba60Sopenharmony_ci            ++record.applyCount;
100906f6ba60Sopenharmony_ci            record.applySize += rawStack->stackConext->mallocSize;
101006f6ba60Sopenharmony_ci            allocAddrMap_[(uint64_t)rawStack->stackConext->addr] =
101106f6ba60Sopenharmony_ci                std::pair(rawStack->stackConext->mallocSize, &recordIter->second);
101206f6ba60Sopenharmony_ci            statisticsPeriodData_[stackId] = &recordIter->second;
101306f6ba60Sopenharmony_ci        }
101406f6ba60Sopenharmony_ci    } else {
101506f6ba60Sopenharmony_ci        RecordStatistic record;
101606f6ba60Sopenharmony_ci        record.pid = rawStack->stackConext->pid;
101706f6ba60Sopenharmony_ci        record.callstackId = stackId;
101806f6ba60Sopenharmony_ci        record.applyCount = 1;
101906f6ba60Sopenharmony_ci        record.applySize = rawStack->stackConext->mallocSize;
102006f6ba60Sopenharmony_ci        switch (rawStack->stackConext->type) {
102106f6ba60Sopenharmony_ci            case MALLOC_MSG: {
102206f6ba60Sopenharmony_ci                record.type = RecordStatisticsEvent::MALLOC;
102306f6ba60Sopenharmony_ci                break;
102406f6ba60Sopenharmony_ci            }
102506f6ba60Sopenharmony_ci            case MMAP_MSG: {
102606f6ba60Sopenharmony_ci                record.type = RecordStatisticsEvent::MMAP;
102706f6ba60Sopenharmony_ci                break;
102806f6ba60Sopenharmony_ci            }
102906f6ba60Sopenharmony_ci            case MMAP_FILE_PAGE_MSG: {
103006f6ba60Sopenharmony_ci                record.type = RecordStatisticsEvent::FILE_PAGE_MSG;
103106f6ba60Sopenharmony_ci                break;
103206f6ba60Sopenharmony_ci            }
103306f6ba60Sopenharmony_ci            case MEMORY_USING_MSG: {
103406f6ba60Sopenharmony_ci                record.type = RecordStatisticsEvent::MEMORY_USING_MSG;
103506f6ba60Sopenharmony_ci                record.tagId = rawStack->stackConext->tagId;
103606f6ba60Sopenharmony_ci                break;
103706f6ba60Sopenharmony_ci            }
103806f6ba60Sopenharmony_ci            default: {
103906f6ba60Sopenharmony_ci                PROFILER_LOG_ERROR(LOG_CORE, "SetAllocStatisticsData event type error");
104006f6ba60Sopenharmony_ci                break;
104106f6ba60Sopenharmony_ci            }
104206f6ba60Sopenharmony_ci        }
104306f6ba60Sopenharmony_ci
104406f6ba60Sopenharmony_ci        auto [recordIter, stat] = recordStatisticsMap_.emplace(stackId, record);
104506f6ba60Sopenharmony_ci        allocAddrMap_[(uint64_t)rawStack->stackConext->addr] =
104606f6ba60Sopenharmony_ci            std::pair(rawStack->stackConext->mallocSize, &recordIter->second);
104706f6ba60Sopenharmony_ci        statisticsPeriodData_[stackId] = &recordIter->second;
104806f6ba60Sopenharmony_ci    }
104906f6ba60Sopenharmony_ci}
105006f6ba60Sopenharmony_ci
105106f6ba60Sopenharmony_civoid StackPreprocess::WriteFrames(RawStackPtr rawStack, const std::vector<CallFrame>& callFrames)
105206f6ba60Sopenharmony_ci{
105306f6ba60Sopenharmony_ci    CHECK_TRUE(fpHookData_ != nullptr, NO_RETVAL, "fpHookData_ is nullptr, please check file_name(%s)",
105406f6ba60Sopenharmony_ci        hookConfig_.file_name().c_str());
105506f6ba60Sopenharmony_ci    if (rawStack->stackConext->type == PR_SET_VMA_MSG) {
105606f6ba60Sopenharmony_ci        const std::string prefix = "Anonymous:";
105706f6ba60Sopenharmony_ci        std::string tagName(reinterpret_cast<char*>(rawStack->data));
105806f6ba60Sopenharmony_ci        fprintf(fpHookData_, "prctl;%u;%u;%" PRId64 ";%ld;0x%" PRIx64 ":tag:%s\n",
105906f6ba60Sopenharmony_ci            rawStack->stackConext->pid, rawStack->stackConext->tid,
106006f6ba60Sopenharmony_ci            (int64_t)rawStack->stackConext->ts.tv_sec, rawStack->stackConext->ts.tv_nsec,
106106f6ba60Sopenharmony_ci            (uint64_t)rawStack->stackConext->addr, (prefix + tagName).c_str());
106206f6ba60Sopenharmony_ci        return;
106306f6ba60Sopenharmony_ci    }
106406f6ba60Sopenharmony_ci    std::string tag = "";
106506f6ba60Sopenharmony_ci    switch (rawStack->stackConext->type) {
106606f6ba60Sopenharmony_ci        case FREE_MSG:
106706f6ba60Sopenharmony_ci            tag = "free";
106806f6ba60Sopenharmony_ci            break;
106906f6ba60Sopenharmony_ci        case MALLOC_MSG:
107006f6ba60Sopenharmony_ci            tag = "malloc";
107106f6ba60Sopenharmony_ci            break;
107206f6ba60Sopenharmony_ci        case MMAP_MSG:
107306f6ba60Sopenharmony_ci            tag = "mmap";
107406f6ba60Sopenharmony_ci            break;
107506f6ba60Sopenharmony_ci        case MUNMAP_MSG:
107606f6ba60Sopenharmony_ci            tag = "munmap";
107706f6ba60Sopenharmony_ci            break;
107806f6ba60Sopenharmony_ci        default:
107906f6ba60Sopenharmony_ci            break;
108006f6ba60Sopenharmony_ci    }
108106f6ba60Sopenharmony_ci
108206f6ba60Sopenharmony_ci    fprintf(fpHookData_, "%s;%u;%u;%" PRId64 ";%ld;0x%" PRIx64 ";%zu\n", tag.c_str(),
108306f6ba60Sopenharmony_ci        rawStack->stackConext->pid, rawStack->stackConext->tid, (int64_t)rawStack->stackConext->ts.tv_sec,
108406f6ba60Sopenharmony_ci        rawStack->stackConext->ts.tv_nsec, (uint64_t)rawStack->stackConext->addr, rawStack->stackConext->mallocSize);
108506f6ba60Sopenharmony_ci    size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH;
108606f6ba60Sopenharmony_ci    for (; idx < callFrames.size(); ++idx) {
108706f6ba60Sopenharmony_ci        (void)fprintf(fpHookData_, "0x%" PRIx64 ";0x%" PRIx64 ";%s;%s;0x%" PRIx64 ";%" PRIu64 "\n",
108806f6ba60Sopenharmony_ci            callFrames[idx].ip_, callFrames[idx].sp_, std::string(callFrames[idx].symbolName_).c_str(),
108906f6ba60Sopenharmony_ci            std::string(callFrames[idx].filePath_).c_str(), callFrames[idx].offset_, callFrames[idx].symbolOffset_);
109006f6ba60Sopenharmony_ci    }
109106f6ba60Sopenharmony_ci}
109206f6ba60Sopenharmony_ci
109306f6ba60Sopenharmony_citemplate <typename T>
109406f6ba60Sopenharmony_ciinline void StackPreprocess::SetFrameInfo(T& frame, CallFrame& callFrame)
109506f6ba60Sopenharmony_ci{
109606f6ba60Sopenharmony_ci    frame.set_ip(callFrame.ip_);
109706f6ba60Sopenharmony_ci    if (hookConfig_.offline_symbolization()) {
109806f6ba60Sopenharmony_ci        // when js mixes offline symbols, the js call stack is reported according to the online symbolization
109906f6ba60Sopenharmony_ci        if (callFrame.isJsFrame_ && callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0) {
110006f6ba60Sopenharmony_ci            frame.set_sp(callFrame.sp_);
110106f6ba60Sopenharmony_ci            frame.set_offset(callFrame.offset_);
110206f6ba60Sopenharmony_ci            frame.set_symbol_offset(callFrame.symbolOffset_);
110306f6ba60Sopenharmony_ci            frame.set_symbol_name_id(callFrame.symbolNameId_);
110406f6ba60Sopenharmony_ci            frame.set_file_path_id(callFrame.filePathId_);
110506f6ba60Sopenharmony_ci        }
110606f6ba60Sopenharmony_ci        return;
110706f6ba60Sopenharmony_ci    }
110806f6ba60Sopenharmony_ci    frame.set_sp(callFrame.sp_);
110906f6ba60Sopenharmony_ci    if (!(callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0)) {
111006f6ba60Sopenharmony_ci        frame.set_symbol_name(std::string(callFrame.symbolName_));
111106f6ba60Sopenharmony_ci        frame.set_file_path(std::string(callFrame.filePath_));
111206f6ba60Sopenharmony_ci    }
111306f6ba60Sopenharmony_ci    frame.set_offset(callFrame.offset_);
111406f6ba60Sopenharmony_ci    frame.set_symbol_offset(callFrame.symbolOffset_);
111506f6ba60Sopenharmony_ci    if (callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0) {
111606f6ba60Sopenharmony_ci        frame.set_symbol_name_id(callFrame.symbolNameId_);
111706f6ba60Sopenharmony_ci        frame.set_file_path_id(callFrame.filePathId_);
111806f6ba60Sopenharmony_ci    }
111906f6ba60Sopenharmony_ci}
112006f6ba60Sopenharmony_ci
112106f6ba60Sopenharmony_citemplate <typename T>
112206f6ba60Sopenharmony_ciinline void StackPreprocess::ReportSymbolNameMap(CallFrame& callFrame, T& stackData)
112306f6ba60Sopenharmony_ci{
112406f6ba60Sopenharmony_ci    if (callFrame.needReport_ & SYMBOL_NAME_ID_REPORT) {
112506f6ba60Sopenharmony_ci        auto hookData = stackData.add_events();
112606f6ba60Sopenharmony_ci        auto symbolMap = hookData->mutable_symbol_name();
112706f6ba60Sopenharmony_ci        symbolMap->set_id(callFrame.symbolNameId_);
112806f6ba60Sopenharmony_ci        symbolMap->set_name(std::string(callFrame.symbolName_));
112906f6ba60Sopenharmony_ci        symbolMap->set_pid(pid_);
113006f6ba60Sopenharmony_ci    }
113106f6ba60Sopenharmony_ci}
113206f6ba60Sopenharmony_ci
113306f6ba60Sopenharmony_citemplate <typename T>
113406f6ba60Sopenharmony_ciinline void StackPreprocess::ReportFilePathMap(CallFrame& callFrame, T& stackData)
113506f6ba60Sopenharmony_ci{
113606f6ba60Sopenharmony_ci    if (callFrame.needReport_ & FILE_PATH_ID_REPORT) {
113706f6ba60Sopenharmony_ci        auto hookData = stackData.add_events();
113806f6ba60Sopenharmony_ci        auto filePathMap = hookData->mutable_file_path();
113906f6ba60Sopenharmony_ci        filePathMap->set_id(callFrame.filePathId_);
114006f6ba60Sopenharmony_ci        filePathMap->set_name(std::string(callFrame.filePath_));
114106f6ba60Sopenharmony_ci        filePathMap->set_pid(pid_);
114206f6ba60Sopenharmony_ci    }
114306f6ba60Sopenharmony_ci}
114406f6ba60Sopenharmony_ci
114506f6ba60Sopenharmony_citemplate <typename T>
114606f6ba60Sopenharmony_ciinline void StackPreprocess::ReportFrameMap(CallFrame& callFrame, T& stackData)
114706f6ba60Sopenharmony_ci{
114806f6ba60Sopenharmony_ci    if (callFrame.needReport_ & CALL_FRAME_REPORT) {
114906f6ba60Sopenharmony_ci        if ((!hookConfig_.fp_unwind()) && callFrame.callFrameId_ == DWARF_ERROR_ID && !unwindFailReport_) {
115006f6ba60Sopenharmony_ci            return;
115106f6ba60Sopenharmony_ci        } else if ((!hookConfig_.fp_unwind()) && callFrame.callFrameId_ == DWARF_ERROR_ID && unwindFailReport_) {
115206f6ba60Sopenharmony_ci            unwindFailReport_ = false;
115306f6ba60Sopenharmony_ci        }
115406f6ba60Sopenharmony_ci        ReportSymbolNameMap(callFrame, stackData);
115506f6ba60Sopenharmony_ci        ReportFilePathMap(callFrame, stackData);
115606f6ba60Sopenharmony_ci        auto hookData = stackData.add_events();
115706f6ba60Sopenharmony_ci        auto frameMap = hookData->mutable_frame_map();
115806f6ba60Sopenharmony_ci        frameMap->set_id(callFrame.callFrameId_);
115906f6ba60Sopenharmony_ci        auto frame = frameMap->mutable_frame();
116006f6ba60Sopenharmony_ci        SetFrameInfo(*frame, callFrame);
116106f6ba60Sopenharmony_ci        frameMap->set_pid(pid_);
116206f6ba60Sopenharmony_ci    }
116306f6ba60Sopenharmony_ci}
116406f6ba60Sopenharmony_ci
116506f6ba60Sopenharmony_civoid StackPreprocess::SetMapsInfo()
116606f6ba60Sopenharmony_ci{
116706f6ba60Sopenharmony_ci    std::lock_guard<std::mutex> guard(mtx_);
116806f6ba60Sopenharmony_ci    for (auto& itemSoBegin : runtime_instance->GetOfflineMaps()) {
116906f6ba60Sopenharmony_ci        auto& maps = runtime_instance->GetMapsCache();
117006f6ba60Sopenharmony_ci        auto mapsIter = maps.find(itemSoBegin);
117106f6ba60Sopenharmony_ci        if (mapsIter == maps.end()) {
117206f6ba60Sopenharmony_ci            continue;
117306f6ba60Sopenharmony_ci        }
117406f6ba60Sopenharmony_ci
117506f6ba60Sopenharmony_ci        ElfSymbolTable symbolInfo;
117606f6ba60Sopenharmony_ci        auto& curMemMaps = mapsIter->second;
117706f6ba60Sopenharmony_ci        GetSymbols(curMemMaps->name_, symbolInfo);
117806f6ba60Sopenharmony_ci        if (symbolInfo.symEntSize == 0) {
117906f6ba60Sopenharmony_ci            continue;
118006f6ba60Sopenharmony_ci        }
118106f6ba60Sopenharmony_ci        std::visit([&](auto& stackData) {
118206f6ba60Sopenharmony_ci            auto hookData = stackData.add_events();
118306f6ba60Sopenharmony_ci            auto filepathMap = hookData->mutable_file_path();
118406f6ba60Sopenharmony_ci            filepathMap->set_id(curMemMaps->filePathId_);
118506f6ba60Sopenharmony_ci            filepathMap->set_name(curMemMaps->name_);
118606f6ba60Sopenharmony_ci            filepathMap->set_pid(pid_);
118706f6ba60Sopenharmony_ci            SetSymbolInfo(curMemMaps->filePathId_, symbolInfo, stackData);
118806f6ba60Sopenharmony_ci
118906f6ba60Sopenharmony_ci            for (auto& map : curMemMaps->GetMaps()) {
119006f6ba60Sopenharmony_ci                if (map->prots & PROT_EXEC) {
119106f6ba60Sopenharmony_ci                    auto nativeHookData = stackData.add_events();
119206f6ba60Sopenharmony_ci                    auto mapSerialize = nativeHookData->mutable_maps_info();
119306f6ba60Sopenharmony_ci                    mapSerialize->set_pid(pid_);
119406f6ba60Sopenharmony_ci                    mapSerialize->set_start(map->begin);
119506f6ba60Sopenharmony_ci                    mapSerialize->set_end(map->end);
119606f6ba60Sopenharmony_ci                    mapSerialize->set_offset(map->offset);
119706f6ba60Sopenharmony_ci                    mapSerialize->set_file_path_id(curMemMaps->filePathId_);
119806f6ba60Sopenharmony_ci                }
119906f6ba60Sopenharmony_ci            }
120006f6ba60Sopenharmony_ci            FlushData(stackData);
120106f6ba60Sopenharmony_ci            }, stackData_);
120206f6ba60Sopenharmony_ci    }
120306f6ba60Sopenharmony_ci    runtime_instance->ClearOfflineMaps();
120406f6ba60Sopenharmony_ci}
120506f6ba60Sopenharmony_ci
120606f6ba60Sopenharmony_citemplate <typename T>
120706f6ba60Sopenharmony_civoid StackPreprocess::SetSymbolInfo(uint32_t filePathId, ElfSymbolTable& symbolInfo, T& batchNativeHookData)
120806f6ba60Sopenharmony_ci{
120906f6ba60Sopenharmony_ci    if (symbolInfo.symEntSize == 0) {
121006f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "SetSymbolInfo get symbolInfo failed");
121106f6ba60Sopenharmony_ci        return;
121206f6ba60Sopenharmony_ci    }
121306f6ba60Sopenharmony_ci    auto hookData = batchNativeHookData.add_events();
121406f6ba60Sopenharmony_ci    auto symTable = hookData->mutable_symbol_tab();
121506f6ba60Sopenharmony_ci    symTable->set_file_path_id(filePathId);
121606f6ba60Sopenharmony_ci    symTable->set_text_exec_vaddr(symbolInfo.textVaddr);
121706f6ba60Sopenharmony_ci    symTable->set_text_exec_vaddr_file_offset(symbolInfo.textOffset);
121806f6ba60Sopenharmony_ci    symTable->set_sym_entry_size(symbolInfo.symEntSize);
121906f6ba60Sopenharmony_ci    symTable->set_sym_table(symbolInfo.symTable.data(), symbolInfo.symTable.size());
122006f6ba60Sopenharmony_ci    symTable->set_str_table(symbolInfo.strTable.data(), symbolInfo.strTable.size());
122106f6ba60Sopenharmony_ci    symTable->set_pid(pid_);
122206f6ba60Sopenharmony_ci}
122306f6ba60Sopenharmony_ci
122406f6ba60Sopenharmony_citemplate <typename T>
122506f6ba60Sopenharmony_civoid StackPreprocess::FlushCheck(T& stackData)
122606f6ba60Sopenharmony_ci{
122706f6ba60Sopenharmony_ci    if (hookConfig_.statistics_interval() > 0) {
122806f6ba60Sopenharmony_ci        if (!statisticsModelFlushCallstack_) {
122906f6ba60Sopenharmony_ci            return;
123006f6ba60Sopenharmony_ci        }
123106f6ba60Sopenharmony_ci        if constexpr (std::is_same<T, ::BatchNativeHookData>::value) {
123206f6ba60Sopenharmony_ci            FlushData(stackData);
123306f6ba60Sopenharmony_ci        } else {
123406f6ba60Sopenharmony_ci            uint64_t dataLen = static_cast<uint64_t>(stackData.Size());
123506f6ba60Sopenharmony_ci            if (dataLen > flushSize_) {
123606f6ba60Sopenharmony_ci                FlushData(stackData);
123706f6ba60Sopenharmony_ci            }
123806f6ba60Sopenharmony_ci        }
123906f6ba60Sopenharmony_ci        statisticsModelFlushCallstack_ = false;
124006f6ba60Sopenharmony_ci    } else {
124106f6ba60Sopenharmony_ci        FlushData(stackData);
124206f6ba60Sopenharmony_ci    }
124306f6ba60Sopenharmony_ci}
124406f6ba60Sopenharmony_ci
124506f6ba60Sopenharmony_civoid StackPreprocess::FlushData(BatchNativeHookData& stackData)
124606f6ba60Sopenharmony_ci{
124706f6ba60Sopenharmony_ci    if (buffer_ == nullptr) {
124806f6ba60Sopenharmony_ci        return;
124906f6ba60Sopenharmony_ci    }
125006f6ba60Sopenharmony_ci    if (stackData.events().size() > 0) {
125106f6ba60Sopenharmony_ci        size_t length = stackData.ByteSizeLong();
125206f6ba60Sopenharmony_ci        stackData.SerializeToArray(buffer_.get(), length);
125306f6ba60Sopenharmony_ci        if (length < bufferSize_) {
125406f6ba60Sopenharmony_ci            if (isHookStandaloneSerialize_) {
125506f6ba60Sopenharmony_ci                std::string str;
125606f6ba60Sopenharmony_ci                ForStandard::BatchNativeHookData StandardStackData;
125706f6ba60Sopenharmony_ci                StandardStackData.ParseFromArray(buffer_.get(), length);
125806f6ba60Sopenharmony_ci                google::protobuf::TextFormat::PrintToString(StandardStackData, &str);
125906f6ba60Sopenharmony_ci                size_t n = fwrite(str.data(), 1, str.size(), fpHookData_);
126006f6ba60Sopenharmony_ci                fflush(fpHookData_);
126106f6ba60Sopenharmony_ci                std::get<::BatchNativeHookData>(stackData_).clear_events();
126206f6ba60Sopenharmony_ci                PROFILER_LOG_DEBUG(LOG_CORE, "Flush Data fwrite n = %zu str.size() = %zu", n, str.size());
126306f6ba60Sopenharmony_ci            } else {
126406f6ba60Sopenharmony_ci                Flush(buffer_.get(), length);
126506f6ba60Sopenharmony_ci            }
126606f6ba60Sopenharmony_ci        } else {
126706f6ba60Sopenharmony_ci            PROFILER_LOG_ERROR(LOG_CORE, "the data is larger than MAX_BUFFER_SIZE, flush failed");
126806f6ba60Sopenharmony_ci        }
126906f6ba60Sopenharmony_ci    }
127006f6ba60Sopenharmony_ci}
127106f6ba60Sopenharmony_ci
127206f6ba60Sopenharmony_civoid StackPreprocess::FlushData(ProtoEncoder::BatchNativeHookData& stackData)
127306f6ba60Sopenharmony_ci{
127406f6ba60Sopenharmony_ci    if (stackData.Size() == 0) {
127506f6ba60Sopenharmony_ci        return;
127606f6ba60Sopenharmony_ci    }
127706f6ba60Sopenharmony_ci
127806f6ba60Sopenharmony_ci    int messageLen = stackData.Finish();
127906f6ba60Sopenharmony_ci    RandomWriteCtx* ctx = nullptr;
128006f6ba60Sopenharmony_ci    if (!isSaService_) {
128106f6ba60Sopenharmony_ci        resultWriter_->finishReport(resultWriter_, messageLen);
128206f6ba60Sopenharmony_ci        resultWriter_->flush(resultWriter_);
128306f6ba60Sopenharmony_ci        ctx = resultWriter_->startReport(resultWriter_);
128406f6ba60Sopenharmony_ci    } else {
128506f6ba60Sopenharmony_ci        profilerPluginData_.finishAdd_data(messageLen);
128606f6ba60Sopenharmony_ci        FinishReport();
128706f6ba60Sopenharmony_ci        ctx = StartReport();
128806f6ba60Sopenharmony_ci    }
128906f6ba60Sopenharmony_ci
129006f6ba60Sopenharmony_ci    if (ctx == nullptr) {
129106f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__);
129206f6ba60Sopenharmony_ci        return;
129306f6ba60Sopenharmony_ci    }
129406f6ba60Sopenharmony_ci    stackData_ = ProtoEncoder::BatchNativeHookData(ctx);
129506f6ba60Sopenharmony_ci}
129606f6ba60Sopenharmony_ci
129706f6ba60Sopenharmony_civoid StackPreprocess::Flush(const uint8_t* src, size_t size)
129806f6ba60Sopenharmony_ci{
129906f6ba60Sopenharmony_ci    if (src == nullptr) {
130006f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "Flush src is nullptr");
130106f6ba60Sopenharmony_ci        return;
130206f6ba60Sopenharmony_ci    }
130306f6ba60Sopenharmony_ci
130406f6ba60Sopenharmony_ci    if (writer_ == nullptr) {
130506f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "Flush writer_ is nullptr");
130606f6ba60Sopenharmony_ci        return;
130706f6ba60Sopenharmony_ci    }
130806f6ba60Sopenharmony_ci    writer_->Write(src, size);
130906f6ba60Sopenharmony_ci    writer_->Flush();
131006f6ba60Sopenharmony_ci
131106f6ba60Sopenharmony_ci    std::get<::BatchNativeHookData>(stackData_).clear_events();
131206f6ba60Sopenharmony_ci}
131306f6ba60Sopenharmony_ci
131406f6ba60Sopenharmony_civoid StackPreprocess::GetSymbols(const std::string& filePath, ElfSymbolTable& symbols)
131506f6ba60Sopenharmony_ci{
131606f6ba60Sopenharmony_ci    std::shared_ptr<DfxElf> elfPtr = std::make_shared<DfxElf>(filePath);
131706f6ba60Sopenharmony_ci
131806f6ba60Sopenharmony_ci    symbols.textVaddr = elfPtr->GetStartVaddr();
131906f6ba60Sopenharmony_ci    symbols.textOffset = elfPtr->GetStartOffset();
132006f6ba60Sopenharmony_ci    if (symbols.textVaddr == (std::numeric_limits<uint64_t>::max)()) {
132106f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "GetSymbols get textVaddr failed");
132206f6ba60Sopenharmony_ci        return;
132306f6ba60Sopenharmony_ci    }
132406f6ba60Sopenharmony_ci
132506f6ba60Sopenharmony_ci    std::string symSecName;
132606f6ba60Sopenharmony_ci    std::string strSecName;
132706f6ba60Sopenharmony_ci    ShdrInfo shdr;
132806f6ba60Sopenharmony_ci    if (elfPtr->GetSectionInfo(shdr, ".symtab")) {
132906f6ba60Sopenharmony_ci        symSecName = ".symtab";
133006f6ba60Sopenharmony_ci        strSecName = ".strtab";
133106f6ba60Sopenharmony_ci    } else if (elfPtr->GetSectionInfo(shdr, ".dynsym")) {
133206f6ba60Sopenharmony_ci        symSecName = ".dynsym";
133306f6ba60Sopenharmony_ci        strSecName = ".dynstr";
133406f6ba60Sopenharmony_ci    } else {
133506f6ba60Sopenharmony_ci        return;
133606f6ba60Sopenharmony_ci    }
133706f6ba60Sopenharmony_ci    symbols.symEntSize = shdr.entSize;
133806f6ba60Sopenharmony_ci    symbols.symTable.resize(shdr.size);
133906f6ba60Sopenharmony_ci    if (!elfPtr->GetSectionData(symbols.symTable.data(), shdr.size, symSecName)) {
134006f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "GetSymbols get symbol section data failed");
134106f6ba60Sopenharmony_ci        return;
134206f6ba60Sopenharmony_ci    }
134306f6ba60Sopenharmony_ci    if (!elfPtr->GetSectionInfo(shdr, strSecName)) {
134406f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "GetSymbols get str section failed");
134506f6ba60Sopenharmony_ci        return;
134606f6ba60Sopenharmony_ci    }
134706f6ba60Sopenharmony_ci    symbols.strTable.resize(shdr.size);
134806f6ba60Sopenharmony_ci    if (!elfPtr->GetSectionData(symbols.strTable.data(), shdr.size, strSecName)) {
134906f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "GetSymbols get str section failed");
135006f6ba60Sopenharmony_ci        return;
135106f6ba60Sopenharmony_ci    }
135206f6ba60Sopenharmony_ci}
135306f6ba60Sopenharmony_ci
135406f6ba60Sopenharmony_cibool StackPreprocess::FlushRecordStatistics()
135506f6ba60Sopenharmony_ci{
135606f6ba60Sopenharmony_ci    if (statisticsPeriodData_.empty()) {
135706f6ba60Sopenharmony_ci        return false;
135806f6ba60Sopenharmony_ci    }
135906f6ba60Sopenharmony_ci    std::visit([&](auto& stackData) {
136006f6ba60Sopenharmony_ci        FlushData(stackData);
136106f6ba60Sopenharmony_ci        }, stackData_);
136206f6ba60Sopenharmony_ci    std::visit([&](auto& stackData) {
136306f6ba60Sopenharmony_ci        struct timespec ts;
136406f6ba60Sopenharmony_ci        clock_gettime(hookDataClockId_, &ts);
136506f6ba60Sopenharmony_ci        for (auto [addr, statistics] : statisticsPeriodData_) {
136606f6ba60Sopenharmony_ci            auto hookData = stackData.add_events();
136706f6ba60Sopenharmony_ci            hookData->set_tv_sec(ts.tv_sec);
136806f6ba60Sopenharmony_ci            hookData->set_tv_nsec(ts.tv_nsec);
136906f6ba60Sopenharmony_ci            auto recordEvent = hookData->mutable_statistics_event();
137006f6ba60Sopenharmony_ci            recordEvent->set_pid(statistics->pid);
137106f6ba60Sopenharmony_ci            recordEvent->set_callstack_id(statistics->callstackId);
137206f6ba60Sopenharmony_ci            recordEvent->set_type(statistics->type);
137306f6ba60Sopenharmony_ci            recordEvent->set_apply_count(statistics->applyCount);
137406f6ba60Sopenharmony_ci            recordEvent->set_release_count(statistics->releaseCount);
137506f6ba60Sopenharmony_ci            recordEvent->set_apply_size(statistics->applySize);
137606f6ba60Sopenharmony_ci            recordEvent->set_release_size(statistics->releaseSize);
137706f6ba60Sopenharmony_ci        }
137806f6ba60Sopenharmony_ci        FlushData(stackData);
137906f6ba60Sopenharmony_ci        }, stackData_);
138006f6ba60Sopenharmony_ci    statisticsPeriodData_.clear();
138106f6ba60Sopenharmony_ci    return true;
138206f6ba60Sopenharmony_ci}
138306f6ba60Sopenharmony_ci
138406f6ba60Sopenharmony_civoid StackPreprocess::SaveMemTag(uint32_t tagId, const std::string& tagName)
138506f6ba60Sopenharmony_ci{
138606f6ba60Sopenharmony_ci    std::string temp;
138706f6ba60Sopenharmony_ci    bool res = memTagMap_.Find(tagId, temp);
138806f6ba60Sopenharmony_ci    if (!res) {
138906f6ba60Sopenharmony_ci        memTagMap_.EnsureInsert(tagId, tagName);
139006f6ba60Sopenharmony_ci    }
139106f6ba60Sopenharmony_ci}
139206f6ba60Sopenharmony_ci
139306f6ba60Sopenharmony_cibool StackPreprocess::GetMemTag(uint32_t tagId, std::string& tagName)
139406f6ba60Sopenharmony_ci{
139506f6ba60Sopenharmony_ci    return memTagMap_.Find(tagId, tagName);
139606f6ba60Sopenharmony_ci}
139706f6ba60Sopenharmony_ci
139806f6ba60Sopenharmony_civoid StackPreprocess::SaveJsRawStack(uint64_t jsChainId, const char* jsRawStack)
139906f6ba60Sopenharmony_ci{
140006f6ba60Sopenharmony_ci    auto iterChainId = jsStackMap_.find(jsChainId);
140106f6ba60Sopenharmony_ci    if (iterChainId == jsStackMap_.end()) {
140206f6ba60Sopenharmony_ci        auto iterRawStack = jsStackSet_.find(jsRawStack);
140306f6ba60Sopenharmony_ci        if (iterRawStack == jsStackSet_.end()) {
140406f6ba60Sopenharmony_ci            auto iter = jsStackSet_.insert(jsRawStack);
140506f6ba60Sopenharmony_ci            jsStackMap_[jsChainId] = iter.first->c_str();
140606f6ba60Sopenharmony_ci        } else {
140706f6ba60Sopenharmony_ci            jsStackMap_[jsChainId] = iterRawStack->c_str();
140806f6ba60Sopenharmony_ci        }
140906f6ba60Sopenharmony_ci    }
141006f6ba60Sopenharmony_ci}
141106f6ba60Sopenharmony_ci
141206f6ba60Sopenharmony_ciconst char* StackPreprocess::GetJsRawStack(uint64_t jsChainId)
141306f6ba60Sopenharmony_ci{
141406f6ba60Sopenharmony_ci    auto iter = jsStackMap_.find(jsChainId);
141506f6ba60Sopenharmony_ci    if (iter != jsStackMap_.end()) {
141606f6ba60Sopenharmony_ci        return iter->second;
141706f6ba60Sopenharmony_ci    }
141806f6ba60Sopenharmony_ci    return nullptr;
141906f6ba60Sopenharmony_ci}
142006f6ba60Sopenharmony_ci
142106f6ba60Sopenharmony_ciunsigned StackPreprocess::LgFloor(unsigned long val)
142206f6ba60Sopenharmony_ci{
142306f6ba60Sopenharmony_ci    val |= (val >> RIGHT_MOVE_1);
142406f6ba60Sopenharmony_ci    val |= (val >> RIGHT_MOVE_2);
142506f6ba60Sopenharmony_ci    val |= (val >> RIGHT_MOVE_4);
142606f6ba60Sopenharmony_ci    val |= (val >> RIGHT_MOVE_8);
142706f6ba60Sopenharmony_ci    val |= (val >> RIGHT_MOVE_16);
142806f6ba60Sopenharmony_ci    if (sizeof(val) > 4) {              // 4: sizeThreshold
142906f6ba60Sopenharmony_ci        int constant = sizeof(val) * 4; // 4: sizeThreshold
143006f6ba60Sopenharmony_ci        val |= (val >> constant);
143106f6ba60Sopenharmony_ci    }
143206f6ba60Sopenharmony_ci    val++;
143306f6ba60Sopenharmony_ci    if (val == 0) {
143406f6ba60Sopenharmony_ci        return 8 * sizeof(val) - 1; // 8: 8byte
143506f6ba60Sopenharmony_ci    }
143606f6ba60Sopenharmony_ci    return __builtin_ffsl(val) - 2; // 2: adjustment
143706f6ba60Sopenharmony_ci}
143806f6ba60Sopenharmony_ci
143906f6ba60Sopenharmony_ciuint64_t StackPreprocess::PowCeil(uint64_t val)
144006f6ba60Sopenharmony_ci{
144106f6ba60Sopenharmony_ci    size_t msbIndex = LgFloor(val - 1);
144206f6ba60Sopenharmony_ci    return 1ULL << (msbIndex + 1);
144306f6ba60Sopenharmony_ci}
144406f6ba60Sopenharmony_ci
144506f6ba60Sopenharmony_cisize_t StackPreprocess::ComputeAlign(size_t size)
144606f6ba60Sopenharmony_ci{
144706f6ba60Sopenharmony_ci    if (size == 0) {
144806f6ba60Sopenharmony_ci        return 0;
144906f6ba60Sopenharmony_ci    }
145006f6ba60Sopenharmony_ci    unsigned index = 0;
145106f6ba60Sopenharmony_ci    if (size <= (size_t(1) << SC_LG_TINY_MAXCLASS)) {
145206f6ba60Sopenharmony_ci        unsigned lgTmin = SC_LG_TINY_MAXCLASS - SC_NTINY + 1;
145306f6ba60Sopenharmony_ci        unsigned lgCeil = LgFloor(PowCeil(size));
145406f6ba60Sopenharmony_ci        index = (lgCeil < lgTmin) ? 0 : lgCeil - lgTmin;
145506f6ba60Sopenharmony_ci    } else {
145606f6ba60Sopenharmony_ci        unsigned floor = LgFloor((size << 1) - 1);
145706f6ba60Sopenharmony_ci        unsigned shift = (floor < SC_LG_NGROUP + LG_QUANTUM) ? 0 : floor - (SC_LG_NGROUP + LG_QUANTUM);
145806f6ba60Sopenharmony_ci        unsigned grp = shift << SC_LG_NGROUP;
145906f6ba60Sopenharmony_ci        unsigned lgDelta = (floor < SC_LG_NGROUP + LG_QUANTUM + 1) ? LG_QUANTUM : floor - SC_LG_NGROUP - 1;
146006f6ba60Sopenharmony_ci        size_t deltaInverseMask = size_t(-1) << lgDelta;
146106f6ba60Sopenharmony_ci        unsigned mod = ((((size - 1) & deltaInverseMask) >> lgDelta)) & ((size_t(1) << SC_LG_NGROUP) - 1);
146206f6ba60Sopenharmony_ci        index = SC_NTINY + grp + mod;
146306f6ba60Sopenharmony_ci    }
146406f6ba60Sopenharmony_ci
146506f6ba60Sopenharmony_ci    if (index < NTBINS) {
146606f6ba60Sopenharmony_ci        return (size_t(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index));
146706f6ba60Sopenharmony_ci    }
146806f6ba60Sopenharmony_ci    size_t reducedIndex = index - NTBINS;
146906f6ba60Sopenharmony_ci    size_t grpVal = reducedIndex >> LG_SIZE_CLASS_GROUP;
147006f6ba60Sopenharmony_ci    size_t modVal = reducedIndex & ((size_t(1) << LG_SIZE_CLASS_GROUP) - 1);
147106f6ba60Sopenharmony_ci    size_t grpSizeMask = ~((!!grpVal) - 1);
147206f6ba60Sopenharmony_ci    size_t grpSize = ((size_t(1) << (LG_QUANTUM + (LG_SIZE_CLASS_GROUP - 1))) << grpVal) & grpSizeMask;
147306f6ba60Sopenharmony_ci    size_t shiftVal = (grpVal == 0) ? 1 : grpVal;
147406f6ba60Sopenharmony_ci    size_t lgDeltaVal = shiftVal + (LG_QUANTUM - 1);
147506f6ba60Sopenharmony_ci    size_t modSize = (modVal + 1) << lgDeltaVal;
147606f6ba60Sopenharmony_ci    size_t usize = grpSize + modSize;
147706f6ba60Sopenharmony_ci    return usize;
147806f6ba60Sopenharmony_ci}
147906f6ba60Sopenharmony_ci
148006f6ba60Sopenharmony_civoid StackPreprocess::WriteHookConfig()
148106f6ba60Sopenharmony_ci{
148206f6ba60Sopenharmony_ci    const size_t configSize = hookConfig_.ByteSizeLong();
148306f6ba60Sopenharmony_ci    auto buffer = std::make_unique<uint8_t[]>(configSize);
148406f6ba60Sopenharmony_ci    hookConfig_.SerializeToArray(buffer.get(), configSize);
148506f6ba60Sopenharmony_ci
148606f6ba60Sopenharmony_ci    writer_->ResetPos();
148706f6ba60Sopenharmony_ci    profilerPluginData_.Reset(writer_->GetCtx());
148806f6ba60Sopenharmony_ci    profilerPluginData_.set_name("nativehook_config");
148906f6ba60Sopenharmony_ci    profilerPluginData_.set_version("1.02");
149006f6ba60Sopenharmony_ci    profilerPluginData_.set_status(0);
149106f6ba60Sopenharmony_ci    profilerPluginData_.set_data(buffer.get(), configSize);
149206f6ba60Sopenharmony_ci
149306f6ba60Sopenharmony_ci    FinishReport();
149406f6ba60Sopenharmony_ci
149506f6ba60Sopenharmony_ci    auto ctx = StartReport();
149606f6ba60Sopenharmony_ci    if (ctx == nullptr) {
149706f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s: get RandomWriteCtx FAILED!", __func__);
149806f6ba60Sopenharmony_ci        return;
149906f6ba60Sopenharmony_ci    }
150006f6ba60Sopenharmony_ci    stackData_ = ProtoEncoder::BatchNativeHookData(ctx);
150106f6ba60Sopenharmony_ci}
150206f6ba60Sopenharmony_ci
150306f6ba60Sopenharmony_ciRandomWriteCtx* StackPreprocess::StartReport()
150406f6ba60Sopenharmony_ci{
150506f6ba60Sopenharmony_ci    writer_->ResetPos();
150606f6ba60Sopenharmony_ci    profilerPluginData_.Reset(writer_->GetCtx());
150706f6ba60Sopenharmony_ci    profilerPluginData_.set_name("nativehook");
150806f6ba60Sopenharmony_ci    profilerPluginData_.set_version("1.02");
150906f6ba60Sopenharmony_ci    profilerPluginData_.set_status(0);
151006f6ba60Sopenharmony_ci    return profilerPluginData_.startAdd_data();
151106f6ba60Sopenharmony_ci}
151206f6ba60Sopenharmony_ci
151306f6ba60Sopenharmony_civoid StackPreprocess::FinishReport()
151406f6ba60Sopenharmony_ci{
151506f6ba60Sopenharmony_ci    struct timespec ts;
151606f6ba60Sopenharmony_ci    clock_gettime(pluginDataClockId_, &ts);
151706f6ba60Sopenharmony_ci    profilerPluginData_.set_clock_id(static_cast<ProfilerPluginData_ClockId>(pluginDataClockId_));
151806f6ba60Sopenharmony_ci    profilerPluginData_.set_tv_sec(ts.tv_sec);
151906f6ba60Sopenharmony_ci    profilerPluginData_.set_tv_nsec(ts.tv_nsec);
152006f6ba60Sopenharmony_ci
152106f6ba60Sopenharmony_ci    int32_t len = profilerPluginData_.Finish();
152206f6ba60Sopenharmony_ci    if (writer_ == nullptr) {
152306f6ba60Sopenharmony_ci        PROFILER_LOG_ERROR(LOG_CORE, "%s: the writer is nullptr!", __func__);
152406f6ba60Sopenharmony_ci        return;
152506f6ba60Sopenharmony_ci    }
152606f6ba60Sopenharmony_ci    writer_->FinishReport(len);
152706f6ba60Sopenharmony_ci}
152806f6ba60Sopenharmony_ci
152906f6ba60Sopenharmony_civoid StackPreprocess::FillFpNativeIp(RawStackPtr& rawData)
153006f6ba60Sopenharmony_ci{
153106f6ba60Sopenharmony_ci#if defined(__aarch64__)
153206f6ba60Sopenharmony_ci    uintptr_t pacMask = 0xFFFFFF8000000000;
153306f6ba60Sopenharmony_ci#else
153406f6ba60Sopenharmony_ci    uintptr_t pacMask = 0;
153506f6ba60Sopenharmony_ci#endif
153606f6ba60Sopenharmony_ci    uint64_t* fpIp = reinterpret_cast<uint64_t *>(rawData->data);
153706f6ba60Sopenharmony_ci    for (uint8_t idx = 0; idx < rawData->fpDepth ; ++idx) {
153806f6ba60Sopenharmony_ci        if (fpIp[idx] == 0) {
153906f6ba60Sopenharmony_ci            break;
154006f6ba60Sopenharmony_ci        }
154106f6ba60Sopenharmony_ci        callFrames_.emplace_back(fpIp[idx] & (~pacMask));
154206f6ba60Sopenharmony_ci    }
154306f6ba60Sopenharmony_ci}
154406f6ba60Sopenharmony_ci
154506f6ba60Sopenharmony_civoid StackPreprocess::FillFpJsData(RawStackPtr& rawData)
154606f6ba60Sopenharmony_ci{
154706f6ba60Sopenharmony_ci    if (hookConfig_.statistics_interval() > 0) {
154806f6ba60Sopenharmony_ci        switch (rawData->stackConext->type) {
154906f6ba60Sopenharmony_ci            case FREE_MSG:
155006f6ba60Sopenharmony_ci            case MUNMAP_MSG:
155106f6ba60Sopenharmony_ci            case MEMORY_UNUSING_MSG:
155206f6ba60Sopenharmony_ci                 return;
155306f6ba60Sopenharmony_ci            default:
155406f6ba60Sopenharmony_ci                break;
155506f6ba60Sopenharmony_ci        }
155606f6ba60Sopenharmony_ci    }
155706f6ba60Sopenharmony_ci    fpJsCallStacks_.clear();
155806f6ba60Sopenharmony_ci    /**
155906f6ba60Sopenharmony_ci      *     jsStackData:
156006f6ba60Sopenharmony_ci      *              ts_malloc1|entry/src/main/ets/pages/Index.ets:5:5,ts_malloc2|entry/src/main/ets/pages/Index.ets:8:5
156106f6ba60Sopenharmony_ci      *                        |                                      |
156206f6ba60Sopenharmony_ci      *                        JS_SYMBOL_FILEPATH_SEP                 JS_CALL_STACK_DEPTH_SEP
156306f6ba60Sopenharmony_ci      *     jsCallStack:
156406f6ba60Sopenharmony_ci      *                  ts_malloc1|entry/src/main/ets/pages/Index.ets:5:5
156506f6ba60Sopenharmony_ci      *                            / \
156606f6ba60Sopenharmony_ci      *                           |   |
156706f6ba60Sopenharmony_ci      *     jsSymbolFilePathSepPos    |
156806f6ba60Sopenharmony_ci      *                               jsFilePathPos = jsSymbolFilePathSepPos + 1
156906f6ba60Sopenharmony_ci      */
157006f6ba60Sopenharmony_ci    AdvancedSplitString(rawData->jsStackData, JS_CALL_STACK_DEPTH_SEP, fpJsCallStacks_);
157106f6ba60Sopenharmony_ci    for (std::string& jsCallStack: fpJsCallStacks_) {
157206f6ba60Sopenharmony_ci        std::string::size_type jsSymbolFilePathSepPos = jsCallStack.find_first_of(JS_SYMBOL_FILEPATH_SEP);
157306f6ba60Sopenharmony_ci        if (jsSymbolFilePathSepPos == std::string::npos) {
157406f6ba60Sopenharmony_ci            PROFILER_LOG_ERROR(LOG_CORE, "%s: jsCallStack find FAILED!", __func__);
157506f6ba60Sopenharmony_ci            continue;
157606f6ba60Sopenharmony_ci        }
157706f6ba60Sopenharmony_ci        std::string::size_type jsFilePathPos = jsSymbolFilePathSepPos + 1;
157806f6ba60Sopenharmony_ci        jsCallStack[jsSymbolFilePathSepPos] = '\0'; // "ts_malloc1'\0'entry/src/main/ets/pages/Index.ets:5:5"
157906f6ba60Sopenharmony_ci        CallFrame& jsCallFrame = callFrames_.emplace_back(0, 0, true);
158006f6ba60Sopenharmony_ci        jsCallFrame.symbolName_ = StringViewMemoryHold::GetInstance().HoldStringView(jsCallStack.c_str());
158106f6ba60Sopenharmony_ci        jsCallFrame.filePath_ = StringViewMemoryHold::GetInstance().HoldStringView(jsCallStack.c_str() + jsFilePathPos);
158206f6ba60Sopenharmony_ci        if (hookConfig_.offline_symbolization()) {
158306f6ba60Sopenharmony_ci            DfxSymbol symbol;
158406f6ba60Sopenharmony_ci            if (!runtime_instance->ArktsGetSymbolCache(jsCallFrame, symbol)) {
158506f6ba60Sopenharmony_ci                symbol.filePathId_ = runtime_instance->FillArkTsFilePath(jsCallFrame.filePath_);
158606f6ba60Sopenharmony_ci                symbol.symbolName_ = jsCallFrame.symbolName_;
158706f6ba60Sopenharmony_ci                symbol.module_ = jsCallFrame.filePath_;
158806f6ba60Sopenharmony_ci                symbol.symbolId_ = runtime_instance->GetJsSymbolCacheSize();
158906f6ba60Sopenharmony_ci                runtime_instance->FillSymbolNameId(jsCallFrame, symbol);
159006f6ba60Sopenharmony_ci                runtime_instance->FillFileSet(jsCallFrame, symbol);
159106f6ba60Sopenharmony_ci                jsCallFrame.needReport_ |= CALL_FRAME_REPORT;
159206f6ba60Sopenharmony_ci                runtime_instance->FillJsSymbolCache(jsCallFrame, symbol);
159306f6ba60Sopenharmony_ci            }
159406f6ba60Sopenharmony_ci            jsCallFrame.callFrameId_ = symbol.symbolId_;
159506f6ba60Sopenharmony_ci            jsCallFrame.symbolNameId_ = symbol.symbolNameId_;
159606f6ba60Sopenharmony_ci            jsCallFrame.filePathId_ = symbol.filePathId_;
159706f6ba60Sopenharmony_ci            jsCallFrame.filePath_ = symbol.module_;
159806f6ba60Sopenharmony_ci            jsCallFrame.symbolName_ = symbol.symbolName_;
159906f6ba60Sopenharmony_ci        }
160006f6ba60Sopenharmony_ci    }
160106f6ba60Sopenharmony_ci}
160206f6ba60Sopenharmony_ci
160306f6ba60Sopenharmony_civoid StackPreprocess::FillDwarfErrorStack()
160406f6ba60Sopenharmony_ci{
160506f6ba60Sopenharmony_ci#if defined(__aarch64__)
160606f6ba60Sopenharmony_ci    uintptr_t pacMask = 0xFFFFFF8000000000;
160706f6ba60Sopenharmony_ci#else
160806f6ba60Sopenharmony_ci    uintptr_t pacMask = 0;
160906f6ba60Sopenharmony_ci#endif
161006f6ba60Sopenharmony_ci    CallFrame& jsCallFrame = callFrames_.emplace_back(0 & (~pacMask));
161106f6ba60Sopenharmony_ci    jsCallFrame.symbolName_ = "UnwindErrorDwarf";
161206f6ba60Sopenharmony_ci    jsCallFrame.isJsFrame_ = true;
161306f6ba60Sopenharmony_ci    jsCallFrame.needReport_ |= CALL_FRAME_REPORT;
161406f6ba60Sopenharmony_ci    jsCallFrame.needReport_ |= SYMBOL_NAME_ID_REPORT;
161506f6ba60Sopenharmony_ci    jsCallFrame.needReport_ |= FILE_PATH_ID_REPORT;
161606f6ba60Sopenharmony_ci    jsCallFrame.callFrameId_ = DWARF_ERROR_ID;
161706f6ba60Sopenharmony_ci    jsCallFrame.symbolNameId_ = DWARF_ERROR_ID;
161806f6ba60Sopenharmony_ci    jsCallFrame.filePathId_ = DWARF_ERROR_ID;
161906f6ba60Sopenharmony_ci    jsCallFrame.filePath_ = "no-file-path";
162006f6ba60Sopenharmony_ci}
162106f6ba60Sopenharmony_ci
162206f6ba60Sopenharmony_civoid StackPreprocess::FlushRecordApplyAndReleaseMatchData()
162306f6ba60Sopenharmony_ci{
162406f6ba60Sopenharmony_ci    if (applyAndReleaseMatchPeriodListData_.empty()) {
162506f6ba60Sopenharmony_ci        return;
162606f6ba60Sopenharmony_ci    }
162706f6ba60Sopenharmony_ci    std::visit([&](auto& stackData) {
162806f6ba60Sopenharmony_ci        for (const auto& rawStack: applyAndReleaseMatchPeriodListData_) {
162906f6ba60Sopenharmony_ci            auto hookData = stackData.add_events();
163006f6ba60Sopenharmony_ci            hookData->set_tv_sec(rawStack.ts.tv_sec);
163106f6ba60Sopenharmony_ci            hookData->set_tv_nsec(rawStack.ts.tv_nsec);
163206f6ba60Sopenharmony_ci            if (rawStack.type == MALLOC_MSG) {
163306f6ba60Sopenharmony_ci                auto allocEvent = hookData->mutable_alloc_event();
163406f6ba60Sopenharmony_ci                SetEventFrame(rawStack, allocEvent, rawStack.stackMapId);
163506f6ba60Sopenharmony_ci            } else if (rawStack.type == FREE_MSG) {
163606f6ba60Sopenharmony_ci                auto freeEvent = hookData->mutable_free_event();
163706f6ba60Sopenharmony_ci                SetEventFrame(rawStack, freeEvent, rawStack.stackMapId);
163806f6ba60Sopenharmony_ci            } else if (rawStack.type == MMAP_MSG) {
163906f6ba60Sopenharmony_ci                auto mmapEvent = hookData->mutable_mmap_event();
164006f6ba60Sopenharmony_ci                SetEventFrame(rawStack, mmapEvent, rawStack.stackMapId);
164106f6ba60Sopenharmony_ci            } else if (rawStack.type == MMAP_FILE_PAGE_MSG) {
164206f6ba60Sopenharmony_ci                auto mmapEvent = hookData->mutable_mmap_event();
164306f6ba60Sopenharmony_ci                const std::string prefix = "FilePage:";
164406f6ba60Sopenharmony_ci                std::string tagName;
164506f6ba60Sopenharmony_ci                if (GetMemTag(rawStack.tagId, tagName)) {
164606f6ba60Sopenharmony_ci                    tagName = prefix + tagName;
164706f6ba60Sopenharmony_ci                }
164806f6ba60Sopenharmony_ci                SetEventFrame(rawStack, mmapEvent, rawStack.stackMapId, tagName);
164906f6ba60Sopenharmony_ci            } else if (rawStack.type == MUNMAP_MSG) {
165006f6ba60Sopenharmony_ci                auto munmapEvent = hookData->mutable_munmap_event();
165106f6ba60Sopenharmony_ci                SetEventFrame(rawStack, munmapEvent, rawStack.stackMapId);
165206f6ba60Sopenharmony_ci            } else if (rawStack.type == PR_SET_VMA_MSG) {
165306f6ba60Sopenharmony_ci                auto tagEvent = hookData->mutable_tag_event();
165406f6ba60Sopenharmony_ci                const std::string prefix = "Anonymous:";
165506f6ba60Sopenharmony_ci                tagEvent->set_addr(rawStack.addr);
165606f6ba60Sopenharmony_ci                tagEvent->set_size(rawStack.mallocSize);
165706f6ba60Sopenharmony_ci                tagEvent->set_tag(prefix + prctlPeriodTags_[rawStack.tagId]);
165806f6ba60Sopenharmony_ci                tagEvent->set_pid(pid_);
165906f6ba60Sopenharmony_ci            } else if (rawStack.type == MEMORY_USING_MSG) {
166006f6ba60Sopenharmony_ci                auto mmapEvent = hookData->mutable_mmap_event();
166106f6ba60Sopenharmony_ci                std::string tagName;
166206f6ba60Sopenharmony_ci                GetMemTag(rawStack.tagId, tagName);
166306f6ba60Sopenharmony_ci                SetEventFrame(rawStack, mmapEvent, rawStack.stackMapId, tagName);
166406f6ba60Sopenharmony_ci            } else if (rawStack.type == MEMORY_UNUSING_MSG) {
166506f6ba60Sopenharmony_ci                auto munmapEvent = hookData->mutable_munmap_event();
166606f6ba60Sopenharmony_ci                SetEventFrame(rawStack, munmapEvent, rawStack.stackMapId);
166706f6ba60Sopenharmony_ci            }
166806f6ba60Sopenharmony_ci        }
166906f6ba60Sopenharmony_ci        FlushData(stackData);
167006f6ba60Sopenharmony_ci        }, stackData_);
167106f6ba60Sopenharmony_ci    applyAndReleaseMatchPeriodListData_.clear();
167206f6ba60Sopenharmony_ci    applyAndReleaseMatchIntervallMap_.clear();
167306f6ba60Sopenharmony_ci    prctlPeriodTags_.clear();
167406f6ba60Sopenharmony_ci}