14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_DFX_STACKINFO_JS_STACKINFO_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_DFX_STACKINFO_JS_STACKINFO_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <csignal> 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/aot_file/aot_file_manager.h" 214514f5e3Sopenharmony_ci#include "ecmascript/extractortool/src/source_map.h" 224514f5e3Sopenharmony_ci#include "ecmascript/frames.h" 234514f5e3Sopenharmony_ci#include "ecmascript/js_thread.h" 244514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/js_pandafile_manager.h" 254514f5e3Sopenharmony_ci#include "ecmascript/dfx/dump_code/jit_dump_elf.h" 264514f5e3Sopenharmony_ci#if defined(PANDA_TARGET_OHOS) 274514f5e3Sopenharmony_ci#include "ecmascript/extractortool/src/zip_file.h" 284514f5e3Sopenharmony_ci#endif 294514f5e3Sopenharmony_ci 304514f5e3Sopenharmony_cinamespace panda::ecmascript { 314514f5e3Sopenharmony_citypedef bool (*ReadMemFunc)(void *ctx, uintptr_t addr, uintptr_t *val); 324514f5e3Sopenharmony_cibool ArkFrameCheck(uintptr_t frameType); 334514f5e3Sopenharmony_cibool IsJsFunctionFrame(uintptr_t frameType); 344514f5e3Sopenharmony_cibool IsNativeFunctionFrame(uintptr_t frameType); 354514f5e3Sopenharmony_cibool IsAotFunctionFrame(uintptr_t frameType); 364514f5e3Sopenharmony_cibool IsFastJitFunctionFrame(uintptr_t frameType); 374514f5e3Sopenharmony_cibool IsFastJitFunctionFrame(const FrameType frameType); 384514f5e3Sopenharmony_citemplate<typename T> 394514f5e3Sopenharmony_civoid ParseJsFrameInfo(JSPandaFile *jsPandaFile, DebugInfoExtractor *debugExtractor, 404514f5e3Sopenharmony_ci EntityId methodId, uintptr_t offset, T &jsFrame, SourceMap *sourceMap = nullptr); 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_ci 434514f5e3Sopenharmony_cistatic constexpr uint16_t URL_MAX = 1024; 444514f5e3Sopenharmony_cistatic constexpr uint16_t FUNCTIONNAME_MAX = 1024; 454514f5e3Sopenharmony_ci 464514f5e3Sopenharmony_cistruct JsFrameInfo { 474514f5e3Sopenharmony_ci std::string functionName; 484514f5e3Sopenharmony_ci std::string fileName; 494514f5e3Sopenharmony_ci std::string pos; 504514f5e3Sopenharmony_ci uintptr_t *nativePointer = nullptr; 514514f5e3Sopenharmony_ci}; 524514f5e3Sopenharmony_ci 534514f5e3Sopenharmony_cistruct JsFunction { 544514f5e3Sopenharmony_ci char functionName[FUNCTIONNAME_MAX]; 554514f5e3Sopenharmony_ci char url[URL_MAX]; 564514f5e3Sopenharmony_ci int32_t line; 574514f5e3Sopenharmony_ci int32_t column; 584514f5e3Sopenharmony_ci uintptr_t codeBegin; 594514f5e3Sopenharmony_ci uintptr_t codeSize; 604514f5e3Sopenharmony_ci}; 614514f5e3Sopenharmony_ci 624514f5e3Sopenharmony_cistruct MethodInfo { 634514f5e3Sopenharmony_ci uintptr_t methodId; 644514f5e3Sopenharmony_ci uintptr_t codeBegin; 654514f5e3Sopenharmony_ci uint32_t codeSize; 664514f5e3Sopenharmony_ci MethodInfo(uintptr_t methodId, uintptr_t codeBegin, uint32_t codeSize) 674514f5e3Sopenharmony_ci : methodId(methodId), codeBegin(codeBegin), codeSize(codeSize) {} 684514f5e3Sopenharmony_ci friend bool operator<(const MethodInfo &lhs, const MethodInfo &rhs) 694514f5e3Sopenharmony_ci { 704514f5e3Sopenharmony_ci return lhs.codeBegin < rhs.codeBegin; 714514f5e3Sopenharmony_ci } 724514f5e3Sopenharmony_ci}; 734514f5e3Sopenharmony_ci 744514f5e3Sopenharmony_cistruct CodeInfo { 754514f5e3Sopenharmony_ci uintptr_t offset; 764514f5e3Sopenharmony_ci uintptr_t methodId; 774514f5e3Sopenharmony_ci uint32_t codeSize; 784514f5e3Sopenharmony_ci CodeInfo(uintptr_t offset, uintptr_t methodId, uint32_t codeSize) 794514f5e3Sopenharmony_ci : offset(offset), methodId(methodId), codeSize(codeSize) {} 804514f5e3Sopenharmony_ci}; 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_cistruct JsFrameDebugInfo { 834514f5e3Sopenharmony_ci EntityId methodId; 844514f5e3Sopenharmony_ci uint32_t offset; 854514f5e3Sopenharmony_ci std::string hapPath; 864514f5e3Sopenharmony_ci std::string filePath; 874514f5e3Sopenharmony_ci JsFrameDebugInfo(EntityId methodId, uint32_t offset, std::string &hapPath, std::string &filePath) 884514f5e3Sopenharmony_ci : methodId(methodId), offset(offset), hapPath(hapPath), filePath(filePath) {} 894514f5e3Sopenharmony_ci}; 904514f5e3Sopenharmony_ci 914514f5e3Sopenharmony_cistruct ArkUnwindParam { 924514f5e3Sopenharmony_ci void *ctx; 934514f5e3Sopenharmony_ci ReadMemFunc readMem; 944514f5e3Sopenharmony_ci uintptr_t *fp; 954514f5e3Sopenharmony_ci uintptr_t *sp; 964514f5e3Sopenharmony_ci uintptr_t *pc; 974514f5e3Sopenharmony_ci uintptr_t *methodId; 984514f5e3Sopenharmony_ci bool *isJsFrame; 994514f5e3Sopenharmony_ci std::vector<uintptr_t> &jitCache; 1004514f5e3Sopenharmony_ci ArkUnwindParam(void *ctx, ReadMemFunc readMem, uintptr_t *fp, uintptr_t *sp, uintptr_t *pc, uintptr_t *methodId, 1014514f5e3Sopenharmony_ci bool *isJsFrame, std::vector<uintptr_t> &jitCache) 1024514f5e3Sopenharmony_ci : ctx(ctx), readMem(readMem), fp(fp), sp(sp), pc(pc), methodId(methodId), 1034514f5e3Sopenharmony_ci isJsFrame(isJsFrame), jitCache(jitCache) {} 1044514f5e3Sopenharmony_ci}; 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_cistruct JsFrame { 1074514f5e3Sopenharmony_ci char functionName[FUNCTIONNAME_MAX]; 1084514f5e3Sopenharmony_ci char url[URL_MAX]; 1094514f5e3Sopenharmony_ci int32_t line; 1104514f5e3Sopenharmony_ci int32_t column; 1114514f5e3Sopenharmony_ci}; 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_ciclass JSStackTrace { 1144514f5e3Sopenharmony_cipublic: 1154514f5e3Sopenharmony_ci JSStackTrace() = default; 1164514f5e3Sopenharmony_ci ~JSStackTrace(); 1174514f5e3Sopenharmony_ci static JSStackTrace *GetInstance(); 1184514f5e3Sopenharmony_ci static std::optional<MethodInfo> ReadMethodInfo(panda_file::MethodDataAccessor &mda); 1194514f5e3Sopenharmony_ci static CVector<MethodInfo> ReadAllMethodInfos(std::shared_ptr<JSPandaFile> jsPandaFile); 1204514f5e3Sopenharmony_ci static std::optional<CodeInfo> TranslateByteCodePc(uintptr_t realPc, const CVector<MethodInfo> &vec); 1214514f5e3Sopenharmony_ci bool GetJsFrameInfo(uintptr_t byteCodePc, uintptr_t methodId, uintptr_t mapBase, 1224514f5e3Sopenharmony_ci uintptr_t loadOffset, JsFunction *jsFunction); 1234514f5e3Sopenharmony_ci static void Destory(); 1244514f5e3Sopenharmony_ciprivate: 1254514f5e3Sopenharmony_ci bool AddMethodInfos(uintptr_t mapBase); 1264514f5e3Sopenharmony_ci 1274514f5e3Sopenharmony_ci CVector<MethodInfo> methodInfo_; 1284514f5e3Sopenharmony_ci std::unordered_map<uintptr_t, std::shared_ptr<JSPandaFile>> jsPandaFiles_; 1294514f5e3Sopenharmony_ci std::unordered_map<uintptr_t, CVector<MethodInfo>> methodInfos_; 1304514f5e3Sopenharmony_ci static JSStackTrace *trace_; 1314514f5e3Sopenharmony_ci static std::mutex mutex_; 1324514f5e3Sopenharmony_ci}; 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ciclass JSSymbolExtractor { 1354514f5e3Sopenharmony_cipublic: 1364514f5e3Sopenharmony_ci JSSymbolExtractor() = default; 1374514f5e3Sopenharmony_ci ~JSSymbolExtractor(); 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ci static JSSymbolExtractor* Create(); 1404514f5e3Sopenharmony_ci static bool Destory(JSSymbolExtractor* extractor); 1414514f5e3Sopenharmony_ci 1424514f5e3Sopenharmony_ci void CreateJSPandaFile(); 1434514f5e3Sopenharmony_ci void CreateJSPandaFile(uint8_t *data, size_t dataSize); 1444514f5e3Sopenharmony_ci void CreateSourceMap(const std::string &hapPath); 1454514f5e3Sopenharmony_ci void CreateSourceMap(uint8_t *data, size_t dataSize); 1464514f5e3Sopenharmony_ci void CreateDebugExtractor(); 1474514f5e3Sopenharmony_ci bool ParseHapFileData(std::string& hapName); 1484514f5e3Sopenharmony_ci 1494514f5e3Sopenharmony_ci uint8_t* GetData(); 1504514f5e3Sopenharmony_ci uintptr_t GetLoadOffset(); 1514514f5e3Sopenharmony_ci uintptr_t GetDataSize(); 1524514f5e3Sopenharmony_ci 1534514f5e3Sopenharmony_ci JSPandaFile* GetJSPandaFile(uint8_t *data = nullptr, size_t dataSize = 0); 1544514f5e3Sopenharmony_ci DebugInfoExtractor* GetDebugExtractor(); 1554514f5e3Sopenharmony_ci SourceMap* GetSourceMap(uint8_t *data = nullptr, size_t dataSize = 0); 1564514f5e3Sopenharmony_ci CVector<MethodInfo> GetMethodInfos(); 1574514f5e3Sopenharmony_ci 1584514f5e3Sopenharmony_ciprivate: 1594514f5e3Sopenharmony_ci CVector<MethodInfo> methodInfo_; 1604514f5e3Sopenharmony_ci uintptr_t loadOffset_ {0}; 1614514f5e3Sopenharmony_ci uintptr_t dataSize_ {0}; 1624514f5e3Sopenharmony_ci uint8_t* data_ {nullptr}; 1634514f5e3Sopenharmony_ci std::shared_ptr<JSPandaFile> jsPandaFile_ {nullptr}; 1644514f5e3Sopenharmony_ci std::unique_ptr<DebugInfoExtractor> debugExtractor_ {nullptr}; 1654514f5e3Sopenharmony_ci std::shared_ptr<SourceMap> sourceMap_ {nullptr}; 1664514f5e3Sopenharmony_ci}; 1674514f5e3Sopenharmony_ci 1684514f5e3Sopenharmony_ciclass JsStackInfo { 1694514f5e3Sopenharmony_ciprivate: 1704514f5e3Sopenharmony_ci struct LastBuilderCache { 1714514f5e3Sopenharmony_ci const JSPandaFile *pf{nullptr}; 1724514f5e3Sopenharmony_ci DebugInfoExtractor *extractor{nullptr}; 1734514f5e3Sopenharmony_ci }; 1744514f5e3Sopenharmony_cipublic: 1754514f5e3Sopenharmony_ci static std::string BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets); 1764514f5e3Sopenharmony_ci static inline std::string BuildJsStackTrace(JSThread *thread, bool needNative) 1774514f5e3Sopenharmony_ci { 1784514f5e3Sopenharmony_ci // If jsErrorObj not be pass in, MachineCode object of its stack frame while not be keep alive 1794514f5e3Sopenharmony_ci JSHandle<JSObject> jsErrorObj; 1804514f5e3Sopenharmony_ci return BuildJsStackTrace(thread, needNative, jsErrorObj); 1814514f5e3Sopenharmony_ci } 1824514f5e3Sopenharmony_ci static std::string BuildJsStackTrace(JSThread *thread, bool needNative, const JSHandle<JSObject> &jsErrorObj); 1834514f5e3Sopenharmony_ci static std::vector<JsFrameInfo> BuildJsStackInfo(JSThread *thread, bool currentStack = false); 1844514f5e3Sopenharmony_ci static std::string BuildMethodTrace(Method *method, uint32_t pcOffset, LastBuilderCache &lastCache, 1854514f5e3Sopenharmony_ci bool enableStackSourceFile = true); 1864514f5e3Sopenharmony_ci static AOTFileManager *loader; 1874514f5e3Sopenharmony_ci static JSRuntimeOptions *options; 1884514f5e3Sopenharmony_ci static void BuildCrashInfo(bool isJsCrash, uintptr_t pc = 0, JSThread *thread = nullptr); 1894514f5e3Sopenharmony_ci static inline void BuildCrashInfo(JSThread *thread) 1904514f5e3Sopenharmony_ci { 1914514f5e3Sopenharmony_ci BuildCrashInfo(true, 0, thread); // pc is useless for JsCrash, pass 0 as placeholder 1924514f5e3Sopenharmony_ci } 1934514f5e3Sopenharmony_ci static std::unordered_map<EntityId, std::string> nameMap; 1944514f5e3Sopenharmony_ci static std::unordered_map<EntityId, std::vector<uint8>> machineCodeMap; 1954514f5e3Sopenharmony_ci static void DumpJitCode(JSThread *thread); 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ciprivate: 1984514f5e3Sopenharmony_ci static std::string BuildJsStackTraceInfo(JSThread *thread, Method *method, FrameIterator &it, 1994514f5e3Sopenharmony_ci uint32_t pcOffset, const JSHandle<JSObject> &jsErrorObj, 2004514f5e3Sopenharmony_ci LastBuilderCache &lastCache); 2014514f5e3Sopenharmony_ci static constexpr int32_t InitialLength = 50; 2024514f5e3Sopenharmony_ci static constexpr int32_t InitialDeeps = 5; 2034514f5e3Sopenharmony_ci}; 2044514f5e3Sopenharmony_ci} // namespace panda::ecmascript 2054514f5e3Sopenharmony_ci#endif // ECMASCRIPT_DFX_STACKINFO_JS_STACKINFO_H 2064514f5e3Sopenharmony_ciextern "C" int ark_parse_js_frame_info( 2074514f5e3Sopenharmony_ci uintptr_t byteCodePc, uintptr_t methodId, uintptr_t mapBase, uintptr_t loadOffset, uint8_t *data, 2084514f5e3Sopenharmony_ci uint64_t dataSize, uintptr_t extractorptr, panda::ecmascript::JsFunction *jsFunction); 2094514f5e3Sopenharmony_ciextern "C" int ark_translate_js_frame_info( 2104514f5e3Sopenharmony_ci uint8_t *data, size_t dataSize, panda::ecmascript::JsFunction *jsFunction); 2114514f5e3Sopenharmony_ciextern "C" int step_ark_with_record_jit(panda::ecmascript::ArkUnwindParam *arkUnwindParam); 2124514f5e3Sopenharmony_ciextern "C" int ark_write_jit_code( 2134514f5e3Sopenharmony_ci void *ctx, panda::ecmascript::ReadMemFunc readMem, int fd, const uintptr_t *const jitCodeArray, 2144514f5e3Sopenharmony_ci const size_t jitSize); 2154514f5e3Sopenharmony_ciextern "C" int step_ark( 2164514f5e3Sopenharmony_ci void *ctx, panda::ecmascript::ReadMemFunc readMem, uintptr_t *fp, uintptr_t *sp, 2174514f5e3Sopenharmony_ci uintptr_t *pc, uintptr_t *methodId, bool *isJsFrame); 2184514f5e3Sopenharmony_ciextern "C" int ark_create_js_symbol_extractor(uintptr_t *extractorptr); 2194514f5e3Sopenharmony_ciextern "C" int ark_destory_js_symbol_extractor(uintptr_t extractorptr); 2204514f5e3Sopenharmony_ciextern "C" int ark_parse_js_file_info( 2214514f5e3Sopenharmony_ci uintptr_t byteCodePc, uintptr_t methodId, uintptr_t mapBase, const char* filePath, uintptr_t extractorptr, 2224514f5e3Sopenharmony_ci panda::ecmascript::JsFunction *jsFunction); 2234514f5e3Sopenharmony_ciextern "C" int get_ark_native_frame_info( 2244514f5e3Sopenharmony_ci int pid, uintptr_t *pc, uintptr_t *fp, uintptr_t *sp, panda::ecmascript::JsFrame *jsFrame, size_t &size); 2254514f5e3Sopenharmony_ciextern "C" int ark_parse_js_frame_info_local(uintptr_t byteCodePc, uintptr_t methodId, uintptr_t mapBase, 2264514f5e3Sopenharmony_ci uintptr_t loadOffset, panda::ecmascript::JsFunction *jsFunction); 2274514f5e3Sopenharmony_ciextern "C" int ark_destory_local(); 2284514f5e3Sopenharmony_ci// define in dfx_signal_handler.h 2294514f5e3Sopenharmony_citypedef void(*ThreadInfoCallback)(char *buf, size_t len, void *ucontext); 2304514f5e3Sopenharmony_ciextern "C" void SetThreadInfoCallback(ThreadInfoCallback func) __attribute__((weak));