diff --git a/interfaces/innerkits/unwinder/include/dfx_hap.h b/interfaces/innerkits/unwinder/include/dfx_hap.h index 82147c5110a6d915aead7595d655c760ac855525..104488e447667a21c8012a7311cc65bdd9496777 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 c73978f95c2fa67863889939f00c017d6a9c50e0..160d403336801f98215d72f8dad92bd27abd4622 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 b817de836e4f91b02c13ef10852c31732e14ea8c..d0f3b766c058353054784b21b93fcf8a5d68a262 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 f8b90cb937d4f7f9d0d122180b4580a805a316e6..9f7413e2b4e3927e9d029038b37d6b93ba864bab 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 d5c9a266236f4aa8fd77624c5b59532fc6880825..34eb4031d1963e15b1fda8eb010fc72f95e72b10 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 e621518420e28bb898da1213696da788d5dca968..e6dd9867a07d1d68fafa07d4d98d50d95841e06a 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");