1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/platform/aot_crash_info.h"
17 #if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
18 #include "parameters.h"
19 #endif
20
21 namespace panda::ecmascript {
22 #ifdef JIT_ESCAPE_ENABLE
23 static struct sigaction s_oldSa[SIGSYS + 1]; // SIGSYS = 31
GetSignalHandler(int signal,siginfo_t * info,void * context)24 void GetSignalHandler(int signal, siginfo_t *info, void *context)
25 {
26 [[maybe_unused]] ucontext_t *ucontext = reinterpret_cast<ucontext_t*>(context);
27 [[maybe_unused]] mcontext_t &mcontext = ucontext->uc_mcontext;
28 uintptr_t pc = 0;
29 #if defined(PANDA_TARGET_AMD64)
30 pc = static_cast<uintptr_t>(mcontext.gregs[REG_RIP]);
31 #elif defined(PANDA_TARGET_ARM64)
32 pc = static_cast<uintptr_t>(mcontext.pc);
33 #endif
34 if (JsStackInfo::loader == nullptr) {
35 ecmascript::JsStackInfo::BuildCrashInfo(false);
36 } else if (!JsStackInfo::loader->InsideStub(pc) && !JsStackInfo::loader->InsideAOT(pc)) {
37 ecmascript::JsStackInfo::BuildCrashInfo(false);
38 } else {
39 ecmascript::JsStackInfo::BuildCrashInfo(false, pc);
40 }
41 sigaction(signal, &s_oldSa[signal], nullptr);
42 int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), info->si_signo, info);
43 if (rc != 0) {
44 LOG_ECMA(ERROR) << "GetSignalHandler() failed to resend signal during crash";
45 }
46 }
47
SignalReg(int signo)48 void SignalReg(int signo)
49 {
50 sigaction(signo, nullptr, &s_oldSa[signo]);
51 struct sigaction newAction;
52 newAction.sa_flags = SA_RESTART | SA_SIGINFO;
53 newAction.sa_sigaction = GetSignalHandler;
54 sigaction(signo, &newAction, nullptr);
55 }
56 #endif
57
SignalAllReg()58 void SignalAllReg()
59 {
60 #ifdef JIT_ESCAPE_ENABLE
61 SignalReg(SIGABRT);
62 SignalReg(SIGBUS);
63 SignalReg(SIGSEGV);
64 SignalReg(SIGILL);
65 SignalReg(SIGKILL);
66 SignalReg(SIGSTKFLT);
67 SignalReg(SIGFPE);
68 SignalReg(SIGTRAP);
69 #endif
70 }
71
IsAotEscapedOrNotInEnableList(EcmaVM * vm,const std::string & bundleName) const72 bool AotCrashInfo::IsAotEscapedOrNotInEnableList(EcmaVM *vm, const std::string &bundleName) const
73 {
74 if (!vm->GetJSOptions().WasAOTOutputFileSet() &&
75 !ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
76 LOG_ECMA(INFO) << "Stop load AOT because it's not in enable list";
77 return true;
78 }
79 if (IsAotEscaped()) {
80 LOG_ECMA(INFO) << "Stop load AOT because there are more crashes";
81 return true;
82 }
83 return false;
84 }
85
IsAotEscapedOrCompiledOnce(AotCompilerPreprocessor & cPreprocessor,int32_t & ret) const86 bool AotCrashInfo::IsAotEscapedOrCompiledOnce(AotCompilerPreprocessor &cPreprocessor, int32_t &ret) const
87 {
88 if (!cPreprocessor.GetMainPkgArgs()) {
89 return false;
90 }
91 std::string pgoRealPath = cPreprocessor.GetMainPkgArgs()->GetPgoDir();
92 pgoRealPath.append(ohos::OhosConstants::PATH_SEPARATOR);
93 pgoRealPath.append(ohos::OhosConstants::AOT_RUNTIME_INFO_NAME);
94 if (ohos::EnableAotJitListHelper::GetInstance()->IsAotCompileSuccessOnce(pgoRealPath)) {
95 ret = 0;
96 LOG_ECMA(INFO) << "Aot has compile success once or escaped.";
97 return true;
98 }
99 if (IsAotEscaped(pgoRealPath)) {
100 ret = -1;
101 LOG_ECMA(INFO) << "Aot has escaped";
102 return true;
103 }
104 return false;
105 }
106
SetOptionPGOProfiler(JSRuntimeOptions * options,const std::string & bundleName) const107 void AotCrashInfo::SetOptionPGOProfiler(JSRuntimeOptions *options, const std::string &bundleName) const
108 {
109 #ifdef AOT_ESCAPE_ENABLE
110 if (ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
111 options->SetEnablePGOProfiler(true);
112 if (options->GetAOTHasException() || ecmascript::AnFileDataManager::GetInstance()->IsEnable()) {
113 options->SetEnablePGOProfiler(false);
114 LOG_ECMA(INFO) << "Aot has compile success once or escaped.";
115 }
116 }
117 #endif
118 (void)options;
119 (void)bundleName;
120 }
121
IsAotEscaped(const std::string & pgoRealPath)122 bool AotCrashInfo::IsAotEscaped(const std::string &pgoRealPath)
123 {
124 if (AotCrashInfo::GetAotEscapeDisable()) {
125 return false;
126 }
127 auto escapeMap = ohos::AotRuntimeInfo::GetInstance().CollectCrashSum(pgoRealPath);
128 int totalCrashes = escapeMap[ohos::RuntimeInfoType::AOT_CRASH] +
129 escapeMap[ohos::RuntimeInfoType::JIT] +
130 escapeMap[ohos::RuntimeInfoType::OTHERS] +
131 escapeMap[ohos::RuntimeInfoType::JS];
132 return totalCrashes >= OPT_CODE_CRASH_THRESHOLD;
133 }
134
IsJitEscape()135 bool AotCrashInfo::IsJitEscape()
136 {
137 auto escapeMap = ohos::AotRuntimeInfo::GetInstance().CollectCrashSum();
138 int totalCrashes = escapeMap[ohos::RuntimeInfoType::AOT_CRASH] +
139 escapeMap[ohos::RuntimeInfoType::JIT] +
140 escapeMap[ohos::RuntimeInfoType::OTHERS] +
141 escapeMap[ohos::RuntimeInfoType::JS];
142 return totalCrashes >= OPT_CODE_CRASH_THRESHOLD;
143 }
144
GetAotEscapeDisable()145 bool AotCrashInfo::GetAotEscapeDisable()
146 {
147 #if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
148 return OHOS::system::GetBoolParameter(AOT_ESCAPE_DISABLE, false);
149 #endif
150 return false;
151 }
152
GetSandBoxPath()153 std::string AotCrashInfo::GetSandBoxPath()
154 {
155 return ohos::OhosConstants::SANDBOX_ARK_PROFILE_PATH;
156 }
157
GetAotCrashCount()158 int AotCrashInfo::GetAotCrashCount()
159 {
160 return AOT_CRASH_COUNT;
161 }
162
GetJitCrashCount()163 int AotCrashInfo::GetJitCrashCount()
164 {
165 return JIT_CRASH_COUNT;
166 }
167
GetJsCrashCount()168 int AotCrashInfo::GetJsCrashCount()
169 {
170 return JS_CRASH_COUNT;
171 }
172
GetOthersCrashCount()173 int AotCrashInfo::GetOthersCrashCount()
174 {
175 return OTHERS_CRASH_COUNT;
176 }
177
178 } // namespace panda::ecmascript
179