mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
支持hiperf ark帧解析
issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I8VCJK Signed-off-by: shaoyijiang <shaoyijiang@huawei.com> Change-Id: Ic0fa1ecdc04d7e17ed40d720c67e53937458f742
This commit is contained in:
parent
5212133062
commit
507096fd28
2
BUILD.gn
2
BUILD.gn
@ -656,6 +656,7 @@ ecma_source = [
|
||||
"ecmascript/ecma_vm.cpp",
|
||||
"ecmascript/element_accessor.cpp",
|
||||
"ecmascript/elements.cpp",
|
||||
"ecmascript/extractortool/src/source_map.cpp",
|
||||
"ecmascript/frames.cpp",
|
||||
"ecmascript/free_object.cpp",
|
||||
"ecmascript/generator_helper.cpp",
|
||||
@ -900,7 +901,6 @@ ecma_stackinfo_source = [
|
||||
"ecmascript/extractortool/src/extractor.cpp",
|
||||
"ecmascript/extractortool/src/file_mapper.cpp",
|
||||
"ecmascript/extractortool/src/file_path_utils.cpp",
|
||||
"ecmascript/extractortool/src/source_map.cpp",
|
||||
"ecmascript/extractortool/src/zip_file_reader_io.cpp",
|
||||
"ecmascript/extractortool/src/zip_file_reader_mem.cpp",
|
||||
"ecmascript/extractortool/src/zip_file_reader.cpp",
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "ecmascript/dfx/stackinfo/js_stackinfo.h"
|
||||
#include "ecmascript/base/builtins_base.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/extractortool/src/source_map.h"
|
||||
#include "ecmascript/interpreter/frame_handler.h"
|
||||
#include "ecmascript/interpreter/interpreter.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
@ -25,7 +26,6 @@
|
||||
#include "ecmascript/platform/os.h"
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
#include "ecmascript/extractortool/src/extractor.h"
|
||||
#include "ecmascript/extractortool/src/source_map.h"
|
||||
#endif
|
||||
#if defined(ENABLE_EXCEPTION_BACKTRACE)
|
||||
#include "ecmascript/platform/backtrace.h"
|
||||
@ -379,6 +379,240 @@ bool GetTypeOffsetAndPrevOffsetFromFrameType(uintptr_t frameType, uintptr_t &typ
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArkFrameCheck(uintptr_t frameType)
|
||||
{
|
||||
return static_cast<FrameType>(frameType) == FrameType::OPTIMIZED_ENTRY_FRAME ||
|
||||
static_cast<FrameType>(frameType) == FrameType::ASM_INTERPRETER_ENTRY_FRAME;
|
||||
}
|
||||
|
||||
bool IsFunctionFrame(uintptr_t frameType)
|
||||
{
|
||||
// ato need stackmaps, the pc value is not set.
|
||||
// FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
|
||||
// FrameType::OPTIMIZED_JS_FUNCTION_FRAME:
|
||||
return static_cast<FrameType>(frameType) == FrameType::ASM_INTERPRETER_FRAME ||
|
||||
static_cast<FrameType>(frameType) == FrameType::INTERPRETER_CONSTRUCTOR_FRAME ||
|
||||
static_cast<FrameType>(frameType) == FrameType::INTERPRETER_FRAME ||
|
||||
static_cast<FrameType>(frameType) == FrameType::INTERPRETER_FAST_NEW_FRAME;
|
||||
}
|
||||
|
||||
std::optional<MethodInfo> ReadMethodInfo(panda_file::MethodDataAccessor &mda)
|
||||
{
|
||||
uintptr_t methodId = mda.GetMethodId().GetOffset();
|
||||
auto codeId = mda.GetCodeId();
|
||||
if (!codeId) {
|
||||
return std::nullopt;
|
||||
}
|
||||
panda_file::CodeDataAccessor cda(mda.GetPandaFile(), codeId.value());
|
||||
uint32_t codeSize = cda.GetCodeSize();
|
||||
uintptr_t codeBegin = reinterpret_cast<uintptr_t>(cda.GetInstructions());
|
||||
return std::make_optional<MethodInfo>(methodId, codeBegin, codeSize);
|
||||
}
|
||||
|
||||
std::vector<MethodInfo> ReadAllMethodInfos(std::shared_ptr<JSPandaFile> jsPandaFile)
|
||||
{
|
||||
std::vector<MethodInfo> result;
|
||||
const panda_file::File *pf = jsPandaFile->GetPandaFile();
|
||||
Span<const uint32_t> classIndexes = jsPandaFile->GetClasses();
|
||||
for (const uint32_t index : classIndexes) {
|
||||
panda_file::File::EntityId classId(index);
|
||||
if (jsPandaFile->IsExternal(classId)) {
|
||||
continue;
|
||||
}
|
||||
panda_file::ClassDataAccessor cda(*pf, classId);
|
||||
cda.EnumerateMethods([&result, jsPandaFile](panda_file::MethodDataAccessor &mda) {
|
||||
auto info = ReadMethodInfo(mda);
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
result.push_back(info.value());
|
||||
});
|
||||
}
|
||||
|
||||
std::sort(result.begin(), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<CodeInfo> TranslateByteCodePc(uintptr_t realPc, const std::vector<MethodInfo> &vec)
|
||||
{
|
||||
uint32_t left = 0;
|
||||
uint32_t right = vec.size() - 1;
|
||||
for (; left <= right;) {
|
||||
uint32_t mid = (left + right) / 2;
|
||||
bool isRight = realPc >= (vec[mid].codeBegin + vec[mid].codeSize);
|
||||
bool isLeft = realPc < vec[mid].codeBegin;
|
||||
// codeBegin <= realPc < codeBegin + codeSize
|
||||
if (!isRight && !isLeft) {
|
||||
return std::make_optional<CodeInfo>(realPc - vec[mid].codeBegin, vec[mid].methodId, vec[mid].codeSize);
|
||||
} else if (isRight) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid -1;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool ArkParseJsFrameInfo(uintptr_t byteCodePc, uintptr_t mapBase, uintptr_t loadOffset,
|
||||
uint8_t *data, uint64_t dataSize, JsFunction *jsFunction)
|
||||
{
|
||||
loadOffset = loadOffset % PageSize();
|
||||
auto pf = panda_file::OpenPandaFileFromSecureMemory(data, dataSize);
|
||||
CString fileName = "";
|
||||
std::shared_ptr<JSPandaFile> jsPandaFile = std::make_shared<JSPandaFile>(pf.release(), fileName);
|
||||
auto methodInfos = ReadAllMethodInfos(jsPandaFile);
|
||||
uintptr_t realOffset = byteCodePc - mapBase - loadOffset;
|
||||
uintptr_t pfBasePtr = reinterpret_cast<uintptr_t>(jsPandaFile->GetBase());
|
||||
auto codeInfo = TranslateByteCodePc(realOffset + pfBasePtr, methodInfos);
|
||||
if (!codeInfo) {
|
||||
return false;
|
||||
}
|
||||
auto methodId = EntityId(codeInfo.value().methodId);
|
||||
std::string name = MethodLiteral::ParseFunctionName(jsPandaFile.get(), methodId);
|
||||
name = name.empty() ? "anonymous" : name;
|
||||
|
||||
auto debugExtractor = std::make_unique<DebugInfoExtractor>(jsPandaFile.get());
|
||||
std::string url = debugExtractor->GetSourceFile(methodId);
|
||||
auto offset = codeInfo.value().offset;
|
||||
// line number and column number
|
||||
int lineNumber = 0;
|
||||
int columnNumber = 0;
|
||||
auto callbackLineFunc = [&lineNumber](int32_t line) -> bool {
|
||||
lineNumber = line + 1;
|
||||
return true;
|
||||
};
|
||||
auto callbackColumnFunc = [&columnNumber](int32_t column) -> bool {
|
||||
columnNumber = column + 1;
|
||||
return true;
|
||||
};
|
||||
if (!debugExtractor->MatchLineWithOffset(callbackLineFunc, methodId, offset) ||
|
||||
!debugExtractor->MatchColumnWithOffset(callbackColumnFunc, methodId, offset)) {
|
||||
lineNumber = 0;
|
||||
columnNumber = 0;
|
||||
}
|
||||
|
||||
jsFunction->codeBegin = byteCodePc - offset;
|
||||
jsFunction->codeSize = codeInfo.value().codeSize;
|
||||
jsFunction->line = lineNumber;
|
||||
jsFunction->column = columnNumber;
|
||||
size_t nameSize = name.size() + 1;
|
||||
size_t urlSize = url.size() + 1;
|
||||
if (strcpy_s(jsFunction->functionName, nameSize, name.c_str()) != EOK ||
|
||||
strcpy_s(jsFunction->url, urlSize, url.c_str()) != EOK) {
|
||||
LOG_FULL(FATAL) << "strcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArkTranslateJsFrameInfo(uint8_t *data, size_t dataSize, [[maybe_unused]]JsFunction *jsFunction)
|
||||
{
|
||||
SourceMap sourceMap;
|
||||
std::string strUrl = jsFunction->url;
|
||||
sourceMap.Init(data, dataSize, strUrl);
|
||||
bool ret = sourceMap.TranslateUrlPositionBySourceMap(strUrl, jsFunction->line, jsFunction->column);
|
||||
size_t strUrlSize = strUrl.size() + 1;
|
||||
if (strcpy_s(jsFunction->url, strUrlSize, strUrl.c_str()) != EOK) {
|
||||
LOG_FULL(FATAL) << "strcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uintptr_t GetBytecodeOffset(void *ctx, ReadMemFunc readMem, uintptr_t frameType, uintptr_t currentPtr)
|
||||
{
|
||||
// currentPtr points to the frametype.
|
||||
uintptr_t bytecodePc = 0;
|
||||
FrameType type = static_cast<FrameType>(frameType);
|
||||
switch (type) {
|
||||
case FrameType::ASM_INTERPRETER_FRAME:
|
||||
case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
|
||||
currentPtr -= AsmInterpretedFrame::GetTypeOffset();
|
||||
currentPtr += AsmInterpretedFrame::GetPcOffset(false);
|
||||
readMem(ctx, currentPtr, &bytecodePc);
|
||||
return bytecodePc;
|
||||
}
|
||||
case FrameType::INTERPRETER_FRAME:
|
||||
case FrameType::INTERPRETER_FAST_NEW_FRAME: {
|
||||
currentPtr -= InterpretedFrame::GetTypeOffset();
|
||||
currentPtr += InterpretedFrame::GetPcOffset(false);
|
||||
readMem(ctx, currentPtr, &bytecodePc);
|
||||
return bytecodePc;
|
||||
}
|
||||
// aot need stackmaps
|
||||
case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ArkGetNextFrame(void *ctx, ReadMemFunc readMem, uintptr_t ¤tPtr, uintptr_t &frameType, uintptr_t &pc)
|
||||
{
|
||||
currentPtr -= sizeof(FrameType);
|
||||
if (!readMem(ctx, currentPtr, &frameType)) {
|
||||
return false;
|
||||
}
|
||||
if (ArkFrameCheck(frameType)) {
|
||||
return true;
|
||||
}
|
||||
bool ret = false;
|
||||
if (IsFunctionFrame(frameType)) {
|
||||
pc = GetBytecodeOffset(ctx, readMem, frameType, currentPtr);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
uintptr_t typeOffset = 0;
|
||||
uintptr_t prevOffset = 0;
|
||||
if (!GetTypeOffsetAndPrevOffsetFromFrameType(frameType, typeOffset, prevOffset)) {
|
||||
return false;
|
||||
}
|
||||
currentPtr -= typeOffset;
|
||||
currentPtr += prevOffset;
|
||||
if (!readMem(ctx, currentPtr, ¤tPtr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
return true;
|
||||
}
|
||||
return ArkGetNextFrame(ctx, readMem, currentPtr, frameType, pc);
|
||||
}
|
||||
|
||||
bool StepArk(void *ctx, ReadMemFunc readMem, uintptr_t *fp, uintptr_t *sp, uintptr_t *pc, bool *isJsFrame)
|
||||
{
|
||||
constexpr size_t FP_SIZE = 8;
|
||||
constexpr size_t LR_SIZE = 8;
|
||||
uintptr_t currentPtr = *fp;
|
||||
if (currentPtr == 0) {
|
||||
LOG_ECMA(ERROR) << "fp is nullptr in StepArk()!";
|
||||
return false;
|
||||
}
|
||||
|
||||
uintptr_t frameType = 0;
|
||||
if (ArkGetNextFrame(ctx, readMem, currentPtr, frameType, *pc)) {
|
||||
if (ArkFrameCheck(frameType)) {
|
||||
currentPtr += sizeof(FrameType);
|
||||
bool ret = readMem(ctx, currentPtr, fp);
|
||||
currentPtr += FP_SIZE;
|
||||
ret &= readMem(ctx, currentPtr, pc);
|
||||
currentPtr += LR_SIZE;
|
||||
ret &= readMem(ctx, currentPtr, sp);
|
||||
*isJsFrame = false;
|
||||
return ret;
|
||||
} else {
|
||||
*fp = currentPtr;
|
||||
*sp = currentPtr;
|
||||
*isJsFrame = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
uintptr_t ArkGetFunction(int pid, uintptr_t currentPtr, uintptr_t frameType)
|
||||
{
|
||||
@ -740,12 +974,6 @@ bool ArkGetNextFrame(uintptr_t ¤tPtr, uintptr_t typeOffset,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArkFrameCheck(uintptr_t frameType)
|
||||
{
|
||||
return static_cast<FrameType>(frameType) == FrameType::OPTIMIZED_ENTRY_FRAME ||
|
||||
static_cast<FrameType>(frameType) == FrameType::ASM_INTERPRETER_ENTRY_FRAME;
|
||||
}
|
||||
|
||||
bool GetArkNativeFrameInfo(int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp,
|
||||
panda::ecmascript::JsFrame *jsFrame, size_t &size)
|
||||
{
|
||||
@ -1010,6 +1238,34 @@ bool GetArkJSHeapCrashInfo(int pid, uintptr_t *bytecodePc, uintptr_t *fp, bool o
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
__attribute__((visibility("default"))) int step_ark(
|
||||
void *ctx, panda::ecmascript::ReadMemFunc readMem, uintptr_t *fp, uintptr_t *sp, uintptr_t *pc, bool *isJsFrame)
|
||||
{
|
||||
if (panda::ecmascript::StepArk(ctx, readMem, fp, sp, pc, isJsFrame)) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) int ark_parse_js_frame_info(
|
||||
uintptr_t byteCodePc, uintptr_t mapBase, uintptr_t loadOffset, uint8_t *data,
|
||||
uint64_t dataSize, panda::ecmascript::JsFunction *jsFunction)
|
||||
{
|
||||
if (panda::ecmascript::ArkParseJsFrameInfo(byteCodePc, mapBase, loadOffset, data, dataSize, jsFunction)) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) int ark_translate_js_frame_info(
|
||||
uint8_t *data, size_t dataSize, panda::ecmascript::JsFunction *jsFunction)
|
||||
{
|
||||
if (panda::ecmascript::ArkTranslateJsFrameInfo(data, dataSize, jsFunction)) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) int step_ark_managed_native_frame(
|
||||
int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz)
|
||||
{
|
||||
|
@ -20,12 +20,12 @@
|
||||
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
|
||||
#include "ecmascript/js_thread.h"
|
||||
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
constexpr uint16_t URL_MAX = 1024;
|
||||
constexpr uint16_t FUNCTIONNAME_MAX = 1024;
|
||||
#endif
|
||||
|
||||
namespace panda::ecmascript {
|
||||
typedef bool (*ReadMemFunc)(void *ctx, uintptr_t addr, uintptr_t *val);
|
||||
|
||||
static constexpr uint16_t URL_MAX = 1024;
|
||||
static constexpr uint16_t FUNCTIONNAME_MAX = 1024;
|
||||
|
||||
struct JsFrameInfo {
|
||||
std::string functionName;
|
||||
std::string fileName;
|
||||
@ -33,10 +33,33 @@ struct JsFrameInfo {
|
||||
uintptr_t *nativePointer = nullptr;
|
||||
};
|
||||
|
||||
struct JsFrameParam {
|
||||
std::string PandaFileName;
|
||||
panda_file::File::EntityId methodId;
|
||||
uint32_t byteCodeOffset;
|
||||
struct JsFunction {
|
||||
char functionName[FUNCTIONNAME_MAX];
|
||||
char url[URL_MAX];
|
||||
int32_t line;
|
||||
int32_t column;
|
||||
uintptr_t codeBegin;
|
||||
uintptr_t codeSize;
|
||||
};
|
||||
|
||||
struct MethodInfo {
|
||||
uintptr_t methodId;
|
||||
uintptr_t codeBegin;
|
||||
uint32_t codeSize;
|
||||
MethodInfo(uintptr_t methodId, uintptr_t codeBegin, uint32_t codeSize)
|
||||
: methodId(methodId), codeBegin(codeBegin), codeSize(codeSize) {}
|
||||
friend bool operator<(const MethodInfo &lhs, const MethodInfo &rhs)
|
||||
{
|
||||
return lhs.codeBegin < rhs.codeBegin;
|
||||
}
|
||||
};
|
||||
|
||||
struct CodeInfo {
|
||||
uintptr_t offset;
|
||||
uintptr_t methodId;
|
||||
uint32_t codeSize;
|
||||
CodeInfo(uintptr_t offset, uintptr_t methodId, uint32_t codeSize)
|
||||
: offset(offset), methodId(methodId), codeSize(codeSize) {}
|
||||
};
|
||||
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
@ -63,6 +86,13 @@ extern "C" int step_ark_managed_native_frame(
|
||||
int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, char *buf, size_t buf_sz);
|
||||
extern "C" int get_ark_js_heap_crash_info(
|
||||
int pid, uintptr_t *x20, uintptr_t *fp, int out_js_info, char *buf, size_t buf_sz);
|
||||
extern "C" int ark_parse_js_frame_info(
|
||||
uintptr_t byteCodePc, uintptr_t mapBase, uintptr_t loadOffset, uint8_t *data, uint64_t dataSize,
|
||||
panda::ecmascript::JsFunction *jsFunction);
|
||||
extern "C" int ark_translate_js_frame_info(
|
||||
uint8_t *data, size_t dataSize, panda::ecmascript::JsFunction *jsFunction);
|
||||
extern "C" int step_ark(
|
||||
void *ctx, panda::ecmascript::ReadMemFunc readMem, uintptr_t *fp, uintptr_t *sp, uintptr_t *pc, bool *isJsFrame);
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
extern "C" int get_ark_native_frame_info(
|
||||
int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, panda::ecmascript::JsFrame *jsFrame, size_t &size);
|
||||
|
@ -47,6 +47,7 @@ constexpr int32_t DIGIT_NUM = 64;
|
||||
const std::string MEGER_SOURCE_MAP_PATH = "ets/sourceMaps.map";
|
||||
} // namespace
|
||||
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
bool SourceMap::ReadSourceMapData(const std::string& hapPath, std::string& content)
|
||||
{
|
||||
if (hapPath.empty()) {
|
||||
@ -66,6 +67,7 @@ bool SourceMap::ReadSourceMapData(const std::string& hapPath, std::string& conte
|
||||
content.assign(dataPtr.get(), dataPtr.get() + len);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t StringToInt(const std::string& value)
|
||||
{
|
||||
@ -100,6 +102,7 @@ uint32_t Base64CharToInt(char charCode)
|
||||
return DIGIT_NUM;
|
||||
};
|
||||
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
void SourceMap::Init(const std::string& url, const std::string& hapPath)
|
||||
{
|
||||
std::string sourceMapData;
|
||||
@ -107,6 +110,14 @@ void SourceMap::Init(const std::string& url, const std::string& hapPath)
|
||||
SplitSourceMap(url, sourceMapData);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void SourceMap::Init(uint8_t *data, size_t dataSize, const std::string& url)
|
||||
{
|
||||
std::string content;
|
||||
content.assign(data, data + dataSize);
|
||||
SplitSourceMap(url, content);
|
||||
}
|
||||
|
||||
void SourceMap::SplitSourceMap(const std::string& url, const std::string& sourceMapData)
|
||||
{
|
||||
|
@ -68,7 +68,10 @@ public:
|
||||
SourceMap() = default;
|
||||
~SourceMap() = default;
|
||||
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
void Init(const std::string& url, const std::string& hapPath);
|
||||
#endif
|
||||
void Init(uint8_t *data, size_t dataSize, const std::string& url);
|
||||
bool TranslateUrlPositionBySourceMap(std::string& url, int& line, int& column);
|
||||
static void ExtractStackInfo(const std::string& stackStr, std::vector<std::string>& res);
|
||||
|
||||
@ -81,8 +84,9 @@ private:
|
||||
MappingInfo Find(int32_t row, int32_t col, const SourceMapData& targetMap, const std::string& key);
|
||||
void GetPosInfo(const std::string& temp, int32_t start, std::string& line, std::string& column);
|
||||
bool GetLineAndColumnNumbers(int& line, int& column, SourceMapData& targetMap, std::string& key);
|
||||
#if defined(PANDA_TARGET_OHOS)
|
||||
bool ReadSourceMapData(const std::string& hapPath, std::string& content);
|
||||
|
||||
#endif
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<SourceMapData>> sourceMaps_;
|
||||
};
|
||||
|
@ -347,6 +347,9 @@
|
||||
get_ark_js_heap_crash_info;
|
||||
step_ark_managed_native_frame;
|
||||
get_ark_native_frame_info;
|
||||
ark_parse_js_frame_info;
|
||||
ark_translate_js_frame_info;
|
||||
step_ark;
|
||||
};
|
||||
local:
|
||||
*;
|
||||
|
Loading…
Reference in New Issue
Block a user