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