• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     if (memset_s(&newAction, sizeof(newAction), 0, sizeof(newAction)) != EOK) {
53         LOG_ECMA(ERROR) << "memset_s newAction failed : " << strerror(errno);
54         return;
55     }
56     newAction.sa_flags = SA_RESTART | SA_SIGINFO;
57     newAction.sa_sigaction = GetSignalHandler;
58     sigaction(signo, &newAction, nullptr);
59 }
60 #endif
61 
SignalAllReg()62 void SignalAllReg()
63 {
64 #ifdef JIT_ESCAPE_ENABLE
65     SignalReg(SIGABRT);
66     SignalReg(SIGBUS);
67     SignalReg(SIGSEGV);
68     SignalReg(SIGILL);
69     SignalReg(SIGKILL);
70     SignalReg(SIGSTKFLT);
71     SignalReg(SIGFPE);
72     SignalReg(SIGTRAP);
73 #endif
74 }
75 
IsAotEscapedOrNotInEnableList(EcmaVM * vm,const std::string & bundleName) const76 bool AotCrashInfo::IsAotEscapedOrNotInEnableList(EcmaVM *vm, const std::string &bundleName) const
77 {
78     if (!vm->GetJSOptions().WasAOTOutputFileSet() &&
79         !ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
80         LOG_ECMA(INFO) << "Stop load AOT because it's not in enable list";
81         return true;
82     }
83     if (IsAotEscaped()) {
84         LOG_ECMA(INFO) << "Stop load AOT because there are more crashes";
85         return true;
86     }
87     return false;
88 }
89 
IsAotEscapedOrCompiledOnce(AotCompilerPreprocessor & cPreprocessor,int32_t & ret) const90 bool AotCrashInfo::IsAotEscapedOrCompiledOnce(AotCompilerPreprocessor &cPreprocessor, int32_t &ret) const
91 {
92     if (!cPreprocessor.GetMainPkgArgs()) {
93         return false;
94     }
95     std::string pgoRealPath = cPreprocessor.GetMainPkgArgs()->GetPgoDir();
96     pgoRealPath.append(ohos::OhosConstants::PATH_SEPARATOR);
97     pgoRealPath.append(ohos::OhosConstants::AOT_RUNTIME_INFO_NAME);
98     if (ohos::EnableAotJitListHelper::GetInstance()->IsAotCompileSuccessOnce(pgoRealPath)) {
99         ret = 0;
100         LOG_ECMA(INFO) << "Aot has compile success once or escaped.";
101         return true;
102     }
103     if (IsAotEscaped(pgoRealPath)) {
104         ret = -1;
105         LOG_ECMA(INFO) << "Aot has escaped";
106         return true;
107     }
108     return false;
109 }
110 
SetOptionPGOProfiler(JSRuntimeOptions * options,const std::string & bundleName) const111 void AotCrashInfo::SetOptionPGOProfiler(JSRuntimeOptions *options, const std::string &bundleName) const
112 {
113 #ifdef AOT_ESCAPE_ENABLE
114     if (ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
115         options->SetEnablePGOProfiler(true);
116         if (options->GetAOTHasException() || ecmascript::AnFileDataManager::GetInstance()->IsEnable()) {
117             options->SetEnablePGOProfiler(false);
118             LOG_ECMA(INFO) << "Aot has compile success once or escaped.";
119         }
120     }
121 #endif
122     (void)options;
123     (void)bundleName;
124 }
125 
IsAotEscaped(const std::string & pgoRealPath)126 bool AotCrashInfo::IsAotEscaped(const std::string &pgoRealPath)
127 {
128     if (AotCrashInfo::GetAotEscapeDisable()) {
129         return false;
130     }
131     auto escapeMap = ohos::AotRuntimeInfo::GetInstance().CollectCrashSum(pgoRealPath);
132     int totalCrashes = escapeMap[ohos::RuntimeInfoType::AOT_CRASH] +
133                        escapeMap[ohos::RuntimeInfoType::JIT] +
134                        escapeMap[ohos::RuntimeInfoType::OTHERS] +
135                        escapeMap[ohos::RuntimeInfoType::JS];
136     return totalCrashes >= OPT_CODE_CRASH_THRESHOLD;
137 }
138 
IsJitEscape()139 bool AotCrashInfo::IsJitEscape()
140 {
141     auto escapeMap = ohos::AotRuntimeInfo::GetInstance().CollectCrashSum();
142     int totalCrashes = escapeMap[ohos::RuntimeInfoType::AOT_CRASH] +
143                        escapeMap[ohos::RuntimeInfoType::JIT] +
144                        escapeMap[ohos::RuntimeInfoType::OTHERS] +
145                        escapeMap[ohos::RuntimeInfoType::JS];
146     return totalCrashes >= OPT_CODE_CRASH_THRESHOLD;
147 }
148 
GetAotEscapeDisable()149 bool AotCrashInfo::GetAotEscapeDisable()
150 {
151 #if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
152         return OHOS::system::GetBoolParameter(AOT_ESCAPE_DISABLE, false);
153 #endif
154         return false;
155 }
156 
GetSandBoxPath()157 std::string AotCrashInfo::GetSandBoxPath()
158 {
159     return ohos::OhosConstants::SANDBOX_ARK_PROFILE_PATH;
160 }
161 
GetAotCrashCount()162 int AotCrashInfo::GetAotCrashCount()
163 {
164     return AOT_CRASH_COUNT;
165 }
166 
GetJitCrashCount()167 int AotCrashInfo::GetJitCrashCount()
168 {
169     return JIT_CRASH_COUNT;
170 }
171 
GetJsCrashCount()172 int AotCrashInfo::GetJsCrashCount()
173 {
174     return JS_CRASH_COUNT;
175 }
176 
GetOthersCrashCount()177 int AotCrashInfo::GetOthersCrashCount()
178 {
179     return OTHERS_CRASH_COUNT;
180 }
181 
182 }  // namespace panda::ecmascript
183