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(¤t_time) == -1) { 2294514f5e3Sopenharmony_ci return false; 2304514f5e3Sopenharmony_ci } 2314514f5e3Sopenharmony_ci struct tm *local_time = localtime(¤t_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