14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_COMPILER_OHOS_RUNTIME_BUILD_INFO_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_OHOS_RUNTIME_BUILD_INFO_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include <sys/time.h>
204514f5e3Sopenharmony_ci#include <fcntl.h>
214514f5e3Sopenharmony_ci#include <mutex>
224514f5e3Sopenharmony_ci#include <stdio.h>
234514f5e3Sopenharmony_ci
244514f5e3Sopenharmony_ci#include "ecmascript/platform/directory.h"
254514f5e3Sopenharmony_ci#include "ecmascript/platform/file.h"
264514f5e3Sopenharmony_ci#include "ecmascript/platform/map.h"
274514f5e3Sopenharmony_ci#include "libpandafile/file.h"
284514f5e3Sopenharmony_ci#include "llvm/BinaryFormat/ELF.h"
294514f5e3Sopenharmony_ci#include "ohos_constants.h"
304514f5e3Sopenharmony_ci#include "utils/json_parser.h"
314514f5e3Sopenharmony_ci#include "utils/json_builder.h"
324514f5e3Sopenharmony_ci
334514f5e3Sopenharmony_cinamespace panda::ecmascript::ohos {
344514f5e3Sopenharmony_ci#define RUNTIME_INFO_TYPE(V)                                         \
354514f5e3Sopenharmony_ci    V(AOT_CRASH)                                                     \
364514f5e3Sopenharmony_ci    V(OTHERS)                                                        \
374514f5e3Sopenharmony_ci    V(NONE)                                                          \
384514f5e3Sopenharmony_ci    V(JIT)                                                           \
394514f5e3Sopenharmony_ci    V(JS)                                                            \
404514f5e3Sopenharmony_ci    V(AOT_BUILD)                                                     \
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_cienum class RuntimeInfoType {
434514f5e3Sopenharmony_ci    AOT_CRASH,
444514f5e3Sopenharmony_ci    JIT,
454514f5e3Sopenharmony_ci    OTHERS,
464514f5e3Sopenharmony_ci    NONE,
474514f5e3Sopenharmony_ci    JS,
484514f5e3Sopenharmony_ci    AOT_BUILD,
494514f5e3Sopenharmony_ci};
504514f5e3Sopenharmony_ci
514514f5e3Sopenharmony_ciclass AotRuntimeInfo {
524514f5e3Sopenharmony_cipublic:
534514f5e3Sopenharmony_ci    constexpr static const int USEC_PER_SEC = 1000 * 1000;
544514f5e3Sopenharmony_ci    constexpr static const int NSEC_PER_USEC = 1000;
554514f5e3Sopenharmony_ci    constexpr static const int NT_GNU_BUILD_ID = 3;
564514f5e3Sopenharmony_ci    constexpr static const int CRASH_INFO_SIZE = 3;
574514f5e3Sopenharmony_ci    constexpr static const int MAX_LENGTH = 255;
584514f5e3Sopenharmony_ci    constexpr static const int BUFFER_SIZE = 4096;
594514f5e3Sopenharmony_ci    constexpr static const int TIME_STAMP_SIZE = 21;
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    constexpr static const int RUNTIME_INDEX_BUILDID = 0;
624514f5e3Sopenharmony_ci    constexpr static const int RUNTIME_INDEX_TIMESTAMP = 1;
634514f5e3Sopenharmony_ci    constexpr static const int RUNTIME_INDEX_TYPE = 2;
644514f5e3Sopenharmony_ci
654514f5e3Sopenharmony_ci    static AotRuntimeInfo &GetInstance()
664514f5e3Sopenharmony_ci    {
674514f5e3Sopenharmony_ci        static AotRuntimeInfo singleAotRuntimeInfo;
684514f5e3Sopenharmony_ci        return singleAotRuntimeInfo;
694514f5e3Sopenharmony_ci    }
704514f5e3Sopenharmony_ci
714514f5e3Sopenharmony_ci    void BuildCompileRuntimeInfo(RuntimeInfoType type, const std::string &pgoPath)
724514f5e3Sopenharmony_ci    {
734514f5e3Sopenharmony_ci        std::unique_lock<std::mutex> lock(fileMutex_);
744514f5e3Sopenharmony_ci        static char soBuildId[NAME_MAX] = { '\0' };
754514f5e3Sopenharmony_ci        if (!GetRuntimeBuildId(soBuildId, NAME_MAX) || IsCharEmpty(soBuildId)) {
764514f5e3Sopenharmony_ci            LOG_ECMA(INFO) << "can't get so buildId.";
774514f5e3Sopenharmony_ci            return;
784514f5e3Sopenharmony_ci        }
794514f5e3Sopenharmony_ci        std::string realOutPath;
804514f5e3Sopenharmony_ci        if (!ecmascript::RealPath(pgoPath, realOutPath, false)) {
814514f5e3Sopenharmony_ci            LOG_ECMA(INFO) << "Build compile pgo path fail.";
824514f5e3Sopenharmony_ci            return;
834514f5e3Sopenharmony_ci        }
844514f5e3Sopenharmony_ci        static char lines[MAX_LENGTH][BUFFER_SIZE];
854514f5e3Sopenharmony_ci        for (int i = 0; i < MAX_LENGTH; i++) {
864514f5e3Sopenharmony_ci            memset_s(lines[i], BUFFER_SIZE, '\0', BUFFER_SIZE);
874514f5e3Sopenharmony_ci        }
884514f5e3Sopenharmony_ci        GetRuntimeInfoByPath(lines, realOutPath.c_str(), soBuildId);
894514f5e3Sopenharmony_ci        static char timestamp[TIME_STAMP_SIZE] = { '\0' };
904514f5e3Sopenharmony_ci        if (!GetMicrosecondsTimeStamp(timestamp, TIME_STAMP_SIZE)) {
914514f5e3Sopenharmony_ci            return;
924514f5e3Sopenharmony_ci        }
934514f5e3Sopenharmony_ci
944514f5e3Sopenharmony_ci        int lineCount = getLength(lines, MAX_LENGTH);
954514f5e3Sopenharmony_ci        if (lineCount < MAX_LENGTH) {
964514f5e3Sopenharmony_ci            if (!BuildRuntimeInfoPart(lines[lineCount], soBuildId, timestamp, type)) {
974514f5e3Sopenharmony_ci                return;
984514f5e3Sopenharmony_ci            }
994514f5e3Sopenharmony_ci        }
1004514f5e3Sopenharmony_ci        SetRuntimeInfo(realOutPath.c_str(), lines, MAX_LENGTH);
1014514f5e3Sopenharmony_ci    }
1024514f5e3Sopenharmony_ci
1034514f5e3Sopenharmony_ci    void BuildCrashRuntimeInfo(RuntimeInfoType type)
1044514f5e3Sopenharmony_ci    {
1054514f5e3Sopenharmony_ci        std::unique_lock<std::mutex> lock(fileMutex_);
1064514f5e3Sopenharmony_ci        static char soBuildId[NAME_MAX] = { '\0' };
1074514f5e3Sopenharmony_ci        if (!GetRuntimeBuildId(soBuildId, NAME_MAX) || IsCharEmpty(soBuildId)) {
1084514f5e3Sopenharmony_ci            return;
1094514f5e3Sopenharmony_ci        }
1104514f5e3Sopenharmony_ci        static char lines[MAX_LENGTH][BUFFER_SIZE];
1114514f5e3Sopenharmony_ci        for (int i = 0; i < MAX_LENGTH; i++) {
1124514f5e3Sopenharmony_ci            memset_s(lines[i], BUFFER_SIZE, '\0', BUFFER_SIZE);
1134514f5e3Sopenharmony_ci        }
1144514f5e3Sopenharmony_ci        GetCrashRuntimeInfoList(lines);
1154514f5e3Sopenharmony_ci        static char timestamp[TIME_STAMP_SIZE] = { '\0' };
1164514f5e3Sopenharmony_ci        if (!GetMicrosecondsTimeStamp(timestamp, TIME_STAMP_SIZE)) {
1174514f5e3Sopenharmony_ci            return;
1184514f5e3Sopenharmony_ci        }
1194514f5e3Sopenharmony_ci        int lineCount = getLength(lines, MAX_LENGTH);
1204514f5e3Sopenharmony_ci        if (lineCount < MAX_LENGTH) {
1214514f5e3Sopenharmony_ci            if (!BuildRuntimeInfoPart(lines[lineCount], soBuildId, timestamp, type)) {
1224514f5e3Sopenharmony_ci                return;
1234514f5e3Sopenharmony_ci            }
1244514f5e3Sopenharmony_ci        }
1254514f5e3Sopenharmony_ci        static char realOutPath[PATH_MAX] = { '\0' };
1264514f5e3Sopenharmony_ci        if (!GetCrashSandBoxRealPath(realOutPath, PATH_MAX) || IsCharEmpty(realOutPath)) {
1274514f5e3Sopenharmony_ci            return;
1284514f5e3Sopenharmony_ci        }
1294514f5e3Sopenharmony_ci        SetRuntimeInfo(realOutPath, lines, MAX_LENGTH);
1304514f5e3Sopenharmony_ci    }
1314514f5e3Sopenharmony_ci
1324514f5e3Sopenharmony_ci    int GetCompileCountByType(RuntimeInfoType type, const std::string &pgoRealPath = "")
1334514f5e3Sopenharmony_ci    {
1344514f5e3Sopenharmony_ci        std::map<RuntimeInfoType, int> escapeMap = CollectCrashSum(pgoRealPath);
1354514f5e3Sopenharmony_ci        if (escapeMap.count(type) == 0) {
1364514f5e3Sopenharmony_ci            return 0;
1374514f5e3Sopenharmony_ci        }
1384514f5e3Sopenharmony_ci        return escapeMap[type];
1394514f5e3Sopenharmony_ci    }
1404514f5e3Sopenharmony_ci
1414514f5e3Sopenharmony_ci    std::map<RuntimeInfoType, int> CollectCrashSum(const std::string &pgoRealPath = "")
1424514f5e3Sopenharmony_ci    {
1434514f5e3Sopenharmony_ci        if (IsLoadedMap()) {
1444514f5e3Sopenharmony_ci            return escapeMap_;
1454514f5e3Sopenharmony_ci        }
1464514f5e3Sopenharmony_ci        char lines[MAX_LENGTH][BUFFER_SIZE];
1474514f5e3Sopenharmony_ci        for (int i = 0; i < MAX_LENGTH; i++) {
1484514f5e3Sopenharmony_ci            memset_s(lines[i], BUFFER_SIZE, '\0', BUFFER_SIZE);
1494514f5e3Sopenharmony_ci        }
1504514f5e3Sopenharmony_ci        if (IsCharEmpty(pgoRealPath.c_str())) {
1514514f5e3Sopenharmony_ci            GetCrashRuntimeInfoList(lines);
1524514f5e3Sopenharmony_ci        } else {
1534514f5e3Sopenharmony_ci            GetRealPathRuntimeInfoList(lines, pgoRealPath);
1544514f5e3Sopenharmony_ci        }
1554514f5e3Sopenharmony_ci        char *typeChar = new char[NAME_MAX];
1564514f5e3Sopenharmony_ci        for (int i = 0; i < MAX_LENGTH; i++) {
1574514f5e3Sopenharmony_ci            if (lines[i][0] != '\0') {
1584514f5e3Sopenharmony_ci                if (strcpy_s(typeChar, NAME_MAX, GetInfoFromBuffer(lines[i], RUNTIME_INDEX_TYPE)) !=0) {
1594514f5e3Sopenharmony_ci                    continue;
1604514f5e3Sopenharmony_ci                }
1614514f5e3Sopenharmony_ci                std::string typeStr(typeChar);
1624514f5e3Sopenharmony_ci                escapeMap_[GetRuntimeInfoTypeByStr(typeStr)]++;
1634514f5e3Sopenharmony_ci            }
1644514f5e3Sopenharmony_ci        }
1654514f5e3Sopenharmony_ci        SetLoadedMap(true);
1664514f5e3Sopenharmony_ci        delete[] typeChar;
1674514f5e3Sopenharmony_ci        return escapeMap_;
1684514f5e3Sopenharmony_ci    }
1694514f5e3Sopenharmony_ci
1704514f5e3Sopenharmony_ci    const char *GetRuntimeInfoTypeStr(const RuntimeInfoType type) const
1714514f5e3Sopenharmony_ci    {
1724514f5e3Sopenharmony_ci        switch (type) {
1734514f5e3Sopenharmony_ci            case RuntimeInfoType::AOT_CRASH:
1744514f5e3Sopenharmony_ci                return "AOT_CRASH";
1754514f5e3Sopenharmony_ci            case RuntimeInfoType::JIT:
1764514f5e3Sopenharmony_ci                return "JIT";
1774514f5e3Sopenharmony_ci            case RuntimeInfoType::OTHERS:
1784514f5e3Sopenharmony_ci                return "OTHERS";
1794514f5e3Sopenharmony_ci            case RuntimeInfoType::NONE:
1804514f5e3Sopenharmony_ci                return "NONE";
1814514f5e3Sopenharmony_ci            case RuntimeInfoType::JS:
1824514f5e3Sopenharmony_ci                return "JS";
1834514f5e3Sopenharmony_ci            case RuntimeInfoType::AOT_BUILD:
1844514f5e3Sopenharmony_ci                return "AOT_BUILD";
1854514f5e3Sopenharmony_ci            default:
1864514f5e3Sopenharmony_ci                return "NONE";
1874514f5e3Sopenharmony_ci        }
1884514f5e3Sopenharmony_ci    }
1894514f5e3Sopenharmony_ci
1904514f5e3Sopenharmony_ci    RuntimeInfoType GetRuntimeInfoTypeByStr(std::string &type) const
1914514f5e3Sopenharmony_ci    {
1924514f5e3Sopenharmony_ci        const std::map<std::string, RuntimeInfoType> strMap = {
1934514f5e3Sopenharmony_ci#define RUNTIME_INFO_TYPE_MAP(name) { #name, RuntimeInfoType::name },
1944514f5e3Sopenharmony_ci        RUNTIME_INFO_TYPE(RUNTIME_INFO_TYPE_MAP)
1954514f5e3Sopenharmony_ci#undef RUNTIME_INFO_TYPE_MAP
1964514f5e3Sopenharmony_ci        };
1974514f5e3Sopenharmony_ci        if (strMap.count(type) > 0) {
1984514f5e3Sopenharmony_ci            return strMap.at(type);
1994514f5e3Sopenharmony_ci        }
2004514f5e3Sopenharmony_ci        return RuntimeInfoType::NONE;
2014514f5e3Sopenharmony_ci    }
2024514f5e3Sopenharmony_ci
2034514f5e3Sopenharmony_ci    virtual bool GetRuntimeBuildId(char *buildId, int length) const
2044514f5e3Sopenharmony_ci    {
2054514f5e3Sopenharmony_ci        if (!FileExist(OhosConstants::RUNTIME_SO_PATH)) {
2064514f5e3Sopenharmony_ci            return false;
2074514f5e3Sopenharmony_ci        }
2084514f5e3Sopenharmony_ci        static char realPath[PATH_MAX] = { '\0' };
2094514f5e3Sopenharmony_ci        if (!ecmascript::RealPathByChar(OhosConstants::RUNTIME_SO_PATH, realPath, PATH_MAX, false)) {
2104514f5e3Sopenharmony_ci            return false;
2114514f5e3Sopenharmony_ci        }
2124514f5e3Sopenharmony_ci        if (!FileExist(realPath)) {
2134514f5e3Sopenharmony_ci            return false;
2144514f5e3Sopenharmony_ci        }
2154514f5e3Sopenharmony_ci        ecmascript::MemMap fileMap = ecmascript::FileMap(realPath, FILE_RDONLY, PAGE_PROT_READ);
2164514f5e3Sopenharmony_ci        if (fileMap.GetOriginAddr() == nullptr) {
2174514f5e3Sopenharmony_ci            return false;
2184514f5e3Sopenharmony_ci        }
2194514f5e3Sopenharmony_ci        ParseELFSectionsForBuildId(fileMap, buildId, length);
2204514f5e3Sopenharmony_ci        ecmascript::FileUnMap(fileMap);
2214514f5e3Sopenharmony_ci        fileMap.Reset();
2224514f5e3Sopenharmony_ci        return true;
2234514f5e3Sopenharmony_ci    }
2244514f5e3Sopenharmony_ci
2254514f5e3Sopenharmony_ci    virtual bool GetMicrosecondsTimeStamp(char *timestamp, size_t length) const
2264514f5e3Sopenharmony_ci    {
2274514f5e3Sopenharmony_ci        time_t current_time;
2284514f5e3Sopenharmony_ci        if (time(&current_time) == -1) {
2294514f5e3Sopenharmony_ci            return false;
2304514f5e3Sopenharmony_ci        }
2314514f5e3Sopenharmony_ci        struct tm *local_time = localtime(&current_time);
2324514f5e3Sopenharmony_ci        if (local_time == NULL) {
2334514f5e3Sopenharmony_ci            return false;
2344514f5e3Sopenharmony_ci        }
2354514f5e3Sopenharmony_ci        size_t result = strftime(timestamp, length, "%Y-%m-%d %H:%M:%S", local_time);
2364514f5e3Sopenharmony_ci        if (result == 0) {
2374514f5e3Sopenharmony_ci            return false;
2384514f5e3Sopenharmony_ci        }
2394514f5e3Sopenharmony_ci        return true;
2404514f5e3Sopenharmony_ci    }
2414514f5e3Sopenharmony_ci
2424514f5e3Sopenharmony_ci    virtual bool GetCrashSandBoxRealPath(char *realOutPath, size_t length) const
2434514f5e3Sopenharmony_ci    {
2444514f5e3Sopenharmony_ci        if (!ecmascript::RealPathByChar(OhosConstants::SANDBOX_ARK_PROFILE_PATH, realOutPath, length, false)) {
2454514f5e3Sopenharmony_ci            return false;
2464514f5e3Sopenharmony_ci        }
2474514f5e3Sopenharmony_ci        if (strcat_s(realOutPath, NAME_MAX, OhosConstants::PATH_SEPARATOR) != 0) {
2484514f5e3Sopenharmony_ci            return false;
2494514f5e3Sopenharmony_ci        }
2504514f5e3Sopenharmony_ci        if (strcat_s(realOutPath, NAME_MAX, OhosConstants::AOT_RUNTIME_INFO_NAME) !=0) {
2514514f5e3Sopenharmony_ci            return false;
2524514f5e3Sopenharmony_ci        }
2534514f5e3Sopenharmony_ci        return true;
2544514f5e3Sopenharmony_ci    }
2554514f5e3Sopenharmony_ciprotected:
2564514f5e3Sopenharmony_ci
2574514f5e3Sopenharmony_ci    bool IsCharEmpty(const char *value) const
2584514f5e3Sopenharmony_ci    {
2594514f5e3Sopenharmony_ci        if (value == NULL || *value == '\0') {
2604514f5e3Sopenharmony_ci            return true;
2614514f5e3Sopenharmony_ci        }
2624514f5e3Sopenharmony_ci        return false;
2634514f5e3Sopenharmony_ci    }
2644514f5e3Sopenharmony_ci
2654514f5e3Sopenharmony_ci    bool BuildRuntimeInfoPart(char *runtimeInfoPart, const char *soBuildId, const char *timestamp,
2664514f5e3Sopenharmony_ci        RuntimeInfoType type) const
2674514f5e3Sopenharmony_ci    {
2684514f5e3Sopenharmony_ci        if (strcat_s(runtimeInfoPart, NAME_MAX, soBuildId) != 0) {
2694514f5e3Sopenharmony_ci            return false;
2704514f5e3Sopenharmony_ci        }
2714514f5e3Sopenharmony_ci        if (strcat_s(runtimeInfoPart, NAME_MAX, OhosConstants::SPLIT_STR) != 0) {
2724514f5e3Sopenharmony_ci            return false;
2734514f5e3Sopenharmony_ci        }
2744514f5e3Sopenharmony_ci        if (strcat_s(runtimeInfoPart, NAME_MAX, timestamp) != 0) {
2754514f5e3Sopenharmony_ci            return false;
2764514f5e3Sopenharmony_ci        }
2774514f5e3Sopenharmony_ci        if (strcat_s(runtimeInfoPart, NAME_MAX, OhosConstants::SPLIT_STR) != 0) {
2784514f5e3Sopenharmony_ci            return false;
2794514f5e3Sopenharmony_ci        }
2804514f5e3Sopenharmony_ci        if (strcat_s(runtimeInfoPart, NAME_MAX, GetRuntimeInfoTypeStr(type)) != 0) {
2814514f5e3Sopenharmony_ci            return false;
2824514f5e3Sopenharmony_ci        }
2834514f5e3Sopenharmony_ci        return true;
2844514f5e3Sopenharmony_ci    }
2854514f5e3Sopenharmony_ci
2864514f5e3Sopenharmony_ci    const char *GetInfoFromBuffer(char *line, int index) const
2874514f5e3Sopenharmony_ci    {
2884514f5e3Sopenharmony_ci        char *saveptr;
2894514f5e3Sopenharmony_ci        char buffer[BUFFER_SIZE] = { '\0' };
2904514f5e3Sopenharmony_ci        if (strncpy_s(buffer, BUFFER_SIZE - 1, line, sizeof(buffer) - 1) != 0) {
2914514f5e3Sopenharmony_ci            return "";
2924514f5e3Sopenharmony_ci        }
2934514f5e3Sopenharmony_ci        char *token = strtok_r(buffer, OhosConstants::SPLIT_STR, &saveptr);
2944514f5e3Sopenharmony_ci
2954514f5e3Sopenharmony_ci        for (int i = 0; i < index; i++) {
2964514f5e3Sopenharmony_ci            token = strtok_r(NULL, OhosConstants::SPLIT_STR, &saveptr);
2974514f5e3Sopenharmony_ci        }
2984514f5e3Sopenharmony_ci        return token;
2994514f5e3Sopenharmony_ci    }
3004514f5e3Sopenharmony_ci
3014514f5e3Sopenharmony_ci    int getLength(char lines[][BUFFER_SIZE], int maxInput) const
3024514f5e3Sopenharmony_ci    {
3034514f5e3Sopenharmony_ci        int count = 0;
3044514f5e3Sopenharmony_ci        for (int i = 0; i < maxInput; i++) {
3054514f5e3Sopenharmony_ci            if (lines[i][0] != '\0') {
3064514f5e3Sopenharmony_ci                count++;
3074514f5e3Sopenharmony_ci            }
3084514f5e3Sopenharmony_ci        }
3094514f5e3Sopenharmony_ci        return count;
3104514f5e3Sopenharmony_ci    }
3114514f5e3Sopenharmony_ci
3124514f5e3Sopenharmony_ci    void GetCrashRuntimeInfoList(char lines[][BUFFER_SIZE]) const
3134514f5e3Sopenharmony_ci    {
3144514f5e3Sopenharmony_ci        static char realOutPath[PATH_MAX] = { '\0' };
3154514f5e3Sopenharmony_ci        if (!GetCrashSandBoxRealPath(realOutPath, PATH_MAX)) {
3164514f5e3Sopenharmony_ci            return;
3174514f5e3Sopenharmony_ci        }
3184514f5e3Sopenharmony_ci        if (!FileExist(realOutPath)) {
3194514f5e3Sopenharmony_ci            return;
3204514f5e3Sopenharmony_ci        }
3214514f5e3Sopenharmony_ci        static char soBuildId[NAME_MAX] = { '\0' };
3224514f5e3Sopenharmony_ci        if (!GetRuntimeBuildId(soBuildId, NAME_MAX)) {
3234514f5e3Sopenharmony_ci            return;
3244514f5e3Sopenharmony_ci        }
3254514f5e3Sopenharmony_ci        if (IsCharEmpty(soBuildId)) {
3264514f5e3Sopenharmony_ci            return;
3274514f5e3Sopenharmony_ci        }
3284514f5e3Sopenharmony_ci        GetRuntimeInfoByPath(lines, realOutPath, soBuildId);
3294514f5e3Sopenharmony_ci        return;
3304514f5e3Sopenharmony_ci    }
3314514f5e3Sopenharmony_ci
3324514f5e3Sopenharmony_ci    void GetRealPathRuntimeInfoList(char lines[][BUFFER_SIZE], const std::string &pgoRealPath) const
3334514f5e3Sopenharmony_ci    {
3344514f5e3Sopenharmony_ci        std::string realOutPath;
3354514f5e3Sopenharmony_ci        if (!ecmascript::RealPath(pgoRealPath, realOutPath, false)) {
3364514f5e3Sopenharmony_ci            return;
3374514f5e3Sopenharmony_ci        }
3384514f5e3Sopenharmony_ci        if (!FileExist(realOutPath.c_str())) {
3394514f5e3Sopenharmony_ci            return;
3404514f5e3Sopenharmony_ci        }
3414514f5e3Sopenharmony_ci        char soBuildId[NAME_MAX] = { '\0' };
3424514f5e3Sopenharmony_ci        if (!GetRuntimeBuildId(soBuildId, NAME_MAX)) {
3434514f5e3Sopenharmony_ci            return;
3444514f5e3Sopenharmony_ci        }
3454514f5e3Sopenharmony_ci        if (IsCharEmpty(soBuildId)) {
3464514f5e3Sopenharmony_ci            return;
3474514f5e3Sopenharmony_ci        }
3484514f5e3Sopenharmony_ci        GetRuntimeInfoByPath(lines, realOutPath.c_str(), soBuildId);
3494514f5e3Sopenharmony_ci    }
3504514f5e3Sopenharmony_ci
3514514f5e3Sopenharmony_ci    virtual void SetRuntimeInfo(const char *realOutPath, char lines[][BUFFER_SIZE], int length) const
3524514f5e3Sopenharmony_ci    {
3534514f5e3Sopenharmony_ci        int fd = open(realOutPath,  O_WRONLY | O_CREAT | O_TRUNC, 0666);
3544514f5e3Sopenharmony_ci        if (fd == -1) {
3554514f5e3Sopenharmony_ci            return;
3564514f5e3Sopenharmony_ci        }
3574514f5e3Sopenharmony_ci        for (int i = 0; i < length && lines[i] != NULL; i++) {
3584514f5e3Sopenharmony_ci            if (lines[i][0] != '\0') {
3594514f5e3Sopenharmony_ci                write(fd, lines[i], strlen(lines[i]));
3604514f5e3Sopenharmony_ci                write(fd, "\n", 1);
3614514f5e3Sopenharmony_ci            }
3624514f5e3Sopenharmony_ci        }
3634514f5e3Sopenharmony_ci        close(fd);
3644514f5e3Sopenharmony_ci    }
3654514f5e3Sopenharmony_ci
3664514f5e3Sopenharmony_ci    void GetRuntimeInfoByPath(char lines[][BUFFER_SIZE], const char *realOutPath, const char *soBuildId) const
3674514f5e3Sopenharmony_ci    {
3684514f5e3Sopenharmony_ci        int fd = open(realOutPath, O_RDONLY);
3694514f5e3Sopenharmony_ci        if (fd == -1) {
3704514f5e3Sopenharmony_ci            return;
3714514f5e3Sopenharmony_ci        }
3724514f5e3Sopenharmony_ci        char buffer[BUFFER_SIZE] = { '\0' };
3734514f5e3Sopenharmony_ci        char *saveptr;
3744514f5e3Sopenharmony_ci        char *token;
3754514f5e3Sopenharmony_ci        ssize_t bytesRead;
3764514f5e3Sopenharmony_ci        int lineCount = 0;
3774514f5e3Sopenharmony_ci        while ((bytesRead = read(fd, buffer, BUFFER_SIZE - 1)) > 0) {
3784514f5e3Sopenharmony_ci            token = strtok_r(buffer, "\n", &saveptr);
3794514f5e3Sopenharmony_ci            while (token != NULL) {
3804514f5e3Sopenharmony_ci                if (strcmp(GetInfoFromBuffer(token, RUNTIME_INDEX_BUILDID), soBuildId) == 0 &&
3814514f5e3Sopenharmony_ci                    lineCount < MAX_LENGTH &&
3824514f5e3Sopenharmony_ci                    strcpy_s(lines[lineCount], BUFFER_SIZE, token) == 0) {
3834514f5e3Sopenharmony_ci                    lineCount++;
3844514f5e3Sopenharmony_ci                }
3854514f5e3Sopenharmony_ci                token = strtok_r(NULL, "\n", &saveptr);
3864514f5e3Sopenharmony_ci            }
3874514f5e3Sopenharmony_ci        }
3884514f5e3Sopenharmony_ci        close(fd);
3894514f5e3Sopenharmony_ci    }
3904514f5e3Sopenharmony_ci
3914514f5e3Sopenharmony_ci    void ParseELFSectionsForBuildId(ecmascript::MemMap &fileMap, char *buildId, int length) const
3924514f5e3Sopenharmony_ci    {
3934514f5e3Sopenharmony_ci        llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMap.GetOriginAddr());
3944514f5e3Sopenharmony_ci        char *addr = reinterpret_cast<char *>(ehdr);
3954514f5e3Sopenharmony_ci        llvm::ELF::Elf64_Shdr *shdr = reinterpret_cast<llvm::ELF::Elf64_Shdr *>(addr + ehdr->e_shoff);
3964514f5e3Sopenharmony_ci        ASSERT(ehdr->e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-1));
3974514f5e3Sopenharmony_ci        llvm::ELF::Elf64_Shdr strdr = shdr[ehdr->e_shstrndx];
3984514f5e3Sopenharmony_ci        int secId = -1;
3994514f5e3Sopenharmony_ci        static const char sectionName[] = ".note.gnu.build-id";
4004514f5e3Sopenharmony_ci        for (size_t i = 0; i < ehdr->e_shnum; i++) {
4014514f5e3Sopenharmony_ci            llvm::ELF::Elf64_Word shName = shdr[i].sh_name;
4024514f5e3Sopenharmony_ci            char *curShName = reinterpret_cast<char *>(addr) + shName + strdr.sh_offset;
4034514f5e3Sopenharmony_ci            if (strcmp(sectionName, curShName) == 0) {
4044514f5e3Sopenharmony_ci                secId = static_cast<int>(i);
4054514f5e3Sopenharmony_ci                break;
4064514f5e3Sopenharmony_ci            }
4074514f5e3Sopenharmony_ci        }
4084514f5e3Sopenharmony_ci        if (secId == -1) {
4094514f5e3Sopenharmony_ci            return;
4104514f5e3Sopenharmony_ci        }
4114514f5e3Sopenharmony_ci        llvm::ELF::Elf64_Shdr secShdr = shdr[secId];
4124514f5e3Sopenharmony_ci        uint64_t buildIdOffset = secShdr.sh_offset;
4134514f5e3Sopenharmony_ci        uint64_t buildIdSize = secShdr.sh_size;
4144514f5e3Sopenharmony_ci        llvm::ELF::Elf64_Nhdr *nhdr = reinterpret_cast<llvm::ELF::Elf64_Nhdr *>(addr + buildIdOffset);
4154514f5e3Sopenharmony_ci        char *curShNameForNhdr = reinterpret_cast<char *>(addr + buildIdOffset + sizeof(*nhdr));
4164514f5e3Sopenharmony_ci        if (buildIdSize - sizeof(*nhdr) < nhdr->n_namesz) {
4174514f5e3Sopenharmony_ci            return;
4184514f5e3Sopenharmony_ci        }
4194514f5e3Sopenharmony_ci
4204514f5e3Sopenharmony_ci        static const char gnu[] = "GNU";
4214514f5e3Sopenharmony_ci        if (strcmp(curShNameForNhdr, gnu) != 0 || nhdr->n_type != NT_GNU_BUILD_ID) {
4224514f5e3Sopenharmony_ci            return;
4234514f5e3Sopenharmony_ci        }
4244514f5e3Sopenharmony_ci        if ((buildIdSize - sizeof(*nhdr) - AlignValues(nhdr->n_namesz, 4) < nhdr->n_descsz) || nhdr->n_descsz == 0) {
4254514f5e3Sopenharmony_ci            return;
4264514f5e3Sopenharmony_ci        }
4274514f5e3Sopenharmony_ci
4284514f5e3Sopenharmony_ci        char *curShNameValueForNhdr = reinterpret_cast<char *>(addr + buildIdOffset + sizeof(*nhdr) +
4294514f5e3Sopenharmony_ci            AlignValues(nhdr->n_namesz, 4));
4304514f5e3Sopenharmony_ci        GetReadableBuildId(curShNameValueForNhdr, buildId, length);
4314514f5e3Sopenharmony_ci    }
4324514f5e3Sopenharmony_ci
4334514f5e3Sopenharmony_ci    void GetReadableBuildId(char *buildIdHex, char *buildId, int length) const
4344514f5e3Sopenharmony_ci    {
4354514f5e3Sopenharmony_ci        if (IsCharEmpty(buildIdHex)) {
4364514f5e3Sopenharmony_ci            return;
4374514f5e3Sopenharmony_ci        }
4384514f5e3Sopenharmony_ci        static const char HEXTABLE[] = "0123456789abcdef";
4394514f5e3Sopenharmony_ci        static const int HEXLENGTH = 16;
4404514f5e3Sopenharmony_ci        static const int HEX_EXPAND_PARAM = 2;
4414514f5e3Sopenharmony_ci        const int len = strlen(buildIdHex);
4424514f5e3Sopenharmony_ci
4434514f5e3Sopenharmony_ci        for (int i = 0; i < len; i++) {
4444514f5e3Sopenharmony_ci            int lowHexExpand = i * HEX_EXPAND_PARAM + 1;
4454514f5e3Sopenharmony_ci            if (lowHexExpand >= length) {
4464514f5e3Sopenharmony_ci                break;
4474514f5e3Sopenharmony_ci            }
4484514f5e3Sopenharmony_ci            unsigned int n = buildIdHex[i];
4494514f5e3Sopenharmony_ci            buildId[lowHexExpand - 1] = HEXTABLE[(n >> 4) % HEXLENGTH]; // 4 : higher 4 bit of uint8
4504514f5e3Sopenharmony_ci            buildId[lowHexExpand] = HEXTABLE[n % HEXLENGTH];
4514514f5e3Sopenharmony_ci        }
4524514f5e3Sopenharmony_ci    }
4534514f5e3Sopenharmony_ci
4544514f5e3Sopenharmony_ci    uint64_t AlignValues(uint64_t val, uint64_t align) const
4554514f5e3Sopenharmony_ci    {
4564514f5e3Sopenharmony_ci        return (val + AlignBytes(align)) & AlignMask(align);
4574514f5e3Sopenharmony_ci    }
4584514f5e3Sopenharmony_ci
4594514f5e3Sopenharmony_ci    uint64_t AlignMask(uint64_t align) const
4604514f5e3Sopenharmony_ci    {
4614514f5e3Sopenharmony_ci        return ~(static_cast<uint64_t>((align) - 1));
4624514f5e3Sopenharmony_ci    }
4634514f5e3Sopenharmony_ci
4644514f5e3Sopenharmony_ci    uint64_t AlignBytes(uint64_t align) const
4654514f5e3Sopenharmony_ci    {
4664514f5e3Sopenharmony_ci        return (align) - 1;
4674514f5e3Sopenharmony_ci    }
4684514f5e3Sopenharmony_ci
4694514f5e3Sopenharmony_ci    bool IsLoadedMap()
4704514f5e3Sopenharmony_ci    {
4714514f5e3Sopenharmony_ci        return isLoadedMap_;
4724514f5e3Sopenharmony_ci    }
4734514f5e3Sopenharmony_ci
4744514f5e3Sopenharmony_ci    void SetLoadedMap(bool value)
4754514f5e3Sopenharmony_ci    {
4764514f5e3Sopenharmony_ci        isLoadedMap_ = value;
4774514f5e3Sopenharmony_ci    }
4784514f5e3Sopenharmony_ci
4794514f5e3Sopenharmony_ci    std::map<RuntimeInfoType, int> escapeMap_;
4804514f5e3Sopenharmony_ci    bool isLoadedMap_ = false;
4814514f5e3Sopenharmony_ci    std::mutex fileMutex_;
4824514f5e3Sopenharmony_ci};
4834514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
4844514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_COMPILER_OHOS_RUNTIME_BUILD_INFO_H