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 174514f5e3Sopenharmony_ci#include "ecmascript/platform/aot_crash_info.h" 184514f5e3Sopenharmony_ci#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE) 194514f5e3Sopenharmony_ci#include "parameters.h" 204514f5e3Sopenharmony_ci#endif 214514f5e3Sopenharmony_ci 224514f5e3Sopenharmony_cinamespace panda::ecmascript { 234514f5e3Sopenharmony_ci#ifdef JIT_ESCAPE_ENABLE 244514f5e3Sopenharmony_cistatic struct sigaction s_oldSa[SIGSYS + 1]; // SIGSYS = 31 254514f5e3Sopenharmony_civoid GetSignalHandler(int signal, siginfo_t *info, void *context) 264514f5e3Sopenharmony_ci{ 274514f5e3Sopenharmony_ci [[maybe_unused]] ucontext_t *ucontext = reinterpret_cast<ucontext_t*>(context); 284514f5e3Sopenharmony_ci [[maybe_unused]] mcontext_t &mcontext = ucontext->uc_mcontext; 294514f5e3Sopenharmony_ci uintptr_t pc = 0; 304514f5e3Sopenharmony_ci#if defined(PANDA_TARGET_AMD64) 314514f5e3Sopenharmony_ci pc = static_cast<uintptr_t>(mcontext.gregs[REG_RIP]); 324514f5e3Sopenharmony_ci#elif defined(PANDA_TARGET_ARM64) 334514f5e3Sopenharmony_ci pc = static_cast<uintptr_t>(mcontext.pc); 344514f5e3Sopenharmony_ci#endif 354514f5e3Sopenharmony_ci if (JsStackInfo::loader == nullptr) { 364514f5e3Sopenharmony_ci ecmascript::JsStackInfo::BuildCrashInfo(false); 374514f5e3Sopenharmony_ci } else if (!JsStackInfo::loader->InsideStub(pc) && !JsStackInfo::loader->InsideAOT(pc)) { 384514f5e3Sopenharmony_ci ecmascript::JsStackInfo::BuildCrashInfo(false); 394514f5e3Sopenharmony_ci } else { 404514f5e3Sopenharmony_ci ecmascript::JsStackInfo::BuildCrashInfo(false, pc); 414514f5e3Sopenharmony_ci } 424514f5e3Sopenharmony_ci sigaction(signal, &s_oldSa[signal], nullptr); 434514f5e3Sopenharmony_ci int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), info->si_signo, info); 444514f5e3Sopenharmony_ci if (rc != 0) { 454514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "GetSignalHandler() failed to resend signal during crash"; 464514f5e3Sopenharmony_ci } 474514f5e3Sopenharmony_ci} 484514f5e3Sopenharmony_ci 494514f5e3Sopenharmony_civoid SignalReg(int signo) 504514f5e3Sopenharmony_ci{ 514514f5e3Sopenharmony_ci sigaction(signo, nullptr, &s_oldSa[signo]); 524514f5e3Sopenharmony_ci struct sigaction newAction; 534514f5e3Sopenharmony_ci newAction.sa_flags = SA_RESTART | SA_SIGINFO; 544514f5e3Sopenharmony_ci newAction.sa_sigaction = GetSignalHandler; 554514f5e3Sopenharmony_ci sigaction(signo, &newAction, nullptr); 564514f5e3Sopenharmony_ci} 574514f5e3Sopenharmony_ci#endif 584514f5e3Sopenharmony_ci 594514f5e3Sopenharmony_civoid SignalAllReg() 604514f5e3Sopenharmony_ci{ 614514f5e3Sopenharmony_ci#ifdef JIT_ESCAPE_ENABLE 624514f5e3Sopenharmony_ci SignalReg(SIGABRT); 634514f5e3Sopenharmony_ci SignalReg(SIGBUS); 644514f5e3Sopenharmony_ci SignalReg(SIGSEGV); 654514f5e3Sopenharmony_ci SignalReg(SIGILL); 664514f5e3Sopenharmony_ci SignalReg(SIGKILL); 674514f5e3Sopenharmony_ci SignalReg(SIGSTKFLT); 684514f5e3Sopenharmony_ci SignalReg(SIGFPE); 694514f5e3Sopenharmony_ci SignalReg(SIGTRAP); 704514f5e3Sopenharmony_ci#endif 714514f5e3Sopenharmony_ci} 724514f5e3Sopenharmony_ci 734514f5e3Sopenharmony_cibool AotCrashInfo::IsAotEscapedOrNotInEnableList(EcmaVM *vm, const std::string &bundleName) const 744514f5e3Sopenharmony_ci{ 754514f5e3Sopenharmony_ci if (!vm->GetJSOptions().WasAOTOutputFileSet() && 764514f5e3Sopenharmony_ci !ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) { 774514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "Stop load AOT because it's not in enable list"; 784514f5e3Sopenharmony_ci return true; 794514f5e3Sopenharmony_ci } 804514f5e3Sopenharmony_ci if (IsAotEscaped()) { 814514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "Stop load AOT because there are more crashes"; 824514f5e3Sopenharmony_ci return true; 834514f5e3Sopenharmony_ci } 844514f5e3Sopenharmony_ci return false; 854514f5e3Sopenharmony_ci} 864514f5e3Sopenharmony_ci 874514f5e3Sopenharmony_cibool AotCrashInfo::IsAotEscapedOrCompiledOnce(AotCompilerPreprocessor &cPreprocessor, int32_t &ret) const 884514f5e3Sopenharmony_ci{ 894514f5e3Sopenharmony_ci if (!cPreprocessor.GetMainPkgArgs()) { 904514f5e3Sopenharmony_ci return false; 914514f5e3Sopenharmony_ci } 924514f5e3Sopenharmony_ci std::string pgoRealPath = cPreprocessor.GetMainPkgArgs()->GetPgoDir(); 934514f5e3Sopenharmony_ci pgoRealPath.append(ohos::OhosConstants::PATH_SEPARATOR); 944514f5e3Sopenharmony_ci pgoRealPath.append(ohos::OhosConstants::AOT_RUNTIME_INFO_NAME); 954514f5e3Sopenharmony_ci if (ohos::EnableAotJitListHelper::GetInstance()->IsAotCompileSuccessOnce(pgoRealPath)) { 964514f5e3Sopenharmony_ci ret = 0; 974514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "Aot has compile success once or escaped."; 984514f5e3Sopenharmony_ci return true; 994514f5e3Sopenharmony_ci } 1004514f5e3Sopenharmony_ci if (IsAotEscaped(pgoRealPath)) { 1014514f5e3Sopenharmony_ci ret = -1; 1024514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "Aot has escaped"; 1034514f5e3Sopenharmony_ci return true; 1044514f5e3Sopenharmony_ci } 1054514f5e3Sopenharmony_ci return false; 1064514f5e3Sopenharmony_ci} 1074514f5e3Sopenharmony_ci 1084514f5e3Sopenharmony_civoid AotCrashInfo::SetOptionPGOProfiler(JSRuntimeOptions *options, const std::string &bundleName) const 1094514f5e3Sopenharmony_ci{ 1104514f5e3Sopenharmony_ci#ifdef AOT_ESCAPE_ENABLE 1114514f5e3Sopenharmony_ci if (ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) { 1124514f5e3Sopenharmony_ci options->SetEnablePGOProfiler(true); 1134514f5e3Sopenharmony_ci if (options->GetAOTHasException() || 1144514f5e3Sopenharmony_ci ohos::EnableAotJitListHelper::GetInstance()->IsAotCompileSuccessOnce() || 1154514f5e3Sopenharmony_ci IsAotEscaped()) { 1164514f5e3Sopenharmony_ci options->SetEnablePGOProfiler(false); 1174514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "Aot has compile success once or escaped."; 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci#endif 1214514f5e3Sopenharmony_ci (void)options; 1224514f5e3Sopenharmony_ci (void)bundleName; 1234514f5e3Sopenharmony_ci} 1244514f5e3Sopenharmony_ci 1254514f5e3Sopenharmony_cibool AotCrashInfo::IsAotEscaped(const std::string &pgoRealPath) 1264514f5e3Sopenharmony_ci{ 1274514f5e3Sopenharmony_ci if (AotCrashInfo::GetAotEscapeDisable()) { 1284514f5e3Sopenharmony_ci return false; 1294514f5e3Sopenharmony_ci } 1304514f5e3Sopenharmony_ci auto escapeMap = ohos::AotRuntimeInfo::GetInstance().CollectCrashSum(pgoRealPath); 1314514f5e3Sopenharmony_ci int totalCrashes = escapeMap[ohos::RuntimeInfoType::AOT_CRASH] + 1324514f5e3Sopenharmony_ci escapeMap[ohos::RuntimeInfoType::JIT] + 1334514f5e3Sopenharmony_ci escapeMap[ohos::RuntimeInfoType::OTHERS] + 1344514f5e3Sopenharmony_ci escapeMap[ohos::RuntimeInfoType::JS]; 1354514f5e3Sopenharmony_ci return totalCrashes >= OPT_CODE_CRASH_THRESHOLD; 1364514f5e3Sopenharmony_ci} 1374514f5e3Sopenharmony_ci 1384514f5e3Sopenharmony_cibool AotCrashInfo::IsJitEscape() 1394514f5e3Sopenharmony_ci{ 1404514f5e3Sopenharmony_ci auto escapeMap = ohos::AotRuntimeInfo::GetInstance().CollectCrashSum(); 1414514f5e3Sopenharmony_ci int totalCrashes = escapeMap[ohos::RuntimeInfoType::AOT_CRASH] + 1424514f5e3Sopenharmony_ci escapeMap[ohos::RuntimeInfoType::JIT] + 1434514f5e3Sopenharmony_ci escapeMap[ohos::RuntimeInfoType::OTHERS] + 1444514f5e3Sopenharmony_ci escapeMap[ohos::RuntimeInfoType::JS]; 1454514f5e3Sopenharmony_ci return totalCrashes >= OPT_CODE_CRASH_THRESHOLD; 1464514f5e3Sopenharmony_ci} 1474514f5e3Sopenharmony_ci 1484514f5e3Sopenharmony_cibool AotCrashInfo::GetAotEscapeDisable() 1494514f5e3Sopenharmony_ci{ 1504514f5e3Sopenharmony_ci#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE) 1514514f5e3Sopenharmony_ci return OHOS::system::GetBoolParameter(AOT_ESCAPE_DISABLE, false); 1524514f5e3Sopenharmony_ci#endif 1534514f5e3Sopenharmony_ci return false; 1544514f5e3Sopenharmony_ci} 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_cistd::string AotCrashInfo::GetSandBoxPath() 1574514f5e3Sopenharmony_ci{ 1584514f5e3Sopenharmony_ci return ohos::OhosConstants::SANDBOX_ARK_PROFILE_PATH; 1594514f5e3Sopenharmony_ci} 1604514f5e3Sopenharmony_ci 1614514f5e3Sopenharmony_ciint AotCrashInfo::GetAotCrashCount() 1624514f5e3Sopenharmony_ci{ 1634514f5e3Sopenharmony_ci return AOT_CRASH_COUNT; 1644514f5e3Sopenharmony_ci} 1654514f5e3Sopenharmony_ci 1664514f5e3Sopenharmony_ciint AotCrashInfo::GetJitCrashCount() 1674514f5e3Sopenharmony_ci{ 1684514f5e3Sopenharmony_ci return JIT_CRASH_COUNT; 1694514f5e3Sopenharmony_ci} 1704514f5e3Sopenharmony_ci 1714514f5e3Sopenharmony_ciint AotCrashInfo::GetJsCrashCount() 1724514f5e3Sopenharmony_ci{ 1734514f5e3Sopenharmony_ci return JS_CRASH_COUNT; 1744514f5e3Sopenharmony_ci} 1754514f5e3Sopenharmony_ci 1764514f5e3Sopenharmony_ciint AotCrashInfo::GetOthersCrashCount() 1774514f5e3Sopenharmony_ci{ 1784514f5e3Sopenharmony_ci return OTHERS_CRASH_COUNT; 1794514f5e3Sopenharmony_ci} 1804514f5e3Sopenharmony_ci 1814514f5e3Sopenharmony_ci} // namespace panda::ecmascript 182