From 2aa51589699a0459e28324891dd417ce96167cea Mon Sep 17 00:00:00 2001 From: chuaizhzh Date: Sat, 26 Jul 2025 17:25:32 +0800 Subject: [PATCH] fix:ts compile Signed-off-by: chuaizhzh --- trace_streamer/pare_third_party.sh | 60 +- .../patch_hiperf/hiviewdfx_faultloggerd.patch | 1827 +++++++++++++++-- 2 files changed, 1690 insertions(+), 197 deletions(-) diff --git a/trace_streamer/pare_third_party.sh b/trace_streamer/pare_third_party.sh index a0b7cfa8..1a695a4f 100755 --- a/trace_streamer/pare_third_party.sh +++ b/trace_streamer/pare_third_party.sh @@ -29,26 +29,17 @@ fi cd third_party if [ ! -f "sqlite/BUILD.gn" ];then - rm -rf sqlite - git clone git@gitee.com:openharmony/third_party_sqlite.git - if [ -d "third_party_sqlite" ];then - mv third_party_sqlite sqlite - cd sqlite - git reset --hard d21e412dbc6f2cdde2e4c9828e2450fcfca4fbe9 - cd .. - $cp ../prebuilts/patch_sqlite/sqlite3build.gn ../third_party/sqlite/BUILD.gn - fi + git clone git@gitee.com:openharmony/third_party_sqlite.git sqlite + cd sqlite + git reset --hard d21e412dbc6f2cdde2e4c9828e2450fcfca4fbe9 + cd .. fi + if [ ! -f "protobuf/BUILD.gn" ];then - rm -rf protobuf - git clone git@gitee.com:openharmony/third_party_protobuf.git - if [ -d "third_party_protobuf" ];then - mv third_party_protobuf protobuf - cd protobuf - git reset --hard aceafed4cf26d7a6be8169ae887cc13b749d5515 - cd .. - $cp ../prebuilts/patch_protobuf/protobufbuild.gn ../third_party/protobuf/BUILD.gn - fi + git clone git@gitee.com:openharmony/third_party_protobuf.git protobuf + cd protobuf + git reset --hard aceafed4cf26d7a6be8169ae887cc13b749d5515 + cd .. fi if [ ! -f "zlib/BUILD.gn" ];then @@ -57,27 +48,14 @@ fi if [ ! -f "bzip2/BUILD.gn" ];then git clone --depth=1 git@gitee.com:openharmony/third_party_bzip2.git bzip2 - cd bzip2 - ./install.sh $(pwd) - cd .. fi if [ ! -f "googletest/BUILD.gn" ];then - rm -rf googletest - git clone --depth=1 git@gitee.com:openharmony/third_party_googletest.git - if [ -d "third_party_googletest" ];then - mv third_party_googletest googletest - $cp ../prebuilts/patch_googletest/googletestbuild.gn ../third_party/googletest/BUILD.gn - $patch -p1 < ../prebuilts/patch_googletest/gtest.patch - fi + git clone --depth=1 git@gitee.com:openharmony/third_party_googletest.git googletest fi -if [ ! -f "json/BUILD.gn" ];then - rm -rf json - git clone --depth=1 git@gitee.com:openharmony/third_party_json.git - if [ -d "third_party_json" ];then - mv third_party_json json - fi +if [ ! -d "json" ];then + git clone --depth=1 git@gitee.com:openharmony/third_party_json.git json fi if [ ! -d "libbpf" ];then @@ -87,6 +65,7 @@ fi if [ ! -d "hiviewdfx/faultloggerd" ];then git clone --depth=1 git@gitee.com:openharmony/hiviewdfx_faultloggerd.git hiviewdfx/faultloggerd/ cd hiviewdfx/faultloggerd + perl -pi -e 's/\r$//' interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp $patch -p1 < ../../../prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch cd ../../ fi @@ -103,15 +82,8 @@ if [ ! -d "commonlibrary/c_utils" ];then git clone --depth=1 git@gitee.com:openharmony/commonlibrary_c_utils.git commonlibrary/c_utils fi -if [ ! -f "profiler/device/plugins/ftrace_plugin/include/ftrace_common_type.h" ];then - rm -rf profiler - git clone --depth=1 git@gitee.com:openharmony/developtools_profiler.git - if [ -d "developtools_profiler" ];then - mkdir -p profiler/device/plugins/ftrace_plugin/include - $cp developtools_profiler/device/plugins/ftrace_plugin/include/ftrace_common_type.h profiler/device/plugins/ftrace_plugin/include - $cp developtools_profiler/device/plugins/ftrace_plugin/include/ftrace_namespace.h profiler/device/plugins/ftrace_plugin/include - rm -rf developtools_profiler - fi +if [ ! -d "profiler" ];then + git clone --depth=1 git@gitee.com:openharmony/developtools_profiler.git profiler fi if [ ! -d "llvm-project" ];then @@ -126,4 +98,4 @@ if [ ! -d "llvm-project" ];then # REF: https://gitee.com/openharmony/third_party_llvm-project/blob/master/llvm/utils/gn/.gn ln -s $root_dir/third_party/llvm-project/llvm llvm fi -fi +fi \ No newline at end of file diff --git a/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch b/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch index 088df2a3..42745c1d 100644 --- a/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch +++ b/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch @@ -1,159 +1,1680 @@ -diff --git a/common/dfxutil/string_view_util.h b/common/dfxutil/string_view_util.h -index b44a59ea775b368b93391ce19b440f617c309477..7dbd3568df9035edea91e920bf12fa5c58fe116f 100644 ---- a/common/dfxutil/string_view_util.h -+++ b/common/dfxutil/string_view_util.h -@@ -24,6 +24,24 @@ - - namespace OHOS { - namespace HiviewDFX { -+#ifdef is_mac -+class SpinLock { -+public: -+ void lock() -+ { -+ while (locked_.test_and_set(std::memory_order_acquire)) { -+ ; -+ } -+ } -+ void unlock() -+ { -+ locked_.clear(std::memory_order_release); -+ } -+ -+private: -+ std::atomic_flag locked_ = ATOMIC_FLAG_INIT; -+}; -+#endif - class StringViewHold { - public: - static StringViewHold &Get() -@@ -34,50 +52,77 @@ public: - - const char* Hold(STRING_VIEW view) - { -+#ifndef is_mac - pthread_spin_lock(&spin_lock_); -+#else -+ std::lock_guard lockGurand(spinlock_); -+#endif - if (view.size() == 0) { -+#ifndef is_mac - pthread_spin_unlock(&spin_lock_); -+#endif - return ""; - } - - char *p = new (std::nothrow) char[view.size() + 1]; - if (p == nullptr) { -+#ifndef is_mac - pthread_spin_unlock(&spin_lock_); -+#endif - return ""; - } - if (memset_s(p, view.size() + 1, '\0', view.size() + 1) != 0) { -+#ifndef is_mac - pthread_spin_unlock(&spin_lock_); -+#endif - return ""; - } - std::copy(view.data(), view.data() + view.size(), p); - views_.emplace_back(p); -+#ifndef is_mac - pthread_spin_unlock(&spin_lock_); -+#endif - return p; - } - - // only use in UT - void Clean() - { -+#ifndef is_mac - pthread_spin_lock(&spin_lock_); -+#else -+ std::lock_guard lockGurand(spinlock_); -+#endif - for (auto &p : views_) { - delete[] p; - } - views_.clear(); -+#ifndef is_mac - pthread_spin_unlock(&spin_lock_); -+#endif - } -+ - private: -+#ifndef is_mac - StringViewHold() - { - pthread_spin_init(&spin_lock_, PTHREAD_PROCESS_PRIVATE); - } -+#endif - ~StringViewHold() - { - Clean(); -+#ifndef is_mac - pthread_spin_destroy(&spin_lock_); -+#endif - } - - std::vector views_; -+#ifndef is_mac - pthread_spinlock_t spin_lock_; -+#else -+ SpinLock spinlock_; -+#endif - }; - } // namespace HiviewDFX - } // namespace OHOS -diff --git a/interfaces/common/byte_order.h b/interfaces/common/byte_order.h -index 3c40993ec56288deec6e40420a97d182587e9b62..a55d9db076a6fe1476a52a102fb968adb08073d7 100644 ---- a/interfaces/common/byte_order.h -+++ b/interfaces/common/byte_order.h -@@ -16,7 +16,7 @@ - #ifndef BYTE_ORDER_H - #define BYTE_ORDER_H - --#if is_mingw -+#if is_mingw || is_mac - #define UNWIND_LITTLE_ENDIAN 1234 - #define UNWIND_BIG_ENDIAN 4321 - #define UNWIND_BYTE_ORDER -1 // Unknown -diff --git a/interfaces/innerkits/unwinder/include/dfx_elf_define.h b/interfaces/innerkits/unwinder/include/dfx_elf_define.h -index 6bc9394912c193417cbfe588551b07c255fce62a..a71d76b5641ec347f014736173137cf1115c446b 100644 ---- a/interfaces/innerkits/unwinder/include/dfx_elf_define.h -+++ b/interfaces/innerkits/unwinder/include/dfx_elf_define.h -@@ -17,7 +17,7 @@ - - #include - #include --#if !is_mingw -+#if !is_mingw && !is_mac - #include - #include - #endif -diff --git a/interfaces/innerkits/unwinder/include/dfx_elf_parser.h b/interfaces/innerkits/unwinder/include/dfx_elf_parser.h -index b4c84437735176d28f7756930a8027152fc08155..86a4bdd197918e6246edf683eec2d213b1414803 100644 ---- a/interfaces/innerkits/unwinder/include/dfx_elf_parser.h -+++ b/interfaces/innerkits/unwinder/include/dfx_elf_parser.h -@@ -16,7 +16,7 @@ - #define DFX_ELF_PARSER_H - - #include --#if is_mingw -+#if is_mingw || is_mac - #include "dfx_nonlinux_define.h" - #else - #include -diff --git a/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp b/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp -index 9398e59acea6722bb1bfebcd0f312ee826a6f5a1..d071f2b934610fb15a921972a9eb97f3c646506f 100644 ---- a/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp -+++ b/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp -@@ -20,7 +20,7 @@ - #include - #include +diff --git a/common/dfxutil/smart_fd.h b/common/dfxutil/smart_fd.h +index fd5e838..858ae73 100644 +--- a/common/dfxutil/smart_fd.h ++++ b/common/dfxutil/smart_fd.h +@@ -28,9 +28,11 @@ public: + SmartFd() = default; + explicit SmartFd(int fd, bool fdsan = true) : fd_(fd), fdsan_(fdsan) + { ++#if is_ohos + if (fd_ >= 0 && fdsan_) { + fdsan_exchange_owner_tag(fd_, 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN)); + } ++#endif + } + + ~SmartFd() +@@ -85,11 +87,14 @@ private: + if (fd_ < 0) { + return; + } ++#if is_ohos + if (fdsan_) { + fdsan_close_with_tag(fd_, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN)); + return; + } ++#else + close(fd_); ++#endif + } + + int fd_{-1}; +diff --git a/common/dfxutil/string_view_util.h b/common/dfxutil/string_view_util.h +index b44a59e..7dbd356 100644 +--- a/common/dfxutil/string_view_util.h ++++ b/common/dfxutil/string_view_util.h +@@ -24,6 +24,24 @@ + + namespace OHOS { + namespace HiviewDFX { ++#ifdef is_mac ++class SpinLock { ++public: ++ void lock() ++ { ++ while (locked_.test_and_set(std::memory_order_acquire)) { ++ ; ++ } ++ } ++ void unlock() ++ { ++ locked_.clear(std::memory_order_release); ++ } ++ ++private: ++ std::atomic_flag locked_ = ATOMIC_FLAG_INIT; ++}; ++#endif + class StringViewHold { + public: + static StringViewHold &Get() +@@ -34,50 +52,77 @@ public: + + const char* Hold(STRING_VIEW view) + { ++#ifndef is_mac + pthread_spin_lock(&spin_lock_); ++#else ++ std::lock_guard lockGurand(spinlock_); ++#endif + if (view.size() == 0) { ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + return ""; + } + + char *p = new (std::nothrow) char[view.size() + 1]; + if (p == nullptr) { ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + return ""; + } + if (memset_s(p, view.size() + 1, '\0', view.size() + 1) != 0) { ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + return ""; + } + std::copy(view.data(), view.data() + view.size(), p); + views_.emplace_back(p); ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + return p; + } + + // only use in UT + void Clean() + { ++#ifndef is_mac + pthread_spin_lock(&spin_lock_); ++#else ++ std::lock_guard lockGurand(spinlock_); ++#endif + for (auto &p : views_) { + delete[] p; + } + views_.clear(); ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + } ++ + private: ++#ifndef is_mac + StringViewHold() + { + pthread_spin_init(&spin_lock_, PTHREAD_PROCESS_PRIVATE); + } ++#endif + ~StringViewHold() + { + Clean(); ++#ifndef is_mac + pthread_spin_destroy(&spin_lock_); ++#endif + } + + std::vector views_; ++#ifndef is_mac + pthread_spinlock_t spin_lock_; ++#else ++ SpinLock spinlock_; ++#endif + }; + } // namespace HiviewDFX + } // namespace OHOS +diff --git a/interfaces/common/byte_order.h b/interfaces/common/byte_order.h +index 3c40993..a55d9db 100644 +--- a/interfaces/common/byte_order.h ++++ b/interfaces/common/byte_order.h +@@ -16,7 +16,7 @@ + #ifndef BYTE_ORDER_H + #define BYTE_ORDER_H + +-#if is_mingw ++#if is_mingw || is_mac + #define UNWIND_LITTLE_ENDIAN 1234 + #define UNWIND_BIG_ENDIAN 4321 + #define UNWIND_BYTE_ORDER -1 // Unknown +diff --git a/interfaces/innerkits/unwinder/include/dfx_elf_define.h b/interfaces/innerkits/unwinder/include/dfx_elf_define.h +index 6bc9394..a71d76b 100644 +--- a/interfaces/innerkits/unwinder/include/dfx_elf_define.h ++++ b/interfaces/innerkits/unwinder/include/dfx_elf_define.h +@@ -17,7 +17,7 @@ + + #include #include +-#if !is_mingw ++#if !is_mingw && !is_mac + #include + #include + #endif +diff --git a/interfaces/innerkits/unwinder/include/dfx_elf_parser.h b/interfaces/innerkits/unwinder/include/dfx_elf_parser.h +index b4c8443..86a4bdd 100644 +--- a/interfaces/innerkits/unwinder/include/dfx_elf_parser.h ++++ b/interfaces/innerkits/unwinder/include/dfx_elf_parser.h +@@ -16,7 +16,7 @@ + #define DFX_ELF_PARSER_H + + #include -#if is_mingw +#if is_mingw || is_mac #include "dfx_nonlinux_define.h" #else #include +diff --git a/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp b/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp +index 9398e59..79d230e 100644 +--- a/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp ++++ b/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp +@@ -1,749 +1,749 @@ +-/* +- * Copyright (c) 2021-2025 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 "dfx_elf.h" +- +-#include +-#include +-#include +-#include +-#include +-#if is_mingw +-#include "dfx_nonlinux_define.h" +-#else +-#include +-#include +-#endif +-#include +-#include +-#include +-#include +- +-#include "dfx_define.h" +-#include "dfx_log.h" +-#include "dfx_instr_statistic.h" +-#include "dfx_util.h" +-#include "dfx_maps.h" +-#include "dfx_trace_dlsym.h" +-#include "dwarf_define.h" +-#include "elf_factory.h" +-#include "string_util.h" +-#include "unwinder_config.h" +- +-namespace OHOS { +-namespace HiviewDFX { +-namespace { +-#undef LOG_DOMAIN +-#undef LOG_TAG +-#define LOG_DOMAIN 0xD002D11 +-#define LOG_TAG "DfxElf" +-#if is_ohos && !is_mingw +-enum HdrSection { +- SECTION_TEXT = 0, +- SECTION_ARMEXIDX = 1, +- SECTION_DYNAMIC = 2, +- SECTION_EHFRAMEHDR = 3 +-}; +-#endif +-} +- +-void DfxElf::Init() +-{ +- uti_.namePtr = 0; +- uti_.format = -1; +- hasTableInfo_ = false; +-} +- +-void DfxElf::Clear() +-{ +- if (elfParse_ != nullptr) { +- elfParse_.reset(); +- elfParse_ = nullptr; +- } +- +- if (mmap_ != nullptr) { +- mmap_->Clear(); +- mmap_.reset(); +- mmap_ = nullptr; +- } +-} +- +-bool DfxElf::InitHeaders() +-{ +- if (mmap_ == nullptr) { +- return false; +- } +- +- if (elfParse_ != nullptr) { +- return true; +- } +- +- uint8_t ident[SELFMAG + 1]; +- if (!Read(0, ident, SELFMAG) || !IsValidElf(ident, SELFMAG)) { +- return false; +- } +- +- if (!Read(EI_CLASS, &classType_, sizeof(uint8_t))) { +- return false; +- } +- +- if (classType_ == ELFCLASS32) { +- elfParse_ = std::unique_ptr(new ElfParser32(mmap_)); +- } else if (classType_ == ELFCLASS64) { +- elfParse_ = std::unique_ptr(new ElfParser64(mmap_)); +- } else { +- DFXLOGW("InitHeaders failed, classType: %{public}d", classType_); +- return false; +- } +- if (elfParse_ != nullptr) { +- valid_ = true; +- elfParse_->InitHeaders(); +- } +- return valid_; +-} +- +-bool DfxElf::IsValid() +-{ +- if (valid_ == false) { +- InitHeaders(); +- } +- return valid_; +-} +- +-uint8_t DfxElf::GetClassType() +-{ +- if (IsValid()) { +- return classType_; +- } +- return ELFCLASSNONE; +-} +- +-ArchType DfxElf::GetArchType() +-{ +- if (IsValid()) { +- elfParse_->GetArchType(); +- } +- return ARCH_UNKNOWN; +-} +- +-int64_t DfxElf::GetLoadBias() +-{ +- if (loadBias_ == 0) { +- if (IsValid()) { +- loadBias_ = elfParse_->GetLoadBias(); +- DFXLOGU("Elf loadBias: %{public}" PRIx64 "", (uint64_t)loadBias_); +- } +- } +- return loadBias_; +-} +- +-uint64_t DfxElf::GetLoadBase(uint64_t mapStart, uint64_t mapOffset) +-{ +- if (loadBase_ == static_cast(-1)) { +- if (IsValid()) { +- DFXLOGU("mapStart: %{public}" PRIx64 ", mapOffset: %{public}" PRIx64 "", +- (uint64_t)mapStart, (uint64_t)mapOffset); +- loadBase_ = mapStart - mapOffset - static_cast(GetLoadBias()); +- DFXLOGU("Elf loadBase: %{public}" PRIx64 "", (uint64_t)loadBase_); +- } +- } +- return loadBase_; +-} +- +-void DfxElf::SetLoadBase(uint64_t base) +-{ +- loadBase_ = base; +-} +- +-void DfxElf::SetBaseOffset(uint64_t offset) +-{ +- baseOffset_ = offset; +-} +- +-uint64_t DfxElf::GetBaseOffset() +-{ +- return baseOffset_; +-} +- +-uint64_t DfxElf::GetStartPc() +-{ +- if (startPc_ == static_cast(-1)) { +- if (IsValid()) { +- auto startVaddr = elfParse_->GetStartVaddr(); +- if (loadBase_ != static_cast(-1) && startVaddr != static_cast(-1)) { +- startPc_ = startVaddr + loadBase_; +- DFXLOGU("Elf startPc: %{public}" PRIx64 "", (uint64_t)startPc_); +- } +- } +- } +- return startPc_; +-} +- +-uint64_t DfxElf::GetStartVaddr() +-{ +- if (IsValid()) { +- return elfParse_->GetStartVaddr(); +- } +- return 0; +-} +- +-uint64_t DfxElf::GetEndPc() +-{ +- if (endPc_ == 0) { +- if (IsValid()) { +- auto endVaddr = elfParse_->GetEndVaddr(); +- if (loadBase_ != static_cast(-1) && endVaddr != 0) { +- endPc_ = endVaddr + loadBase_; +- DFXLOGU("Elf endPc: %{public}" PRIx64 "", (uint64_t)endPc_); +- } +- } +- } +- return endPc_; +-} +- +-uint64_t DfxElf::GetEndVaddr() +-{ +- if (IsValid()) { +- return elfParse_->GetEndVaddr(); +- } +- return 0; +-} +- +-uint64_t DfxElf::GetStartOffset() +-{ +- if (IsValid()) { +- return elfParse_->GetStartOffset(); +- } +- return 0; +-} +- +-uint64_t DfxElf::GetRelPc(uint64_t pc, uint64_t mapStart, uint64_t mapOffset) +-{ +- return (pc - GetLoadBase(mapStart, mapOffset)); +-} +- +-uint64_t DfxElf::GetElfSize() +-{ +- if (!IsValid()) { +- return 0; +- } +- return elfParse_->GetElfSize(); +-} +- +-std::string DfxElf::GetElfName() +-{ +- if (!IsValid()) { +- return ""; +- } +- return elfParse_->GetElfName(); +-} +- +-void DfxElf::SetBuildId(const std::string& buildId) +-{ +- buildId_ = buildId; +-} +- +-std::string DfxElf::GetBuildId(uint64_t noteAddr, uint64_t noteSize) +-{ +- return ElfParser::ParseHexBuildId(noteAddr, noteSize); +-} +- +-std::string DfxElf::GetBuildId() +-{ +- if (buildId_.empty()) { +- if (!IsValid()) { +- return ""; +- } +- return elfParse_->GetBuildId(); +- } +- return buildId_; +-} +- +- +-uintptr_t DfxElf::GetGlobalPointer() +-{ +- if (!IsValid()) { +- return 0; +- } +- return elfParse_->GetGlobalPointer(); +-} +- +-bool DfxElf::GetSectionInfo(ShdrInfo& shdr, const std::string secName) +-{ +- if (!IsValid()) { +- return false; +- } +- return elfParse_->GetSectionInfo(shdr, secName); +-} +- +-bool DfxElf::GetSectionData(unsigned char* buf, uint64_t size, std::string secName) +-{ +- if (!IsValid()) { +- return false; +- } +- return elfParse_->GetSectionData(buf, size, secName); +-} +- +-GnuDebugDataHdr DfxElf::GetGnuDebugDataHdr() +-{ +- if (!IsValid()) { +- return {}; +- } +- return elfParse_->GetGnuDebugDataHdr(); +-} +- +-bool DfxElf::IsMiniDebugInfoValid() +-{ +- if (miniDebugInfo_ == nullptr) { +-#if defined(ENABLE_MINIDEBUGINFO) +- MiniDebugInfoFactory miniDebugInfoFactory(elfParse_->GetGnuDebugDataHdr()); +- miniDebugInfo_ = miniDebugInfoFactory.Create(); +-#endif +- } +- return miniDebugInfo_ != nullptr; +-} +- +-const std::set& DfxElf::GetFuncSymbols() +-{ +- if (!IsValid() || !funcSymbols_.empty()) { +- return funcSymbols_; +- } +- if (IsMiniDebugInfoValid()) { +- funcSymbols_ = miniDebugInfo_->elfParse_->GetFuncSymbols(); +- DFXLOGU("Get MiniDebugInfo FuncSymbols, size: %{public}zu", funcSymbols_.size()); +- } +- const auto &symbols = elfParse_->GetFuncSymbols(); +- funcSymbols_.insert(symbols.begin(), symbols.end()); +- DFXLOGU("GetFuncSymbols, size: %{public}zu", funcSymbols_.size()); +- return funcSymbols_; +-} +- +-bool DfxElf::GetFuncInfoLazily(uint64_t addr, ElfSymbol& elfSymbol) +-{ +- DFX_TRACE_SCOPED_DLSYM("GetFuncInfoLazily"); +- if (FindFuncSymbol(addr, funcSymbols_, elfSymbol)) { +- return true; +- } +- bool findSymbol = elfParse_->GetFuncSymbolByAddr(addr, elfSymbol); +- if (!findSymbol && IsMiniDebugInfoValid()) { +- findSymbol = miniDebugInfo_->elfParse_->GetFuncSymbolByAddr(addr, elfSymbol); +- } +- +- if (findSymbol) { +- funcSymbols_.emplace(elfSymbol); +- DFXLOGU("GetFuncInfoLazily, size: %{public}zu", funcSymbols_.size()); +- } +- return findSymbol; +-} +- +-bool DfxElf::GetFuncInfo(uint64_t addr, ElfSymbol& elfSymbol) +-{ +- if (!IsValid()) { +- return false; +- } +- if (UnwinderConfig::GetEnableLoadSymbolLazily()) { +- return GetFuncInfoLazily(addr, elfSymbol); +- } +- +- const auto &symbols = GetFuncSymbols(); +- return FindFuncSymbol(addr, symbols, elfSymbol); +-} +- +-bool DfxElf::FindFuncSymbol(uint64_t addr, const std::set& symbols, ElfSymbol& elfSymbol) +-{ +- DFX_TRACE_SCOPED_DLSYM("FindFuncSymbol"); +- if (symbols.empty()) { +- return false; +- } +- // Find the first position that is not less than value +- ElfSymbol tmpSym; +- tmpSym.value = addr; +- auto next = symbols.upper_bound(tmpSym); +- if (next != symbols.begin()) { +- next--; +- } +- if (next->value <= addr && addr < (next->value + next->size)) { +- elfSymbol = *next; +- return true; +- } +- return false; +-} +- +-const std::unordered_map& DfxElf::GetPtLoads() +-{ +- return elfParse_->GetPtLoads(); +-} +- +-bool DfxElf::FillUnwindTableByExidx(ShdrInfo shdr, uintptr_t loadBase, struct UnwindTableInfo* uti) +-{ +- if (uti == nullptr) { +- return false; +- } +- uti->gp = 0; +- uti->tableData = loadBase + shdr.addr; +- uti->tableLen = shdr.size; +- INSTR_STATISTIC(InstructionEntriesArmExidx, shdr.size, 0); +- uti->format = UNW_INFO_FORMAT_ARM_EXIDX; +- DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, +- (uint64_t)uti->tableData, (int)uti->tableLen); +- return true; +-} +- +-#if is_ohos && !is_mingw +-bool DfxElf::FillUnwindTableByEhhdrLocal(struct DwarfEhFrameHdr* hdr, struct UnwindTableInfo* uti) +-{ +- if (hdr == nullptr) { +- return false; +- } +- if (hdr->version != DW_EH_VERSION) { +- DFXLOGE("[%{public}d]: version(%{public}d) error", __LINE__, hdr->version); +- return false; +- } +- +- uintptr_t ptr = (uintptr_t)(&(hdr->ehFrame)); +- DFXLOGU("[%{public}d]: hdr: %{public}" PRIx64 ", ehFrame: %{public}" PRIx64 "", __LINE__, +- (uint64_t)hdr, (uint64_t)ptr); +- auto memory = std::make_shared(UNWIND_TYPE_LOCAL); +- DFXLOGU("[%{public}d]: gp: %{public}" PRIx64 ", ehFramePtrEnc: %{public}x, fdeCountEnc: %{public}x", __LINE__, +- (uint64_t)uti->gp, hdr->ehFramePtrEnc, hdr->fdeCountEnc); +- memory->SetDataOffset(uti->gp); +- MAYBE_UNUSED uintptr_t ehFrameStart = memory->ReadEncodedValue(ptr, hdr->ehFramePtrEnc); +- uintptr_t fdeCount = memory->ReadEncodedValue(ptr, hdr->fdeCountEnc); +- DFXLOGU("[%{public}d]: ehFrameStart: %{public}" PRIx64 ", fdeCount: %{public}d", __LINE__, +- (uint64_t)ehFrameStart, (int)fdeCount); +- +- if (hdr->tableEnc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { +- DFXLOGU("tableEnc: %{public}x", hdr->tableEnc); +- if (hdr->fdeCountEnc == DW_EH_PE_omit) { +- fdeCount = ~0UL; +- } +- if (hdr->ehFramePtrEnc == DW_EH_PE_omit) { +- DFXLOGE("ehFramePtrEnc(%{public}x) error", hdr->ehFramePtrEnc); +- return false; +- } +- uti->isLinear = true; +- uti->tableLen = fdeCount; +- uti->tableData = ehFrameStart; +- } else { +- uti->isLinear = false; +- uti->tableLen = (fdeCount * sizeof(DwarfTableEntry)) / sizeof(uintptr_t); +- uti->tableData = ptr; +- uti->segbase = (uintptr_t)hdr; +- } +- uti->format = UNW_INFO_FORMAT_REMOTE_TABLE; +- DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, +- (uint64_t)uti->tableData, (int)uti->tableLen); +- return true; +-} +-#endif +- +-bool DfxElf::FillUnwindTableByEhhdr(struct DwarfEhFrameHdr* hdr, uintptr_t shdrBase, struct UnwindTableInfo* uti) +-{ +- if ((hdr == nullptr) || (uti == nullptr)) { +- return false; +- } +- if (hdr->version != DW_EH_VERSION) { +- DFXLOGE("[%{public}d]: version(%{public}d) error", __LINE__, hdr->version); +- return false; +- } +- uintptr_t ptr = (uintptr_t)(&(hdr->ehFrame)); +- DFXLOGU("[%{public}d]: hdr: %{public}" PRIx64 ", ehFrame: %{public}" PRIx64 "", __LINE__, +- (uint64_t)hdr, (uint64_t)ptr); +- +- uti->gp = GetGlobalPointer(); +- DFXLOGU("[%{public}d]: gp: %{public}" PRIx64 ", ehFramePtrEnc: %{public}x, fdeCountEnc: %{public}x", __LINE__, +- (uint64_t)uti->gp, hdr->ehFramePtrEnc, hdr->fdeCountEnc); +- mmap_->SetDataOffset(uti->gp); +- auto ptrOffset = ptr - reinterpret_cast(GetMmapPtr()); +- MAYBE_UNUSED uintptr_t ehFrameStart = mmap_->ReadEncodedValue(ptrOffset, hdr->ehFramePtrEnc); +- uintptr_t fdeCount = mmap_->ReadEncodedValue(ptrOffset, hdr->fdeCountEnc); +- DFXLOGU("[%{public}d]: ehFrameStart: %{public}" PRIx64 ", fdeCount: %{public}d", __LINE__, +- (uint64_t)ehFrameStart, (int)fdeCount); +- ptr = reinterpret_cast(GetMmapPtr()) + ptrOffset; +- +- if (hdr->tableEnc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { +- DFXLOGU("[%{public}d]: tableEnc: %{public}x", __LINE__, hdr->tableEnc); +- if (hdr->fdeCountEnc == DW_EH_PE_omit) { +- fdeCount = ~0UL; +- } +- if (hdr->ehFramePtrEnc == DW_EH_PE_omit) { +- DFXLOGE("[%{public}d]: ehFramePtrEnc(%{public}x) error", __LINE__, hdr->ehFramePtrEnc); +- return false; +- } +- uti->isLinear = true; +- uti->tableLen = fdeCount; +- uti->tableData = shdrBase + ehFrameStart; +- uti->segbase = shdrBase; +- } else { +- uti->isLinear = false; +- uti->tableLen = (fdeCount * sizeof(DwarfTableEntry)) / sizeof(uintptr_t); +- uti->tableData = shdrBase + ptr - (uintptr_t)hdr; +- uti->segbase = shdrBase; +- } +- uti->format = UNW_INFO_FORMAT_REMOTE_TABLE; +- DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, +- (uint64_t)uti->tableData, (int)uti->tableLen); +- return true; +-} +- +-int DfxElf::FindUnwindTableInfo(uintptr_t pc, std::shared_ptr map, struct UnwindTableInfo& uti) +-{ +- if (hasTableInfo_ && pc >= uti_.startPc && pc < uti_.endPc) { +- uti = uti_; +- DFXLOGU("FindUnwindTableInfo had found"); +- return UNW_ERROR_NONE; +- } +- if (map == nullptr) { +- return UNW_ERROR_INVALID_MAP; +- } +- uintptr_t loadBase = GetLoadBase(map->begin, map->offset); +- uti.startPc = GetStartPc(); +- uti.endPc = GetEndPc(); +- if (pc < uti.startPc || pc >= uti.endPc) { +- DFXLOGU("Elf startPc: %{public}" PRIx64 ", endPc: %{public}" PRIx64 "", +- (uint64_t)uti.startPc, (uint64_t)uti.endPc); +- return UNW_ERROR_PC_NOT_IN_UNWIND_INFO; +- } +- +- ShdrInfo shdr; +-#if defined(__arm__) +- if (GetSectionInfo(shdr, ARM_EXIDX)) { +- hasTableInfo_ = FillUnwindTableByExidx(shdr, loadBase, &uti); +- } +-#endif +- +- if (!hasTableInfo_) { +- struct DwarfEhFrameHdr* hdr = nullptr; +- struct DwarfEhFrameHdr synthHdr; +- if (GetSectionInfo(shdr, EH_FRAME_HDR) && GetMmapPtr() != nullptr) { +- INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); +- hdr = (struct DwarfEhFrameHdr *) (shdr.offset + (char *)GetMmapPtr()); +- } else if (GetSectionInfo(shdr, EH_FRAME) && GetMmapPtr() != nullptr) { +- DFXLOGW("[%{public}d]: Elf(%{public}s) no found .eh_frame_hdr section, " \ +- "using synthetic .eh_frame section", __LINE__, map->name.c_str()); +- INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); +- synthHdr.version = DW_EH_VERSION; +- synthHdr.ehFramePtrEnc = DW_EH_PE_absptr | +- ((sizeof(ElfW(Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); // 4 : four bytes +- synthHdr.fdeCountEnc = DW_EH_PE_omit; +- synthHdr.tableEnc = DW_EH_PE_omit; +- synthHdr.ehFrame = (ElfW(Addr))(shdr.offset + (char*)GetMmapPtr()); +- hdr = &synthHdr; +- } +- uintptr_t shdrBase = static_cast(loadBase + shdr.addr); +- hasTableInfo_ = FillUnwindTableByEhhdr(hdr, shdrBase, &uti); +- } +- +- if (hasTableInfo_) { +- uti_ = uti; +- return UNW_ERROR_NONE; +- } +- return UNW_ERROR_NO_UNWIND_INFO; +-} +- +-int DfxElf::FindUnwindTableLocal(uintptr_t pc, struct UnwindTableInfo& uti) +-{ +-#if is_ohos && !is_mingw +- DlCbData cbData; +- (void)memset_s(&cbData, sizeof(cbData), 0, sizeof(cbData)); +- cbData.pc = pc; +- cbData.uti.format = -1; +- int ret = dl_iterate_phdr(DlPhdrCb, &cbData); +- if (ret > 0) { +- if (cbData.uti.format != -1) { +- uti = cbData.uti; +- return UNW_ERROR_NONE; +- } +- } +- return UNW_ERROR_NO_UNWIND_INFO; +-#else +- return UNW_ERROR_UNSUPPORTED_VERSION; +-#endif +-} +- +-#if is_ohos && !is_mingw +-bool DfxElf::FindSection(struct dl_phdr_info* info, const std::string secName, ShdrInfo& shdr) +-{ +- if (info == nullptr) { +- return false; +- } +- const char* file = info->dlpi_name; +- if (strlen(file) == 0) { +- file = PROC_SELF_EXE_PATH; +- } +- RegularElfFactory elfFactory(file); +- auto elf = elfFactory.Create(); +- if (elf == nullptr) { +- return false; +- } +- +- return elf->GetSectionInfo(shdr, secName); +-} +- +-void DfxElf::ParsePhdr(struct dl_phdr_info* info, const ElfW(Phdr)* (&pHdrSections)[4], const uintptr_t pc) +-{ +- const ElfW(Phdr)* phdr = info->dlpi_phdr; +- for (size_t i = 0; i < info->dlpi_phnum && phdr != nullptr; i++, phdr++) { +- switch (phdr->p_type) { +- case PT_LOAD: { +- ElfW(Addr) vaddr = phdr->p_vaddr + info->dlpi_addr; +- if (pc >= vaddr && pc < vaddr + phdr->p_memsz) { +- pHdrSections[SECTION_TEXT] = phdr; +- } +- break; +- } +-#if defined(__arm__) +- case PT_ARM_EXIDX: { +- pHdrSections[SECTION_ARMEXIDX] = phdr; +- break; +- } +-#endif +- case PT_GNU_EH_FRAME: { +- pHdrSections[SECTION_EHFRAMEHDR] = phdr; +- break; +- } +- case PT_DYNAMIC: { +- pHdrSections[SECTION_DYNAMIC] = phdr; +- break; +- } +- default: +- break; +- } +- } +-} +- +-bool DfxElf::ProccessDynamic(const ElfW(Phdr)* pDynamic, ElfW(Addr) loadBase, UnwindTableInfo* uti) +-{ +- ElfW(Dyn)* dyn = reinterpret_cast(pDynamic->p_vaddr + loadBase); +- if (dyn == nullptr) { +- return false; +- } +- for (; dyn->d_tag != DT_NULL; ++dyn) { +- if (dyn->d_tag == DT_PLTGOT) { +- uti->gp = dyn->d_un.d_ptr; +- break; +- } +- } +- return true; +-} +- +-struct DwarfEhFrameHdr* DfxElf::InitHdr(struct DwarfEhFrameHdr& synthHdr, +- struct dl_phdr_info* info, const ElfW(Phdr)* pEhHdr) +-{ +- struct DwarfEhFrameHdr* hdr = nullptr; +- if (pEhHdr) { +- INSTR_STATISTIC(InstructionEntriesEhFrame, pEhHdr->p_memsz, 0); +- hdr = reinterpret_cast(pEhHdr->p_vaddr + info->dlpi_addr); +- } else { +- ShdrInfo shdr; +- if (FindSection(info, EH_FRAME, shdr)) { +- DFXLOGW("[%{public}d]: Elf(%{public}s) no found .eh_frame_hdr section, " \ +- "using synthetic .eh_frame section", __LINE__, info->dlpi_name); +- INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); +- synthHdr.version = DW_EH_VERSION; +- synthHdr.ehFramePtrEnc = DW_EH_PE_absptr | +- ((sizeof(ElfW(Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); // 4 : four bytes +- synthHdr.fdeCountEnc = DW_EH_PE_omit; +- synthHdr.tableEnc = DW_EH_PE_omit; +- synthHdr.ehFrame = (ElfW(Addr))(shdr.addr + info->dlpi_addr); +- hdr = &synthHdr; +- } +- } +- return hdr; +-} +- +-int DfxElf::DlPhdrCb(struct dl_phdr_info* info, size_t size, void* data) +-{ +- struct DlCbData* cbData = reinterpret_cast(data); +- if ((info == nullptr) || (cbData == nullptr)) { +- return -1; +- } +- UnwindTableInfo* uti = &cbData->uti; +- uintptr_t pc = cbData->pc; +- const int numOfPhdrSections = 4; +- const ElfW(Phdr)* pHdrSections[numOfPhdrSections] = {nullptr}; +- ParsePhdr(info, pHdrSections, pc); +- +- if (pHdrSections[SECTION_TEXT] == nullptr) { +- return 0; +- } +- ElfW(Addr) loadBase = info->dlpi_addr; +- uti->startPc = pHdrSections[SECTION_TEXT]->p_vaddr + loadBase; +- uti->endPc = uti->startPc + pHdrSections[SECTION_TEXT]->p_memsz; +- DFXLOGU("Elf name: %{public}s", info->dlpi_name); +- uti->namePtr = reinterpret_cast(info->dlpi_name); +- +-#if defined(__arm__) +- if (pHdrSections[SECTION_ARMEXIDX]) { +- ShdrInfo shdr; +- shdr.addr = pHdrSections[SECTION_ARMEXIDX]->p_vaddr; +- shdr.size = pHdrSections[SECTION_ARMEXIDX]->p_memsz; +- return FillUnwindTableByExidx(shdr, loadBase, uti); +- } +-#endif +- +- if (pHdrSections[SECTION_DYNAMIC]) { +- if (!ProccessDynamic(pHdrSections[SECTION_DYNAMIC], loadBase, uti)) { +- return 0; +- } +- } else { +- uti->gp = 0; +- } +- +- struct DwarfEhFrameHdr synthHdr; +- struct DwarfEhFrameHdr* hdr = InitHdr(synthHdr, info, pHdrSections[SECTION_EHFRAMEHDR]); +- +- return FillUnwindTableByEhhdrLocal(hdr, uti); +-} +-#endif +- +-bool DfxElf::Read(uintptr_t pos, void* buf, size_t size) +-{ +- if ((mmap_ != nullptr) && (mmap_->Read(pos, buf, size) == size)) { +- return true; +- } +- return false; +-} +- +-const uint8_t* DfxElf::GetMmapPtr() +-{ +- if (mmap_ == nullptr) { +- return nullptr; +- } +- return static_cast(mmap_->Get()); +-} +- +-size_t DfxElf::GetMmapSize() +-{ +- if (mmap_ == nullptr) { +- return 0; +- } +- return mmap_->Size(); +-} +- +-bool DfxElf::IsValidElf(const void* ptr, size_t size) +-{ +- if (ptr == nullptr) { +- return false; +- } +- +- if (memcmp(ptr, ELFMAG, size) != 0) { +- DFXLOGD("Invalid elf hdr?"); +- return false; +- } +- return true; +-} +-} // namespace HiviewDFX +-} // namespace OHOS ++/* ++ * Copyright (c) 2021-2025 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 "dfx_elf.h" ++ ++#include ++#include ++#include ++#include ++#include ++#if is_mingw || is_mac ++#include "dfx_nonlinux_define.h" ++#else ++#include ++#include ++#endif ++#include ++#include ++#include ++#include ++ ++#include "dfx_define.h" ++#include "dfx_log.h" ++#include "dfx_instr_statistic.h" ++#include "dfx_util.h" ++#include "dfx_maps.h" ++#include "dfx_trace_dlsym.h" ++#include "dwarf_define.h" ++#include "elf_factory.h" ++#include "string_util.h" ++#include "unwinder_config.h" ++ ++namespace OHOS { ++namespace HiviewDFX { ++namespace { ++#undef LOG_DOMAIN ++#undef LOG_TAG ++#define LOG_DOMAIN 0xD002D11 ++#define LOG_TAG "DfxElf" ++#if is_ohos && !is_mingw ++enum HdrSection { ++ SECTION_TEXT = 0, ++ SECTION_ARMEXIDX = 1, ++ SECTION_DYNAMIC = 2, ++ SECTION_EHFRAMEHDR = 3 ++}; ++#endif ++} ++ ++void DfxElf::Init() ++{ ++ uti_.namePtr = 0; ++ uti_.format = -1; ++ hasTableInfo_ = false; ++} ++ ++void DfxElf::Clear() ++{ ++ if (elfParse_ != nullptr) { ++ elfParse_.reset(); ++ elfParse_ = nullptr; ++ } ++ ++ if (mmap_ != nullptr) { ++ mmap_->Clear(); ++ mmap_.reset(); ++ mmap_ = nullptr; ++ } ++} ++ ++bool DfxElf::InitHeaders() ++{ ++ if (mmap_ == nullptr) { ++ return false; ++ } ++ ++ if (elfParse_ != nullptr) { ++ return true; ++ } ++ ++ uint8_t ident[SELFMAG + 1]; ++ if (!Read(0, ident, SELFMAG) || !IsValidElf(ident, SELFMAG)) { ++ return false; ++ } ++ ++ if (!Read(EI_CLASS, &classType_, sizeof(uint8_t))) { ++ return false; ++ } ++ ++ if (classType_ == ELFCLASS32) { ++ elfParse_ = std::unique_ptr(new ElfParser32(mmap_)); ++ } else if (classType_ == ELFCLASS64) { ++ elfParse_ = std::unique_ptr(new ElfParser64(mmap_)); ++ } else { ++ DFXLOGW("InitHeaders failed, classType: %{public}d", classType_); ++ return false; ++ } ++ if (elfParse_ != nullptr) { ++ valid_ = true; ++ elfParse_->InitHeaders(); ++ } ++ return valid_; ++} ++ ++bool DfxElf::IsValid() ++{ ++ if (valid_ == false) { ++ InitHeaders(); ++ } ++ return valid_; ++} ++ ++uint8_t DfxElf::GetClassType() ++{ ++ if (IsValid()) { ++ return classType_; ++ } ++ return ELFCLASSNONE; ++} ++ ++ArchType DfxElf::GetArchType() ++{ ++ if (IsValid()) { ++ elfParse_->GetArchType(); ++ } ++ return ARCH_UNKNOWN; ++} ++ ++int64_t DfxElf::GetLoadBias() ++{ ++ if (loadBias_ == 0) { ++ if (IsValid()) { ++ loadBias_ = elfParse_->GetLoadBias(); ++ DFXLOGU("Elf loadBias: %{public}" PRIx64 "", (uint64_t)loadBias_); ++ } ++ } ++ return loadBias_; ++} ++ ++uint64_t DfxElf::GetLoadBase(uint64_t mapStart, uint64_t mapOffset) ++{ ++ if (loadBase_ == static_cast(-1)) { ++ if (IsValid()) { ++ DFXLOGU("mapStart: %{public}" PRIx64 ", mapOffset: %{public}" PRIx64 "", ++ (uint64_t)mapStart, (uint64_t)mapOffset); ++ loadBase_ = mapStart - mapOffset - static_cast(GetLoadBias()); ++ DFXLOGU("Elf loadBase: %{public}" PRIx64 "", (uint64_t)loadBase_); ++ } ++ } ++ return loadBase_; ++} ++ ++void DfxElf::SetLoadBase(uint64_t base) ++{ ++ loadBase_ = base; ++} ++ ++void DfxElf::SetBaseOffset(uint64_t offset) ++{ ++ baseOffset_ = offset; ++} ++ ++uint64_t DfxElf::GetBaseOffset() ++{ ++ return baseOffset_; ++} ++ ++uint64_t DfxElf::GetStartPc() ++{ ++ if (startPc_ == static_cast(-1)) { ++ if (IsValid()) { ++ auto startVaddr = elfParse_->GetStartVaddr(); ++ if (loadBase_ != static_cast(-1) && startVaddr != static_cast(-1)) { ++ startPc_ = startVaddr + loadBase_; ++ DFXLOGU("Elf startPc: %{public}" PRIx64 "", (uint64_t)startPc_); ++ } ++ } ++ } ++ return startPc_; ++} ++ ++uint64_t DfxElf::GetStartVaddr() ++{ ++ if (IsValid()) { ++ return elfParse_->GetStartVaddr(); ++ } ++ return 0; ++} ++ ++uint64_t DfxElf::GetEndPc() ++{ ++ if (endPc_ == 0) { ++ if (IsValid()) { ++ auto endVaddr = elfParse_->GetEndVaddr(); ++ if (loadBase_ != static_cast(-1) && endVaddr != 0) { ++ endPc_ = endVaddr + loadBase_; ++ DFXLOGU("Elf endPc: %{public}" PRIx64 "", (uint64_t)endPc_); ++ } ++ } ++ } ++ return endPc_; ++} ++ ++uint64_t DfxElf::GetEndVaddr() ++{ ++ if (IsValid()) { ++ return elfParse_->GetEndVaddr(); ++ } ++ return 0; ++} ++ ++uint64_t DfxElf::GetStartOffset() ++{ ++ if (IsValid()) { ++ return elfParse_->GetStartOffset(); ++ } ++ return 0; ++} ++ ++uint64_t DfxElf::GetRelPc(uint64_t pc, uint64_t mapStart, uint64_t mapOffset) ++{ ++ return (pc - GetLoadBase(mapStart, mapOffset)); ++} ++ ++uint64_t DfxElf::GetElfSize() ++{ ++ if (!IsValid()) { ++ return 0; ++ } ++ return elfParse_->GetElfSize(); ++} ++ ++std::string DfxElf::GetElfName() ++{ ++ if (!IsValid()) { ++ return ""; ++ } ++ return elfParse_->GetElfName(); ++} ++ ++void DfxElf::SetBuildId(const std::string& buildId) ++{ ++ buildId_ = buildId; ++} ++ ++std::string DfxElf::GetBuildId(uint64_t noteAddr, uint64_t noteSize) ++{ ++ return ElfParser::ParseHexBuildId(noteAddr, noteSize); ++} ++ ++std::string DfxElf::GetBuildId() ++{ ++ if (buildId_.empty()) { ++ if (!IsValid()) { ++ return ""; ++ } ++ return elfParse_->GetBuildId(); ++ } ++ return buildId_; ++} ++ ++ ++uintptr_t DfxElf::GetGlobalPointer() ++{ ++ if (!IsValid()) { ++ return 0; ++ } ++ return elfParse_->GetGlobalPointer(); ++} ++ ++bool DfxElf::GetSectionInfo(ShdrInfo& shdr, const std::string secName) ++{ ++ if (!IsValid()) { ++ return false; ++ } ++ return elfParse_->GetSectionInfo(shdr, secName); ++} ++ ++bool DfxElf::GetSectionData(unsigned char* buf, uint64_t size, std::string secName) ++{ ++ if (!IsValid()) { ++ return false; ++ } ++ return elfParse_->GetSectionData(buf, size, secName); ++} ++ ++GnuDebugDataHdr DfxElf::GetGnuDebugDataHdr() ++{ ++ if (!IsValid()) { ++ return {}; ++ } ++ return elfParse_->GetGnuDebugDataHdr(); ++} ++ ++bool DfxElf::IsMiniDebugInfoValid() ++{ ++ if (miniDebugInfo_ == nullptr) { ++#if defined(ENABLE_MINIDEBUGINFO) ++ MiniDebugInfoFactory miniDebugInfoFactory(elfParse_->GetGnuDebugDataHdr()); ++ miniDebugInfo_ = miniDebugInfoFactory.Create(); ++#endif ++ } ++ return miniDebugInfo_ != nullptr; ++} ++ ++const std::set& DfxElf::GetFuncSymbols() ++{ ++ if (!IsValid() || !funcSymbols_.empty()) { ++ return funcSymbols_; ++ } ++ if (IsMiniDebugInfoValid()) { ++ funcSymbols_ = miniDebugInfo_->elfParse_->GetFuncSymbols(); ++ DFXLOGU("Get MiniDebugInfo FuncSymbols, size: %{public}zu", funcSymbols_.size()); ++ } ++ const auto &symbols = elfParse_->GetFuncSymbols(); ++ funcSymbols_.insert(symbols.begin(), symbols.end()); ++ DFXLOGU("GetFuncSymbols, size: %{public}zu", funcSymbols_.size()); ++ return funcSymbols_; ++} ++ ++bool DfxElf::GetFuncInfoLazily(uint64_t addr, ElfSymbol& elfSymbol) ++{ ++ DFX_TRACE_SCOPED_DLSYM("GetFuncInfoLazily"); ++ if (FindFuncSymbol(addr, funcSymbols_, elfSymbol)) { ++ return true; ++ } ++ bool findSymbol = elfParse_->GetFuncSymbolByAddr(addr, elfSymbol); ++ if (!findSymbol && IsMiniDebugInfoValid()) { ++ findSymbol = miniDebugInfo_->elfParse_->GetFuncSymbolByAddr(addr, elfSymbol); ++ } ++ ++ if (findSymbol) { ++ funcSymbols_.emplace(elfSymbol); ++ DFXLOGU("GetFuncInfoLazily, size: %{public}zu", funcSymbols_.size()); ++ } ++ return findSymbol; ++} ++ ++bool DfxElf::GetFuncInfo(uint64_t addr, ElfSymbol& elfSymbol) ++{ ++ if (!IsValid()) { ++ return false; ++ } ++ if (UnwinderConfig::GetEnableLoadSymbolLazily()) { ++ return GetFuncInfoLazily(addr, elfSymbol); ++ } ++ ++ const auto &symbols = GetFuncSymbols(); ++ return FindFuncSymbol(addr, symbols, elfSymbol); ++} ++ ++bool DfxElf::FindFuncSymbol(uint64_t addr, const std::set& symbols, ElfSymbol& elfSymbol) ++{ ++ DFX_TRACE_SCOPED_DLSYM("FindFuncSymbol"); ++ if (symbols.empty()) { ++ return false; ++ } ++ // Find the first position that is not less than value ++ ElfSymbol tmpSym; ++ tmpSym.value = addr; ++ auto next = symbols.upper_bound(tmpSym); ++ if (next != symbols.begin()) { ++ next--; ++ } ++ if (next->value <= addr && addr < (next->value + next->size)) { ++ elfSymbol = *next; ++ return true; ++ } ++ return false; ++} ++ ++const std::unordered_map& DfxElf::GetPtLoads() ++{ ++ return elfParse_->GetPtLoads(); ++} ++ ++bool DfxElf::FillUnwindTableByExidx(ShdrInfo shdr, uintptr_t loadBase, struct UnwindTableInfo* uti) ++{ ++ if (uti == nullptr) { ++ return false; ++ } ++ uti->gp = 0; ++ uti->tableData = loadBase + shdr.addr; ++ uti->tableLen = shdr.size; ++ INSTR_STATISTIC(InstructionEntriesArmExidx, shdr.size, 0); ++ uti->format = UNW_INFO_FORMAT_ARM_EXIDX; ++ DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, ++ (uint64_t)uti->tableData, (int)uti->tableLen); ++ return true; ++} ++ ++#if is_ohos && !is_mingw ++bool DfxElf::FillUnwindTableByEhhdrLocal(struct DwarfEhFrameHdr* hdr, struct UnwindTableInfo* uti) ++{ ++ if (hdr == nullptr) { ++ return false; ++ } ++ if (hdr->version != DW_EH_VERSION) { ++ DFXLOGE("[%{public}d]: version(%{public}d) error", __LINE__, hdr->version); ++ return false; ++ } ++ ++ uintptr_t ptr = (uintptr_t)(&(hdr->ehFrame)); ++ DFXLOGU("[%{public}d]: hdr: %{public}" PRIx64 ", ehFrame: %{public}" PRIx64 "", __LINE__, ++ (uint64_t)hdr, (uint64_t)ptr); ++ auto memory = std::make_shared(UNWIND_TYPE_LOCAL); ++ DFXLOGU("[%{public}d]: gp: %{public}" PRIx64 ", ehFramePtrEnc: %{public}x, fdeCountEnc: %{public}x", __LINE__, ++ (uint64_t)uti->gp, hdr->ehFramePtrEnc, hdr->fdeCountEnc); ++ memory->SetDataOffset(uti->gp); ++ MAYBE_UNUSED uintptr_t ehFrameStart = memory->ReadEncodedValue(ptr, hdr->ehFramePtrEnc); ++ uintptr_t fdeCount = memory->ReadEncodedValue(ptr, hdr->fdeCountEnc); ++ DFXLOGU("[%{public}d]: ehFrameStart: %{public}" PRIx64 ", fdeCount: %{public}d", __LINE__, ++ (uint64_t)ehFrameStart, (int)fdeCount); ++ ++ if (hdr->tableEnc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { ++ DFXLOGU("tableEnc: %{public}x", hdr->tableEnc); ++ if (hdr->fdeCountEnc == DW_EH_PE_omit) { ++ fdeCount = ~0UL; ++ } ++ if (hdr->ehFramePtrEnc == DW_EH_PE_omit) { ++ DFXLOGE("ehFramePtrEnc(%{public}x) error", hdr->ehFramePtrEnc); ++ return false; ++ } ++ uti->isLinear = true; ++ uti->tableLen = fdeCount; ++ uti->tableData = ehFrameStart; ++ } else { ++ uti->isLinear = false; ++ uti->tableLen = (fdeCount * sizeof(DwarfTableEntry)) / sizeof(uintptr_t); ++ uti->tableData = ptr; ++ uti->segbase = (uintptr_t)hdr; ++ } ++ uti->format = UNW_INFO_FORMAT_REMOTE_TABLE; ++ DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, ++ (uint64_t)uti->tableData, (int)uti->tableLen); ++ return true; ++} ++#endif ++ ++bool DfxElf::FillUnwindTableByEhhdr(struct DwarfEhFrameHdr* hdr, uintptr_t shdrBase, struct UnwindTableInfo* uti) ++{ ++ if ((hdr == nullptr) || (uti == nullptr)) { ++ return false; ++ } ++ if (hdr->version != DW_EH_VERSION) { ++ DFXLOGE("[%{public}d]: version(%{public}d) error", __LINE__, hdr->version); ++ return false; ++ } ++ uintptr_t ptr = (uintptr_t)(&(hdr->ehFrame)); ++ DFXLOGU("[%{public}d]: hdr: %{public}" PRIx64 ", ehFrame: %{public}" PRIx64 "", __LINE__, ++ (uint64_t)hdr, (uint64_t)ptr); ++ ++ uti->gp = GetGlobalPointer(); ++ DFXLOGU("[%{public}d]: gp: %{public}" PRIx64 ", ehFramePtrEnc: %{public}x, fdeCountEnc: %{public}x", __LINE__, ++ (uint64_t)uti->gp, hdr->ehFramePtrEnc, hdr->fdeCountEnc); ++ mmap_->SetDataOffset(uti->gp); ++ auto ptrOffset = ptr - reinterpret_cast(GetMmapPtr()); ++ MAYBE_UNUSED uintptr_t ehFrameStart = mmap_->ReadEncodedValue(ptrOffset, hdr->ehFramePtrEnc); ++ uintptr_t fdeCount = mmap_->ReadEncodedValue(ptrOffset, hdr->fdeCountEnc); ++ DFXLOGU("[%{public}d]: ehFrameStart: %{public}" PRIx64 ", fdeCount: %{public}d", __LINE__, ++ (uint64_t)ehFrameStart, (int)fdeCount); ++ ptr = reinterpret_cast(GetMmapPtr()) + ptrOffset; ++ ++ if (hdr->tableEnc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { ++ DFXLOGU("[%{public}d]: tableEnc: %{public}x", __LINE__, hdr->tableEnc); ++ if (hdr->fdeCountEnc == DW_EH_PE_omit) { ++ fdeCount = ~0UL; ++ } ++ if (hdr->ehFramePtrEnc == DW_EH_PE_omit) { ++ DFXLOGE("[%{public}d]: ehFramePtrEnc(%{public}x) error", __LINE__, hdr->ehFramePtrEnc); ++ return false; ++ } ++ uti->isLinear = true; ++ uti->tableLen = fdeCount; ++ uti->tableData = shdrBase + ehFrameStart; ++ uti->segbase = shdrBase; ++ } else { ++ uti->isLinear = false; ++ uti->tableLen = (fdeCount * sizeof(DwarfTableEntry)) / sizeof(uintptr_t); ++ uti->tableData = shdrBase + ptr - (uintptr_t)hdr; ++ uti->segbase = shdrBase; ++ } ++ uti->format = UNW_INFO_FORMAT_REMOTE_TABLE; ++ DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, ++ (uint64_t)uti->tableData, (int)uti->tableLen); ++ return true; ++} ++ ++int DfxElf::FindUnwindTableInfo(uintptr_t pc, std::shared_ptr map, struct UnwindTableInfo& uti) ++{ ++ if (hasTableInfo_ && pc >= uti_.startPc && pc < uti_.endPc) { ++ uti = uti_; ++ DFXLOGU("FindUnwindTableInfo had found"); ++ return UNW_ERROR_NONE; ++ } ++ if (map == nullptr) { ++ return UNW_ERROR_INVALID_MAP; ++ } ++ uintptr_t loadBase = GetLoadBase(map->begin, map->offset); ++ uti.startPc = GetStartPc(); ++ uti.endPc = GetEndPc(); ++ if (pc < uti.startPc || pc >= uti.endPc) { ++ DFXLOGU("Elf startPc: %{public}" PRIx64 ", endPc: %{public}" PRIx64 "", ++ (uint64_t)uti.startPc, (uint64_t)uti.endPc); ++ return UNW_ERROR_PC_NOT_IN_UNWIND_INFO; ++ } ++ ++ ShdrInfo shdr; ++#if defined(__arm__) ++ if (GetSectionInfo(shdr, ARM_EXIDX)) { ++ hasTableInfo_ = FillUnwindTableByExidx(shdr, loadBase, &uti); ++ } ++#endif ++ ++ if (!hasTableInfo_) { ++ struct DwarfEhFrameHdr* hdr = nullptr; ++ struct DwarfEhFrameHdr synthHdr; ++ if (GetSectionInfo(shdr, EH_FRAME_HDR) && GetMmapPtr() != nullptr) { ++ INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); ++ hdr = (struct DwarfEhFrameHdr *) (shdr.offset + (char *)GetMmapPtr()); ++ } else if (GetSectionInfo(shdr, EH_FRAME) && GetMmapPtr() != nullptr) { ++ DFXLOGW("[%{public}d]: Elf(%{public}s) no found .eh_frame_hdr section, " \ ++ "using synthetic .eh_frame section", __LINE__, map->name.c_str()); ++ INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); ++ synthHdr.version = DW_EH_VERSION; ++ synthHdr.ehFramePtrEnc = DW_EH_PE_absptr | ++ ((sizeof(ElfW(Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); // 4 : four bytes ++ synthHdr.fdeCountEnc = DW_EH_PE_omit; ++ synthHdr.tableEnc = DW_EH_PE_omit; ++ synthHdr.ehFrame = (ElfW(Addr))(shdr.offset + (char*)GetMmapPtr()); ++ hdr = &synthHdr; ++ } ++ uintptr_t shdrBase = static_cast(loadBase + shdr.addr); ++ hasTableInfo_ = FillUnwindTableByEhhdr(hdr, shdrBase, &uti); ++ } ++ ++ if (hasTableInfo_) { ++ uti_ = uti; ++ return UNW_ERROR_NONE; ++ } ++ return UNW_ERROR_NO_UNWIND_INFO; ++} ++ ++int DfxElf::FindUnwindTableLocal(uintptr_t pc, struct UnwindTableInfo& uti) ++{ ++#if is_ohos && !is_mingw ++ DlCbData cbData; ++ (void)memset_s(&cbData, sizeof(cbData), 0, sizeof(cbData)); ++ cbData.pc = pc; ++ cbData.uti.format = -1; ++ int ret = dl_iterate_phdr(DlPhdrCb, &cbData); ++ if (ret > 0) { ++ if (cbData.uti.format != -1) { ++ uti = cbData.uti; ++ return UNW_ERROR_NONE; ++ } ++ } ++ return UNW_ERROR_NO_UNWIND_INFO; ++#else ++ return UNW_ERROR_UNSUPPORTED_VERSION; ++#endif ++} ++ ++#if is_ohos && !is_mingw ++bool DfxElf::FindSection(struct dl_phdr_info* info, const std::string secName, ShdrInfo& shdr) ++{ ++ if (info == nullptr) { ++ return false; ++ } ++ const char* file = info->dlpi_name; ++ if (strlen(file) == 0) { ++ file = PROC_SELF_EXE_PATH; ++ } ++ RegularElfFactory elfFactory(file); ++ auto elf = elfFactory.Create(); ++ if (elf == nullptr) { ++ return false; ++ } ++ ++ return elf->GetSectionInfo(shdr, secName); ++} ++ ++void DfxElf::ParsePhdr(struct dl_phdr_info* info, const ElfW(Phdr)* (&pHdrSections)[4], const uintptr_t pc) ++{ ++ const ElfW(Phdr)* phdr = info->dlpi_phdr; ++ for (size_t i = 0; i < info->dlpi_phnum && phdr != nullptr; i++, phdr++) { ++ switch (phdr->p_type) { ++ case PT_LOAD: { ++ ElfW(Addr) vaddr = phdr->p_vaddr + info->dlpi_addr; ++ if (pc >= vaddr && pc < vaddr + phdr->p_memsz) { ++ pHdrSections[SECTION_TEXT] = phdr; ++ } ++ break; ++ } ++#if defined(__arm__) ++ case PT_ARM_EXIDX: { ++ pHdrSections[SECTION_ARMEXIDX] = phdr; ++ break; ++ } ++#endif ++ case PT_GNU_EH_FRAME: { ++ pHdrSections[SECTION_EHFRAMEHDR] = phdr; ++ break; ++ } ++ case PT_DYNAMIC: { ++ pHdrSections[SECTION_DYNAMIC] = phdr; ++ break; ++ } ++ default: ++ break; ++ } ++ } ++} ++ ++bool DfxElf::ProccessDynamic(const ElfW(Phdr)* pDynamic, ElfW(Addr) loadBase, UnwindTableInfo* uti) ++{ ++ ElfW(Dyn)* dyn = reinterpret_cast(pDynamic->p_vaddr + loadBase); ++ if (dyn == nullptr) { ++ return false; ++ } ++ for (; dyn->d_tag != DT_NULL; ++dyn) { ++ if (dyn->d_tag == DT_PLTGOT) { ++ uti->gp = dyn->d_un.d_ptr; ++ break; ++ } ++ } ++ return true; ++} ++ ++struct DwarfEhFrameHdr* DfxElf::InitHdr(struct DwarfEhFrameHdr& synthHdr, ++ struct dl_phdr_info* info, const ElfW(Phdr)* pEhHdr) ++{ ++ struct DwarfEhFrameHdr* hdr = nullptr; ++ if (pEhHdr) { ++ INSTR_STATISTIC(InstructionEntriesEhFrame, pEhHdr->p_memsz, 0); ++ hdr = reinterpret_cast(pEhHdr->p_vaddr + info->dlpi_addr); ++ } else { ++ ShdrInfo shdr; ++ if (FindSection(info, EH_FRAME, shdr)) { ++ DFXLOGW("[%{public}d]: Elf(%{public}s) no found .eh_frame_hdr section, " \ ++ "using synthetic .eh_frame section", __LINE__, info->dlpi_name); ++ INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); ++ synthHdr.version = DW_EH_VERSION; ++ synthHdr.ehFramePtrEnc = DW_EH_PE_absptr | ++ ((sizeof(ElfW(Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); // 4 : four bytes ++ synthHdr.fdeCountEnc = DW_EH_PE_omit; ++ synthHdr.tableEnc = DW_EH_PE_omit; ++ synthHdr.ehFrame = (ElfW(Addr))(shdr.addr + info->dlpi_addr); ++ hdr = &synthHdr; ++ } ++ } ++ return hdr; ++} ++ ++int DfxElf::DlPhdrCb(struct dl_phdr_info* info, size_t size, void* data) ++{ ++ struct DlCbData* cbData = reinterpret_cast(data); ++ if ((info == nullptr) || (cbData == nullptr)) { ++ return -1; ++ } ++ UnwindTableInfo* uti = &cbData->uti; ++ uintptr_t pc = cbData->pc; ++ const int numOfPhdrSections = 4; ++ const ElfW(Phdr)* pHdrSections[numOfPhdrSections] = {nullptr}; ++ ParsePhdr(info, pHdrSections, pc); ++ ++ if (pHdrSections[SECTION_TEXT] == nullptr) { ++ return 0; ++ } ++ ElfW(Addr) loadBase = info->dlpi_addr; ++ uti->startPc = pHdrSections[SECTION_TEXT]->p_vaddr + loadBase; ++ uti->endPc = uti->startPc + pHdrSections[SECTION_TEXT]->p_memsz; ++ DFXLOGU("Elf name: %{public}s", info->dlpi_name); ++ uti->namePtr = reinterpret_cast(info->dlpi_name); ++ ++#if defined(__arm__) ++ if (pHdrSections[SECTION_ARMEXIDX]) { ++ ShdrInfo shdr; ++ shdr.addr = pHdrSections[SECTION_ARMEXIDX]->p_vaddr; ++ shdr.size = pHdrSections[SECTION_ARMEXIDX]->p_memsz; ++ return FillUnwindTableByExidx(shdr, loadBase, uti); ++ } ++#endif ++ ++ if (pHdrSections[SECTION_DYNAMIC]) { ++ if (!ProccessDynamic(pHdrSections[SECTION_DYNAMIC], loadBase, uti)) { ++ return 0; ++ } ++ } else { ++ uti->gp = 0; ++ } ++ ++ struct DwarfEhFrameHdr synthHdr; ++ struct DwarfEhFrameHdr* hdr = InitHdr(synthHdr, info, pHdrSections[SECTION_EHFRAMEHDR]); ++ ++ return FillUnwindTableByEhhdrLocal(hdr, uti); ++} ++#endif ++ ++bool DfxElf::Read(uintptr_t pos, void* buf, size_t size) ++{ ++ if ((mmap_ != nullptr) && (mmap_->Read(pos, buf, size) == size)) { ++ return true; ++ } ++ return false; ++} ++ ++const uint8_t* DfxElf::GetMmapPtr() ++{ ++ if (mmap_ == nullptr) { ++ return nullptr; ++ } ++ return static_cast(mmap_->Get()); ++} ++ ++size_t DfxElf::GetMmapSize() ++{ ++ if (mmap_ == nullptr) { ++ return 0; ++ } ++ return mmap_->Size(); ++} ++ ++bool DfxElf::IsValidElf(const void* ptr, size_t size) ++{ ++ if (ptr == nullptr) { ++ return false; ++ } ++ ++ if (memcmp(ptr, ELFMAG, size) != 0) { ++ DFXLOGD("Invalid elf hdr?"); ++ return false; ++ } ++ return true; ++} ++} // namespace HiviewDFX ++} // namespace OHOS -- Gitee