From 20061ee7bddf411c80fbbc7e6bd6e663f92352e7 Mon Sep 17 00:00:00 2001 From: dong-bosi123 Date: Mon, 8 Sep 2025 21:44:50 +0800 Subject: [PATCH] fix the dfxoffline parse js bug Signed-off-by: dong-bosi123 --- .../innerkits/unwinder/include/dfx_hap.h | 5 +- .../unwinder/include/dfx_offline_parser.h | 4 +- .../innerkits/unwinder/src/ark/dfx_hap.cpp | 46 ++++++++- .../unwinder/src/utils/dfx_offline_parser.cpp | 95 ++++++------------- test/unittest/unwind/dfx_hap_test.cpp | 45 +++++++++ tools/dump_catcher/main.cpp | 2 +- 6 files changed, 125 insertions(+), 72 deletions(-) diff --git a/interfaces/innerkits/unwinder/include/dfx_hap.h b/interfaces/innerkits/unwinder/include/dfx_hap.h index 82147c511..104488e44 100644 --- a/interfaces/innerkits/unwinder/include/dfx_hap.h +++ b/interfaces/innerkits/unwinder/include/dfx_hap.h @@ -30,8 +30,8 @@ public: DfxHap() = default; ~DfxHap(); - bool ParseHapInfo(pid_t pid, uint64_t pc, std::shared_ptr map, JsFunction *jsFunction); - + bool ParseHapInfo(pid_t pid, uint64_t pc, std::shared_ptr map, JsFunction *jsFunction, + bool isOffline = false); private: bool ParseHapFileInfo(uint64_t pc, std::shared_ptr map, JsFunction *jsFunction); bool ParseHapMemInfo(pid_t pid, uint64_t pc, std::shared_ptr map, @@ -39,6 +39,7 @@ private: bool ParseHapFileData(const std::string& name); bool ParseHapMemData(const pid_t pid, std::shared_ptr map); + bool ParseHapMemInfoForOffline(const std::string& mapName, uint64_t relPc, JsFunction *jsFunction); private: MAYBE_UNUSED uintptr_t arkSymbolExtractorPtr_ = 0; diff --git a/interfaces/innerkits/unwinder/include/dfx_offline_parser.h b/interfaces/innerkits/unwinder/include/dfx_offline_parser.h index c73978f95..160d40333 100644 --- a/interfaces/innerkits/unwinder/include/dfx_offline_parser.h +++ b/interfaces/innerkits/unwinder/include/dfx_offline_parser.h @@ -33,13 +33,11 @@ private: static bool IsJsFrame(const DfxFrame& frame); bool ParseNativeSymbol(DfxFrame& frame); bool ParseJsSymbol(DfxFrame& frame); - bool ParseJsSymbolForArkHap(const DfxFrame& frame, JsFunction& jsFunction); - bool ParseJsSymbolForArkCode(const DfxFrame& frame, JsFunction& jsFunction); std::string GetBundlePath(const std::string& originPath) const; std::shared_ptr GetElfForFrame(const DfxFrame& frame); + std::shared_ptr GetMapForFrame(const DfxFrame& frame); bool CachedEnableMiniDebugInfo_ {false}; bool CachedEnableLoadSymbolLazily_ {false}; - uintptr_t arkSymbolExtractorPtr_ {0}; std::string bundleName_ {""}; std::shared_ptr dfxMaps_ {nullptr}; }; diff --git a/interfaces/innerkits/unwinder/src/ark/dfx_hap.cpp b/interfaces/innerkits/unwinder/src/ark/dfx_hap.cpp index b817de836..d0f3b766c 100644 --- a/interfaces/innerkits/unwinder/src/ark/dfx_hap.cpp +++ b/interfaces/innerkits/unwinder/src/ark/dfx_hap.cpp @@ -15,6 +15,8 @@ #include "dfx_hap.h" +#include + #include "dfx_define.h" #include "dfx_log.h" #include "dfx_maps.h" @@ -41,7 +43,7 @@ DfxHap::~DfxHap() #endif } -bool DfxHap::ParseHapInfo(pid_t pid, uint64_t pc, std::shared_ptr map, JsFunction *jsFunction) +bool DfxHap::ParseHapInfo(pid_t pid, uint64_t pc, std::shared_ptr map, JsFunction *jsFunction, bool isOffline) { #if is_ohos && !is_mingw if (jsFunction == nullptr || map == nullptr) { @@ -62,10 +64,14 @@ bool DfxHap::ParseHapInfo(pid_t pid, uint64_t pc, std::shared_ptr map, J return false; } } else if (DfxMaps::IsArkCodeMapItem(map->name)) { - if (!ParseHapMemInfo(pid, pc, map, jsFunction)) { + if (!isOffline && !ParseHapMemInfo(pid, pc, map, jsFunction)) { DFXLOGW("Failed to parse hap mem info"); return false; } + if (isOffline && !ParseHapMemInfoForOffline(map->name, pc, jsFunction)) { + DFXLOGW("Failed to parse hap mem info for offline"); + return false; + } } return true; #else @@ -73,6 +79,42 @@ bool DfxHap::ParseHapInfo(pid_t pid, uint64_t pc, std::shared_ptr map, J #endif } +bool DfxHap::ParseHapMemInfoForOffline(const std::string& mapName, uint64_t relPc, JsFunction *jsFunction) +{ +#if is_ohos && !is_mingw + if (jsFunction == nullptr || mapName.empty()) { + return false; + } + SmartFd smartFd(open(mapName.c_str(), O_RDONLY)); + if (!smartFd) { + DFXLOGE("Failed to open file: %{public}s, errno(%{public}d)", mapName.c_str(), errno); + return false; + } + off_t size = lseek(smartFd.GetFd(), 0, SEEK_END); + if (size <= 0) { + DFXLOGE("fd is empty or error, fd(%{public}d)", smartFd.GetFd()); + return false; + } + void* mptr = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, smartFd.GetFd(), 0); + if (mptr == MAP_FAILED) { + DFXLOGE("mmap failed, fd(%{public}d), errno(%{public}d)", smartFd.GetFd(), errno); + return false; + } + bool isSuccess = DfxArk::Instance().ParseArkFrameInfo( + static_cast(relPc), 0, 0, + static_cast(mptr), + size, arkSymbolExtractorPtr_, jsFunction) >= 0; + if (!isSuccess) { + DFXLOGW("Failed to parse ark frame info, relPc: %{private}p, codeName: %{private}s", + reinterpret_cast(relPc), mapName.c_str()); + } + munmap(mptr, size); + return isSuccess; +#else + return false; +#endif +} + bool DfxHap::ParseHapFileInfo(uint64_t pc, std::shared_ptr map, JsFunction *jsFunction) { #if is_ohos && !is_mingw diff --git a/interfaces/innerkits/unwinder/src/utils/dfx_offline_parser.cpp b/interfaces/innerkits/unwinder/src/utils/dfx_offline_parser.cpp index f8b90cb93..9f7413e2b 100644 --- a/interfaces/innerkits/unwinder/src/utils/dfx_offline_parser.cpp +++ b/interfaces/innerkits/unwinder/src/utils/dfx_offline_parser.cpp @@ -16,6 +16,7 @@ #include #include "dfx_ark.h" +#include "dfx_hap.h" #include "dfx_log.h" #include "dfx_symbols.h" #include "elf_factory.h" @@ -46,10 +47,6 @@ DfxOfflineParser::~DfxOfflineParser() { UnwinderConfig::SetEnableMiniDebugInfo(CachedEnableMiniDebugInfo_); UnwinderConfig::SetEnableLoadSymbolLazily(CachedEnableLoadSymbolLazily_); - if (arkSymbolExtractorPtr_ != 0) { - DfxArk::Instance().ArkDestoryJsSymbolExtractor(arkSymbolExtractorPtr_); - arkSymbolExtractorPtr_ = 0; - } } bool DfxOfflineParser::ParseSymbolWithFrame(DfxFrame& frame) @@ -78,64 +75,40 @@ bool DfxOfflineParser::ParseNativeSymbol(DfxFrame& frame) return true; } -bool DfxOfflineParser::ParseJsSymbolForArkHap(const DfxFrame& frame, JsFunction& jsFunction) +std::shared_ptr DfxOfflineParser::GetMapForFrame(const DfxFrame& frame) { - std::string realPath = GetBundlePath(frame.mapName); - bool success = DfxArk::Instance().ParseArkFileInfo( - static_cast(frame.relPc), 0, - realPath.c_str(), arkSymbolExtractorPtr_, &jsFunction) >= 0; - if (!success) { - DFXLOGW("Failed to parse ark file info, relPc: %{private}p, hapName: %{private}s", - reinterpret_cast(frame.relPc), realPath.c_str()); - } - return success; -} - -bool DfxOfflineParser::ParseJsSymbolForArkCode(const DfxFrame& frame, JsFunction& jsFunction) -{ - std::string realPath = GetBundlePath(frame.mapName); - SmartFd smartFd(open(realPath.c_str(), O_RDONLY)); - if (!smartFd) { - DFXLOGE("Failed to open file: %{public}s, errno(%{public}d)", realPath.c_str(), errno); - return false; - } - off_t size = lseek(smartFd.GetFd(), 0, SEEK_END); - if (size <= 0) { - DFXLOGE("fd is empty or error, fd(%{public}d)", smartFd.GetFd()); - return false; - } - void* mptr = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, smartFd.GetFd(), 0); - if (mptr == MAP_FAILED) { - DFXLOGE("mmap failed, fd(%{public}d), errno(%{public}d)", smartFd.GetFd(), errno); - return false; + if (dfxMaps_ == nullptr) { + return nullptr; } - bool success = DfxArk::Instance().ParseArkFrameInfo( - static_cast(frame.relPc), 0, 0, - static_cast(mptr), - size, arkSymbolExtractorPtr_, &jsFunction) >= 0; - if (!success) { - DFXLOGW("Failed to parse ark frame info, relPc: %{private}p, codeName: %{private}s", - reinterpret_cast(frame.relPc), realPath.c_str()); + auto maps = dfxMaps_->GetMaps(); + auto it = std::find_if(maps.begin(), maps.end(), [&](const std::shared_ptr& map) { + return map->name == frame.mapName; + }); + if (it != maps.end() && *it) { + return *it; } - munmap(mptr, size); - return success; + return nullptr; } bool DfxOfflineParser::ParseJsSymbol(DfxFrame& frame) { - if (arkSymbolExtractorPtr_ == 0) { - if (DfxArk::Instance().ArkCreateJsSymbolExtractor(&arkSymbolExtractorPtr_) < 0) { - DFXLOGE("Failed to create ark js symbol extractor"); - return false; - } + auto dfxMap = GetMapForFrame(frame); + auto dfxHap = dfxMap ? dfxMap->hap : std::make_shared(); + if (!dfxHap) { + return false; + } + if (!dfxMap) { + dfxMap = std::make_shared(); + dfxMap->name = GetBundlePath(frame.mapName); + dfxMap->hap = dfxHap; + dfxMaps_->AddMap(dfxMap); } JsFunction jsFunction; - bool success = DfxMaps::IsArkHapMapItem(frame.mapName) - ? ParseJsSymbolForArkHap(frame, jsFunction) - : ParseJsSymbolForArkCode(frame, jsFunction); - if (!success) { + bool isSuccess = dfxHap->ParseHapInfo(0, frame.relPc, dfxMap, &jsFunction, true); + if (!isSuccess) { return false; } + frame.isJsFrame = true; frame.mapName = std::string(jsFunction.url); frame.funcName = std::string(jsFunction.functionName); @@ -155,15 +128,9 @@ std::string DfxOfflineParser::GetBundlePath(const std::string& originPath) const std::shared_ptr DfxOfflineParser::GetElfForFrame(const DfxFrame& frame) { - if (dfxMaps_ == nullptr) { - return nullptr; - } - auto maps = dfxMaps_->GetMaps(); - auto it = std::find_if(maps.begin(), maps.end(), [&](const std::shared_ptr& map) { - return map->name == frame.mapName; - }); - if (it != maps.end() && *it) { - return (*it)->elf; + auto dfxMap = GetMapForFrame(frame); + if (dfxMap) { + return dfxMap->elf; } RegularElfFactory factory(GetBundlePath(frame.mapName)); auto elf = factory.Create(); @@ -175,10 +142,10 @@ std::shared_ptr DfxOfflineParser::GetElfForFrame(const DfxFrame& frame) DFXLOGE("elf is invalid"); return nullptr; } - auto newMap = std::make_shared(); - newMap->name = frame.mapName; - newMap->elf = elf; - dfxMaps_->AddMap(newMap); + dfxMap = std::make_shared(); + dfxMap->name = frame.mapName; + dfxMap->elf = elf; + dfxMaps_->AddMap(dfxMap); return elf; } } // namespace HiviewDFX diff --git a/test/unittest/unwind/dfx_hap_test.cpp b/test/unittest/unwind/dfx_hap_test.cpp index d5c9a2662..34eb4031d 100644 --- a/test/unittest/unwind/dfx_hap_test.cpp +++ b/test/unittest/unwind/dfx_hap_test.cpp @@ -142,5 +142,50 @@ HWTEST_F(DfxHapTest, DfxHapTest005, TestSize.Level2) ASSERT_EQ(ret, false); GTEST_LOG_(INFO) << "DfxHapTest005: end."; } + +/** + * @tc.name: DfxHapTest006 + * @tc.desc: test DfxHap ParseOfflineJsSymbol exception + * @tc.type: FUNC + */ +HWTEST_F(DfxHapTest, DfxHapTest006, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "DfxHapTest006: start."; + DfxHap dfxHap; + pid_t pid = 1; + uint64_t pc = 1; + auto map = std::make_shared(); + JsFunction jsFunction; + + bool res = dfxHap.ParseHapInfo(pid, pc, map, nullptr, true); + ASSERT_EQ(res, false); + res = dfxHap.ParseHapInfo(pid, pc, map, &jsFunction, true); + ASSERT_EQ(res, false); + map->name = "test.hap"; + res = dfxHap.ParseHapInfo(pid, pc, map, &jsFunction, true); + ASSERT_EQ(res, false); + GTEST_LOG_(INFO) << "DfxHapTest006: end."; +} + +/** + * @tc.name: DfxHapTest007 + * @tc.desc: test DfxHap ParseOfflineJsSymbolForArkHap exception + * @tc.type: FUNC + */ +HWTEST_F(DfxHapTest, DfxHapTest007, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "DfxHapTest007: start."; + DfxHap dfxHap; + std::string mapName = ""; + bool ret = dfxHap.ParseHapMemInfoForOffline(mapName, 0, nullptr); + ASSERT_EQ(ret, false); + mapName = "test.abc"; + ret = dfxHap.ParseHapMemInfoForOffline(mapName, 0, nullptr); + ASSERT_EQ(ret, false); + JsFunction jsFunction; + ret = dfxHap.ParseHapMemInfoForOffline(mapName, 0, &jsFunction); + ASSERT_EQ(ret, false); + GTEST_LOG_(INFO) << "DfxHapTest007: end."; +} } // namespace HiviewDFX } // namespace OHOS \ No newline at end of file diff --git a/tools/dump_catcher/main.cpp b/tools/dump_catcher/main.cpp index e62151842..e6dd9867a 100644 --- a/tools/dump_catcher/main.cpp +++ b/tools/dump_catcher/main.cpp @@ -39,7 +39,7 @@ static void PrintCommandHelp() printf("-p pid | dump the stacktrace of all the threads with given pid, timeout default 3000ms.\n"); printf("-p pid -t tid | dump the stacktrace of the thread with given tid .\n"); printf("-p pid -T timeout(ms) | dump the stacktrace of the thread with given tid in timeout.\n"); - printf("-k pid | dump the origin kernel stacktrace with noark of the pid.\n"); + printf("-k pid | dump the origin kernel stacktrace without ark of the pid.\n"); printf("-k pid -a | dump the origin kernel stacktrace with ark of the pid.\n"); printf("-k pid -a -f | dump the origin kernel stacktrace with ark of the pid and format parse stack.\n"); printf("-c save pid | begin to coredump the process of the pid.\n"); -- Gitee