mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-06 23:54:03 +00:00
Fix crashes when the phone signal does not allow the use of malloc related functions
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IABHLM?from=project-issue Signed-off-by: harryhrp <herongpeng@huawei.com> Change-Id: Ibfffc984049a97f5a295915b5cd7935c73f33704 Change-Id: Iee9c74ea23bf2983e3c238e5974d3026ffba5e5b
This commit is contained in:
parent
c40f00d60f
commit
5ba737abfa
2
BUILD.gn
2
BUILD.gn
@ -1035,12 +1035,14 @@ if (is_mingw) {
|
||||
"ecmascript/platform/windows/os.cpp",
|
||||
"ecmascript/platform/windows/time.cpp",
|
||||
"ecmascript/platform/windows/log.cpp",
|
||||
"ecmascript/platform/windows/aot_crash_info.cpp",
|
||||
]
|
||||
} else {
|
||||
ecma_platform_source += [
|
||||
"ecmascript/platform/unix/file.cpp",
|
||||
"ecmascript/platform/unix/map.cpp",
|
||||
"ecmascript/platform/unix/time.cpp",
|
||||
"ecmascript/platform/unix/aot_crash_info.cpp",
|
||||
]
|
||||
if (is_mac) {
|
||||
ecma_platform_source += [
|
||||
|
@ -28,9 +28,9 @@
|
||||
#include "ecmascript/log.h"
|
||||
#include "ecmascript/log_wrapper.h"
|
||||
#include "ecmascript/napi/include/jsnapi.h"
|
||||
#include "ecmascript/ohos/aot_crash_info.h"
|
||||
#include "ecmascript/ohos/enable_aot_list_helper.h"
|
||||
#include "ecmascript/ohos/ohos_pkg_args.h"
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
#include "ecmascript/platform/file.h"
|
||||
#include "ecmascript/platform/filesystem.h"
|
||||
#include "ecmascript/platform/os.h"
|
||||
@ -121,7 +121,7 @@ int Main(const int argc, const char **argv)
|
||||
}
|
||||
|
||||
if (IsExistsPkgInfo(cPreprocessor)) {
|
||||
if (ohos::AotCrashInfo::IsAotEscape(cPreprocessor.GetMainPkgArgs()->GetPgoDir())) {
|
||||
if (AotCrashInfo::IsAotEscaped(cPreprocessor.GetMainPkgArgs()->GetPgoDir())) {
|
||||
LOG_COMPILER(ERROR) << "Stop compile AOT because there are multiple crashes";
|
||||
return ERR_FAIL;
|
||||
}
|
||||
|
@ -24,8 +24,8 @@
|
||||
#include "ecmascript/jspandafile/program_object.h"
|
||||
#include "ecmascript/mem/heap-inl.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
#include "ecmascript/ohos/aot_crash_info.h"
|
||||
#include "ecmascript/ohos/aot_runtime_info.h"
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
#include "ecmascript/platform/os.h"
|
||||
#include "ecmascript/stubs/runtime_stubs-inl.h"
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
@ -157,7 +157,7 @@ void JsStackInfo::DumpJitCode(JSThread *thread)
|
||||
}
|
||||
std::string fileName = "jitCode-" + std::to_string(getpid());
|
||||
std::string realOutPath;
|
||||
std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(ohos::AotCrashInfo::GetSandBoxPath());
|
||||
std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(AotCrashInfo::GetSandBoxPath());
|
||||
if (!ecmascript::RealPath(sanboxPath, realOutPath, false)) {
|
||||
return;
|
||||
}
|
||||
@ -246,12 +246,10 @@ std::string JsStackInfo::BuildJsStackTraceInfo(JSThread *thread, Method *method,
|
||||
void JsStackInfo::BuildCrashInfo(bool isJsCrash, FrameType frameType, JSThread *thread)
|
||||
{
|
||||
if (JsStackInfo::loader == nullptr || JsStackInfo::options == nullptr) {
|
||||
LOG_ECMA(ERROR) << "Loader or options initialization error.";
|
||||
return;
|
||||
}
|
||||
if (!JsStackInfo::loader->IsEnableAOT() && !JsStackInfo::options->IsEnableJIT() &&
|
||||
!JsStackInfo::options->IsEnablePGOProfiler()) {
|
||||
LOG_ECMA(INFO) << "Neither AOT nor JIT is enabled.";
|
||||
return;
|
||||
}
|
||||
ohos::RuntimeInfoType type;
|
||||
@ -259,13 +257,13 @@ void JsStackInfo::BuildCrashInfo(bool isJsCrash, FrameType frameType, JSThread *
|
||||
type = ohos::RuntimeInfoType::JS;
|
||||
} else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME ||
|
||||
frameType == FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME) {
|
||||
type = ohos::RuntimeInfoType::AOT;
|
||||
type = ohos::RuntimeInfoType::AOT_CRASH;
|
||||
} else if (IsFastJitFunctionFrame(frameType)) {
|
||||
type = ohos::RuntimeInfoType::JIT;
|
||||
} else {
|
||||
type = ohos::RuntimeInfoType::OTHERS;
|
||||
}
|
||||
ohos::AotRuntimeInfo::GetInstance().BuildCrashRuntimeInfo(ohos::AotRuntimeInfo::GetRuntimeInfoTypeStr(type));
|
||||
ohos::AotRuntimeInfo::GetInstance().BuildCrashRuntimeInfo(type);
|
||||
if (isJsCrash) {
|
||||
DumpJitCode(thread);
|
||||
}
|
||||
|
@ -44,8 +44,8 @@
|
||||
#include "ecmascript/module/module_path_helper.h"
|
||||
#include "ecmascript/module/js_shared_module.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/ohos/aot_crash_info.h"
|
||||
#include "ecmascript/patch/patch_loader.h"
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
|
||||
#include "ecmascript/require/js_cjs_module_cache.h"
|
||||
#include "ecmascript/require/js_require_manager.h"
|
||||
@ -1105,7 +1105,7 @@ bool EcmaContext::LoadAOTFilesInternal(const std::string& aotFileName)
|
||||
{
|
||||
#ifdef AOT_ESCAPE_ENABLE
|
||||
std::string bundleName = pgo::PGOProfilerManager::GetInstance()->GetBundleName();
|
||||
if (ohos::AotCrashInfo::GetInstance().IsAotEscapeOrNotInEnableList(vm_, bundleName)) {
|
||||
if (AotCrashInfo::GetInstance().IsAotEscapedOrNotInEnableList(vm_, bundleName)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@ -92,10 +92,10 @@
|
||||
#include "ecmascript/tagged_queue.h"
|
||||
#include "ecmascript/taskpool/task.h"
|
||||
#include "ecmascript/taskpool/taskpool.h"
|
||||
#include "ecmascript/ohos/aot_crash_info.h"
|
||||
#include "ecmascript/ohos/enable_aot_list_helper.h"
|
||||
#include "ecmascript/ohos/jit_tools.h"
|
||||
#include "ecmascript/ohos/aot_tools.h"
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
|
||||
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
|
||||
#include "parameters.h"
|
||||
@ -104,54 +104,11 @@
|
||||
namespace panda::ecmascript {
|
||||
using RandomGenerator = base::RandomGenerator;
|
||||
using PGOProfilerManager = pgo::PGOProfilerManager;
|
||||
using AotCrashInfo = ohos::AotCrashInfo;
|
||||
using JitTools = ohos::JitTools;
|
||||
AOTFileManager *JsStackInfo::loader = nullptr;
|
||||
JSRuntimeOptions *JsStackInfo::options = nullptr;
|
||||
bool EcmaVM::multiThreadCheck_ = false;
|
||||
|
||||
#ifdef JIT_ESCAPE_ENABLE
|
||||
static struct sigaction s_oldSa[SIGSYS + 1]; // SIGSYS = 31
|
||||
|
||||
void GetSignalHandler(int signal, siginfo_t *info, void *context)
|
||||
{
|
||||
#if defined(__aarch64__) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
|
||||
ucontext_t *ucontext = static_cast<ucontext_t*>(context);
|
||||
uintptr_t fp = ucontext->uc_mcontext.regs[29];
|
||||
FrameIterator frame(reinterpret_cast<JSTaggedType *>(fp));
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false, frame.GetFrameType());
|
||||
#else
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false);
|
||||
#endif
|
||||
sigaction(signal, &s_oldSa[signal], nullptr);
|
||||
int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), info->si_signo, info);
|
||||
if (rc != 0) {
|
||||
LOG_ECMA(ERROR) << "GetSignalHandler() failed to resend signal during crash";
|
||||
}
|
||||
}
|
||||
|
||||
void SignalReg(int signo)
|
||||
{
|
||||
sigaction(signo, nullptr, &s_oldSa[signo]);
|
||||
struct sigaction newAction;
|
||||
newAction.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
newAction.sa_sigaction = GetSignalHandler;
|
||||
sigaction(signo, &newAction, nullptr);
|
||||
}
|
||||
|
||||
void SignalAllReg()
|
||||
{
|
||||
SignalReg(SIGABRT);
|
||||
SignalReg(SIGBUS);
|
||||
SignalReg(SIGSEGV);
|
||||
SignalReg(SIGILL);
|
||||
SignalReg(SIGKILL);
|
||||
SignalReg(SIGSTKFLT);
|
||||
SignalReg(SIGFPE);
|
||||
SignalReg(SIGTRAP);
|
||||
}
|
||||
#endif
|
||||
|
||||
EcmaVM *EcmaVM::Create(const JSRuntimeOptions &options)
|
||||
{
|
||||
Runtime::CreateIfFirstVm(options);
|
||||
@ -212,21 +169,15 @@ void EcmaVM::PostFork()
|
||||
Taskpool::GetCurrentTaskpool()->Initialize();
|
||||
SetPostForked(true);
|
||||
LOG_ECMA(INFO) << "multi-thread check enabled: " << options_.EnableThreadCheck();
|
||||
#if defined(JIT_ESCAPE_ENABLE) || defined(AOT_ESCAPE_ENABLE)
|
||||
SignalAllReg();
|
||||
#endif
|
||||
SharedHeap::GetInstance()->EnableParallelGC(GetJSOptions());
|
||||
DaemonThread::GetInstance()->StartRunning();
|
||||
heap_->EnableParallelGC();
|
||||
std::string bundleName = PGOProfilerManager::GetInstance()->GetBundleName();
|
||||
pgo::PGOTrace::GetInstance()->SetEnable(ohos::AotTools::GetPgoTraceEnable());
|
||||
#ifdef AOT_ESCAPE_ENABLE
|
||||
AotCrashInfo::GetInstance().SetOptionPGOProfiler(&options_, bundleName);
|
||||
#endif
|
||||
ResetPGOProfiler();
|
||||
#ifdef JIT_ESCAPE_ENABLE
|
||||
ohos::JitTools::GetInstance().SetJitEnable(this, bundleName);
|
||||
#endif
|
||||
#ifdef ENABLE_POSTFORK_FORCEEXPAND
|
||||
heap_->NotifyPostFork();
|
||||
heap_->NotifyFinishColdStartSoon();
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "ecmascript/dfx/vmstat/jit_warmup_profiler.h"
|
||||
#include "ecmascript/ohos/jit_tools.h"
|
||||
#include "ecmascript/dfx/dump_code/jit_dump_elf.h"
|
||||
#include "ecmascript/ohos/aot_crash_info.h"
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
@ -222,7 +222,7 @@ void DumpJitCode(JSHandle<MachineCode> &machineCode, JSHandle<Method> &method)
|
||||
fileName = fileName + "_" + std::to_string(addr) + "+" + std::to_string(len);
|
||||
jitDumpElf.AppendSymbolToSymTab(0, 0, len, std::string(filename));
|
||||
std::string realOutPath;
|
||||
std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(ohos::AotCrashInfo::GetSandBoxPath());
|
||||
std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(AotCrashInfo::GetSandBoxPath());
|
||||
if (!ecmascript::RealPath(sanboxPath, realOutPath, false)) {
|
||||
return;
|
||||
}
|
||||
|
@ -92,10 +92,10 @@
|
||||
#include "ecmascript/serializer/value_serializer.h"
|
||||
#include "ecmascript/tagged_array.h"
|
||||
#include "ecmascript/js_weak_container.h"
|
||||
#include "ecmascript/ohos/aot_crash_info.h"
|
||||
#include "ecmascript/ohos/aot_runtime_info.h"
|
||||
#include "ecmascript/ohos/enable_aot_list_helper.h"
|
||||
#include "ecmascript/ohos/framework_helper.h"
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
#ifdef ARK_SUPPORT_INTL
|
||||
#include "ecmascript/js_bigint.h"
|
||||
#include "ecmascript/js_collator.h"
|
||||
@ -202,11 +202,9 @@ using ModulePathHelper = ecmascript::ModulePathHelper;
|
||||
using JsDebuggerManager = ecmascript::tooling::JsDebuggerManager;
|
||||
using FrameIterator = ecmascript::FrameIterator;
|
||||
using Concurrent = ecmascript::Concurrent;
|
||||
using CrashInfo = ecmascript::ohos::AotCrashInfo;
|
||||
using EnableAotJitListHelper = ecmascript::ohos::EnableAotJitListHelper;
|
||||
using PGOProfilerManager = ecmascript::pgo::PGOProfilerManager;
|
||||
using AotRuntimeInfo = ecmascript::ohos::AotRuntimeInfo;
|
||||
using AotCrashInfo = ecmascript::ohos::AotCrashInfo;
|
||||
|
||||
namespace {
|
||||
// NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
|
||||
|
@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H
|
||||
#define ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H
|
||||
|
||||
#include "ohos_constants.h"
|
||||
#include "ecmascript/base/string_helper.h"
|
||||
#include "ecmascript/ohos/aot_runtime_info.h"
|
||||
#include "ecmascript/ohos/enable_aot_list_helper.h"
|
||||
#ifdef AOT_ESCAPE_ENABLE
|
||||
#include "parameters.h"
|
||||
#endif
|
||||
|
||||
namespace panda::ecmascript::ohos {
|
||||
class AotCrashInfo {
|
||||
constexpr static const char *const SPLIT_STR = "|";
|
||||
constexpr static const char *const AOT_ESCAPE_DISABLE = "ark.aot.escape.disable";
|
||||
constexpr static int AOT_CRASH_COUNT = 1;
|
||||
constexpr static int OTHERS_CRASH_COUNT = 3;
|
||||
constexpr static int CRASH_LOG_SIZE = 3;
|
||||
constexpr static int JIT_CRASH_COUNT = 1;
|
||||
constexpr static int JS_CRASH_COUNT = 3;
|
||||
public:
|
||||
|
||||
explicit AotCrashInfo() = default;
|
||||
virtual ~AotCrashInfo() = default;
|
||||
|
||||
static AotCrashInfo &GetInstance()
|
||||
{
|
||||
static AotCrashInfo singleAotCrashInfo;
|
||||
return singleAotCrashInfo;
|
||||
}
|
||||
|
||||
bool IsAotEscapeOrNotInEnableList(EcmaVM *vm, const std::string &bundleName) const
|
||||
{
|
||||
if (!vm->GetJSOptions().WasAOTOutputFileSet() &&
|
||||
!EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
|
||||
LOG_ECMA(INFO) << "Stop load AOT because it's not in enable list";
|
||||
return true;
|
||||
}
|
||||
if (IsAotEscape()) {
|
||||
LOG_ECMA(INFO) << "Stop load AOT because there are more crashes";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetOptionPGOProfiler(JSRuntimeOptions *options, const std::string &bundleName) const
|
||||
{
|
||||
if (EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
|
||||
options->SetEnablePGOProfiler(true);
|
||||
}
|
||||
if (EnableAotJitListHelper::GetInstance()->IsAotCompileSuccessOnce()) {
|
||||
options->SetEnablePGOProfiler(false);
|
||||
LOG_ECMA(INFO) << "Aot has compile success once.";
|
||||
}
|
||||
if (IsAotEscape()) {
|
||||
options->SetEnablePGOProfiler(false);
|
||||
LOG_ECMA(INFO) << "Aot has escaped.";
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsAotEscape(const std::string &pgoRealPath = "")
|
||||
{
|
||||
if (GetAotEscapeDisable()) {
|
||||
return false;
|
||||
}
|
||||
auto escapeMap = AotRuntimeInfo::GetInstance().CollectCrashSum(pgoRealPath);
|
||||
return escapeMap[RuntimeInfoType::AOT] >= GetAotCrashCount() ||
|
||||
escapeMap[RuntimeInfoType::OTHERS] >= GetOthersCrashCount() ||
|
||||
escapeMap[RuntimeInfoType::JS] >= GetJsCrashCount();
|
||||
}
|
||||
|
||||
static bool IsJitEscape()
|
||||
{
|
||||
auto escapeMap = AotRuntimeInfo::GetInstance().CollectCrashSum();
|
||||
return escapeMap[RuntimeInfoType::JIT] >= GetJitCrashCount() ||
|
||||
escapeMap[RuntimeInfoType::AOT] >= GetAotCrashCount() ||
|
||||
escapeMap[RuntimeInfoType::OTHERS] >= GetOthersCrashCount() ||
|
||||
escapeMap[RuntimeInfoType::JS] >= GetJsCrashCount();
|
||||
}
|
||||
|
||||
static bool GetAotEscapeDisable()
|
||||
{
|
||||
#ifdef AOT_ESCAPE_ENABLE
|
||||
return OHOS::system::GetBoolParameter(AOT_ESCAPE_DISABLE, false);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string GetSandBoxPath()
|
||||
{
|
||||
return OhosConstants::SANDBOX_ARK_PROFILE_PATH;
|
||||
}
|
||||
|
||||
static int GetAotCrashCount()
|
||||
{
|
||||
return AOT_CRASH_COUNT;
|
||||
}
|
||||
|
||||
static int GetJitCrashCount()
|
||||
{
|
||||
return JIT_CRASH_COUNT;
|
||||
}
|
||||
|
||||
static int GetJsCrashCount()
|
||||
{
|
||||
return JS_CRASH_COUNT;
|
||||
}
|
||||
|
||||
static int GetOthersCrashCount()
|
||||
{
|
||||
return OTHERS_CRASH_COUNT;
|
||||
}
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_COMPILER_OHOS_AOT_CRASH_INFO_H
|
@ -17,6 +17,8 @@
|
||||
#define ECMASCRIPT_COMPILER_OHOS_RUNTIME_BUILD_INFO_H
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ecmascript/platform/directory.h"
|
||||
#include "ecmascript/platform/file.h"
|
||||
@ -29,7 +31,7 @@
|
||||
|
||||
namespace panda::ecmascript::ohos {
|
||||
#define RUNTIME_INFO_TYPE(V) \
|
||||
V(AOT) \
|
||||
V(AOT_CRASH) \
|
||||
V(OTHERS) \
|
||||
V(NONE) \
|
||||
V(JIT) \
|
||||
@ -37,46 +39,27 @@ namespace panda::ecmascript::ohos {
|
||||
V(AOT_BUILD) \
|
||||
|
||||
enum class RuntimeInfoType {
|
||||
AOT,
|
||||
AOT_CRASH,
|
||||
JIT,
|
||||
OTHERS,
|
||||
NONE,
|
||||
JS,
|
||||
AOT_BUILD,
|
||||
};
|
||||
struct RuntimeInfoPart {
|
||||
std::string buildId;
|
||||
std::string timestamp;
|
||||
std::string type;
|
||||
|
||||
RuntimeInfoPart() = default;
|
||||
RuntimeInfoPart(const std::string &buildId, const std::string ×tamp, const std::string &type)
|
||||
: buildId(buildId), timestamp(timestamp), type(type)
|
||||
{
|
||||
}
|
||||
};
|
||||
/*
|
||||
* The JSON format is as follows
|
||||
* type: "AOT_BUILD" Used at compile time,
|
||||
* "AOT", "JIT", "OTHERS", "JS" Used at crash time.
|
||||
* {"key":
|
||||
* [
|
||||
* {"buildId":"xxxxxx", "timestamp":"123456789", "type":"AOT"},
|
||||
* {"buildId":"xxxxxx", "timestamp":"123456789", "type":"AOT"}
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
|
||||
class AotRuntimeInfo {
|
||||
public:
|
||||
constexpr static const int USEC_PER_SEC = 1000 * 1000;
|
||||
constexpr static const int NSEC_PER_USEC = 1000;
|
||||
constexpr static const int NT_GNU_BUILD_ID = 3;
|
||||
constexpr static const int CRASH_INFO_SIZE = 3;
|
||||
|
||||
constexpr static const char *const RUNTIME_INFO_ARRAY_KEY = "runtime_info_array";
|
||||
constexpr static const char *const RUNTIME_KEY_BUILDID = "buildId";
|
||||
constexpr static const char *const RUNTIME_KEY_TIMESTAMP = "timestamp";
|
||||
constexpr static const char *const RUNTIME_KEY_TYPE = "type";
|
||||
constexpr static const int MAX_LENGTH = 255;
|
||||
constexpr static const int BUFFER_SIZE = 4096;
|
||||
constexpr static const int TIME_STAMP_SIZE = 21;
|
||||
|
||||
constexpr static const int RUNTIME_INDEX_BUILDID = 0;
|
||||
constexpr static const int RUNTIME_INDEX_TIMESTAMP = 1;
|
||||
constexpr static const int RUNTIME_INDEX_TYPE = 2;
|
||||
|
||||
static AotRuntimeInfo &GetInstance()
|
||||
{
|
||||
@ -84,40 +67,70 @@ public:
|
||||
return singleAotRuntimeInfo;
|
||||
}
|
||||
|
||||
void BuildCompileRuntimeInfo(const std::string &type, const std::string &pgoPath) const
|
||||
void BuildCompileRuntimeInfo(RuntimeInfoType type, const std::string &pgoPath) const
|
||||
{
|
||||
std::string soBuildId = GetRuntimeBuildId();
|
||||
if (soBuildId == "") {
|
||||
static char soBuildId[NAME_MAX];
|
||||
if (!GetRuntimeBuildId(soBuildId)) {
|
||||
return;
|
||||
}
|
||||
if (IsCharEmpty(soBuildId)) {
|
||||
LOG_ECMA(INFO) << "can't get so buildId.";
|
||||
return;
|
||||
}
|
||||
std::string realOutPath;
|
||||
std::string runtimePgoRealPath = pgoPath + OhosConstants::PATH_SEPARATOR + OhosConstants::AOT_RUNTIME_INFO_NAME;
|
||||
if (!ecmascript::RealPath(runtimePgoRealPath, realOutPath, false)) {
|
||||
if (!ecmascript::RealPath(pgoPath, realOutPath, false)) {
|
||||
LOG_ECMA(INFO) << "Build compile pgo path fail.";
|
||||
return;
|
||||
}
|
||||
std::vector<RuntimeInfoPart> lines = GetRuntimeInfoByPath(realOutPath, soBuildId);
|
||||
uint64_t timestamp = GetMicrosecondsTimeStamp();
|
||||
RuntimeInfoPart buildLine = RuntimeInfoPart(soBuildId, std::to_string(timestamp), type);
|
||||
lines.emplace_back(buildLine);
|
||||
SetRuntimeInfo(realOutPath, lines);
|
||||
}
|
||||
|
||||
void BuildCrashRuntimeInfo(const std::string &type) const
|
||||
{
|
||||
std::string soBuildId = GetRuntimeBuildId();
|
||||
if (soBuildId == "") {
|
||||
LOG_ECMA(INFO) << "can't get so buildId.";
|
||||
static char lines[MAX_LENGTH][BUFFER_SIZE];
|
||||
for (int i = 0; i < MAX_LENGTH; i++) {
|
||||
memset_s(lines[i], BUFFER_SIZE, '\0', BUFFER_SIZE);
|
||||
}
|
||||
GetRuntimeInfoByPath(lines, realOutPath.c_str(), soBuildId);
|
||||
static char timestamp[TIME_STAMP_SIZE] = { '\0' };
|
||||
if (!GetMicrosecondsTimeStamp(timestamp)) {
|
||||
return;
|
||||
}
|
||||
std::vector<RuntimeInfoPart> lines = GetCrashRuntimeInfoList();
|
||||
uint64_t timestamp = GetMicrosecondsTimeStamp();
|
||||
RuntimeInfoPart buildLine = RuntimeInfoPart(soBuildId, std::to_string(timestamp), type);
|
||||
lines.emplace_back(buildLine);
|
||||
std::string realOutPath = GetCrashSandBoxRealPath();
|
||||
if (realOutPath == "") {
|
||||
LOG_ECMA(INFO) << "Get crash sanbox path fail.";
|
||||
|
||||
int lineCount = getLength(lines, MAX_LENGTH);
|
||||
if (lineCount < MAX_LENGTH) {
|
||||
if (!BuildRuntimeInfoPart(lines[lineCount], soBuildId, timestamp, type)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
SetRuntimeInfo(realOutPath.c_str(), lines);
|
||||
}
|
||||
|
||||
void BuildCrashRuntimeInfo(RuntimeInfoType type) const
|
||||
{
|
||||
static char soBuildId[NAME_MAX];
|
||||
if (!GetRuntimeBuildId(soBuildId)) {
|
||||
return;
|
||||
}
|
||||
if (IsCharEmpty(soBuildId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
static char lines[MAX_LENGTH][BUFFER_SIZE];
|
||||
for (int i = 0; i < MAX_LENGTH; i++) {
|
||||
memset_s(lines[i], BUFFER_SIZE, '\0', BUFFER_SIZE);
|
||||
}
|
||||
GetCrashRuntimeInfoList(lines);
|
||||
static char timestamp[TIME_STAMP_SIZE] = { '\0' };
|
||||
if (!GetMicrosecondsTimeStamp(timestamp)) {
|
||||
return;
|
||||
}
|
||||
int lineCount = getLength(lines, MAX_LENGTH);
|
||||
if (lineCount < MAX_LENGTH) {
|
||||
if (!BuildRuntimeInfoPart(lines[lineCount], soBuildId, timestamp, type)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
static char realOutPath[PATH_MAX];
|
||||
if (!GetCrashSandBoxRealPath(realOutPath)) {
|
||||
return;
|
||||
}
|
||||
if (IsCharEmpty(realOutPath)) {
|
||||
return;
|
||||
}
|
||||
SetRuntimeInfo(realOutPath, lines);
|
||||
@ -137,34 +150,47 @@ public:
|
||||
if (IsLoadedMap()) {
|
||||
return escapeMap_;
|
||||
}
|
||||
std::vector<RuntimeInfoPart> runtimeInfoParts;
|
||||
if (pgoRealPath == "") {
|
||||
runtimeInfoParts = GetCrashRuntimeInfoList();
|
||||
char lines[MAX_LENGTH][BUFFER_SIZE];
|
||||
if (IsCharEmpty(pgoRealPath.c_str())) {
|
||||
GetCrashRuntimeInfoList(lines);
|
||||
} else {
|
||||
runtimeInfoParts = GetRealPathRuntimeInfoList(pgoRealPath);
|
||||
GetRealPathRuntimeInfoList(lines, pgoRealPath);
|
||||
}
|
||||
for (const auto &runtimeInfoPart: runtimeInfoParts) {
|
||||
RuntimeInfoType runtimeInfoType = GetRuntimeInfoTypeByStr(runtimeInfoPart.type);
|
||||
escapeMap_[runtimeInfoType]++;
|
||||
char *typeChar = new char[NAME_MAX];
|
||||
for (int i = 0; i < MAX_LENGTH; i++) {
|
||||
if (lines[i][0] != '\0') {
|
||||
if (strcpy_s(typeChar, NAME_MAX, GetInfoFromBuffer(lines[i], RUNTIME_INDEX_TYPE)) !=0) {
|
||||
continue;
|
||||
}
|
||||
std::string typeStr(typeChar);
|
||||
escapeMap_[GetRuntimeInfoTypeByStr(typeStr)]++;
|
||||
}
|
||||
}
|
||||
SetLoadedMap(true);
|
||||
return escapeMap_;
|
||||
}
|
||||
|
||||
static std::string GetRuntimeInfoTypeStr(RuntimeInfoType type)
|
||||
const char *GetRuntimeInfoTypeStr(const RuntimeInfoType type) const
|
||||
{
|
||||
const std::map<RuntimeInfoType, const char *> strMap = {
|
||||
#define RUNTIME_INFO_TYPE_MAP(name) { RuntimeInfoType::name, #name },
|
||||
RUNTIME_INFO_TYPE(RUNTIME_INFO_TYPE_MAP)
|
||||
#undef RUNTIME_INFO_TYPE_MAP
|
||||
};
|
||||
if (strMap.count(type) > 0) {
|
||||
return strMap.at(type);
|
||||
switch (type) {
|
||||
case RuntimeInfoType::AOT_CRASH:
|
||||
return "AOT_CRASH";
|
||||
case RuntimeInfoType::JIT:
|
||||
return "JIT";
|
||||
case RuntimeInfoType::OTHERS:
|
||||
return "OTHERS";
|
||||
case RuntimeInfoType::NONE:
|
||||
return "NONE";
|
||||
case RuntimeInfoType::JS:
|
||||
return "JS";
|
||||
case RuntimeInfoType::AOT_BUILD:
|
||||
return "AOT_BUILD";
|
||||
default:
|
||||
return "NONE";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static RuntimeInfoType GetRuntimeInfoTypeByStr(std::string type)
|
||||
RuntimeInfoType GetRuntimeInfoTypeByStr(std::string &type) const
|
||||
{
|
||||
const std::map<std::string, RuntimeInfoType> strMap = {
|
||||
#define RUNTIME_INFO_TYPE_MAP(name) { #name, RuntimeInfoType::name },
|
||||
@ -177,149 +203,195 @@ public:
|
||||
return RuntimeInfoType::NONE;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<RuntimeInfoPart> GetCrashRuntimeInfoList() const
|
||||
virtual bool GetRuntimeBuildId(char *buildId) const
|
||||
{
|
||||
std::string realOutPath = GetCrashSandBoxRealPath();
|
||||
std::vector<RuntimeInfoPart> list;
|
||||
if (!FileExist(realOutPath.c_str())) {
|
||||
LOG_ECMA(INFO) << "Get crash sanbox path fail.";
|
||||
return list;
|
||||
}
|
||||
std::string soBuildId = GetRuntimeBuildId();
|
||||
if (soBuildId == "") {
|
||||
LOG_ECMA(INFO) << "can't get so buildId.";
|
||||
return list;
|
||||
}
|
||||
list = GetRuntimeInfoByPath(realOutPath, soBuildId);
|
||||
return list;
|
||||
}
|
||||
|
||||
std::vector<RuntimeInfoPart> GetRealPathRuntimeInfoList(const std::string &pgoRealPath) const
|
||||
{
|
||||
std::vector<RuntimeInfoPart> list;
|
||||
std::string realOutPath;
|
||||
std::string runtimePgoRealPath = pgoRealPath + OhosConstants::PATH_SEPARATOR +
|
||||
OhosConstants::AOT_RUNTIME_INFO_NAME;
|
||||
if (!ecmascript::RealPath(runtimePgoRealPath, realOutPath, false)) {
|
||||
return list;
|
||||
}
|
||||
if (!FileExist(realOutPath.c_str())) {
|
||||
LOG_ECMA(INFO) << "Get pgo real path fail.";
|
||||
return list;
|
||||
}
|
||||
std::string soBuildId = GetRuntimeBuildId();
|
||||
if (soBuildId == "") {
|
||||
LOG_ECMA(INFO) << "can't get so buildId.";
|
||||
return list;
|
||||
}
|
||||
list = GetRuntimeInfoByPath(realOutPath, soBuildId);
|
||||
return list;
|
||||
}
|
||||
|
||||
std::string GetRuntimeBuildId() const
|
||||
{
|
||||
std::string realPath;
|
||||
if (!FileExist(OhosConstants::RUNTIME_SO_PATH)) {
|
||||
return "";
|
||||
return false;
|
||||
}
|
||||
std::string soPath = panda::os::file::File::GetExtendedFilePath(OhosConstants::RUNTIME_SO_PATH);
|
||||
if (!ecmascript::RealPath(soPath, realPath, false)) {
|
||||
return "";
|
||||
static char realPath[PATH_MAX] = { '\0' };
|
||||
if (!ecmascript::RealPathByChar(OhosConstants::RUNTIME_SO_PATH, realPath, PATH_MAX, false)) {
|
||||
return false;
|
||||
}
|
||||
if (!FileExist(realPath.c_str())) {
|
||||
return "";
|
||||
if (!FileExist(realPath)) {
|
||||
return false;
|
||||
}
|
||||
ecmascript::MemMap fileMap = ecmascript::FileMap(realPath.c_str(), FILE_RDONLY, PAGE_PROT_READ);
|
||||
ecmascript::MemMap fileMap = ecmascript::FileMap(realPath, FILE_RDONLY, PAGE_PROT_READ);
|
||||
if (fileMap.GetOriginAddr() == nullptr) {
|
||||
LOG_ECMA(INFO) << "runtime info file mmap failed";
|
||||
return "";
|
||||
return false;
|
||||
}
|
||||
std::string buildId = ParseELFSectionsForBuildId(fileMap);
|
||||
ParseELFSectionsForBuildId(fileMap, buildId);
|
||||
ecmascript::FileUnMap(fileMap);
|
||||
fileMap.Reset();
|
||||
return buildId;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t GetMicrosecondsTimeStamp() const
|
||||
virtual bool GetMicrosecondsTimeStamp(char *timestamp) const
|
||||
{
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC, &time);
|
||||
return time.tv_sec * USEC_PER_SEC + time.tv_nsec / NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
void SetRuntimeInfo(const std::string &realOutPath, std::vector<RuntimeInfoPart> &runtimeInfoParts) const
|
||||
{
|
||||
std::ofstream file(realOutPath.c_str(), std::ofstream::out);
|
||||
JsonObjectBuilder objBuilder;
|
||||
auto arrayObject = [runtimeInfoParts](JsonArrayBuilder &arrayBuilder) {
|
||||
for (const auto &runtimeInfoPart : runtimeInfoParts) {
|
||||
auto addObj = [runtimeInfoPart](JsonObjectBuilder &obj) {
|
||||
obj.AddProperty(RUNTIME_KEY_BUILDID, runtimeInfoPart.buildId);
|
||||
obj.AddProperty(RUNTIME_KEY_TIMESTAMP, runtimeInfoPart.timestamp);
|
||||
obj.AddProperty(RUNTIME_KEY_TYPE, runtimeInfoPart.type);
|
||||
};
|
||||
arrayBuilder.Add(addObj);
|
||||
}
|
||||
};
|
||||
objBuilder.AddProperty(RUNTIME_INFO_ARRAY_KEY, arrayObject);
|
||||
if (file.is_open()) {
|
||||
file << std::move(objBuilder).Build();
|
||||
file.close();
|
||||
} else {
|
||||
LOG_ECMA(INFO) << "open file to set runtime info fail :" << realOutPath.c_str();
|
||||
time_t current_time;
|
||||
if (time(¤t_time) == -1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<RuntimeInfoPart> GetRuntimeInfoByPath(const std::string &realOutPath,
|
||||
const std::string &soBuildId) const
|
||||
{
|
||||
std::ifstream ifile(realOutPath.c_str());
|
||||
std::vector<RuntimeInfoPart> infoParts;
|
||||
if (ifile.is_open()) {
|
||||
std::string jsonStr((std::istreambuf_iterator<char>(ifile)), std::istreambuf_iterator<char>());
|
||||
JsonObject obj(jsonStr);
|
||||
if (obj.GetValue<JsonObject::ArrayT>(RUNTIME_INFO_ARRAY_KEY) == nullptr) {
|
||||
ifile.close();
|
||||
return infoParts;
|
||||
}
|
||||
auto &mainArray = *obj.GetValue<JsonObject::ArrayT>(RUNTIME_INFO_ARRAY_KEY);
|
||||
for (size_t i = 0; i < mainArray.size(); i++) {
|
||||
if (mainArray[i].Get<JsonObject::JsonObjPointer>() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto &innerObj = *(mainArray[i]).Get<JsonObject::JsonObjPointer>()->get();
|
||||
auto buildId = innerObj.GetValue<JsonObject::StringT>(RUNTIME_KEY_BUILDID);
|
||||
auto timestamp = innerObj.GetValue<JsonObject::StringT>(RUNTIME_KEY_TIMESTAMP);
|
||||
auto type = innerObj.GetValue<JsonObject::StringT>(RUNTIME_KEY_TYPE);
|
||||
if (buildId == nullptr || timestamp == nullptr || type == nullptr) {
|
||||
LOG_ECMA(INFO) << "runtime info get wrong json object info.";
|
||||
continue;
|
||||
}
|
||||
std::string buildIdStr = *buildId;
|
||||
if (buildIdStr != soBuildId) {
|
||||
continue;
|
||||
}
|
||||
infoParts.emplace_back(RuntimeInfoPart(*buildId, *timestamp, *type));
|
||||
}
|
||||
ifile.close();
|
||||
struct tm *local_time = localtime(¤t_time);
|
||||
if (local_time == NULL) {
|
||||
return false;
|
||||
}
|
||||
return infoParts;
|
||||
int result = strftime(timestamp, TIME_STAMP_SIZE, "%Y-%m-%d %H:%M:%S", local_time);
|
||||
if (result == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GetCrashSandBoxRealPath() const
|
||||
virtual bool GetCrashSandBoxRealPath(char *realOutPath) const
|
||||
{
|
||||
if (!ecmascript::RealPathByChar(OhosConstants::SANDBOX_ARK_PROFILE_PATH, realOutPath, PATH_MAX, false)) {
|
||||
return false;
|
||||
}
|
||||
if (strcat_s(realOutPath, NAME_MAX, OhosConstants::PATH_SEPARATOR) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (strcat_s(realOutPath, NAME_MAX, OhosConstants::AOT_RUNTIME_INFO_NAME) !=0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
protected:
|
||||
|
||||
bool IsCharEmpty(const char *value) const
|
||||
{
|
||||
if (value == NULL || *value == '\0') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BuildRuntimeInfoPart(char *runtimeInfoPart, const char *soBuildId, const char *timestamp,
|
||||
RuntimeInfoType type) const
|
||||
{
|
||||
if (strcat_s(runtimeInfoPart, NAME_MAX, soBuildId) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (strcat_s(runtimeInfoPart, NAME_MAX, OhosConstants::SPLIT_STR) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (strcat_s(runtimeInfoPart, NAME_MAX, timestamp) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (strcat_s(runtimeInfoPart, NAME_MAX, OhosConstants::SPLIT_STR) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (strcat_s(runtimeInfoPart, NAME_MAX, GetRuntimeInfoTypeStr(type)) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char *GetInfoFromBuffer(char *line, int index) const
|
||||
{
|
||||
char *saveptr;
|
||||
char buffer[BUFFER_SIZE];
|
||||
if (strncpy_s(buffer, BUFFER_SIZE - 1, line, sizeof(buffer) - 1) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
char *token = strtok_r(buffer, OhosConstants::SPLIT_STR, &saveptr);
|
||||
|
||||
for (int i = 0; i < index; i++) {
|
||||
token = strtok_r(NULL, OhosConstants::SPLIT_STR, &saveptr);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
int getLength(char lines[][BUFFER_SIZE], int maxInput) const
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < maxInput; i++) {
|
||||
if (lines[i][0] != '\0') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void GetCrashRuntimeInfoList(char lines[][BUFFER_SIZE]) const
|
||||
{
|
||||
static char realOutPath[PATH_MAX];
|
||||
if (!GetCrashSandBoxRealPath(realOutPath)) {
|
||||
return;
|
||||
}
|
||||
if (!FileExist(realOutPath)) {
|
||||
return;
|
||||
}
|
||||
static char soBuildId[NAME_MAX];
|
||||
if (!GetRuntimeBuildId(soBuildId)) {
|
||||
return;
|
||||
}
|
||||
if (IsCharEmpty(soBuildId)) {
|
||||
return;
|
||||
}
|
||||
GetRuntimeInfoByPath(lines, realOutPath, soBuildId);
|
||||
return;
|
||||
}
|
||||
|
||||
void GetRealPathRuntimeInfoList(char lines[][BUFFER_SIZE], const std::string &pgoRealPath) const
|
||||
{
|
||||
std::string realOutPath;
|
||||
std::string arkProfilePath = OhosConstants::SANDBOX_ARK_PROFILE_PATH;
|
||||
std::string sanboxPath = panda::os::file::File::GetExtendedFilePath(arkProfilePath);
|
||||
if (!ecmascript::RealPath(sanboxPath, realOutPath, false)) {
|
||||
return "";
|
||||
if (!ecmascript::RealPath(pgoRealPath, realOutPath, false)) {
|
||||
return;
|
||||
}
|
||||
realOutPath = realOutPath + OhosConstants::PATH_SEPARATOR + OhosConstants::AOT_RUNTIME_INFO_NAME;
|
||||
return realOutPath;
|
||||
if (!FileExist(realOutPath.c_str())) {
|
||||
return;
|
||||
}
|
||||
char soBuildId[NAME_MAX];
|
||||
if (!GetRuntimeBuildId(soBuildId)) {
|
||||
return;
|
||||
}
|
||||
if (IsCharEmpty(soBuildId)) {
|
||||
return;
|
||||
}
|
||||
GetRuntimeInfoByPath(lines, realOutPath.c_str(), soBuildId);
|
||||
}
|
||||
|
||||
std::string ParseELFSectionsForBuildId(ecmascript::MemMap &fileMap) const
|
||||
void SetRuntimeInfo(const char *realOutPath, char lines[][BUFFER_SIZE]) const
|
||||
{
|
||||
int fd = open(realOutPath, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (fd == -1) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; lines[i] != NULL && i < MAX_LENGTH; i++) {
|
||||
if (lines[i][0] != '\0') {
|
||||
write(fd, lines[i], strlen(lines[i]));
|
||||
write(fd, "\n", 1);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void GetRuntimeInfoByPath(char lines[][BUFFER_SIZE], const char *realOutPath, const char *soBuildId) const
|
||||
{
|
||||
int fd = open(realOutPath, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return;
|
||||
}
|
||||
char buffer[BUFFER_SIZE];
|
||||
char *saveptr;
|
||||
char *token;
|
||||
ssize_t bytesRead;
|
||||
int lineCount = 0;
|
||||
while ((bytesRead = read(fd, buffer, BUFFER_SIZE)) > 0) {
|
||||
token = strtok_r(buffer, "\n", &saveptr);
|
||||
while (token != NULL) {
|
||||
if (strcmp(GetInfoFromBuffer(token, RUNTIME_INDEX_BUILDID), soBuildId) == 0 &&
|
||||
lineCount < MAX_LENGTH &&
|
||||
strcpy_s(lines[lineCount], BUFFER_SIZE, buffer) == 0) {
|
||||
lineCount++;
|
||||
}
|
||||
token = strtok_r(NULL, "\n", &saveptr);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void ParseELFSectionsForBuildId(ecmascript::MemMap &fileMap, char *buildId) const
|
||||
{
|
||||
llvm::ELF::Elf64_Ehdr *ehdr = reinterpret_cast<llvm::ELF::Elf64_Ehdr *>(fileMap.GetOriginAddr());
|
||||
char *addr = reinterpret_cast<char *>(ehdr);
|
||||
@ -327,17 +399,17 @@ private:
|
||||
ASSERT(ehdr->e_shstrndx != static_cast<llvm::ELF::Elf64_Half>(-1));
|
||||
llvm::ELF::Elf64_Shdr strdr = shdr[ehdr->e_shstrndx];
|
||||
int secId = -1;
|
||||
std::string sectionName = ".note.gnu.build-id";
|
||||
static const char sectionName[] = ".note.gnu.build-id";
|
||||
for (size_t i = 0; i < ehdr->e_shnum; i++) {
|
||||
llvm::ELF::Elf64_Word shName = shdr[i].sh_name;
|
||||
char *curShName = reinterpret_cast<char *>(addr) + shName + strdr.sh_offset;
|
||||
if (sectionName.compare(curShName) == 0) {
|
||||
if (strcmp(sectionName, curShName) == 0) {
|
||||
secId = static_cast<int>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (secId == -1) {
|
||||
return "";
|
||||
return;
|
||||
}
|
||||
llvm::ELF::Elf64_Shdr secShdr = shdr[secId];
|
||||
uint64_t buildIdOffset = secShdr.sh_offset;
|
||||
@ -345,43 +417,37 @@ private:
|
||||
llvm::ELF::Elf64_Nhdr *nhdr = reinterpret_cast<llvm::ELF::Elf64_Nhdr *>(addr + buildIdOffset);
|
||||
char *curShNameForNhdr = reinterpret_cast<char *>(addr + buildIdOffset + sizeof(*nhdr));
|
||||
if (buildIdSize - sizeof(*nhdr) < nhdr->n_namesz) {
|
||||
return "";
|
||||
}
|
||||
std::string curShNameStr = curShNameForNhdr;
|
||||
if (curShNameStr.back() == '\0') {
|
||||
curShNameStr.resize(curShNameStr.size() - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (curShNameStr != "GNU" || nhdr->n_type != NT_GNU_BUILD_ID) {
|
||||
return "";
|
||||
static const char gnu[] = "GNU";
|
||||
if (strcmp(curShNameForNhdr, gnu) != 0 || nhdr->n_type != NT_GNU_BUILD_ID) {
|
||||
return;
|
||||
}
|
||||
if ((buildIdSize - sizeof(*nhdr) - AlignValues(nhdr->n_namesz, 4) < nhdr->n_descsz) || nhdr->n_descsz == 0) {
|
||||
return "";
|
||||
return;
|
||||
}
|
||||
|
||||
char *curShNameValueForNhdr = reinterpret_cast<char *>(addr + buildIdOffset + sizeof(*nhdr) +
|
||||
AlignValues(nhdr->n_namesz, 4));
|
||||
std::string curShNameValueForNhdrStr = curShNameValueForNhdr;
|
||||
return GetReadableBuildId(curShNameValueForNhdrStr);
|
||||
GetReadableBuildId(curShNameValueForNhdr, buildId);
|
||||
}
|
||||
|
||||
std::string GetReadableBuildId(std::string &buildIdHex) const
|
||||
void GetReadableBuildId(char *buildIdHex, char *buildId) const
|
||||
{
|
||||
if (buildIdHex.empty()) {
|
||||
return "";
|
||||
if (IsCharEmpty(buildIdHex)) {
|
||||
return;
|
||||
}
|
||||
static const char HEXTABLE[] = "0123456789abcdef";
|
||||
static const int HEXLENGTH = 16;
|
||||
static const int HEX_EXPAND_PARAM = 2;
|
||||
const size_t len = buildIdHex.length();
|
||||
std::string buildId(len * HEX_EXPAND_PARAM, '\0');
|
||||
const int len = strlen(buildIdHex);
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
unsigned int n = buildIdHex[i];
|
||||
buildId[i * HEX_EXPAND_PARAM] = HEXTABLE[(n >> 4) % HEXLENGTH]; // 4 : higher 4 bit of uint8
|
||||
buildId[i * HEX_EXPAND_PARAM + 1] = HEXTABLE[n % HEXLENGTH];
|
||||
}
|
||||
return buildId;
|
||||
}
|
||||
|
||||
uint64_t AlignValues(uint64_t val, uint64_t align) const
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "ecmascript/ohos/aot_runtime_info.h"
|
||||
#include "macros.h"
|
||||
|
||||
#ifdef AOT_ESCAPE_ENABLE
|
||||
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
|
||||
#include "parameters.h"
|
||||
#endif
|
||||
namespace panda::ecmascript::ohos {
|
||||
@ -74,7 +74,7 @@ public:
|
||||
|
||||
static bool GetAotBuildCountDisable()
|
||||
{
|
||||
#ifdef AOT_ESCAPE_ENABLE
|
||||
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
|
||||
return OHOS::system::GetBoolParameter(AOT_BUILD_COUNT_DISABLE, false);
|
||||
#endif
|
||||
return false;
|
||||
@ -85,8 +85,11 @@ public:
|
||||
if (!isCompileSuccess) {
|
||||
return;
|
||||
}
|
||||
ohos::AotRuntimeInfo::GetInstance().BuildCompileRuntimeInfo(
|
||||
ohos::AotRuntimeInfo::GetRuntimeInfoTypeStr(ohos::RuntimeInfoType::AOT_BUILD), pgoPath);
|
||||
std::string runtimePgoRealPath = pgoPath;
|
||||
runtimePgoRealPath.append(ohos::OhosConstants::PATH_SEPARATOR);
|
||||
runtimePgoRealPath.append(ohos::OhosConstants::AOT_RUNTIME_INFO_NAME);
|
||||
ohos::AotRuntimeInfo::GetInstance().BuildCompileRuntimeInfo(ohos::RuntimeInfoType::AOT_BUILD,
|
||||
runtimePgoRealPath);
|
||||
}
|
||||
|
||||
bool IsAotCompileSuccessOnce(const std::string &pgoRealPath = "") const
|
||||
|
@ -15,9 +15,9 @@
|
||||
#ifndef ECMASCRIPT_JIT_TOOLS_H
|
||||
#define ECMASCRIPT_JIT_TOOLS_H
|
||||
|
||||
#include "ecmascript/ohos/aot_crash_info.h"
|
||||
#include "ecmascript/ohos/enable_aot_list_helper.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
|
||||
#if defined(JIT_ESCAPE_ENABLE) || defined(GET_PARAMETER_FOR_JIT)
|
||||
#include "base/startup/init/interfaces/innerkits/include/syspara/parameters.h"
|
||||
|
@ -43,15 +43,52 @@ host_unittest_action("OhosTest") {
|
||||
external_deps += [ "zlib:libz" ]
|
||||
}
|
||||
|
||||
host_unittest_action("CrashTest") {
|
||||
module_out_path = module_output_path
|
||||
|
||||
sources = [
|
||||
# test file
|
||||
"crash_test.cpp",
|
||||
"mock/mock_aot_runtime_info.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
"$js_root:ecma_test_config",
|
||||
"$ark_root/assembler:arkassembler_public_config",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"$ark_third_party_root/icu/icu4c:shared_icui18n",
|
||||
"$ark_third_party_root/icu/icu4c:shared_icuuc",
|
||||
"$js_root:libark_jsruntime_test",
|
||||
"$js_root/ecmascript/compiler:libark_jsoptimizer_set",
|
||||
sdk_libc_secshared_dep,
|
||||
]
|
||||
|
||||
# hiviewdfx libraries
|
||||
external_deps = hiviewdfx_ext_deps
|
||||
deps += hiviewdfx_deps
|
||||
external_deps += [ "zlib:libz" ]
|
||||
}
|
||||
|
||||
group("unittest") {
|
||||
testonly = true
|
||||
deps = [ ":OhosTest" ]
|
||||
deps = [
|
||||
":CrashTest",
|
||||
":OhosTest",
|
||||
]
|
||||
}
|
||||
|
||||
group("host_unittest") {
|
||||
testonly = true
|
||||
deps = [ ":OhosTestAction" ]
|
||||
deps = [
|
||||
":CrashTestAction",
|
||||
":OhosTestAction",
|
||||
]
|
||||
if (is_mac) {
|
||||
deps -= [ ":OhosTestAction" ]
|
||||
deps -= [
|
||||
":CrashTestAction",
|
||||
":OhosTestAction",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
117
ecmascript/ohos/tests/crash_test.cpp
Normal file
117
ecmascript/ohos/tests/crash_test.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "ecmascript/napi/include/jsnapi.h"
|
||||
#include "ecmascript/ohos/aot_runtime_info.h"
|
||||
#include "ecmascript/ohos/tests/mock/mock_aot_runtime_info.h"
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
#include "ecmascript/platform/file.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
|
||||
using namespace panda;
|
||||
using namespace panda::ecmascript;
|
||||
using namespace panda::ecmascript::kungfu;
|
||||
|
||||
namespace panda::test {
|
||||
class CrashTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override {}
|
||||
void TearDown() override {}
|
||||
|
||||
MockAotRuntimeInfo mockAotRuntimeInfo;
|
||||
protected:
|
||||
EcmaVM *vm_ {nullptr};
|
||||
};
|
||||
|
||||
HWTEST_F_L0(CrashTest, CrashGetBuildId)
|
||||
{
|
||||
char soBuildId[NAME_MAX];
|
||||
ohos::AotRuntimeInfo *runtimeInfo = new MockAotRuntimeInfo();
|
||||
runtimeInfo->GetRuntimeBuildId(soBuildId);
|
||||
ASSERT_TRUE(std::string(soBuildId).size() > 0);
|
||||
ASSERT_EQ(std::string(soBuildId), "abcd1234567890");
|
||||
}
|
||||
|
||||
HWTEST_F_L0(CrashTest, GetMicrosecondsTimeStamp)
|
||||
{
|
||||
char timestamp[ohos::AotRuntimeInfo::TIME_STAMP_SIZE];
|
||||
ohos::AotRuntimeInfo *runtimeInfo = new MockAotRuntimeInfo();
|
||||
runtimeInfo->GetMicrosecondsTimeStamp(timestamp);
|
||||
ASSERT_TRUE(std::string(timestamp).size() > 0);
|
||||
ASSERT_EQ(std::string(timestamp), "1970-01-01 00:00:00");
|
||||
}
|
||||
|
||||
HWTEST_F_L0(CrashTest, BuildCrashRuntimeInfo)
|
||||
{
|
||||
char timestamp[ohos::AotRuntimeInfo::TIME_STAMP_SIZE];
|
||||
char soBuildId[NAME_MAX];
|
||||
ohos::AotRuntimeInfo *runtimeInfo = new MockAotRuntimeInfo();
|
||||
runtimeInfo->GetMicrosecondsTimeStamp(timestamp);
|
||||
runtimeInfo->GetRuntimeBuildId(soBuildId);
|
||||
char sanboxRealPath[PATH_MAX];
|
||||
mkdir(MockAotRuntimeInfo::SANBOX_DIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
std::ofstream file(sanboxRealPath);
|
||||
file.close();
|
||||
runtimeInfo->GetCrashSandBoxRealPath(sanboxRealPath);
|
||||
|
||||
runtimeInfo->BuildCrashRuntimeInfo(ecmascript::ohos::RuntimeInfoType::AOT_CRASH);
|
||||
std::map<ecmascript::ohos::RuntimeInfoType, int> escapeMap = runtimeInfo->CollectCrashSum();
|
||||
ASSERT_EQ(escapeMap[ecmascript::ohos::RuntimeInfoType::AOT_CRASH], 1);
|
||||
ASSERT_EQ(runtimeInfo->GetCompileCountByType(ecmascript::ohos::RuntimeInfoType::AOT_CRASH), 1);
|
||||
|
||||
unlink(sanboxRealPath);
|
||||
rmdir(MockAotRuntimeInfo::SANBOX_DIR);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(CrashTest, BuildCompileRuntimeInfo)
|
||||
{
|
||||
char timestamp[ohos::AotRuntimeInfo::TIME_STAMP_SIZE];
|
||||
char soBuildId[NAME_MAX];
|
||||
ohos::AotRuntimeInfo *runtimeInfo = new MockAotRuntimeInfo();
|
||||
runtimeInfo->GetMicrosecondsTimeStamp(timestamp);
|
||||
runtimeInfo->GetRuntimeBuildId(soBuildId);
|
||||
char sanboxRealPath[PATH_MAX];
|
||||
mkdir(MockAotRuntimeInfo::SANBOX_DIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
std::ofstream file(sanboxRealPath);
|
||||
file.close();
|
||||
runtimeInfo->GetCrashSandBoxRealPath(sanboxRealPath);
|
||||
|
||||
runtimeInfo->BuildCompileRuntimeInfo(ecmascript::ohos::RuntimeInfoType::AOT_CRASH, sanboxRealPath);
|
||||
std::map<ecmascript::ohos::RuntimeInfoType, int> escapeMapRealPath = runtimeInfo->CollectCrashSum(sanboxRealPath);
|
||||
ASSERT_EQ(escapeMapRealPath[ecmascript::ohos::RuntimeInfoType::AOT_CRASH], 1);
|
||||
ASSERT_EQ(runtimeInfo->GetCompileCountByType(ecmascript::ohos::RuntimeInfoType::AOT_CRASH, sanboxRealPath), 1);
|
||||
|
||||
unlink(sanboxRealPath);
|
||||
rmdir(MockAotRuntimeInfo::SANBOX_DIR);
|
||||
}
|
||||
} // namespace panda::test
|
60
ecmascript/ohos/tests/mock/mock_aot_runtime_info.cpp
Normal file
60
ecmascript/ohos/tests/mock/mock_aot_runtime_info.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/ohos/tests/mock/mock_aot_runtime_info.h"
|
||||
|
||||
namespace panda::test {
|
||||
MockAotRuntimeInfo::MockAotRuntimeInfo()
|
||||
{}
|
||||
MockAotRuntimeInfo::~MockAotRuntimeInfo()
|
||||
{}
|
||||
bool MockAotRuntimeInfo::GetRuntimeBuildId(char *buildId) const
|
||||
{
|
||||
char tmp[NAME_MAX] = "abcd1234567890";
|
||||
if (strcpy_s(buildId, NAME_MAX, tmp) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MockAotRuntimeInfo::GetMicrosecondsTimeStamp(char *timestamp) const
|
||||
{
|
||||
char tmp[ecmascript::ohos::AotRuntimeInfo::TIME_STAMP_SIZE] = "1970-01-01 00:00:00";
|
||||
if (strcpy_s(timestamp, ecmascript::ohos::AotRuntimeInfo::TIME_STAMP_SIZE, tmp) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MockAotRuntimeInfo::GetCrashSandBoxRealPath(char *realOutPath) const
|
||||
{
|
||||
if (strcpy_s(realOutPath, NAME_MAX, SANBOX_DIR) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (strcat_s(realOutPath, NAME_MAX, "/") != 0) {
|
||||
return false;
|
||||
}
|
||||
if (strcat_s(realOutPath, NAME_MAX, AOT_RUNTIME_INFO) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MockAotRuntimeInfo::BuildRuntimeInfoPart(char *runtimeInfoPart, const char *soBuildId, const char *timestamp,
|
||||
ecmascript::ohos::RuntimeInfoType type) const
|
||||
{
|
||||
return ecmascript::ohos::AotRuntimeInfo::BuildRuntimeInfoPart(runtimeInfoPart, soBuildId, timestamp, type);
|
||||
}
|
||||
};
|
39
ecmascript/ohos/tests/mock/mock_aot_runtime_info.h
Normal file
39
ecmascript/ohos/tests/mock/mock_aot_runtime_info.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MOCK_ECMASCRIPT_AOT_RUNTIME_INFO_H
|
||||
#define MOCK_ECMASCRIPT_AOT_RUNTIME_INFO_H
|
||||
|
||||
#include "ecmascript/ohos/aot_runtime_info.h"
|
||||
|
||||
namespace panda::test {
|
||||
class MockAotRuntimeInfo : public ecmascript::ohos::AotRuntimeInfo {
|
||||
public:
|
||||
static constexpr const char *SANBOX_DIR = "ohos-crash-test";
|
||||
static constexpr const char *AOT_RUNTIME_INFO = "aot_runtime_info.log";
|
||||
|
||||
MockAotRuntimeInfo();
|
||||
~MockAotRuntimeInfo();
|
||||
|
||||
bool GetRuntimeBuildId(char *buildId) const override;
|
||||
bool GetMicrosecondsTimeStamp(char *timestamp) const override;
|
||||
bool GetCrashSandBoxRealPath(char *realOutPath) const override;
|
||||
|
||||
bool BuildRuntimeInfoPart(char *runtimeInfoPart, const char *soBuildId, const char *timestamp,
|
||||
ecmascript::ohos::RuntimeInfoType type) const;
|
||||
void SetRuntimeInfo(const char *realOutPath, char lines[][BUFFER_SIZE]) const;
|
||||
};
|
||||
}; // namespace panda::test
|
||||
#endif // MOCK_ECMASCRIPT_AOT_RUNTIME_INFO_H
|
65
ecmascript/platform/aot_crash_info.h
Normal file
65
ecmascript/platform/aot_crash_info.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_PLATFORM_AOT_RUNTIME_INFO_H
|
||||
#define ECMASCRIPT_PLATFORM_AOT_RUNTIME_INFO_H
|
||||
|
||||
#include <signal.h>
|
||||
#include <string>
|
||||
|
||||
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
|
||||
#include "ecmascript/dfx/stackinfo/js_stackinfo.h"
|
||||
#include "ecmascript/ohos/ohos_pkg_args.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "llvm/BinaryFormat/ELF.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
#ifdef JIT_ESCAPE_ENABLE
|
||||
void GetSignalHandler(int signal, siginfo_t *info, void *context);
|
||||
void SignalReg(int signo);
|
||||
#endif
|
||||
void SignalAllReg();
|
||||
|
||||
using AotCompilerPreprocessor = kungfu::AotCompilerPreprocessor;
|
||||
class AotCrashInfo {
|
||||
constexpr static const char *const AOT_ESCAPE_DISABLE = "ark.aot.escape.disable";
|
||||
constexpr static int AOT_CRASH_COUNT = 1;
|
||||
constexpr static int OTHERS_CRASH_COUNT = 3;
|
||||
constexpr static int JIT_CRASH_COUNT = 1;
|
||||
constexpr static int JS_CRASH_COUNT = 3;
|
||||
public:
|
||||
explicit AotCrashInfo() = default;
|
||||
virtual ~AotCrashInfo() = default;
|
||||
|
||||
static AotCrashInfo &GetInstance()
|
||||
{
|
||||
static AotCrashInfo singleAotCrashInfo;
|
||||
return singleAotCrashInfo;
|
||||
}
|
||||
|
||||
bool IsAotEscapedOrNotInEnableList(EcmaVM *vm, const std::string &bundleName) const;
|
||||
void SetOptionPGOProfiler(JSRuntimeOptions *options, const std::string &bundleName) const;
|
||||
bool PUBLIC_API IsAotEscapedOrCompiledOnce(AotCompilerPreprocessor &cPreprocessor, int32_t &ret) const;
|
||||
static bool PUBLIC_API IsAotEscaped(const std::string &pgoRealPath = "");
|
||||
static bool IsJitEscape();
|
||||
static bool GetAotEscapeDisable();
|
||||
static std::string GetSandBoxPath();
|
||||
static int GetAotCrashCount();
|
||||
static int GetJitCrashCount();
|
||||
static int GetJsCrashCount();
|
||||
static int GetOthersCrashCount();
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_PLATFORM_AOT_RUNTIME_INFO_H
|
@ -66,6 +66,7 @@ using fd_t = int;
|
||||
std::string PUBLIC_API GetFileDelimiter();
|
||||
std::string PUBLIC_API GetPathSeparator();
|
||||
bool PUBLIC_API RealPath(const std::string &path, std::string &realPath, bool readOnly = true);
|
||||
bool PUBLIC_API RealPathByChar(const char *path, char *realPath, int rowLength, bool readOnly);
|
||||
void DPrintf(fd_t fd, const std::string &buffer);
|
||||
void Close(fd_t fd);
|
||||
void FSync(fd_t fd);
|
||||
|
172
ecmascript/platform/unix/aot_crash_info.cpp
Normal file
172
ecmascript/platform/unix/aot_crash_info.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
#include "ecmascript/ohos/enable_aot_list_helper.h"
|
||||
#include "ecmascript/ohos/aot_runtime_info.h"
|
||||
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
|
||||
#include "parameters.h"
|
||||
#endif
|
||||
|
||||
namespace panda::ecmascript {
|
||||
#ifdef JIT_ESCAPE_ENABLE
|
||||
static struct sigaction s_oldSa[SIGSYS + 1]; // SIGSYS = 31
|
||||
void GetSignalHandler(int signal, siginfo_t *info, void *context)
|
||||
{
|
||||
(void)context;
|
||||
#if defined(__aarch64__) && !defined(PANDA_TARGET_MACOS) && !defined(PANDA_TARGET_IOS)
|
||||
ucontext_t *ucontext = static_cast<ucontext_t*>(context);
|
||||
uintptr_t fp = ucontext->uc_mcontext.regs[29];
|
||||
FrameIterator frame(reinterpret_cast<JSTaggedType *>(fp));
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false, frame.GetFrameType());
|
||||
#else
|
||||
ecmascript::JsStackInfo::BuildCrashInfo(false);
|
||||
#endif
|
||||
sigaction(signal, &s_oldSa[signal], nullptr);
|
||||
int rc = syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), info->si_signo, info);
|
||||
if (rc != 0) {
|
||||
LOG_ECMA(ERROR) << "GetSignalHandler() failed to resend signal during crash";
|
||||
}
|
||||
}
|
||||
|
||||
void SignalReg(int signo)
|
||||
{
|
||||
sigaction(signo, nullptr, &s_oldSa[signo]);
|
||||
struct sigaction newAction;
|
||||
newAction.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
newAction.sa_sigaction = GetSignalHandler;
|
||||
sigaction(signo, &newAction, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SignalAllReg()
|
||||
{
|
||||
#ifdef JIT_ESCAPE_ENABLE
|
||||
SignalReg(SIGABRT);
|
||||
SignalReg(SIGBUS);
|
||||
SignalReg(SIGSEGV);
|
||||
SignalReg(SIGILL);
|
||||
SignalReg(SIGKILL);
|
||||
SignalReg(SIGSTKFLT);
|
||||
SignalReg(SIGFPE);
|
||||
SignalReg(SIGTRAP);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool AotCrashInfo::IsAotEscapedOrNotInEnableList(EcmaVM *vm, const std::string &bundleName) const
|
||||
{
|
||||
if (!vm->GetJSOptions().WasAOTOutputFileSet() &&
|
||||
!ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
|
||||
LOG_ECMA(INFO) << "Stop load AOT because it's not in enable list";
|
||||
return true;
|
||||
}
|
||||
if (IsAotEscaped()) {
|
||||
LOG_ECMA(INFO) << "Stop load AOT because there are more crashes";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AotCrashInfo::IsAotEscapedOrCompiledOnce(AotCompilerPreprocessor &cPreprocessor, int32_t &ret) const
|
||||
{
|
||||
if (!cPreprocessor.GetMainPkgArgs()) {
|
||||
return false;
|
||||
}
|
||||
std::string pgoRealPath = cPreprocessor.GetMainPkgArgs()->GetPgoDir();
|
||||
pgoRealPath.append(ohos::OhosConstants::PATH_SEPARATOR);
|
||||
pgoRealPath.append(ohos::OhosConstants::AOT_RUNTIME_INFO_NAME);
|
||||
if (ohos::EnableAotJitListHelper::GetInstance()->IsAotCompileSuccessOnce(pgoRealPath)) {
|
||||
ret = 0;
|
||||
LOG_ECMA(INFO) << "Aot has compile success once or escaped.";
|
||||
return true;
|
||||
}
|
||||
if (IsAotEscaped(pgoRealPath)) {
|
||||
ret = -1;
|
||||
LOG_ECMA(INFO) << "Aot has escaped";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AotCrashInfo::SetOptionPGOProfiler(JSRuntimeOptions *options, const std::string &bundleName) const
|
||||
{
|
||||
#ifdef AOT_ESCAPE_ENABLE
|
||||
if (ohos::EnableAotJitListHelper::GetInstance()->IsEnableAot(bundleName)) {
|
||||
options->SetEnablePGOProfiler(true);
|
||||
}
|
||||
if (ohos::EnableAotJitListHelper::GetInstance()->IsAotCompileSuccessOnce() || IsAotEscaped()) {
|
||||
options->SetEnablePGOProfiler(false);
|
||||
LOG_ECMA(INFO) << "Aot has compile success once or escaped.";
|
||||
}
|
||||
#endif
|
||||
(void)options;
|
||||
(void)bundleName;
|
||||
}
|
||||
|
||||
bool AotCrashInfo::IsAotEscaped(const std::string &pgoRealPath)
|
||||
{
|
||||
if (AotCrashInfo::GetAotEscapeDisable()) {
|
||||
return false;
|
||||
}
|
||||
auto escapeMap = ohos::AotRuntimeInfo::GetInstance().CollectCrashSum(pgoRealPath);
|
||||
return escapeMap[ohos::RuntimeInfoType::AOT_CRASH] >= AotCrashInfo::GetAotCrashCount() ||
|
||||
escapeMap[ohos::RuntimeInfoType::OTHERS] >= AotCrashInfo::GetOthersCrashCount() ||
|
||||
escapeMap[ohos::RuntimeInfoType::JS] >= AotCrashInfo::GetJsCrashCount();
|
||||
}
|
||||
|
||||
bool AotCrashInfo::IsJitEscape()
|
||||
{
|
||||
auto escapeMap = ohos::AotRuntimeInfo::GetInstance().CollectCrashSum();
|
||||
return escapeMap[ohos::RuntimeInfoType::JIT] >= AotCrashInfo::GetJitCrashCount() ||
|
||||
escapeMap[ohos::RuntimeInfoType::AOT_CRASH] >= AotCrashInfo::GetAotCrashCount() ||
|
||||
escapeMap[ohos::RuntimeInfoType::OTHERS] >= AotCrashInfo::GetOthersCrashCount() ||
|
||||
escapeMap[ohos::RuntimeInfoType::JS] >= AotCrashInfo::GetJsCrashCount();
|
||||
}
|
||||
|
||||
bool AotCrashInfo::GetAotEscapeDisable()
|
||||
{
|
||||
#if defined(PANDA_TARGET_OHOS) && !defined(STANDALONE_MODE)
|
||||
return OHOS::system::GetBoolParameter(AOT_ESCAPE_DISABLE, false);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string AotCrashInfo::GetSandBoxPath()
|
||||
{
|
||||
return ohos::OhosConstants::SANDBOX_ARK_PROFILE_PATH;
|
||||
}
|
||||
|
||||
int AotCrashInfo::GetAotCrashCount()
|
||||
{
|
||||
return AOT_CRASH_COUNT;
|
||||
}
|
||||
|
||||
int AotCrashInfo::GetJitCrashCount()
|
||||
{
|
||||
return JIT_CRASH_COUNT;
|
||||
}
|
||||
|
||||
int AotCrashInfo::GetJsCrashCount()
|
||||
{
|
||||
return JS_CRASH_COUNT;
|
||||
}
|
||||
|
||||
int AotCrashInfo::GetOthersCrashCount()
|
||||
{
|
||||
return OTHERS_CRASH_COUNT;
|
||||
}
|
||||
|
||||
} // namespace panda::ecmascript
|
@ -58,6 +58,28 @@ bool RealPath(const std::string &path, std::string &realPath, bool readOnly)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RealPathByChar(const char *path, char *realPath, int rowLength, bool readOnly)
|
||||
{
|
||||
if (strlen(path) == 0 || strlen(path) > PATH_MAX) {
|
||||
return false;
|
||||
}
|
||||
char buffer[PATH_MAX] = { '\0' };
|
||||
if (!realpath(path, buffer)) {
|
||||
// Maybe file does not exist.
|
||||
if (!readOnly && errno == ENOENT) {
|
||||
if (strcpy_s(realPath, rowLength, path) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (strcpy_s(realPath, rowLength, buffer) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DPrintf(fd_t fd, const std::string &buffer)
|
||||
{
|
||||
int ret = dprintf(fd, "%s", buffer.c_str());
|
||||
|
97
ecmascript/platform/windows/aot_crash_info.cpp
Normal file
97
ecmascript/platform/windows/aot_crash_info.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/platform/aot_crash_info.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
#ifdef JIT_ESCAPE_ENABLE
|
||||
void GetSignalHandler(int signal, siginfo_t *info, void *context)
|
||||
{
|
||||
(void)signal;
|
||||
(void)info;
|
||||
(void)context;
|
||||
}
|
||||
|
||||
void SignalReg(int signo)
|
||||
{
|
||||
(void)signo;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SignalAllReg()
|
||||
{
|
||||
}
|
||||
|
||||
bool AotCrashInfo::IsAotEscapedOrNotInEnableList(EcmaVM *vm, const std::string &bundleName) const
|
||||
{
|
||||
(void)vm;
|
||||
(void)bundleName;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AotCrashInfo::IsAotEscapedOrCompiledOnce(AotCompilerPreprocessor &cPreprocessor, int32_t &ret) const
|
||||
{
|
||||
(void)cPreprocessor;
|
||||
(void)ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
void AotCrashInfo::SetOptionPGOProfiler(JSRuntimeOptions *options, const std::string &bundleName) const
|
||||
{
|
||||
(void)options;
|
||||
(void)bundleName;
|
||||
}
|
||||
|
||||
bool AotCrashInfo::IsAotEscaped(const std::string &pgoRealPath)
|
||||
{
|
||||
(void)pgoRealPath;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AotCrashInfo::IsJitEscape()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AotCrashInfo::GetAotEscapeDisable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string AotCrashInfo::GetSandBoxPath()
|
||||
{
|
||||
return ohos::OhosConstants::SANDBOX_ARK_PROFILE_PATH;
|
||||
}
|
||||
|
||||
int AotCrashInfo::GetAotCrashCount()
|
||||
{
|
||||
return AOT_CRASH_COUNT;
|
||||
}
|
||||
|
||||
int AotCrashInfo::GetJitCrashCount()
|
||||
{
|
||||
return JIT_CRASH_COUNT;
|
||||
}
|
||||
|
||||
int AotCrashInfo::GetJsCrashCount()
|
||||
{
|
||||
return JS_CRASH_COUNT;
|
||||
}
|
||||
|
||||
int AotCrashInfo::GetOthersCrashCount()
|
||||
{
|
||||
return OTHERS_CRASH_COUNT;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -66,6 +66,15 @@ bool RealPath(const std::string &path, std::string &realPath, [[maybe_unused]] b
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RealPathByChar(const char *path, char *realPath, int rowLength, bool readOnly)
|
||||
{
|
||||
(void)path;
|
||||
(void)realPath;
|
||||
(void)rowLength;
|
||||
(void)readOnly;
|
||||
return false;
|
||||
}
|
||||
|
||||
void DPrintf(fd_t fd, const std::string &buffer)
|
||||
{
|
||||
LOG_ECMA(DEBUG) << "Unsupport dprintf fd(" << fd << ") in windows, buffer:" << buffer;
|
||||
|
@ -88,6 +88,7 @@
|
||||
panda::JsiFastNativeScope::*;
|
||||
panda::JSExecutionScope::*;
|
||||
|
||||
panda::ecmascript::AotCrashInfo*;
|
||||
panda::ecmascript::Log::*;
|
||||
panda::ecmascript::AndroidLog*;
|
||||
panda::ecmascript::Method::*;
|
||||
|
@ -722,6 +722,11 @@
|
||||
<option name="push" value="test/test/libark_jsruntime_test.so -> /data/test" src="out"/>
|
||||
</preparer>
|
||||
</target>
|
||||
<target name="CrashTest">
|
||||
<preparer>
|
||||
<option name="push" value="test/test/libark_jsruntime_test.so -> /data/test" src="out"/>
|
||||
</preparer>
|
||||
</target>
|
||||
<target name="PGOProfilerTest">
|
||||
<preparer>
|
||||
<option name="push" value="test/test/libark_jsruntime_test.so -> /data/test" src="out"/>
|
||||
|
Loading…
Reference in New Issue
Block a user