From d6395f70f863ac07ffe3df2b32ae410944d8d4e4 Mon Sep 17 00:00:00 2001 From: ganchuantao1 Date: Thu, 17 Jul 2025 11:00:22 +0800 Subject: [PATCH] just for test Signed-off-by:ganchuantao1 Signed-off-by: ganchuantao1 --- device/base/include/common.h | 15 - device/plugins/native_daemon/BUILD.gn | 3 - .../native_daemon/include/hook_common.h | 27 +- .../native_daemon/include/hook_manager.h | 20 +- .../native_daemon/include/hook_record.h | 208 ------ .../include/hook_record_factory.h | 59 -- .../native_daemon/include/stack_builder.h | 91 --- .../include/stack_data_repeater.h | 51 +- .../native_daemon/include/stack_preprocess.h | 77 +-- .../plugins/native_daemon/include/utilities.h | 2 - .../native_daemon/include/virtual_runtime.h | 3 +- .../native_memory_profiler_sa_config.h | 1 - .../native_memory_profiler_sa_service.h | 52 +- .../src/native_memory_profiler_sa_config.cpp | 6 +- .../src/native_memory_profiler_sa_service.cpp | 166 ++--- .../native_memory_profiler_sa/test/BUILD.gn | 3 - .../native_daemon/src/hook_manager.cpp | 223 +++--- .../plugins/native_daemon/src/hook_record.cpp | 209 ------ .../native_daemon/src/hook_record_factory.cpp | 249 ------- .../native_daemon/src/hook_service.cpp | 21 +- .../native_daemon/src/stack_builder.cpp | 245 ------- .../native_daemon/src/stack_data_repeater.cpp | 67 +- .../native_daemon/src/stack_preprocess.cpp | 654 ++++++++++++------ .../plugins/native_daemon/src/utilities.cpp | 72 -- .../native_daemon/src/virtual_runtime.cpp | 41 +- device/plugins/native_daemon/test/BUILD.gn | 5 - .../native/hook_record_factory_test.cpp | 196 ------ .../native/include/hook_record_factory_test.h | 26 - .../native/include/stack_builder_test.h | 27 - .../common/native/stack_builder_test.cpp | 189 ----- .../common/native/stack_preprocess_test.cpp | 4 +- device/plugins/native_hook/BUILD.gn | 1 - .../native_hook/include/address_handler.h | 76 -- .../native_hook/include/hook_socket_client.h | 21 +- .../native_hook/include/runtime_stack_range.h | 1 - .../native_hook/include/stack_writer.h | 4 - .../native_hook/src/address_handler.cpp | 163 ----- .../plugins/native_hook/src/hook_client.cpp | 200 ++---- .../native_hook/src/hook_socket_client.cpp | 107 ++- .../native_hook/src/runtime_stack_range.cpp | 42 +- .../plugins/native_hook/src/stack_writer.cpp | 7 - device/plugins/native_hook/test/BUILD.gn | 1 - .../test/unittest/address_handler_test.cpp | 176 ----- .../test/unittest/check_hook_data_test.cpp | 68 +- .../test/unittest/hook_socket_client_test.cpp | 41 +- .../test/unittest/stack_writer_test.cpp | 133 ---- .../native_hook/native_hook_config.proto | 1 - 47 files changed, 966 insertions(+), 3088 deletions(-) delete mode 100644 device/plugins/native_daemon/include/hook_record.h delete mode 100644 device/plugins/native_daemon/include/hook_record_factory.h delete mode 100644 device/plugins/native_daemon/include/stack_builder.h delete mode 100644 device/plugins/native_daemon/src/hook_record.cpp delete mode 100644 device/plugins/native_daemon/src/hook_record_factory.cpp delete mode 100644 device/plugins/native_daemon/src/stack_builder.cpp delete mode 100644 device/plugins/native_daemon/test/unittest/common/native/hook_record_factory_test.cpp delete mode 100644 device/plugins/native_daemon/test/unittest/common/native/include/hook_record_factory_test.h delete mode 100644 device/plugins/native_daemon/test/unittest/common/native/include/stack_builder_test.h delete mode 100644 device/plugins/native_daemon/test/unittest/common/native/stack_builder_test.cpp delete mode 100644 device/plugins/native_hook/include/address_handler.h delete mode 100644 device/plugins/native_hook/src/address_handler.cpp delete mode 100644 device/plugins/native_hook/test/unittest/address_handler_test.cpp diff --git a/device/base/include/common.h b/device/base/include/common.h index a6daa140f..6e5607db8 100644 --- a/device/base/include/common.h +++ b/device/base/include/common.h @@ -70,20 +70,5 @@ enum ErrorType { RET_FAIL = -1, RET_SUCC = 0, }; - -class SpinLock { -public: - void Lock() - { - while (flag.test_and_set(std::memory_order_acquire)) {} - } - - void Unlock() - { - flag.clear(std::memory_order_release); - } -private: - std::atomic_flag flag = ATOMIC_FLAG_INIT; -}; } // COMMON #endif // COMMON_H \ No newline at end of file diff --git a/device/plugins/native_daemon/BUILD.gn b/device/plugins/native_daemon/BUILD.gn index 85fd18368..eb8ec388f 100644 --- a/device/plugins/native_daemon/BUILD.gn +++ b/device/plugins/native_daemon/BUILD.gn @@ -63,13 +63,10 @@ ohos_executable("native_daemon") { "src/dwarf_encoding.cpp", "src/get_thread_id.cpp", "src/hook_manager.cpp", - "src/hook_record.cpp", - "src/hook_record_factory.cpp", "src/hook_service.cpp", "src/hook_standalone.cpp", "src/main.cpp", "src/register.cpp", - "src/stack_builder.cpp", "src/stack_data_repeater.cpp", "src/stack_preprocess.cpp", "src/symbols_file.cpp", diff --git a/device/plugins/native_daemon/include/hook_common.h b/device/plugins/native_daemon/include/hook_common.h index 935e98e32..0915450a6 100644 --- a/device/plugins/native_daemon/include/hook_common.h +++ b/device/plugins/native_daemon/include/hook_common.h @@ -31,20 +31,18 @@ namespace OHOS { namespace Developtools { namespace NativeDaemon { -constexpr int STACK_DATA_SIZE = 400000; -constexpr int SPEED_UP_THRESHOLD = STACK_DATA_SIZE / 2; -constexpr int SLOW_DOWN_THRESHOLD = STACK_DATA_SIZE / 4; -constexpr int32_t MIN_STACK_DEPTH = 6; +const int STACK_DATA_SIZE = 40000; +const int SPEED_UP_THRESHOLD = STACK_DATA_SIZE / 2; +const int SLOW_DOWN_THRESHOLD = STACK_DATA_SIZE / 4; +const int32_t MIN_STACK_DEPTH = 6; // filter two layers of dwarf stack in libnative_hook.z.so const size_t FILTER_STACK_DEPTH = 2; const size_t MAX_CALL_FRAME_UNWIND_SIZE = MAX_UNWIND_DEPTH + FILTER_STACK_DEPTH; // dlopen function minimum stack depth const int32_t DLOPEN_MIN_UNWIND_DEPTH = 5; +const uint32_t MMAP_FILE_TYPE = (1u << 8); // default max js stack depth const int32_t DEFAULT_MAX_JS_STACK_DEPTH = 10; -constexpr int SHARED_MEMORY_NUM = 1; -constexpr uint64_t DWARF_ERROR_ID = 999999; -constexpr uint64_t SIZE_MASK = 0xFFFFFF0000000000; } } } @@ -75,21 +73,8 @@ enum { THREAD_NAME_MSG, PR_SET_VMA_MSG, JS_STACK_MSG, - MMAP_FILE_TYPE, NMD_MSG, END_MSG, - FREE_MSG_SIMP, - UNKNOWN, -}; - -enum SymbolType { - NATIVE_SYMBOL, - JS_SYMBOL, -}; - -struct Range { - uint64_t start; - uint64_t end; }; struct alignas(8) MmapFileRawData { // 8 is 8 bit @@ -177,7 +162,6 @@ struct alignas(8) ClientConfig { // 8 is 8 bit largestSize = 0; secondLargestSize = 0; maxGrowthSize = 0; - targetSoName = ""; } std::string ToString() @@ -220,6 +204,5 @@ struct alignas(8) ClientConfig { // 8 is 8 bit uint32_t largestSize = 0; uint32_t secondLargestSize = 0; uint32_t maxGrowthSize = 0; - std::string targetSoName; }; #endif // HOOK_COMMON_H \ No newline at end of file diff --git a/device/plugins/native_daemon/include/hook_manager.h b/device/plugins/native_daemon/include/hook_manager.h index 9f744c1de..2607f50b6 100644 --- a/device/plugins/native_daemon/include/hook_manager.h +++ b/device/plugins/native_daemon/include/hook_manager.h @@ -20,8 +20,7 @@ #include #include #include -#include "hook_record_factory.h" -#include "hook_record.h" + #include "buffer_writer.h" #include "manager_interface.h" #include "epoll_event_poller.h" @@ -63,13 +62,15 @@ public: ~HookManagerCtx() {} int32_t pid = -1; std::string processName; - std::vector> shareMemoryBlockList; - std::vector> eventNotifierList; - std::vector> eventPollerList; - std::vector smbNames; + std::string smbName; + std::shared_ptr shareMemoryBlock = nullptr; + std::shared_ptr eventNotifier = nullptr; + std::unique_ptr eventPoller = nullptr; std::shared_ptr stackData = nullptr; std::shared_ptr stackPreprocess = nullptr; bool isRecordAccurately = false; + std::array, CACHE_ARRAY_SIZE> rawDataArray = {}; + uint32_t rawStackCount = 0; void FlushStackArray(); }; HookManager() = default; @@ -97,14 +98,14 @@ public: void SethookStandalone(bool); bool HandleHookContext(const std::shared_ptr& ctx); void StartPluginSession(std::unordered_map>* pidInfo = nullptr); - void ReadShareMemory(const std::shared_ptr& hookCtx, int sharedMemoryIndex); + void ReadShareMemory(const std::shared_ptr& hookCtx); void SetHookConfig(const NativeHookConfig& hookConfig); void SetHookConfig(const std::shared_ptr& config); int32_t CreatePluginSession(); void RegisterWriter(const std::shared_ptr writer); void WriteHookConfig(); std::string GetCmdArgs(NativeHookConfig traceConfig); - std::vector GetFds(int32_t pid, const std::string& name); + std::pair GetFds(int32_t pid, const std::string& name); inline void SetSaServiceConfig(bool saFlag, bool isProtobufSerialize) { isSaService_ = saFlag; @@ -135,7 +136,7 @@ public: } void SetNmdInfo(std::pair); void FlushRawStackArray(const std::shared_ptr& hookCtx, - std::shared_ptr& hookRecord); + std::shared_ptr& rawStack); std::string simplifiedNmd_; volatile bool nmdComplete_ = false; @@ -171,7 +172,6 @@ private: uint32_t largestSize_ = 0; uint32_t secondLargestSize_ = 0; uint32_t maxGrowthSize_ = 0; - std::shared_ptr factory_{nullptr}; }; } #endif // AGENT_MANAGER_H \ No newline at end of file diff --git a/device/plugins/native_daemon/include/hook_record.h b/device/plugins/native_daemon/include/hook_record.h deleted file mode 100644 index 54247fc5a..000000000 --- a/device/plugins/native_daemon/include/hook_record.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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. - */ -#ifndef HOOK_RECORD_H -#define HOOK_RECORD_H -#include -#include -#include -#include "hook_common.h" -#include "perf_event_record.h" -#include "native_hook_config.pb.h" -#include "native_hook_result.pb.h" -#include "native_hook_result.pbencoder.h" -#include "nocopyable.h" -#include "utilities.h" -#include "logging.h" - -namespace OHOS::Developtools::NativeDaemon { -const std::string MMAP_FILE_PAGE_PREFIX = "FilePage:"; -const std::string PR_SET_VMA_PREFIX = "Anonymous:"; -using NativeHookProto = std::variant; - -struct RawStack { - std::unique_ptr baseStackData = nullptr; // save the shared memory data - BaseStackRawData* stackContext = nullptr; // points to the foundation type data - union { - uint8_t* stackData; - const char* jsStackData = nullptr; - }; - uint8_t* data = nullptr; // fp mode data is ip, dwarf mode data is regs - uint32_t stackSize = 0; - uint8_t fpDepth = 0; // fp mode fpDepth is ip depth, dwarf mode is invalid - bool reportFlag = false; - bool reduceStackFlag = false; - void Reset() - { - baseStackData = nullptr; - stackContext = nullptr; - data = nullptr; - stackData = nullptr; - stackSize = 0; - fpDepth = 0; - reportFlag = false; - reduceStackFlag = false; - } -}; - -struct SerializeInfo { - std::vector* callFrames; - uint32_t stackMapId = 0; - std::string tagName = ""; - NativeHookConfig* config = nullptr; -}; - -using RawStackPtr = std::shared_ptr; - -class HookRecord { -public: - HookRecord() = default; - HookRecord(RawStackPtr rawStack) : rawStack_(rawStack){}; - - virtual uint16_t GetType(); - - virtual void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo){}; - - virtual void Reset(); - - virtual bool IsValid(); - - virtual uint64_t GetAddr(); - - RawStackPtr GetRawStack() - { - return rawStack_; - } - - virtual void SetAddr(uint64_t addr); - - template - void SetEventFrame(T* event, SerializeInfo& hookInfo); - - template - void SetFrameInfo(T& frame, CallFrame& callFrame, NativeHookConfig* config); - - template - void SetSize(T* event); - - virtual ~HookRecord() {}; - RawStackPtr rawStack_ = nullptr; -}; - -using HookRecordPtr = STD_PTR(shared, OHOS::Developtools::NativeDaemon::HookRecord); - -class FreeRecord : public HookRecord { -public: - FreeRecord() {}; - FreeRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; - void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo); - ~FreeRecord() {}; -}; - -class FreeRecordSimp : public HookRecord { -public: - FreeRecordSimp() {}; - FreeRecordSimp(uint64_t freeAddr) : freeAddr_(freeAddr) {}; - ~FreeRecordSimp() {}; - uint16_t GetType() override - { - return FREE_MSG_SIMP; - } - - void Reset() override - { - freeAddr_ = 0; - } - - uint64_t GetAddr() override - { - return freeAddr_; - } - - void SetAddr(uint64_t freeAddr) override - { - freeAddr_ = freeAddr; - } - - bool IsValid() override - { - return (freeAddr_ != 0); - } - -private: - uint64_t freeAddr_ = 0; -}; - -class MallocRecord : public HookRecord { -public: - MallocRecord() {}; - MallocRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; - void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo); -}; - -class MmapRecord : public HookRecord { -public: - MmapRecord() {}; - MmapRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; - void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo); -}; - -class MmapFilePageRecord : public HookRecord { -public: - MmapFilePageRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; - void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo); -}; - -class MunmapRecord : public HookRecord { -public: - MunmapRecord() {}; - MunmapRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; - void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo); -}; - -class PrSetVmaRecord : public HookRecord { -public: - PrSetVmaRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; - void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo); -}; - -class MemoryUsingRecord : public HookRecord { -public: - MemoryUsingRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; - void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo); -}; - -class MemoryUnusingRecord : public HookRecord { -public: - MemoryUnusingRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; - void SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo); -}; - -class NmdRecord : public HookRecord { -public: - NmdRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; -}; - -class JsRecord : public HookRecord { -public: - JsRecord() {}; - JsRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; -}; - -class TagRecord : public HookRecord { -public: - TagRecord(RawStackPtr rawStack) : HookRecord(rawStack) {}; -}; -} -#endif //HOOK_RECORD_H \ No newline at end of file diff --git a/device/plugins/native_daemon/include/hook_record_factory.h b/device/plugins/native_daemon/include/hook_record_factory.h deleted file mode 100644 index e3ff19aaf..000000000 --- a/device/plugins/native_daemon/include/hook_record_factory.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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. - */ - -#ifndef HOOK_RECORD_FACTORY_H -#define HOOK_RECORD_FACTORY_H -#include -#include -#include -#include "hook_common.h" -#include "hook_record.h" - -namespace OHOS::Developtools::NativeDaemon { -constexpr int RAW_DATA_CACHE_INIT_SIZE = 40000; -constexpr int HOOK_RECORD_CACHE_INIT_SIZE = 20000; -constexpr int RAW_DATA_CACHE_MAX_SIZE = 400000; -constexpr int HOOK_RECORD_CACHE_MAX_SIZE = 200000; - -class HookRecordFactory { -public: - HookRecordFactory() = delete; - HookRecordFactory(NativeHookConfig hookConfig); - std::shared_ptr GetHookRecord(const int8_t sharedMemData[], uint32_t size, bool storeData = true); - void SaveHookRecord(HookRecordPtr hookRecord); - - template - std::shared_ptr GetRecordFromCache(std::deque>& dataCache, int16_t type); - std::shared_ptr GetRawStackFromCache(); - void SaveRawStack(RawStackPtr rawStack); - std::shared_ptr CreateStackRecord(uint16_t type, RawStackPtr rawStack); - void SaveRecordToCache(uint16_t type, HookRecordPtr hookRecord); - void InitRawStack(RawStackPtr rawStack, const int8_t sharedMemData[], - uint32_t size, bool storeData); - -private: - NativeHookConfig hookConfig_; - std::deque> rawStackCache_; - std::deque> freeRecordSimpCache_; - std::deque> freeRecordCache_; - std::deque> mallocRecordCache_; - std::deque> mmapRecordCache_; - std::deque> munmapRecordCache_; - std::deque> jsRecordCache_; - std::mutex rawStackMutex_; - std::mutex recordMutex_; -}; -} -#endif //HOOK_RECORD_FACTORY_H \ No newline at end of file diff --git a/device/plugins/native_daemon/include/stack_builder.h b/device/plugins/native_daemon/include/stack_builder.h deleted file mode 100644 index b9d3d205d..000000000 --- a/device/plugins/native_daemon/include/stack_builder.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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. - */ -#ifndef STACK_BUILDER_H -#define STACK_BUILDER_H - -#include "hook_common.h" -#include "hook_record.h" -#include "virtual_runtime.h" -#include "native_hook_config.pb.h" -namespace OHOS::Developtools::NativeDaemon { - -class StackBuilder { -public: - StackBuilder() = delete; - StackBuilder(NativeHookConfig* config, std::shared_ptr runtime) - : hookConfig_(config), runtimeInstance_(runtime) {}; - virtual ~StackBuilder() {}; - virtual void PrepareUnwind(HookRecordPtr hookRecord) {}; - virtual void FillIps(std::vector& callFrames, HookRecordPtr hookRecord) = 0; - virtual void FillJsSymbols(std::vector& callFrames, HookRecordPtr hookRecord) = 0; - virtual void FillNativeSymbols(std::vector& callFrames, HookRecordPtr hookRecord) = 0; - void FillStatsVirtualFrames(std::vector& callFrames, HookRecordPtr hookRecord); - virtual bool IsRecordInfoValid(HookRecordPtr hookRecord) = 0; - virtual void ReplaceErrStack(std::vector& callFrames) {}; - -protected: - NativeHookConfig* hookConfig_; - std::shared_ptr runtimeInstance_{nullptr}; -}; - -class FpStackBuilder : public StackBuilder { -public: - FpStackBuilder() = delete; - FpStackBuilder(NativeHookConfig* config, std::shared_ptr runtime); - void PrepareUnwind(HookRecordPtr hookRecord); - void FillIps(std::vector& callFrames, HookRecordPtr hookRecord); - void FillJsSymbols(std::vector& callFrames, HookRecordPtr hookRecord); - void FillNativeSymbols(std::vector& callFrames, HookRecordPtr hookRecord); - bool IsRecordInfoValid(HookRecordPtr hookRecord); - void FillJsFrame(CallFrame& jsCallFrame); - -private: - std::mutex mtx_; -}; - -class DwarfStackBuilder : public StackBuilder { -public: - DwarfStackBuilder() = delete; - DwarfStackBuilder(NativeHookConfig* config, std::shared_ptr runtime); - void FillIps(std::vector& callFrames, HookRecordPtr hookRecord); - void FillJsSymbols(std::vector& callFrames, HookRecordPtr hookRecord); - void FillNativeSymbols(std::vector& callFrames, HookRecordPtr hookRecord); - bool IsRecordInfoValid(HookRecordPtr hookRecord); - void ReplaceErrStack(std::vector& callFrames); - -private: - size_t stackDepth_ = 0; - size_t minStackDepth_ = 0; -}; - -class BuildStackDirector { -public: - BuildStackDirector() = delete; - BuildStackDirector(NativeHookConfig* config, std::shared_ptr runtime); - std::vector& ConstructCallFrames(HookRecordPtr hookRecord); - void SetBuilder(std::shared_ptr builder) - { - builder_ = builder; - } - bool IsRecordUnwindable(HookRecordPtr); - -private: - std::shared_ptr builder_{nullptr}; - NativeHookConfig* hookConfig_; - std::vector callFrames_; -}; -} - -#endif \ No newline at end of file diff --git a/device/plugins/native_daemon/include/stack_data_repeater.h b/device/plugins/native_daemon/include/stack_data_repeater.h index 113ba150d..ddb7c021a 100644 --- a/device/plugins/native_daemon/include/stack_data_repeater.h +++ b/device/plugins/native_daemon/include/stack_data_repeater.h @@ -24,23 +24,50 @@ #include "native_hook_result.pb.h" #include "hook_common.h" #include "utilities.h" -#include "hook_record.h" - -namespace OHOS::Developtools::NativeDaemon { using BatchNativeHookDataPtr = STD_PTR(shared, BatchNativeHookData); +constexpr const int CACHE_DATA_SIZE = 40000; constexpr const int32_t CACHE_ARRAY_SIZE = 10; class StackDataRepeater { public: + struct RawStack { + std::unique_ptr baseStackData = nullptr; // save the shared memory data + BaseStackRawData* stackConext = nullptr; // points to the foundation type data + union { + uint8_t* stackData; + const char* jsStackData = nullptr; + }; + uint8_t* data = nullptr; // fp mode data is ip, dwarf mode data is regs + uint64_t freeData = 0; + uint32_t stackSize = 0; + uint8_t fpDepth = 0; // fp mode fpDepth is ip depth, dwarf mode is invalid + bool reportFlag = false; + bool reduceStackFlag = false; + void Reset() + { + baseStackData = nullptr; + stackConext = nullptr; + data = nullptr; + stackData = nullptr; + freeData = 0; + stackSize = 0; + fpDepth = 0; + reportFlag = false; + reduceStackFlag = false; + } + }; + explicit StackDataRepeater(size_t maxSize); ~StackDataRepeater(); - bool PutRawStack(const std::shared_ptr& rawData, bool isRecordAccurately); - bool PutRawStackArray(std::array, CACHE_ARRAY_SIZE>& rawDataArray, uint32_t batchCount); - std::shared_ptr TakeRawData(uint32_t during, clockid_t clockId, uint32_t batchCount, - std::shared_ptr batchRawStack[], uint32_t statInterval, bool& isTimeOut); + bool PutRawStack(const std::shared_ptr& rawData, bool isRecordAccurately); + bool PutRawStackArray(std::array, CACHE_ARRAY_SIZE>& rawDataArray, uint32_t batchCount); + std::shared_ptr TakeRawData(uint32_t during, clockid_t clockId, uint32_t batchCount, + std::shared_ptr batchRawStack[], uint32_t statInterval, bool& isTimeOut); void Close(); void Reset(); + std::shared_ptr GetRawStack(); + void ReturnRawStack(std::shared_ptr rawStack); size_t Size(); void ClearCache() { @@ -51,11 +78,11 @@ public: private: std::mutex mutex_; std::mutex cacheMutex_; - std::deque> rawDataCacheQueue_; + std::deque> rawDataCacheQueue_; std::condition_variable slotCondVar_; std::condition_variable itemCondVar_; - std::deque> rawDataQueue_; - std::unordered_map> mallocMap_ = {}; + std::deque> rawDataQueue_; + std::unordered_map> mallocMap_ = {}; size_t maxSize_; uint64_t reducedStackCount_; std::atomic_bool closed_; @@ -63,6 +90,8 @@ private: DISALLOW_COPY_AND_MOVE(StackDataRepeater); }; +using RawStackPtr = STD_PTR(shared, StackDataRepeater::RawStack); + using StackDataRepeaterPtr = STD_PTR(shared, StackDataRepeater); -} + #endif // STACK_DATA_REPEATER_H \ No newline at end of file diff --git a/device/plugins/native_daemon/include/stack_preprocess.h b/device/plugins/native_daemon/include/stack_preprocess.h index bb107ff8d..bcdbb32d0 100644 --- a/device/plugins/native_daemon/include/stack_preprocess.h +++ b/device/plugins/native_daemon/include/stack_preprocess.h @@ -22,9 +22,7 @@ #include #include #include -#include -#include "hook_record_factory.h" -#include "hook_record.h" + #include "logging.h" #include "nocopyable.h" #include "stack_data_repeater.h" @@ -36,43 +34,27 @@ #include "native_hook_result.pbencoder.h" #include "safe_map.h" #include "schedule_task_manager.h" -#include "common.h" -#include "stack_builder.h" -namespace OHOS::Developtools::NativeDaemon { using WriterStructPtr = std::unique_ptr::pointer; - -struct RecordStatistic { - uint32_t pid {0}; - uint32_t callstackId {0}; - uint32_t tagId {0}; - RecordStatisticsEvent::MemoryType type {RecordStatisticsEvent::MALLOC}; - uint64_t applyCount {0}; - uint64_t releaseCount {0}; - uint64_t applySize {0}; - uint64_t releaseSize {0}; -}; - -struct CallStackHash { - uint64_t operator()(const std::vector& stack) const - { - return std::accumulate(stack.begin(), stack.end(), 0); - } -}; - - class StackPreprocess : public std::enable_shared_from_this { public: + struct RecordStatistic { + uint32_t pid {0}; + uint32_t callstackId {0}; + uint32_t tagId {0}; + RecordStatisticsEvent::MemoryType type {RecordStatisticsEvent::MALLOC}; + uint64_t applyCount {0}; + uint64_t releaseCount {0}; + uint64_t applySize {0}; + uint64_t releaseSize {0}; + }; + explicit StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const NativeHookConfig& hookConfig, clockid_t pluginDataClockId, FILE* fpHookData = nullptr, bool isHookStandalone = false, bool isSaService = false, bool isProtobufSerialize = true); ~StackPreprocess(); void SetWriter(const std::shared_ptr& writer); void SetWriter(const WriterStructPtr& writer); - void SetFactory(std::shared_ptr factory) - { - factory_ = factory; - } bool StartTakeResults(); bool StopTakeResults(); void FinishTraceFile(); @@ -141,10 +123,10 @@ private: private: void TakeResults(); template - void SetHookData(HookRecordPtr hookRecord, T& stackData); + void SetHookData(RawStackPtr rawStack, T& stackData); template - void SetHookData(HookRecordPtr hookRecord, std::vector& callFrames, T& stackData); - void WriteFrames(HookRecordPtr hookRecord, const std::vector& callFrames); + void SetHookData(RawStackPtr rawStack, std::vector& callFrames, T& stackData); + void WriteFrames(RawStackPtr RawStack, const std::vector& callFrames); template void SetFrameInfo(T& frame, CallFrame& callFrame); template @@ -170,7 +152,7 @@ private: template uint32_t SetCallStackMap(T& stackData); template - uint32_t GetCallStackId(const HookRecordPtr& hookRecord, std::vector& callFrames, T& stackData); + uint32_t GetCallStackId(const RawStackPtr& rawStack, std::vector& callFrames, T& stackData); uint32_t FindCallStackId(std::vector& callStack); template void SetEventFrame(const RawStackPtr& rawStack, std::vector& callFrames, @@ -179,22 +161,26 @@ private: void SetEventFrame(const ReportEventBaseData& rawStack, T* event, uint32_t stackMapId, const std::string& type = ""); template - void SetAllocStatisticsFrame(const HookRecordPtr& hookRecord, std::vector& callFrames, T& stackData); + void SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector& callFrames, T& stackData); template - void SetAllocStatisticsFrame(const HookRecordPtr& hookRecord, T& stackData); + void SetAllocStatisticsFrame(const RawStackPtr& rawStack, T& stackData); template - void SetApplyAndReleaseMatchFrame(HookRecordPtr hookRecord, std::vector& callFrames, T& stackData); + void SetApplyAndReleaseMatchFrame(RawStackPtr rawStack, std::vector& callFrames, T& stackData); void IntervalFlushRecordStatistics(); void IntervalFlushApplyAndReleaseMatchData(); - bool HandleNoStackEvent(HookRecordPtr& hookRecord); + bool HandleNoStackEvent(RawStackPtr& rawStack); bool SetFreeStatisticsData(uint64_t addr); - void SetAllocStatisticsData(const HookRecordPtr& hookRecord, size_t stackId, bool isExists = false); + void SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists = false); unsigned LgFloor(unsigned long x); uint64_t PowCeil(uint64_t x); + size_t ComputeAlign(size_t size); void ReportOfflineSymbolizationData(); RandomWriteCtx* StartReport(); int32_t FinishReport(); + void FillFpNativeIp(RawStackPtr& rawData); + void FillFpJsData(RawStackPtr& rawData); + void FillDwarfErrorStack(); void FillNapiStack(std::string& tagName, std::vector& callFrames, uint64_t napiIndex); private: std::chrono::steady_clock::time_point lastStatisticsTime_ = std::chrono::steady_clock::now(); @@ -212,13 +198,17 @@ private: uint32_t eventCnts_ = 0; bool flushBasicData_ {true}; std::vector u64regs_; + std::vector callFrames_; + std::vector callStack_; // Key is callStack_, value is call stack id - std::unordered_map, uint32_t, CallStackHash> callStackMap_; + std::map, uint32_t> callStackMap_; std::chrono::seconds statisticsInterval_ {0}; // Key is call stack id, value is recordstatistic data std::unordered_map recordStatisticsMap_; // Key is call stack id, value is recordstatistic data pointer std::unordered_map statisticsPeriodData_; + // Key is alloc or mmap address, value first is mallocsize, second is recordstatistic data pointer + std::unordered_map> allocAddrMap_; // Key is alloc or mmap address, value is ReportEventBaseData list iterator std::unordered_map::iterator> applyAndReleaseMatchIntervallMap_; std::list applyAndReleaseMatchPeriodListData_; @@ -232,9 +222,6 @@ private: bool isHookStandaloneSerialize_ {false}; int32_t pid_ {-1}; std::mutex mtx_; - std::mutex memTagMtx_; - std::mutex jsMapMtx_; - COMMON::SpinLock spinLock_; bool isSaService_{false}; std::mutex allocAddrMapMtx_; bool isProtobufSerialize_{true}; @@ -249,13 +236,11 @@ private: std::set jsStackSet_ = {}; bool unwindFailReport_ = true; std::vector prctlPeriodTags_; // applyAndReleaseMatchInterval mode used + std::vector fpJsCallStacks_; std::atomic napiIndex_{1}; - std::atomic endMsgCount_ {0}; ScheduleTaskManager scheduleTaskManager_; uint32_t nmdFd_ = 0; uint32_t dataFlushSize_ = 0; - std::shared_ptr factory_{nullptr}; }; -} #endif // STACK_PREPROCESS_H \ No newline at end of file diff --git a/device/plugins/native_daemon/include/utilities.h b/device/plugins/native_daemon/include/utilities.h index 25d39c3f6..ac309af0a 100644 --- a/device/plugins/native_daemon/include/utilities.h +++ b/device/plugins/native_daemon/include/utilities.h @@ -213,8 +213,6 @@ std::vector GetEntriesInDir(const std::string &basePath); std::vector GetSubDirs(const std::string &basePath); -size_t ComputeAlign(size_t size); - bool IsDir(const std::string &path); bool IsPath(const std::string &fileName); diff --git a/device/plugins/native_daemon/include/virtual_runtime.h b/device/plugins/native_daemon/include/virtual_runtime.h index 6a972fab2..ab98b795e 100644 --- a/device/plugins/native_daemon/include/virtual_runtime.h +++ b/device/plugins/native_daemon/include/virtual_runtime.h @@ -81,7 +81,7 @@ public: std::vector& callFrames, size_t maxStackLevel); bool GetSymbolName(pid_t pid, pid_t tid, std::vector& callFrames, int offset, bool first, - SymbolType type = SymbolType::NATIVE_SYMBOL); + bool onlyjs = false); void ClearMaps(); void FillMapsCache(std::string& currentFileName, std::shared_ptr mapItem); void HandleMapInfo(std::vector info, const std::string& filePath, pid_t pid, pid_t tid); @@ -205,7 +205,6 @@ private: std::map> mapsCache_; // key is memMap soBegin, value is MemMaps std::vector offlineMapAddr_; // element is memMap soBegin std::unordered_map jsUrlMap_; // Key is js url , value is filePathId - std::mutex mtx_; }; } // namespace NativeDaemon } // namespace Developtools diff --git a/device/plugins/native_daemon/native_memory_profiler_sa/include/native_memory_profiler_sa_config.h b/device/plugins/native_daemon/native_memory_profiler_sa/include/native_memory_profiler_sa_config.h index 79034d19f..478af14ce 100644 --- a/device/plugins/native_daemon/native_memory_profiler_sa/include/native_memory_profiler_sa_config.h +++ b/device/plugins/native_daemon/native_memory_profiler_sa/include/native_memory_profiler_sa_config.h @@ -65,7 +65,6 @@ public: int32_t jsStackReport_{0}; uint8_t maxJsStackDepth_{0}; std::string filterNapiName_; - std::string targetSoName_; uint32_t largestSize_{0}; uint32_t secondLargestSize_{0}; uint32_t maxGrowthSize_{0}; diff --git a/device/plugins/native_daemon/native_memory_profiler_sa/include/native_memory_profiler_sa_service.h b/device/plugins/native_daemon/native_memory_profiler_sa/include/native_memory_profiler_sa_service.h index 351e60d88..8f8bcad11 100644 --- a/device/plugins/native_daemon/native_memory_profiler_sa/include/native_memory_profiler_sa_service.h +++ b/device/plugins/native_daemon/native_memory_profiler_sa/include/native_memory_profiler_sa_service.h @@ -27,22 +27,6 @@ #include "service_entry.h" namespace OHOS::Developtools::NativeDaemon { - -struct TaskConfig { - TaskConfig(std::shared_ptr manager, int32_t pid, const std::string& processName, - const std::string& filePath, int32_t timerFd, bool startupMode, uint32_t fd = 0) - : hookMgr(manager), pid(pid), processName(processName), filePath(filePath), timerFd(timerFd), - isStartupMode(startupMode), fd(fd) {} - ~TaskConfig() {}; - std::shared_ptr hookMgr = nullptr; - int32_t pid{0}; - std::string processName; - std::string filePath; - int32_t timerFd{-1}; - bool isStartupMode{false}; - uint32_t fd{0}; -}; - class NativeMemoryProfilerSaService : public SystemAbility, public NativeMemoryProfilerSaStub, public ServiceBase { DECLARE_SYSTEM_ABILITY(NativeMemoryProfilerSaService); public: @@ -56,25 +40,51 @@ public: int32_t Start(std::shared_ptr& config, MessageParcel &reply) override; int32_t Start(std::shared_ptr& config, std::string& replyStats) override { return 0; } - static void StopHook(uint32_t pid, std::string name = ""); - static void ClientDisconnectCallback(int socketFd); - static bool HasProfilingPermission(); - static void CloseSocketFd(int pid); - static void DelayedShutdown(bool cancel); private: + void StopHook(uint32_t pid, std::string name = ""); int32_t StartHook(std::shared_ptr& config, uint32_t fd = 0); int32_t StartHookLock(std::shared_ptr& config, uint32_t fd, std::shared_ptr& hook, std::string& args); int32_t StartHook(std::shared_ptr& config, uint32_t fd, MessageParcel &reply); + struct TaskConfig; bool CheckConfig(std::shared_ptr& config, uint32_t fd = 0); void FillTaskConfigContext(int32_t pid, const std::string& name); bool ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size) override; + void DelayedShutdown(bool cancel); std::string GetCmdArgs(std::shared_ptr& config); + void CloseSocketFd(int pid); private: + struct TaskConfig { + TaskConfig(std::shared_ptr manager, int32_t pid, const std::string& processName, + const std::string& filePath, int32_t timerFd, bool startupMode, uint32_t fd = 0) + : hookMgr(manager), pid(pid), processName(processName), filePath(filePath), timerFd(timerFd), + isStartupMode(startupMode), fd(fd) {} + ~TaskConfig() {}; + std::shared_ptr hookMgr = nullptr; + int32_t pid{0}; + std::string processName; + std::string filePath; + int32_t timerFd{-1}; + bool isStartupMode{false}; + uint32_t fd{0}; + }; + bool HasProfilingPermission(); + std::unordered_map> nameAndFilePathCtx_; + std::unordered_map> pidCtx_; + std::mutex mtx_; std::mutex nmdMtx_; + ScheduleTaskManager scheduleTaskManager_; + bool hasStartupMode_{false}; std::string startupModeProcessName_; + int32_t taskNum_{0}; + std::shared_ptr serviceEntry_{nullptr}; + int32_t delayedShutdownTimerFd_{-1}; + std::unordered_map> nmdPidType_; + std::unordered_map pidFds_; + std::mutex pidFdMtx_; + std::unordered_map> pidInfo_; }; } // namespace OHOS::Developtools::NativeDaemon diff --git a/device/plugins/native_daemon/native_memory_profiler_sa/src/native_memory_profiler_sa_config.cpp b/device/plugins/native_daemon/native_memory_profiler_sa/src/native_memory_profiler_sa_config.cpp index 12bcc25d6..4eebfb33d 100644 --- a/device/plugins/native_daemon/native_memory_profiler_sa/src/native_memory_profiler_sa_config.cpp +++ b/device/plugins/native_daemon/native_memory_profiler_sa/src/native_memory_profiler_sa_config.cpp @@ -55,7 +55,6 @@ bool NativeMemoryProfilerSaConfig::Marshalling(Parcel& parcel) const WRITEINT32(parcel, jsStackReport_); WRITEUINT8(parcel, maxJsStackDepth_); WRITESTRING(parcel, filterNapiName_); - WRITESTRING(parcel, targetSoName_); WRITEUINT32(parcel, largestSize_); WRITEUINT32(parcel, secondLargestSize_); WRITEUINT32(parcel, maxGrowthSize_); @@ -102,7 +101,6 @@ bool NativeMemoryProfilerSaConfig::Unmarshalling(Parcel& parcel, std::shared_ptr READINT32(parcel, config->jsStackReport_); READUINT8(parcel, config->maxJsStackDepth_); READSTRING(parcel, config->filterNapiName_); - READSTRING(parcel, config->targetSoName_); READUINT32(parcel, config->largestSize_); READUINT32(parcel, config->secondLargestSize_); READUINT32(parcel, config->maxGrowthSize_); @@ -126,9 +124,9 @@ void NativeMemoryProfilerSaConfig::PrintConfig(std::shared_ptrfpUnwind_, config->blocked_, config->recordAccurately_); PROFILER_LOG_DEBUG(LOG_CORE, "startupMode: %d, memtraceEnable: %d, offlineSymbolization: %d, callframeCompress: %d," \ - "statisticsInterval: %d, clockId: %d, targetSoName: %s", + "statisticsInterval: %d, clockId: %d", config->startupMode_, config->memtraceEnable_, config->offlineSymbolization_, config->callframeCompress_, - config->statisticsInterval_, config->clockId_, config->targetSoName_.c_str()); + config->statisticsInterval_, config->clockId_); PROFILER_LOG_DEBUG(LOG_CORE, "jsStackReport: %d, maxJsStackDepth_: %d, filterNapiName_: %s", config->jsStackReport_, config->maxJsStackDepth_, config->filterNapiName_.c_str()); diff --git a/device/plugins/native_daemon/native_memory_profiler_sa/src/native_memory_profiler_sa_service.cpp b/device/plugins/native_daemon/native_memory_profiler_sa/src/native_memory_profiler_sa_service.cpp index 3bfd70e79..b56d8a85c 100644 --- a/device/plugins/native_daemon/native_memory_profiler_sa/src/native_memory_profiler_sa_service.cpp +++ b/device/plugins/native_daemon/native_memory_profiler_sa/src/native_memory_profiler_sa_service.cpp @@ -38,54 +38,24 @@ constexpr int FILE_MODE = 0644; constexpr int32_t SIMP_NMD = 3; constexpr int32_t NMD_WAIT_MS = 100; constexpr int32_t NMD_WAIT_TIMES = 50; -constexpr int VEC_SHIFT = 2; - -static std::unordered_map> g_nameAndFilePathCtx; -static std::unordered_map> g_pidCtx; -static std::mutex g_mtx; -static ScheduleTaskManager g_scheduleTaskManager; -static bool g_hasStartupMode{false}; -static int32_t g_taskNum{0}; -static std::shared_ptr g_serviceEntry{nullptr}; -static int32_t g_delayedShutdownTimerFd{-1}; -static std::unordered_map> g_nmdPidType; -static std::unordered_map g_pidFds; -static std::mutex g_pidFdMtx; -static std::unordered_map> g_pidInfo; } NativeMemoryProfilerSaService::NativeMemoryProfilerSaService() : SystemAbility(NATIVE_DAEMON_SYSTEM_ABILITY_ID, true) { serviceName_ = "HookService"; - g_serviceEntry = std::make_shared(); - if (!g_serviceEntry->StartServer(DEFAULT_UNIX_SOCKET_HOOK_PATH, - reinterpret_cast(&ClientDisconnectCallback))) { - g_serviceEntry = nullptr; + serviceEntry_ = std::make_shared(); + if (!serviceEntry_->StartServer(DEFAULT_UNIX_SOCKET_HOOK_PATH)) { + serviceEntry_ = nullptr; PROFILER_LOG_ERROR(LOG_CORE, "Start IPC Service FAIL"); return; } - g_serviceEntry->RegisterService(*this); + serviceEntry_->RegisterService(*this); DelayedShutdown(false); } NativeMemoryProfilerSaService::~NativeMemoryProfilerSaService() { - g_serviceEntry = nullptr; -} - -void NativeMemoryProfilerSaService::ClientDisconnectCallback(int socketFd) -{ - std::unique_lock lock(g_pidFdMtx); - pid_t pidval = 0; - for (auto iter = g_pidFds.begin(); iter != g_pidFds.end(); ++iter) { - if (iter->second == socketFd) { - pidval = iter->first; - break; - } - } - PROFILER_LOG_ERROR(LOG_CORE, "ClientDisconnectCallback get pid: %d", static_cast(pidval)); - lock.unlock(); - StopHook(static_cast(pidval)); + serviceEntry_ = nullptr; } bool NativeMemoryProfilerSaService::StartServiceAbility() @@ -129,7 +99,7 @@ int32_t NativeMemoryProfilerSaService::Start(std::shared_ptrprintNmd_) { std::lock_guard guard(nmdMtx_); - g_nmdPidType[config->nmdPid_] = std::make_pair(0, config->nmdType_); + nmdPidType_[config->nmdPid_] = std::make_pair(0, config->nmdType_); if (!config->printNmdOnly_) { return RET_OK; } @@ -142,7 +112,7 @@ int32_t NativeMemoryProfilerSaService::Start(std::shared_ptrprintNmd_) { std::lock_guard guard(nmdMtx_); - g_nmdPidType[config->nmdPid_] = std::make_pair(0, config->nmdType_); + nmdPidType_[config->nmdPid_] = std::make_pair(0, config->nmdType_); if (!config->printNmdOnly_) { return RET_OK; } @@ -166,7 +136,7 @@ int32_t NativeMemoryProfilerSaService::DumpData(uint32_t fd, std::shared_ptrprintNmd_) { std::lock_guard guard(nmdMtx_); - g_nmdPidType[config->nmdPid_] = std::make_pair(fd, config->nmdType_); + nmdPidType_[config->nmdPid_] = std::make_pair(fd, config->nmdType_); if (!config->printNmdOnly_) { return RET_OK; } @@ -180,12 +150,12 @@ int32_t NativeMemoryProfilerSaService::DumpData(uint32_t fd, std::shared_ptr lock(g_pidFdMtx); - if ((g_pidFds.find(pid) != g_pidFds.end()) && (g_pidFds[pid] != 0)) { - int socketFd = g_pidFds[pid]; - g_pidFds.erase(pid); + std::unique_lock lock(pidFdMtx_); + if ((pidFds_.find(pid) != pidFds_.end()) && (pidFds_[pid] != 0)) { + int socketFd = pidFds_[pid]; + pidFds_.erase(pid); lock.unlock(); - g_serviceEntry->RemoveContext(socketFd); + serviceEntry_->RemoveContext(socketFd); } else { PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService::CloseSocketFd pid invalid"); } @@ -197,13 +167,13 @@ void NativeMemoryProfilerSaService::StopHook(uint32_t pid, std::string name) PROFILER_LOG_ERROR(LOG_CORE, "StopHook failed, no profiling permission!"); return; } - std::lock_guard guard(g_mtx); + std::lock_guard guard(mtx_); std::shared_ptr config = nullptr; if (pid > 0) { - if (auto taskIter = g_pidCtx.find(pid); taskIter != g_pidCtx.end()) { + if (auto taskIter = pidCtx_.find(pid); taskIter != pidCtx_.end()) { config = taskIter->second; } - } else if (auto taskIter = g_nameAndFilePathCtx.find(name); taskIter != g_nameAndFilePathCtx.end()) { + } else if (auto taskIter = nameAndFilePathCtx_.find(name); taskIter != nameAndFilePathCtx_.end()) { config = taskIter->second; pid = static_cast(config->hookMgr->GetPid()); } @@ -215,20 +185,20 @@ void NativeMemoryProfilerSaService::StopHook(uint32_t pid, std::string name) CloseSocketFd(static_cast(pid)); config->hookMgr->StopPluginSession({}); config->hookMgr->DestroyPluginSession({}); - g_nameAndFilePathCtx.erase(config->processName); - g_nameAndFilePathCtx.erase(config->filePath); - g_pidCtx.erase(config->pid); - g_pidInfo.erase(static_cast(pid)); - if (g_nmdPidType.find(config->pid) != g_nmdPidType.end()) { - g_nmdPidType.erase(config->pid); + nameAndFilePathCtx_.erase(config->processName); + nameAndFilePathCtx_.erase(config->filePath); + pidCtx_.erase(config->pid); + pidInfo_.erase(static_cast(pid)); + if (nmdPidType_.find(config->pid) != nmdPidType_.end()) { + nmdPidType_.erase(config->pid); } if (config->isStartupMode) { - g_hasStartupMode = false; + hasStartupMode_ = false; } if (config->fd > 0) { close(config->fd); } - if (--g_taskNum == 0) { + if (--taskNum_ == 0) { PROFILER_LOG_INFO(LOG_CORE, "StringViewMemoryHold clear"); StringViewMemoryHold::GetInstance().Clear(); DelayedShutdown(false); @@ -272,7 +242,7 @@ int32_t NativeMemoryProfilerSaService::StartHookLock(std::shared_ptr& hook, std::string& args) { - std::lock_guard guard(g_mtx); + std::lock_guard guard(mtx_); if (config->filePath_.empty() && fd == 0) { std::string filePathStr = (config->pid_ > 0) ? std::to_string(config->pid_) : config->processName_; config->filePath_ = FILE_PATH_HEAD + filePathStr + FILE_PATH_TAIL; @@ -316,8 +286,8 @@ int32_t NativeMemoryProfilerSaService::StartHookLock(std::shared_ptrpid_ > 0) { std::lock_guard nmdGuard(nmdMtx_); - if (g_nmdPidType.find(config->pid_) != g_nmdPidType.end()) { - hook->SetNmdInfo(g_nmdPidType[config->pid_]); + if (nmdPidType_.find(config->pid_) != nmdPidType_.end()) { + hook->SetNmdInfo(nmdPidType_[config->pid_]); } } if (hook->CreatePluginSession() != RET_OK) { @@ -328,9 +298,9 @@ int32_t NativeMemoryProfilerSaService::StartHookLock(std::shared_ptrprintNmdOnly_) { hook->WriteHookConfig(); } - hook->StartPluginSession(&g_pidInfo); + hook->StartPluginSession(&pidInfo_); - int32_t timerFd = g_scheduleTaskManager.ScheduleTask( + int32_t timerFd = scheduleTaskManager_.ScheduleTask( [this, config] { this->StopHook(config->pid_, config->processName_); }, config->duration_ * TIME_BASE, true); @@ -345,21 +315,21 @@ int32_t NativeMemoryProfilerSaService::StartHookLock(std::shared_ptr(hook, config->pid_, config->processName_, config->filePath_, timerFd, config->startupMode_, fd); CHECK_NOTNULL(hook, RET_ERR, "Failed to create TaskConfig"); - if (!g_hasStartupMode && config->startupMode_) { - g_hasStartupMode = true; + if (!hasStartupMode_ && config->startupMode_) { + hasStartupMode_ = true; startupModeProcessName_ = config->processName_; } if (configCtx->pid > 0) { - g_pidCtx[configCtx->pid] = configCtx; + pidCtx_[configCtx->pid] = configCtx; } else if (!configCtx->processName.empty()) { - g_nameAndFilePathCtx[configCtx->processName] = configCtx; + nameAndFilePathCtx_[configCtx->processName] = configCtx; } if (fd == 0) { - g_nameAndFilePathCtx[configCtx->filePath] = configCtx; + nameAndFilePathCtx_[configCtx->filePath] = configCtx; } - ++g_taskNum; + ++taskNum_; DelayedShutdown(true); COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_SUCC, "success"); return RET_OK; @@ -427,12 +397,12 @@ int32_t NativeMemoryProfilerSaService::StartHook(std::shared_ptr& config, uint32_t fd) { - if (g_taskNum + 1 > MAX_TASK_NUM) { + if (taskNum_ + 1 > MAX_TASK_NUM) { PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: Support up to 4 tasks at the same time"); return false; } - if (g_hasStartupMode && config->startupMode_) { + if (hasStartupMode_ && config->startupMode_) { PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: tasks with an existing startup mode, name: %s", startupModeProcessName_.c_str()); return false; @@ -440,12 +410,12 @@ bool NativeMemoryProfilerSaService::CheckConfig(std::shared_ptrpid_ > 0) { config->processName_.clear(); - if (g_pidCtx.find(config->pid_) != g_pidCtx.end()) { + if (pidCtx_.find(config->pid_) != pidCtx_.end()) { PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: hook has started, pid: %d", config->pid_); return false; } } else if (!config->processName_.empty()) { - if (g_nameAndFilePathCtx.find(config->processName_) != g_nameAndFilePathCtx.end()) { + if (nameAndFilePathCtx_.find(config->processName_) != nameAndFilePathCtx_.end()) { PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: hook has started, process name: %s", config->processName_.c_str()); return false; @@ -460,7 +430,7 @@ bool NativeMemoryProfilerSaService::CheckConfig(std::shared_ptrfilePath_.empty()) { - if (g_nameAndFilePathCtx.find(config->filePath_) != g_nameAndFilePathCtx.end()) { + if (nameAndFilePathCtx_.find(config->filePath_) != nameAndFilePathCtx_.end()) { PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService: File %s is being used.", config->filePath_.c_str()); return false; @@ -474,18 +444,18 @@ bool NativeMemoryProfilerSaService::CheckConfig(std::shared_ptr guard(g_mtx); - if (auto iter = g_pidCtx.find(pid); iter != g_pidCtx.end()) { + std::lock_guard guard(mtx_); + if (auto iter = pidCtx_.find(pid); iter != pidCtx_.end()) { iter->second->processName = name; - g_nameAndFilePathCtx[name] = iter->second; + nameAndFilePathCtx_[name] = iter->second; if (iter->second->isStartupMode) { - g_hasStartupMode = false; + hasStartupMode_ = false; } - } else if (auto it = g_nameAndFilePathCtx.find(name); it != g_nameAndFilePathCtx.end()) { + } else if (auto it = nameAndFilePathCtx_.find(name); it != nameAndFilePathCtx_.end()) { it->second->pid = pid; - g_pidCtx[pid] = it->second; + pidCtx_[pid] = it->second; if (it->second->isStartupMode) { - g_hasStartupMode = false; + hasStartupMode_ = false; } } else { PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService: fill TaskConfig context failed"); @@ -514,11 +484,11 @@ bool NativeMemoryProfilerSaService::ProtocolProc(SocketContext &context, uint32_ if (bundleName.substr(0, 2) == "./") { // 2: size, Command line programs will be prefixed with "./" bundleName = bundleName.substr(2); // 2: point } - bool startupMode = g_hasStartupMode; + bool startupMode = hasStartupMode_; FillTaskConfigContext(peerConfig, bundleName); // Save the relevant context for subsequent inspection - std::lock_guard guard(g_mtx); - if (auto iter = g_pidCtx.find(peerConfig); iter != g_pidCtx.end()) { + std::lock_guard guard(mtx_); + if (auto iter = pidCtx_.find(peerConfig); iter != pidCtx_.end()) { if (!startupMode) { int socketHandle = context.GetSocketHandle(); struct ucred cred; @@ -527,13 +497,19 @@ bool NativeMemoryProfilerSaService::ProtocolProc(SocketContext &context, uint32_ PROFILER_LOG_ERROR(LOG_CORE, "ProtocolProc getsockopt failed"); return false; } - if (!((g_pidInfo.find(cred.pid) != g_pidInfo.end()) && (g_pidInfo[cred.pid].first == cred.uid) && - (g_pidInfo[cred.pid].second == cred.gid))) { + if (!((pidInfo_.find(cred.pid) != pidInfo_.end()) && (pidInfo_[cred.pid].first == cred.uid) && + (pidInfo_[cred.pid].second == cred.gid))) { PROFILER_LOG_ERROR(LOG_CORE, "ProtocolProc process uid gid check failed"); return false; } } + auto [eventFd, smbFd] = iter->second->hookMgr->GetFds(peerConfig, bundleName); iter->second->hookMgr->SetPid(peerConfig); + if (eventFd == smbFd) { + PROFILER_LOG_ERROR(LOG_CORE, + "Get eventFd and smbFd failed!, name: %s, pid: %d", bundleName.c_str(), peerConfig); + return false; + } PROFILER_LOG_INFO(LOG_CORE, "ProtocolProc, receive message from hook client, and send hook config to process %d, name: %s", peerConfig, bundleName.c_str()); @@ -544,25 +520,15 @@ bool NativeMemoryProfilerSaService::ProtocolProc(SocketContext &context, uint32_ } clientConfig.isSaMode = true; context.SendHookConfig(reinterpret_cast(&clientConfig), sizeof(clientConfig)); - std::vector fdVec = iter->second->hookMgr->GetFds(peerConfig, bundleName); - for (int i = 0; i < SHARED_MEMORY_NUM; ++i) { - int eventFd = fdVec[i * VEC_SHIFT]; - int smbFd = fdVec[i * VEC_SHIFT + 1]; - if (eventFd == smbFd) { - PROFILER_LOG_ERROR(LOG_CORE, - "Get eventFd and smbFd failed!, name: %s, pid: %d", bundleName.c_str(), peerConfig); - return false; - } - context.SendFileDescriptor(smbFd); - context.SendFileDescriptor(eventFd); - } + context.SendFileDescriptor(smbFd); + context.SendFileDescriptor(eventFd); iter->second->hookMgr->ResetStartupParam(); } else { PROFILER_LOG_ERROR(LOG_CORE, "ProtocolProc: send config failed"); return false; } - std::unique_lock socketLock(g_pidFdMtx); - g_pidFds[static_cast(peerConfig)] = context.GetSocketHandle(); + std::unique_lock socketLock(pidFdMtx_); + pidFds_[static_cast(peerConfig)] = context.GetSocketHandle(); socketLock.unlock(); return true; } @@ -570,10 +536,10 @@ bool NativeMemoryProfilerSaService::ProtocolProc(SocketContext &context, uint32_ void NativeMemoryProfilerSaService::DelayedShutdown(bool cancel) { if (cancel) { - g_scheduleTaskManager.UnscheduleTask(g_delayedShutdownTimerFd); - g_delayedShutdownTimerFd = -1; + scheduleTaskManager_.UnscheduleTask(delayedShutdownTimerFd_); + delayedShutdownTimerFd_ = -1; } else { - int32_t timerFd = g_scheduleTaskManager.ScheduleTask( + int32_t timerFd = scheduleTaskManager_.ScheduleTask( []() { int ret = SystemSetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "0"); if (ret < 0) { @@ -587,7 +553,7 @@ void NativeMemoryProfilerSaService::DelayedShutdown(bool cancel) PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService:DelayedShutdown Schedule Task failed"); return; } - g_delayedShutdownTimerFd = timerFd; + delayedShutdownTimerFd_ = timerFd; } } } // namespace OHOS::Developtools::NativeDaemon \ No newline at end of file diff --git a/device/plugins/native_daemon/native_memory_profiler_sa/test/BUILD.gn b/device/plugins/native_daemon/native_memory_profiler_sa/test/BUILD.gn index 508dcb537..06d05b2b8 100644 --- a/device/plugins/native_daemon/native_memory_profiler_sa/test/BUILD.gn +++ b/device/plugins/native_daemon/native_memory_profiler_sa/test/BUILD.gn @@ -81,11 +81,8 @@ ohos_unittest("native_memory_profiler_sa_ut") { "../../src/dwarf_encoding.cpp", "../../src/get_thread_id.cpp", "../../src/hook_manager.cpp", - "../../src/hook_record.cpp", - "../../src/hook_record_factory.cpp", "../../src/hook_service.cpp", "../../src/register.cpp", - "../../src/stack_builder.cpp", "../../src/stack_data_repeater.cpp", "../../src/stack_preprocess.cpp", "../../src/symbols_file.cpp", diff --git a/device/plugins/native_daemon/src/hook_manager.cpp b/device/plugins/native_daemon/src/hook_manager.cpp index 24f4419da..b502ec3f9 100644 --- a/device/plugins/native_daemon/src/hook_manager.cpp +++ b/device/plugins/native_daemon/src/hook_manager.cpp @@ -32,8 +32,6 @@ #include "utilities.h" #include "virtual_runtime.h" #include "native_memory_profiler_sa_service.h" -#include "hook_record.h" -#include "hook_record_factory.h" namespace OHOS::Developtools::NativeDaemon { namespace { @@ -47,20 +45,17 @@ const std::string VERSION = "1.02"; constexpr int32_t RESPONSE_MAX_PID_COUNT = 8; constexpr int32_t MAX_PID_COUNT = 4; constexpr int32_t SIMP_NMD = 3; -constexpr int DOUBLE = 2; -static thread_local std::array, CACHE_ARRAY_SIZE> g_rawDataArray = {}; -static thread_local uint32_t g_rawStackCount = 0; } HookManager::~HookManager() { hookService_ = nullptr; for (const auto& item : hookCtx_) { - for (size_t i = 0; i < item->shareMemoryBlockList.size(); ++i) { - item->shareMemoryBlockList[i] = nullptr; + if (item->eventPoller != nullptr) { + item->eventPoller = nullptr; } - for (size_t i = 0; i < item->eventPollerList.size(); ++i) { - item->eventPollerList[i] = nullptr; + if (item->shareMemoryBlock != nullptr) { + item->shareMemoryBlock = nullptr; } if (item->stackPreprocess != nullptr) { item->stackPreprocess = nullptr; @@ -218,7 +213,7 @@ bool HookManager::UnloadPlugin(const uint32_t pluginId) void HookManager::GetClientConfig(ClientConfig& clientConfig) { - clientConfig.shareMemorySize = (static_cast(hookConfig_.smb_pages()) / SHARED_MEMORY_NUM) * PAGE_BYTES; + clientConfig.shareMemorySize = static_cast(hookConfig_.smb_pages() * PAGE_BYTES); clientConfig.filterSize = static_cast(hookConfig_.filter_size()); clientConfig.clockId = COMMON::GetClockId(hookConfig_.clock()); clientConfig.maxStackDepth = hookConfig_.max_stack_depth(); @@ -235,7 +230,6 @@ void HookManager::GetClientConfig(ClientConfig& clientConfig) clientConfig.sampleInterval = hookConfig_.sample_interval(); clientConfig.responseLibraryMode = hookConfig_.response_library_mode(); clientConfig.arktsConfig.jsStackReport = hookConfig_.js_stack_report(); - clientConfig.targetSoName = hookConfig_.target_so_name(); clientConfig.printNmd = printMallocNmd_; clientConfig.nmdType = static_cast(nmdParamInfo_.type); clientConfig.largestSize = largestSize_; @@ -254,38 +248,32 @@ bool HookManager::HandleHookContext(const std::shared_ptr& ctx) if (ctx == nullptr) { return false; } - + if (ctx->pid > 0) { + ctx->smbName = "hooknativesmb_" + std::to_string(ctx->pid); + } else if (!ctx->processName.empty()) { + ctx->smbName = "hooknativesmb_" + ctx->processName; + } else { + PROFILER_LOG_ERROR(LOG_CORE, "HandleHookContext context error, pid: %d, process name: %s", + ctx->pid, ctx->processName.c_str()); + return false; + } // create smb and eventNotifier - uint32_t bufferSize = (static_cast(hookConfig_.smb_pages()) / SHARED_MEMORY_NUM) * PAGE_BYTES; - - for (int i = 0; i < SHARED_MEMORY_NUM; ++i) { - std::string smbName = ""; - if (ctx->pid > 0) { - smbName = "hooknativesmb_" + std::to_string(ctx->pid) + ":" + std::to_string(i); - } else if (!ctx->processName.empty()) { - smbName = "hooknativesmb_" + ctx->processName + ":" + std::to_string(i); - } else { - PROFILER_LOG_ERROR(LOG_CORE, "HandleHookContext context error, pid: %d, process name: %s", - ctx->pid, ctx->processName.c_str()); - return false; - } - ctx->smbNames.push_back(smbName); - auto shareMemoryBlock = ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal(smbName, bufferSize); - CHECK_TRUE(shareMemoryBlock != nullptr, false, "CreateMemoryBlockLocal FAIL %s", smbName.c_str()); - ctx->shareMemoryBlockList.push_back(shareMemoryBlock); - auto eventNotifier = EventNotifier::Create(0, EventNotifier::NONBLOCK); - CHECK_NOTNULL(eventNotifier, false, "create EventNotifier for %s failed!", smbName.c_str()); - ctx->eventNotifierList.push_back(eventNotifier); - PROFILER_LOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n", shareMemoryBlock->GetfileDescriptor(), - eventNotifier->GetFd()); - // start event poller task - auto eventPoller = std::make_shared(DEFAULT_EVENT_POLLING_INTERVAL); - CHECK_NOTNULL(eventPoller, false, "create event poller FAILED!"); + uint32_t bufferSize = static_cast(hookConfig_.smb_pages()) * PAGE_BYTES; /* bufferConfig.pages() */ + ctx->shareMemoryBlock = ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal(ctx->smbName, bufferSize); + CHECK_TRUE(ctx->shareMemoryBlock != nullptr, false, "CreateMemoryBlockLocal FAIL %s", ctx->smbName.c_str()); - eventPoller->Init(); - eventPoller->Start(); - ctx->eventPollerList.push_back(eventPoller); - } + ctx->eventNotifier = EventNotifier::Create(0, EventNotifier::NONBLOCK); + CHECK_NOTNULL(ctx->eventNotifier, false, "create EventNotifier for %s failed!", ctx->smbName.c_str()); + + // start event poller task + ctx->eventPoller = std::make_unique(DEFAULT_EVENT_POLLING_INTERVAL); + CHECK_NOTNULL(ctx->eventPoller, false, "create event poller FAILED!"); + + ctx->eventPoller->Init(); + ctx->eventPoller->Start(); + + PROFILER_LOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n", ctx->shareMemoryBlock->GetfileDescriptor(), + ctx->eventNotifier->GetFd()); ctx->isRecordAccurately = hookConfig_.record_accurately(); PROFILER_LOG_INFO(LOG_CORE, "hookConfig filter size = %d, malloc disable = %d mmap disable = %d", @@ -302,30 +290,25 @@ bool HookManager::HandleHookContext(const std::shared_ptr& ctx) fpHookData_, isHookStandalone_, isSaService_, isProtobufSerialize_); ctx->stackPreprocess->SetFlushSize(shareMemorySize_); ctx->stackPreprocess->SetNmdFd(nmdParamInfo_.fd); - for (int i = 0; i < SHARED_MEMORY_NUM; ++i) { - ctx->eventPollerList[i]->AddFileDescriptor( - ctx->eventNotifierList[i]->GetFd(), - std::bind(&StackPreprocess::TakeResultsFromShmem, ctx->stackPreprocess, - ctx->eventNotifierList[i], ctx->shareMemoryBlockList[i])); - } + ctx->eventPoller->AddFileDescriptor( + ctx->eventNotifier->GetFd(), + std::bind(&StackPreprocess::TakeResultsFromShmem, ctx->stackPreprocess, + ctx->eventNotifier, ctx->shareMemoryBlock)); } else { ctx->stackData = std::make_shared(STACK_DATA_SIZE); CHECK_TRUE(ctx->stackData != nullptr, false, "Create StackDataRepeater FAIL"); ctx->stackPreprocess = std::make_shared(ctx->stackData, hookConfig_, pluginDataClockId, fpHookData_, isHookStandalone_, isSaService_, isProtobufSerialize_); ctx->stackPreprocess->SetFlushSize(shareMemorySize_); - for (int i = 0; i < SHARED_MEMORY_NUM; ++i) { - ctx->eventPollerList[i]->AddFileDescriptor( - ctx->eventNotifierList[i]->GetFd(), - [this, &ctx, i] { this->ReadShareMemory(ctx, i); }); - } + ctx->eventPoller->AddFileDescriptor( + ctx->eventNotifier->GetFd(), + [this, &ctx] { this->ReadShareMemory(ctx); }); } if (isProtobufSerialize_ || isSaService_) { ctx->stackPreprocess->SetWriter(g_buffWriter); } else { ctx->stackPreprocess->SetWriter(const_cast(writerAdapter_->GetStruct())); } - ctx->stackPreprocess->SetFactory(factory_); return true; } @@ -427,15 +410,18 @@ bool HookManager::CreatePluginSession(const std::vector& c return false; } } - if (hookConfig_.fp_unwind() && hookConfig_.offline_symbolization() - && hookConfig_.statistics_interval() > 0) { + if (hookConfig_.fp_unwind() && hookConfig_.record_accurately() + && hookConfig_.blocked() && hookConfig_.offline_symbolization() + && hookConfig_.statistics_interval() > 0 + && hookConfig_.sample_interval() > 1 + && !hookConfig_.js_stack_report()) { noDataQueue_ = true; } if (!isSaService_) { CreateWriter(); } - factory_ = std::make_shared(hookConfig_); + for (const auto& item : hookCtx_) { CHECK_TRUE(HandleHookContext(item), false, "handle hook context failed"); // Create the required resources. } @@ -457,45 +443,55 @@ bool HookManager::CreatePluginSession(const std::vector& c void HookManager::HookManagerCtx::FlushStackArray() { - if (g_rawDataArray.size() > 0 && stackData != nullptr) { - if (!stackData->PutRawStackArray(g_rawDataArray, g_rawStackCount)) { + if (rawDataArray.size() > 0 && stackData != nullptr) { + if (!stackData->PutRawStackArray(rawDataArray, rawStackCount)) { PROFILER_LOG_INFO(LOG_CORE, "PutRawStackArray error"); } - g_rawStackCount = 0; - g_rawDataArray = {}; + rawStackCount = 0; + rawDataArray = {}; } } void HookManager::FlushRawStackArray(const std::shared_ptr& hookCtx, - std::shared_ptr& hookRecord) + std::shared_ptr& rawStack) { - if (hookCtx == nullptr || hookRecord == nullptr) { + if (hookCtx == nullptr || rawStack == nullptr) { return; } - g_rawDataArray[g_rawStackCount] = hookRecord; - ++g_rawStackCount; - if (g_rawStackCount == CACHE_ARRAY_SIZE) { + hookCtx->rawDataArray[hookCtx->rawStackCount] = rawStack; + ++hookCtx->rawStackCount; + if (hookCtx->rawStackCount == CACHE_ARRAY_SIZE) { hookCtx->FlushStackArray(); } } -void HookManager::ReadShareMemory(const std::shared_ptr& hookCtx, int sharedMemoryIndex) +void HookManager::ReadShareMemory(const std::shared_ptr& hookCtx) { - std::shared_ptr shareMemoryBlock = hookCtx->shareMemoryBlockList[sharedMemoryIndex]; - CHECK_NOTNULL(shareMemoryBlock, NO_RETVAL, "smb is null!"); - hookCtx->eventNotifierList[sharedMemoryIndex]->Take(); + CHECK_NOTNULL(hookCtx->shareMemoryBlock, NO_RETVAL, "smb is null!"); + hookCtx->eventNotifier->Take(); + int rawRealSize = 0; while (true) { - std::shared_ptr hookRecord = nullptr; - std::shared_ptr rawStack = nullptr; - bool ret = shareMemoryBlock->TakeData([&](const int8_t data[], uint32_t size) -> bool { - hookRecord = factory_->GetHookRecord(data, size); - rawStack = hookRecord->GetRawStack(); - uint16_t type = hookRecord->GetType(); - if (type == FREE_MSG_SIMP) { + auto rawStack = hookCtx->stackData->GetRawStack(); + bool ret = hookCtx->shareMemoryBlock->TakeData([&](const int8_t data[], uint32_t size) -> bool { + if (size == sizeof(void*)) { + if (data) { + CHECK_TRUE(memcpy_s(&rawStack->freeData, sizeof(rawStack->freeData), data, size) == EOK, false, + "memcpy_s freeData failed!"); + } + rawStack->baseStackData = nullptr; return true; } + rawStack->freeData = 0; + CHECK_TRUE(size >= sizeof(BaseStackRawData), false, "stack data invalid!"); + + rawStack->baseStackData = std::make_unique(size); + CHECK_TRUE(memcpy_s(rawStack->baseStackData.get(), size, data, size) == EOK, false, + "memcpy_s raw data failed!"); - if (type == NMD_MSG && printMallocNmd_) { + rawStack->stackConext = reinterpret_cast(rawStack->baseStackData.get()); + + if (rawStack->stackConext->type == NMD_MSG && printMallocNmd_) { + rawStack->data = rawStack->baseStackData.get() + sizeof(BaseStackRawData); const char* nmdResult = reinterpret_cast(rawStack->data); if (nmdParamInfo_.type == SIMP_NMD) { simplifiedNmd_ = std::string(nmdResult); @@ -507,49 +503,61 @@ void HookManager::ReadShareMemory(const std::shared_ptr& hookCtx (void)write(nmdParamInfo_.fd, nmdResult, strlen(nmdResult)); } return true; - } else if (type == END_MSG) { + } else if (rawStack->stackConext->type == END_MSG) { return true; } + rawStack->data = rawStack->baseStackData.get() + sizeof(BaseStackRawData); rawStack->reportFlag = true; - if (type == MEMORY_TAG || type == THREAD_NAME_MSG || - type == MMAP_FILE_TYPE || type == PR_SET_VMA_MSG || - type == JS_STACK_MSG) { + if (rawStack->stackConext->type == MEMORY_TAG || rawStack->stackConext->type == THREAD_NAME_MSG || + rawStack->stackConext->type == MMAP_FILE_TYPE || rawStack->stackConext->type == PR_SET_VMA_MSG || + rawStack->stackConext->type == JS_STACK_MSG) { return true; } rawStack->reduceStackFlag = false; if (hookConfig_.fp_unwind()) { - if (rawStack->stackContext->jsChainId > 0) { - rawStack->jsStackData = hookCtx->stackPreprocess->GetJsRawStack(rawStack->stackContext->jsChainId); + rawStack->fpDepth = (size - sizeof(BaseStackRawData)) / sizeof(uint64_t); + if (rawStack->stackConext->jsChainId > 0) { + rawStack->jsStackData = hookCtx->stackPreprocess->GetJsRawStack(rawStack->stackConext->jsChainId); } return true; + } else { + rawRealSize = sizeof(BaseStackRawData) + MAX_REG_SIZE * sizeof(char); + } + + rawStack->stackSize = size - rawRealSize; + if (rawStack->stackSize > 0) { + rawStack->stackData = rawStack->baseStackData.get() + rawRealSize; } return true; }); if (!ret) { break; } - uint16_t type = hookRecord->GetType(); - if (type == MEMORY_TAG) { + if (rawStack->baseStackData == nullptr) { + FlushRawStackArray(hookCtx, rawStack); + continue; + } + if (rawStack->stackConext->type == MEMORY_TAG) { std::string tagName = reinterpret_cast(rawStack->data); - hookCtx->stackPreprocess->SaveMemTag(rawStack->stackContext->tagId, tagName); + hookCtx->stackPreprocess->SaveMemTag(rawStack->stackConext->tagId, tagName); continue; - } else if (type == JS_STACK_MSG) { - hookCtx->stackPreprocess->SaveJsRawStack(rawStack->stackContext->jsChainId, + } else if (rawStack->stackConext->type == JS_STACK_MSG) { + hookCtx->stackPreprocess->SaveJsRawStack(rawStack->stackConext->jsChainId, reinterpret_cast(rawStack->data)); continue; - } else if (type == END_MSG) { + } else if (rawStack->stackConext->type == END_MSG) { hookCtx->FlushStackArray(); - if (!hookCtx->stackData->PutRawStack(hookRecord, hookCtx->isRecordAccurately)) { + if (!hookCtx->stackData->PutRawStack(rawStack, hookCtx->isRecordAccurately)) { break; } if (!hookCtx->stackData->PutRawStack(nullptr, false)) { break; } continue; - } else if (type == NMD_MSG) { + } else if (rawStack->stackConext->type == NMD_MSG) { continue; } - FlushRawStackArray(hookCtx, hookRecord); + FlushRawStackArray(hookCtx, rawStack); } } @@ -561,16 +569,16 @@ bool HookManager::DestroyPluginSession(const std::vector& pluginIds) } } for (const auto& item : hookCtx_) { - for (int i = 0; i < SHARED_MEMORY_NUM; ++i) { - if (item->eventPollerList[i] && item->eventNotifierList[i]) { - PROFILER_LOG_ERROR(LOG_CORE, "eventPoller unset! num: %d", i); - item->eventPollerList[i]->RemoveFileDescriptor(item->eventNotifierList[i]->GetFd()); - item->eventPollerList[i]->Stop(); - item->eventPollerList[i]->Finalize(); - } - if (item->shareMemoryBlockList[i]) { - ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal(item->smbNames[i]); + if (item->eventPoller != nullptr) { + PROFILER_LOG_ERROR(LOG_CORE, "eventPoller unset!"); + if (item->eventNotifier != nullptr) { + item->eventPoller->RemoveFileDescriptor(item->eventNotifier->GetFd()); } + item->eventPoller->Stop(); + item->eventPoller->Finalize(); + } + if (item->shareMemoryBlock != nullptr) { + ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal(item->smbName); } if (item->stackData != nullptr) { item->stackData->ClearCache(); @@ -725,7 +733,6 @@ void HookManager::SetHookConfig(const std::shared_ptrjsStackReport_); hookConfig_.set_max_js_stack_depth(config->maxJsStackDepth_); hookConfig_.set_filter_napi_name(config->filterNapiName_); - hookConfig_.set_target_so_name(config->targetSoName_); printMallocNmd_ = config->printNmd_; if (config->hookstandalone_) { isHookStandalone_ = true; @@ -819,7 +826,6 @@ std::string HookManager::GetCmdArgs(NativeHookConfig traceConfig) args << "js_stack_report: " << std::to_string(traceConfig.js_stack_report()) << ", "; args << "max_js_stack_depth: " << std::to_string(traceConfig.max_js_stack_depth()) << ", "; args << "filter_napi_name: " << traceConfig.filter_napi_name() << ", "; - args << "target_so_name: " << traceConfig.target_so_name() << ", "; for (const auto& pid : traceConfig.expand_pids()) { args << "expand_pids: " << std::to_string(pid) << ", "; } @@ -837,7 +843,7 @@ void HookManager::WriteHookConfig() } } -std::vector HookManager::GetFds(int32_t pid, const std::string& name) +std::pair HookManager::GetFds(int32_t pid, const std::string& name) { for (const auto& item : hookCtx_) { if (item->pid == pid || item->processName == name) { @@ -845,15 +851,10 @@ std::vector HookManager::GetFds(int32_t pid, const std::string& name) item->pid = pid; } item->stackPreprocess->SetPid(pid); - std::vector fds; - for (int i = 0; i < SHARED_MEMORY_NUM; ++i) { - fds.push_back(item->eventNotifierList[i]->GetFd()); - fds.push_back(item->shareMemoryBlockList[i]->GetfileDescriptor()); - } - return fds; + return {item->eventNotifier->GetFd(), item->shareMemoryBlock->GetfileDescriptor()}; } } - return std::vector(-1, SHARED_MEMORY_NUM * DOUBLE); + return {-1, -1}; } void HookManager::SetNmdInfo(std::pair info) diff --git a/device/plugins/native_daemon/src/hook_record.cpp b/device/plugins/native_daemon/src/hook_record.cpp deleted file mode 100644 index f2c9eccda..000000000 --- a/device/plugins/native_daemon/src/hook_record.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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 -#include -#include -#include -#include "hook_record.h" - -namespace OHOS::Developtools::NativeDaemon { - -uint16_t HookRecord::GetType() -{ - return (IsValid()) ? rawStack_->stackContext->type : UNKNOWN; -} - -void HookRecord::Reset() -{ - if (rawStack_ != nullptr) { - rawStack_->Reset(); - rawStack_ = nullptr; - } -} - -uint64_t HookRecord::GetAddr() -{ - return (IsValid()) ? reinterpret_cast(rawStack_->stackContext->addr) : 0; -} - -void HookRecord::SetAddr(uint64_t addr) -{ - if (IsValid()) { - rawStack_->stackContext->addr = reinterpret_cast(addr); - } -} - -bool HookRecord::IsValid() -{ - return (rawStack_ && rawStack_->stackContext); -} - -template -void HookRecord::SetEventFrame(T* event, SerializeInfo& hookInfo) -{ - if (!(event && IsValid())) { - PROFILER_LOG_ERROR(LOG_CORE, "hookRecord SetEventFrame get nullptr"); - return; - } - // ignore the first two frame if dwarf unwind - size_t idx = hookInfo.config->fp_unwind() ? 0 : FILTER_STACK_DEPTH; - event->set_pid(rawStack_->stackContext->pid); - event->set_tid(rawStack_->stackContext->tid); - event->set_addr(GetAddr()); - - if (hookInfo.config->callframe_compress() && hookInfo.stackMapId != 0) { - event->set_thread_name_id(rawStack_->stackContext->tid); - event->set_stack_id(hookInfo.stackMapId); - return; - } - for (; idx < (hookInfo.callFrames)->size(); ++idx) { - auto frame = event->add_frame_info(); - SetFrameInfo(*frame, (*(hookInfo.callFrames))[idx], hookInfo.config); - } - event->set_thread_name_id(rawStack_->stackContext->tid); -} - -template -void HookRecord::SetFrameInfo(T& frame, CallFrame& callFrame, NativeHookConfig* config) -{ - if (config == nullptr) { - PROFILER_LOG_ERROR(LOG_CORE, "hookRecord SetFrameInfo invalid config"); - return; - } - frame.set_ip(callFrame.ip_); - if (config->offline_symbolization()) { - // when js mixes offline symbols, the js call stack is reported according to the online symbolization - if (callFrame.isJsFrame_ && callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0) { - frame.set_sp(callFrame.sp_); - frame.set_offset(callFrame.offset_); - frame.set_symbol_offset(callFrame.symbolOffset_); - frame.set_symbol_name_id(callFrame.symbolNameId_); - frame.set_file_path_id(callFrame.filePathId_); - } - return; - } - frame.set_sp(callFrame.sp_); - if (!(callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0)) { - frame.set_symbol_name(std::string(callFrame.symbolName_)); - frame.set_file_path(std::string(callFrame.filePath_)); - } - frame.set_offset(callFrame.offset_); - frame.set_symbol_offset(callFrame.symbolOffset_); - if (callFrame.symbolNameId_ != 0 && callFrame.filePathId_ != 0) { - frame.set_symbol_name_id(callFrame.symbolNameId_); - frame.set_file_path_id(callFrame.filePathId_); - } -} - -template -void HookRecord::SetSize(T* event) -{ - if (event == nullptr) { - PROFILER_LOG_ERROR(LOG_CORE, "hookRecord SetSize invalid event"); - return; - } - auto size = static_cast(rawStack_->stackContext->mallocSize); -#ifdef USE_JEMALLOC - if (GetType() != MEMORY_USING_MSG) { - size = static_cast(ComputeAlign(size)); - } -#endif - event->set_size(size); -} - -void FreeRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo) -{ - std::visit([this, &hookInfo](auto protoData) { - auto freeEvent = protoData->mutable_free_event(); - HookRecord::SetEventFrame(freeEvent, hookInfo); - }, stackData); -} - -void MallocRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo) -{ - std::visit([this, &hookInfo](auto protoData) { - auto allocEvent = protoData->mutable_alloc_event(); - HookRecord::SetSize(allocEvent); - HookRecord::SetEventFrame(allocEvent, hookInfo); - }, stackData); -} - -void MmapRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo) -{ - std::visit([this, &hookInfo](auto protoData) { - auto mmapEvent = protoData->mutable_mmap_event(); - if (hookInfo.tagName != "") { - mmapEvent->set_type(hookInfo.tagName); - } - HookRecord::SetSize(mmapEvent); - HookRecord::SetEventFrame(mmapEvent, hookInfo); - }, stackData); -} - -void MmapFilePageRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo) -{ - std::visit([this, &hookInfo](auto protoData) { - auto mmapEvent = protoData->mutable_mmap_event(); - if (hookInfo.tagName != "") { - mmapEvent->set_type(MMAP_FILE_PAGE_PREFIX + hookInfo.tagName); - } - HookRecord::SetSize(mmapEvent); - HookRecord::SetEventFrame(mmapEvent, hookInfo); - }, stackData); -} - -void MunmapRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo) -{ - std::visit([this, &hookInfo](auto protoData) { - auto munmapEvent = protoData->mutable_munmap_event(); - HookRecord::SetSize(munmapEvent); - HookRecord::SetEventFrame(munmapEvent, hookInfo); - }, stackData); -} - -void PrSetVmaRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo) -{ - std::visit([this](auto protoData) { - auto tagEvent = protoData->mutable_tag_event(); - std::string tagName(reinterpret_cast(rawStack_->data)); - tagEvent->set_addr(reinterpret_cast(rawStack_->stackContext->addr)); - tagEvent->set_size(rawStack_->stackContext->mallocSize); - tagEvent->set_tag(PR_SET_VMA_PREFIX + tagName); - tagEvent->set_pid(rawStack_->stackContext->pid); - }, stackData); -} - -void MemoryUsingRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo) -{ - std::visit([this, &hookInfo](auto protoData) { - auto memUsingEvent = protoData->mutable_mmap_event(); - if (hookInfo.tagName != "") { - memUsingEvent->set_type(hookInfo.tagName); - } - HookRecord::SetSize(memUsingEvent); - HookRecord::SetEventFrame(memUsingEvent, hookInfo); - }, stackData); -} - -void MemoryUnusingRecord::SerializeData(NativeHookProto stackData, SerializeInfo& hookInfo) -{ - std::visit([this, &hookInfo](auto protoData) { - auto munmapEvent = protoData->mutable_munmap_event(); - HookRecord::SetSize(munmapEvent); - HookRecord::SetEventFrame(munmapEvent, hookInfo); - }, stackData); -} -} \ No newline at end of file diff --git a/device/plugins/native_daemon/src/hook_record_factory.cpp b/device/plugins/native_daemon/src/hook_record_factory.cpp deleted file mode 100644 index d46936f7b..000000000 --- a/device/plugins/native_daemon/src/hook_record_factory.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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 "hook_record_factory.h" -#include -#include -#include "hook_common.h" -#include "logging.h" - -namespace OHOS::Developtools::NativeDaemon { - -HookRecordFactory::HookRecordFactory(NativeHookConfig hookConfig) : hookConfig_(hookConfig) -{ - const bool isNoDataQueueMode = (hookConfig_.statistics_interval() > 0 && hookConfig_.fp_unwind() && - hookConfig_.offline_symbolization()); - int rawDataCacheSize = isNoDataQueueMode ? SHARED_MEMORY_NUM : RAW_DATA_CACHE_INIT_SIZE; - int hookRecordCacheSize = isNoDataQueueMode ? SHARED_MEMORY_NUM : HOOK_RECORD_CACHE_INIT_SIZE; - - for (int index = 0; index < rawDataCacheSize; ++index) { - rawStackCache_.emplace_back(std::make_shared()); - } - for (int index = 0; index < hookRecordCacheSize; ++index) { - mallocRecordCache_.emplace_back(std::make_shared()); - mmapRecordCache_.emplace_back(std::make_shared()); - munmapRecordCache_.emplace_back(std::make_shared()); - jsRecordCache_.emplace_back(std::make_shared()); - if (hookConfig_.statistics_interval() > 0) { - freeRecordSimpCache_.emplace_back(std::make_shared()); - } else { - freeRecordCache_.emplace_back(std::make_shared()); - } - } -} - -HookRecordPtr CreateCacheItem(int16_t type) -{ - switch (type) { - case MALLOC_MSG: - return std::make_shared(); - case FREE_MSG: - return std::make_shared(); - case FREE_MSG_SIMP: - return std::make_shared(); - case MMAP_MSG: - return std::make_shared(); - case MUNMAP_MSG: - return std::make_shared(); - case JS_STACK_MSG: - return std::make_shared(); - default: - PROFILER_LOG_ERROR(LOG_CORE, "CreateItem get unexpected type"); - return nullptr; - } -} - -template -std::shared_ptr HookRecordFactory::GetRecordFromCache(std::deque>& dataCache, int16_t type) -{ - std::unique_lock lock(recordMutex_); - if (!dataCache.empty()) { - std::shared_ptr cachedData = std::move(dataCache.back()); - dataCache.pop_back(); - return cachedData; - } - return CreateCacheItem(type); -} - -std::shared_ptr HookRecordFactory::GetRawStackFromCache() -{ - std::unique_lock lock(rawStackMutex_); - if (!rawStackCache_.empty()) { - std::shared_ptr cachedData = std::move(rawStackCache_.back()); - rawStackCache_.pop_back(); - return cachedData; - } - lock.unlock(); - return std::make_shared(); -} - -void HookRecordFactory::SaveRawStack(RawStackPtr rawStack) -{ - std::unique_lock rawStackLock(rawStackMutex_); - if (rawStack && (rawStackCache_.size() <= RAW_DATA_CACHE_MAX_SIZE)) { - rawStackCache_.push_back(std::move(rawStack)); - } -} - -void HookRecordFactory::SaveRecordToCache(uint16_t type, HookRecordPtr hookRecord) -{ - switch (type) { - case FREE_MSG_SIMP: - if (freeRecordSimpCache_.size() < HOOK_RECORD_CACHE_MAX_SIZE) { - freeRecordSimpCache_.push_back(hookRecord); - } - break; - case FREE_MSG: - if (freeRecordCache_.size() < HOOK_RECORD_CACHE_MAX_SIZE) { - freeRecordCache_.push_back(hookRecord); - } - break; - case MALLOC_MSG: - if (mallocRecordCache_.size() < HOOK_RECORD_CACHE_MAX_SIZE) { - mallocRecordCache_.push_back(hookRecord); - } - break; - case MMAP_MSG: - if (mmapRecordCache_.size() < HOOK_RECORD_CACHE_MAX_SIZE) { - mmapRecordCache_.push_back(hookRecord); - } - break; - case MUNMAP_MSG: - if (munmapRecordCache_.size() < HOOK_RECORD_CACHE_MAX_SIZE) { - munmapRecordCache_.push_back(hookRecord); - } - break; - case JS_STACK_MSG: - if (jsRecordCache_.size() < HOOK_RECORD_CACHE_MAX_SIZE) { - jsRecordCache_.push_back(hookRecord); - } - break; - default: - break; - } -} - -void HookRecordFactory::SaveHookRecord(HookRecordPtr hookRecord) -{ - if (hookRecord == nullptr) { - return; - } - auto rawStack = hookRecord->GetRawStack(); - uint16_t type = hookRecord->GetType(); - hookRecord->Reset(); - SaveRawStack(std::move(rawStack)); - std::unique_lock lock(recordMutex_); - SaveRecordToCache(type, std::move(hookRecord)); -} - -std::shared_ptr HookRecordFactory::CreateStackRecord(uint16_t type, RawStackPtr rawStack) -{ - switch (type) { - case MMAP_FILE_PAGE_MSG: - return std::make_shared(rawStack); - case MUNMAP_MSG: { - auto munmapRecord = GetRecordFromCache(munmapRecordCache_, MUNMAP_MSG); - munmapRecord->rawStack_ = rawStack; - return munmapRecord; - } - case MEMORY_UNUSING_MSG: - return std::make_shared(rawStack); - case MEMORY_USING_MSG: - return std::make_shared(rawStack); - case MMAP_FILE_TYPE: - return std::make_shared(rawStack); - case MALLOC_MSG: { - auto mallocRecord = GetRecordFromCache(mallocRecordCache_, MALLOC_MSG); - mallocRecord->rawStack_ = rawStack; - return mallocRecord; - } - case MMAP_MSG: { - auto mmapRecord = GetRecordFromCache(mmapRecordCache_, MMAP_MSG); - mmapRecord->rawStack_ = rawStack; - return mmapRecord; - } - case FREE_MSG: { - auto freeRecord = GetRecordFromCache(freeRecordCache_, FREE_MSG); - freeRecord->rawStack_ = rawStack; - return freeRecord; - } - default: - PROFILER_LOG_ERROR(LOG_CORE, "GetHookRecord get unknown type"); - return nullptr; - } -} - -void HookRecordFactory::InitRawStack(RawStackPtr rawStack, const int8_t sharedMemData[], - uint32_t size, bool storeData) -{ - if (storeData) { - rawStack->baseStackData = std::make_unique(size); - if (memcpy_s(rawStack->baseStackData.get(), size, sharedMemData, size) != EOK) { - PROFILER_LOG_ERROR(LOG_CORE, "HookRecordFactory memcpy_s raw data failed!"); - return; - } - rawStack->stackContext = reinterpret_cast(rawStack->baseStackData.get()); - rawStack->data = rawStack->baseStackData.get() + sizeof(BaseStackRawData); - } else { - rawStack->stackContext = reinterpret_cast(const_cast(sharedMemData)); - rawStack->data = reinterpret_cast(const_cast(sharedMemData)) + sizeof(BaseStackRawData); - } -} - -std::shared_ptr HookRecordFactory::GetHookRecord(const int8_t sharedMemData[], - uint32_t size, bool storeData) -{ - if (size == sizeof(void*)) { - uint64_t freeAddr = 0; - if (memcpy_s(&freeAddr, sizeof(freeAddr), sharedMemData, size) != EOK) { - PROFILER_LOG_ERROR(LOG_CORE, "GetHookRecord memcpy failed"); - } - auto freeRecord = GetRecordFromCache(freeRecordSimpCache_, FREE_MSG_SIMP); - freeRecord->SetAddr(freeAddr); - return freeRecord; - } - auto rawStack = GetRawStackFromCache(); - InitRawStack(rawStack, sharedMemData, size, storeData); - uint16_t type = rawStack->stackContext->type; - switch (type) { - case NMD_MSG: - return std::make_shared(rawStack); - case END_MSG: - case MEMORY_TAG: - case THREAD_NAME_MSG: - return std::make_shared(rawStack); - case PR_SET_VMA_MSG: - return std::make_shared(rawStack); - case JS_STACK_MSG: { - auto jsRecord = GetRecordFromCache(jsRecordCache_, JS_STACK_MSG); - jsRecord->rawStack_ = rawStack; - return jsRecord; - } - default: - break; - } - - if (hookConfig_.fp_unwind()) { - rawStack->fpDepth = (size - sizeof(BaseStackRawData)) / sizeof(uint64_t); - } else { - int rawRealSize = sizeof(BaseStackRawData) + MAX_REG_SIZE * sizeof(char); - rawStack->stackSize = size - rawRealSize; - if (rawStack->stackSize > 0) { - rawStack->stackData = rawStack->baseStackData.get() + rawRealSize; - } - } - return CreateStackRecord(type, rawStack); -} -} \ No newline at end of file diff --git a/device/plugins/native_daemon/src/hook_service.cpp b/device/plugins/native_daemon/src/hook_service.cpp index 0139dd11c..c3c6e79a2 100644 --- a/device/plugins/native_daemon/src/hook_service.cpp +++ b/device/plugins/native_daemon/src/hook_service.cpp @@ -25,8 +25,6 @@ #include "socket_context.h" namespace OHOS::Developtools::NativeDaemon { -const int VEC_SHIFT = 2; - HookService::HookService(const ClientConfig& clientConfig, std::shared_ptr hook, bool multipleProcesses) : clientConfig_(clientConfig), hookMgr_(hook), multipleProcesses_(multipleProcesses) { @@ -125,22 +123,17 @@ bool HookService::ProtocolProc(SocketContext &context, uint32_t pnum, const int8 return false; } } + auto [eventFd, smbFd] = hookMgr_->GetFds(peerConfig, procName); + if (eventFd == smbFd) { + PROFILER_LOG_ERROR(LOG_CORE, "Get eventFd and smbFd failed!, name: %s, pid: %d", procName.c_str(), peerConfig); + return false; + } PROFILER_LOG_DEBUG(LOG_CORE, "ProtocolProc, receive message from hook client, and send hook config to process %d", peerConfig); context.SendHookConfig(reinterpret_cast(&clientConfig_), sizeof(clientConfig_)); - - std::vector fdVec = hookMgr_->GetFds(peerConfig, procName); - for (int i = 0; i < SHARED_MEMORY_NUM; ++i) { - int eventFd = fdVec[i * VEC_SHIFT]; - int smbFd = fdVec[i * VEC_SHIFT + 1]; - if (eventFd == smbFd) { - PROFILER_LOG_ERROR(LOG_CORE, "Get fd failed!, name: %s, pid: %d", procName.c_str(), peerConfig); - return false; - } - context.SendFileDescriptor(smbFd); - context.SendFileDescriptor(eventFd); - } + context.SendFileDescriptor(smbFd); + context.SendFileDescriptor(eventFd); hookMgr_->ResetStartupParam(); std::unique_lock socketLock(pidFdMtx_); pidFds_[static_cast(peerConfig)] = context.GetSocketHandle(); diff --git a/device/plugins/native_daemon/src/stack_builder.cpp b/device/plugins/native_daemon/src/stack_builder.cpp deleted file mode 100644 index 316debeba..000000000 --- a/device/plugins/native_daemon/src/stack_builder.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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 "stack_builder.h" - -namespace OHOS::Developtools::NativeDaemon { -static thread_local std::vector g_fpJsCallStacks; -static thread_local std::vector g_u64regs; -const std::string JS_CALL_STACK_DEPTH_SEP = ","; // ',' is js call stack depth separator -const std::string JS_SYMBOL_FILEPATH_SEP = "|"; // '|' is js symbol and filepath separator - -void StackBuilder::FillStatsVirtualFrames(std::vector& callFrames, HookRecordPtr hookRecord) -{ - auto rawStack = hookRecord->GetRawStack(); - callFrames.emplace_back(rawStack->stackContext->mallocSize | SIZE_MASK); -} - -FpStackBuilder::FpStackBuilder(NativeHookConfig* config, std::shared_ptr runtime) - : StackBuilder(config, runtime) -{ - if (hookConfig_->fp_unwind() && hookConfig_->js_stack_report() > 0) { - g_fpJsCallStacks.reserve(hookConfig_->max_js_stack_depth()); - } -} - -void FpStackBuilder::PrepareUnwind(HookRecordPtr hookRecord) -{ - auto rawData = hookRecord->GetRawStack(); - if (runtimeInstance_ != nullptr) { - runtimeInstance_->UpdateThread(rawData->stackContext->pid, rawData->stackContext->tid); - } -} - -void FpStackBuilder::FillIps(std::vector& callFrames, HookRecordPtr hookRecord) -{ - auto rawData = hookRecord->GetRawStack(); - uint64_t* fpIp = reinterpret_cast(rawData->data); - uint8_t depth = rawData->fpDepth; - for (uint8_t idx = 0; idx < depth; ++idx) { - if (fpIp[idx] == 0) { - break; - } - callFrames.emplace_back(StripPac(fpIp[idx], 0)); - } -} - -void FpStackBuilder::FillJsFrame(CallFrame& jsCallFrame) -{ - DfxSymbol symbol; - if (!runtimeInstance_->ArktsGetSymbolCache(jsCallFrame, symbol)) { - symbol.filePathId_ = runtimeInstance_->FillArkTsFilePath(jsCallFrame.filePath_); - symbol.symbolName_ = jsCallFrame.symbolName_; - symbol.module_ = jsCallFrame.filePath_; - symbol.symbolId_ = runtimeInstance_->GetJsSymbolCacheSize(); - runtimeInstance_->FillSymbolNameId(jsCallFrame, symbol); - runtimeInstance_->FillFileSet(jsCallFrame, symbol); - jsCallFrame.needReport_ |= CALL_FRAME_REPORT; - runtimeInstance_->FillJsSymbolCache(jsCallFrame, symbol); - } - jsCallFrame.callFrameId_ = symbol.symbolId_; - jsCallFrame.symbolNameId_ = symbol.symbolNameId_; - jsCallFrame.filePathId_ = symbol.filePathId_; - jsCallFrame.filePath_ = symbol.module_; - jsCallFrame.symbolName_ = symbol.symbolName_; -} - -void FpStackBuilder::FillJsSymbols(std::vector& callFrames, HookRecordPtr hookRecord) -{ - auto rawData = hookRecord->GetRawStack(); - if (!(rawData->stackContext->jsChainId > 0 && rawData->jsStackData)) { - return; - } - if (hookConfig_->statistics_interval() > 0) { - uint16_t type = hookRecord->GetType(); - if (type == FREE_MSG || type == MUNMAP_MSG || type == MEMORY_UNUSING_MSG) { - return; - } - } - g_fpJsCallStacks.clear(); - if (g_fpJsCallStacks.capacity() == 0) { - g_fpJsCallStacks.reserve(hookConfig_->max_js_stack_depth()); - } - AdvancedSplitString(rawData->jsStackData, JS_CALL_STACK_DEPTH_SEP, g_fpJsCallStacks); - std::lock_guard guard(mtx_); - for (std::string& jsCallStack: g_fpJsCallStacks) { - std::string::size_type jsSymbolFilePathSepPos = jsCallStack.find_first_of(JS_SYMBOL_FILEPATH_SEP); - if (jsSymbolFilePathSepPos == std::string::npos) { - PROFILER_LOG_ERROR(LOG_CORE, "%s: jsCallStack find FAILED!", __func__); - continue; - } - std::string::size_type jsFilePathPos = jsSymbolFilePathSepPos + 1; - jsCallStack[jsSymbolFilePathSepPos] = '\0'; // "ts_malloc1'\0'entry/src/main/ets/pages/Index.ets:5:5" - CallFrame& jsCallFrame = callFrames.emplace_back(0, 0, true); - jsCallFrame.symbolName_ = StringViewMemoryHold::GetInstance().HoldStringView(jsCallStack.c_str()); - jsCallFrame.filePath_ = StringViewMemoryHold::GetInstance().HoldStringView(jsCallStack.c_str() + jsFilePathPos); - if (hookConfig_->offline_symbolization()) { - FillJsFrame(jsCallFrame); - } else { - runtimeInstance_->GetSymbolName(rawData->stackContext->pid, rawData->stackContext->tid, - callFrames, 0, true, SymbolType::JS_SYMBOL); - } - } -} - -void FpStackBuilder::FillNativeSymbols(std::vector& callFrames, HookRecordPtr hookRecord) -{ - auto rawData = hookRecord->GetRawStack(); - std::lock_guard guard(mtx_); - runtimeInstance_->GetSymbolName(rawData->stackContext->pid, rawData->stackContext->tid, - callFrames, 0, true, SymbolType::NATIVE_SYMBOL); -} - -bool FpStackBuilder::IsRecordInfoValid(HookRecordPtr hookRecord) -{ - return hookRecord->IsValid(); -} - -DwarfStackBuilder::DwarfStackBuilder(NativeHookConfig* config, std::shared_ptr runtime) - : StackBuilder(config, runtime) -{ - minStackDepth_ = std::min(hookConfig_->max_stack_depth(), MIN_STACK_DEPTH); - if (hookConfig_->blocked()) { - minStackDepth_ = static_cast(hookConfig_->max_stack_depth()); - } - minStackDepth_ += FILTER_STACK_DEPTH; - stackDepth_ = (static_cast(hookConfig_->max_stack_depth()) > MAX_CALL_FRAME_UNWIND_SIZE) - ? MAX_CALL_FRAME_UNWIND_SIZE - : static_cast(hookConfig_->max_stack_depth()) + FILTER_STACK_DEPTH; -} - -void DwarfStackBuilder::FillIps(std::vector& callFrames, HookRecordPtr hookRecord) -{ - auto rawData = hookRecord->GetRawStack(); -#if defined(__arm__) - if (g_u64regs.size() == 0) { - g_u64regs.resize(PERF_REG_ARM_MAX); - } - uint32_t *regAddrArm = reinterpret_cast(rawData->data); - g_u64regs.assign(regAddrArm, regAddrArm + PERF_REG_ARM_MAX); -#else - if (g_u64regs.size() == 0) { - g_u64regs.resize(PERF_REG_ARM64_MAX); - } - if (memcpy_s(g_u64regs.data(), sizeof(uint64_t) * PERF_REG_ARM64_MAX, rawData->data, - sizeof(uint64_t) * PERF_REG_ARM64_MAX) != EOK) { - PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s regs failed"); - } -#endif - const size_t unwindDepth = rawData->reduceStackFlag ? minStackDepth_ : stackDepth_; - runtimeInstance_->UnwindStack(g_u64regs, rawData->stackData, rawData->stackSize, - rawData->stackContext->pid, rawData->stackContext->tid, callFrames, unwindDepth); -} - -void DwarfStackBuilder::FillJsSymbols(std::vector& callFrames, HookRecordPtr hookRecord) -{ - if (callFrames.size() <= FILTER_STACK_DEPTH) { - return; - } - auto rawData = hookRecord->GetRawStack(); - runtimeInstance_->GetSymbolName(rawData->stackContext->pid, rawData->stackContext->tid, callFrames, - FILTER_STACK_DEPTH, true, SymbolType::JS_SYMBOL); -} - -void DwarfStackBuilder::FillNativeSymbols(std::vector& callFrames, HookRecordPtr hookRecord) -{ - auto rawData = hookRecord->GetRawStack(); - if (callFrames.size() <= FILTER_STACK_DEPTH) { - return; - } - runtimeInstance_->GetSymbolName(rawData->stackContext->pid, rawData->stackContext->tid, callFrames, - FILTER_STACK_DEPTH, true, SymbolType::NATIVE_SYMBOL); -} - -bool DwarfStackBuilder::IsRecordInfoValid(HookRecordPtr hookRecord) -{ - auto rawData = hookRecord->GetRawStack(); - return ((hookRecord->IsValid()) && (rawData->stackSize != 0)); -} - -void DwarfStackBuilder::ReplaceErrStack(std::vector& callFrames) -{ - CallFrame& jsCallFrame = callFrames.emplace_back(0); - jsCallFrame.symbolName_ = "UnwindErrorDwarf"; - jsCallFrame.isJsFrame_ = true; - jsCallFrame.needReport_ |= (CALL_FRAME_REPORT | SYMBOL_NAME_ID_REPORT | FILE_PATH_ID_REPORT); - jsCallFrame.callFrameId_ = DWARF_ERROR_ID; - jsCallFrame.symbolNameId_ = DWARF_ERROR_ID; - jsCallFrame.filePathId_ = DWARF_ERROR_ID; - jsCallFrame.filePath_ = "no-file-path"; -} - -BuildStackDirector::BuildStackDirector(NativeHookConfig* config, std::shared_ptr runtime) - : hookConfig_(config) -{ - if (hookConfig_->fp_unwind()) { - builder_ = std::make_shared(hookConfig_, runtime); - } else { - builder_ = std::make_shared(hookConfig_, runtime); - } -} - -std::vector& BuildStackDirector::ConstructCallFrames(HookRecordPtr hookRecord) -{ - callFrames_.clear(); - if (builder_ == nullptr || hookConfig_ == nullptr) { - return callFrames_; - } - if (callFrames_.capacity() == 0) { - callFrames_.reserve(hookConfig_->max_stack_depth() + hookConfig_->max_js_stack_depth()); - } - if (!IsRecordUnwindable(hookRecord)) { - return callFrames_; - } - if (!builder_->IsRecordInfoValid(hookRecord)) { - builder_->ReplaceErrStack(callFrames_); - return callFrames_; - } - builder_->PrepareUnwind(hookRecord); - builder_->FillIps(callFrames_, hookRecord); - if (hookConfig_->js_stack_report()) { - builder_->FillJsSymbols(callFrames_, hookRecord); - } - if (!hookConfig_->offline_symbolization()) { - builder_->FillNativeSymbols(callFrames_, hookRecord); - } - return callFrames_; -} - -bool BuildStackDirector::IsRecordUnwindable(HookRecordPtr hookRecord) -{ - return (hookRecord->GetType() != PR_SET_VMA_MSG); -} -} \ No newline at end of file diff --git a/device/plugins/native_daemon/src/stack_data_repeater.cpp b/device/plugins/native_daemon/src/stack_data_repeater.cpp index 395858806..e3b4c52de 100644 --- a/device/plugins/native_daemon/src/stack_data_repeater.cpp +++ b/device/plugins/native_daemon/src/stack_data_repeater.cpp @@ -22,6 +22,9 @@ StackDataRepeater::StackDataRepeater(size_t maxSize) maxSize_ = maxSize; closed_ = false; reducedStackCount_ = 0; + for (int index = 0; index < CACHE_DATA_SIZE; ++index) { + rawDataCacheQueue_.emplace_back(std::make_shared()); + } } StackDataRepeater::~StackDataRepeater() @@ -29,7 +32,27 @@ StackDataRepeater::~StackDataRepeater() Close(); } -bool StackDataRepeater::PutRawStackArray(std::array, CACHE_ARRAY_SIZE>& rawDataArray, +RawStackPtr StackDataRepeater::GetRawStack() +{ + std::unique_lock lock(cacheMutex_); + if (!rawDataCacheQueue_.empty()) { + RawStackPtr rawStack = rawDataCacheQueue_.back(); + rawDataCacheQueue_.pop_back(); + return rawStack; + } + return std::make_shared(); +} + +void StackDataRepeater::ReturnRawStack(RawStackPtr rawStack) +{ + std::unique_lock lock(cacheMutex_); + if (rawDataCacheQueue_.size() <= CACHE_DATA_SIZE) { + rawStack->Reset(); + rawDataCacheQueue_.push_back(rawStack); + } +} + +bool StackDataRepeater::PutRawStackArray(std::array, CACHE_ARRAY_SIZE>& rawDataArray, uint32_t batchCount) { std::unique_lock lock(mutex_); @@ -76,12 +99,12 @@ void StackDataRepeater::Close() itemCondVar_.notify_all(); } -bool StackDataRepeater::PutRawStack(const HookRecordPtr& hookData, bool isRecordAccurately) +bool StackDataRepeater::PutRawStack(const RawStackPtr& rawData, bool isRecordAccurately) { bool needInsert = true; std::unique_lock lock(mutex_); - if ((hookData == nullptr) && (rawDataQueue_.size() > 0)) { + if ((rawData == nullptr) && (rawDataQueue_.size() > 0)) { PROFILER_LOG_INFO(LOG_CORE, "no need put nullptr if queue has data, rawDataQueue_.size() = %zu", rawDataQueue_.size()); return true; @@ -93,24 +116,24 @@ bool StackDataRepeater::PutRawStack(const HookRecordPtr& hookData, bool isRecord return false; } - if (__builtin_expect((hookData != nullptr) && !isRecordAccurately, true)) { - if (hookData->GetType() == FREE_MSG || hookData->GetType() == FREE_MSG_SIMP) { - auto temp = mallocMap_.find(hookData->GetAddr()); + if (__builtin_expect((rawData != nullptr) && !isRecordAccurately, true)) { + if (rawData->stackConext->type == FREE_MSG) { + auto temp = mallocMap_.find(rawData->stackConext->addr); // true : pair of malloc and free matched, both malloc and free will be ignored // false : can not match, send free's data anyway if (temp != mallocMap_.end()) { - temp->second->GetRawStack()->reportFlag = false; // will be ignore later - mallocMap_.erase(hookData->GetAddr()); + temp->second->reportFlag = false; // will be ignore later + mallocMap_.erase(rawData->stackConext->addr); needInsert = false; } - } else if (hookData->GetType() == MALLOC_MSG) { - mallocMap_.insert(std::pair>(hookData->GetAddr(), hookData)); + } else if (rawData->stackConext->type == MALLOC_MSG) { + mallocMap_.insert(std::pair>(rawData->stackConext->addr, rawData)); } if (needInsert) { - rawDataQueue_.push_back(hookData); + rawDataQueue_.push_back(rawData); } } else { - rawDataQueue_.push_back(hookData); + rawDataQueue_.push_back(rawData); } lock.unlock(); @@ -118,8 +141,8 @@ bool StackDataRepeater::PutRawStack(const HookRecordPtr& hookData, bool isRecord return true; } -HookRecordPtr StackDataRepeater::TakeRawData(uint32_t during, clockid_t clockId, uint32_t batchCount, - HookRecordPtr batchRawStack[], uint32_t statInterval, bool& isTimeOut) +RawStackPtr StackDataRepeater::TakeRawData(uint32_t during, clockid_t clockId, uint32_t batchCount, + RawStackPtr batchRawStack[], uint32_t statInterval, bool& isTimeOut) { uint32_t rawDataQueueSize = 0; std::unique_lock lock(mutex_); @@ -140,20 +163,18 @@ HookRecordPtr StackDataRepeater::TakeRawData(uint32_t during, clockid_t clockId, if (closed_) { return nullptr; } - HookRecordPtr hookData = nullptr; - RawStackPtr rawStack = nullptr; + RawStackPtr result = nullptr; rawDataQueueSize = rawDataQueue_.size(); int resultSize = rawDataQueueSize > batchCount ? batchCount : rawDataQueueSize; bool needReduceStack = rawDataQueueSize >= SPEED_UP_THRESHOLD; for (int i = 0; i < resultSize; i++) { - hookData = rawDataQueue_.front(); + result = rawDataQueue_.front(); rawDataQueue_.pop_front(); - batchRawStack[i] = hookData; - rawStack = hookData->GetRawStack(); - if ((hookData != nullptr) && (hookData->GetType() == MALLOC_MSG)) { - mallocMap_.erase(hookData->GetAddr()); + batchRawStack[i] = result; + if ((result != nullptr) && (result->stackConext != nullptr) && (result->stackConext->type == MALLOC_MSG)) { + mallocMap_.erase(result->stackConext->addr); if (needReduceStack) { - rawStack->reduceStackFlag = true; + result->reduceStackFlag = true; reducedStackCount_++; } } @@ -161,5 +182,5 @@ HookRecordPtr StackDataRepeater::TakeRawData(uint32_t during, clockid_t clockId, lock.unlock(); slotCondVar_.notify_one(); - return hookData; + return result; } \ No newline at end of file diff --git a/device/plugins/native_daemon/src/stack_preprocess.cpp b/device/plugins/native_daemon/src/stack_preprocess.cpp index d90b3fcde..d5d28521e 100644 --- a/device/plugins/native_daemon/src/stack_preprocess.cpp +++ b/device/plugins/native_daemon/src/stack_preprocess.cpp @@ -28,19 +28,37 @@ #include "google/protobuf/text_format.h" #include "trace_file_writer.h" -constexpr uint32_t MAX_MATCH_CNT = 1000; -constexpr uint32_t MAX_MATCH_INTERVAL = 3600; -constexpr uint32_t LOG_PRINT_TIMES = 10000; -constexpr uint32_t WAIT_STOP_TIME = 5000; -constexpr uint32_t WAIT_TIME_ONCE = 10; -constexpr uint32_t MAX_BATCH_CNT = 40; -constexpr uint64_t JS_OFFLINE_IP_MASK = 0xFFFFFE0000000000; -constexpr uint64_t DWARF_NAPI_CALLBACK = 999999; -constexpr int NAPI_CALL_STACK = 2; // just for napi call stack -constexpr uint32_t FRAME_DEPTH = 2; // add two frames + +constexpr static uint32_t SC_LG_TINY_MIN = 3; +constexpr static uint32_t LG_QUANTUM = 4; +constexpr static uint32_t SC_NTINY = LG_QUANTUM - SC_LG_TINY_MIN; +constexpr static uint32_t SC_LG_TINY_MAXCLASS = (LG_QUANTUM > SC_LG_TINY_MIN ? LG_QUANTUM - 1 : -1); +constexpr static uint32_t SC_LG_NGROUP = 2; +constexpr static uint32_t LG_SIZE_CLASS_GROUP = 2; +constexpr static uint32_t NTBINS = 1; +constexpr static uint32_t LG_TINY_MAXCLASS = 3; +constexpr static uint32_t MAX_MATCH_CNT = 1000; +constexpr static uint32_t MAX_MATCH_INTERVAL = 3600; +constexpr static uint32_t LOG_PRINT_TIMES = 10000; +constexpr static uint32_t WAIT_STOP_TIME = 5000; +constexpr static uint32_t WAIT_TIME_ONCE = 10; +constexpr static uint32_t MAX_BATCH_CNT = 40; +constexpr static uint32_t RIGHT_MOVE_1 = 1; +constexpr static uint32_t RIGHT_MOVE_2 = 2; +constexpr static uint32_t RIGHT_MOVE_4 = 4; +constexpr static uint32_t RIGHT_MOVE_8 = 8; +constexpr static uint32_t RIGHT_MOVE_16 = 16; +constexpr static uint64_t SIZE_MASK = 0xFFFFFF0000000000; +constexpr static uint64_t JS_OFFLINE_IP_MASK = 0xFFFFFE0000000000; +constexpr static uint64_t DWARF_ERROR_ID = 999999; +constexpr static uint64_t DWARF_NAPI_CALLBACK = 999999; +static std::string JS_CALL_STACK_DEPTH_SEP = ","; // ',' is js call stack depth separator +static std::string JS_SYMBOL_FILEPATH_SEP = "|"; // '|' is js symbol and filepath separator +constexpr static int NAPI_CALL_STACK = 2; // just for napi call stack +constexpr static uint32_t FRAME_DEPTH = 2; // add two frames constexpr uint32_t FLUSH_BASELINE_SA = (1U << 20); #ifdef PERFORMANCE_DEBUG -constexpr uint32_t LONG_TIME_THRESHOLD = 1000000; +constexpr static uint32_t LONG_TIME_THRESHOLD = 1000000; static std::atomic timeCost = 0; static std::atomic unwindTimes = 0; #endif @@ -49,10 +67,6 @@ using namespace OHOS::Developtools::NativeDaemon; using namespace OHOS::HiviewDFX; using namespace OHOS::Developtools::Profiler; -static thread_local std::vector g_callStack; -static thread_local std::unordered_map> g_allocAddrMap = {}; -static thread_local std::shared_ptr g_director{nullptr}; - StackPreprocess::StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const NativeHookConfig& hookConfig, clockid_t pluginDataClockId, FILE* fpHookData, bool isHookStandalone, bool isSaService, bool isProtobufSerialize) : dataRepeater_(dataRepeater), hookConfig_(hookConfig), pluginDataClockId_(pluginDataClockId), @@ -76,7 +90,7 @@ StackPreprocess::StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const statisticsInterval_ = std::chrono::seconds(hookConfig_.statistics_interval()); recordStatisticsMap_.reserve(STATISTICS_MAP_SZIE); statisticsPeriodData_.reserve(STATISTICS_PERIOD_DATA_SIZE); - g_allocAddrMap.reserve(ALLOC_ADDRMAMP_SIZE); + allocAddrMap_.reserve(ALLOC_ADDRMAMP_SIZE); } if (hookConfig_.malloc_free_matching_interval() > 0) { applyAndReleaseMatchInterval_ = std::chrono::seconds(hookConfig_.malloc_free_matching_interval()); @@ -92,6 +106,15 @@ StackPreprocess::StackPreprocess(const StackDataRepeaterPtr& dataRepeater, const PROFILER_LOG_ERROR(LOG_CORE, "If you need to save the file, please set the file_name"); } PROFILER_LOG_INFO(LOG_CORE, "isHookStandaloneSerialize_ = %d", isHookStandaloneSerialize_); +#if defined(__arm__) + u64regs_.resize(PERF_REG_ARM_MAX); +#else + u64regs_.resize(PERF_REG_ARM64_MAX); +#endif + callFrames_.reserve(hookConfig_.max_stack_depth() + hookConfig_.max_js_stack_depth()); + if (hookConfig_.fp_unwind() && hookConfig_.js_stack_report() > 0) { + fpJsCallStacks_.reserve(hookConfig_.max_js_stack_depth()); + } } StackPreprocess::~StackPreprocess() @@ -213,13 +236,12 @@ inline void StackPreprocess::IntervalFlushApplyAndReleaseMatchData() } } -bool StackPreprocess::HandleNoStackEvent(HookRecordPtr& hookRecord) +bool StackPreprocess::HandleNoStackEvent(RawStackPtr& rawData) { - auto rawData = hookRecord->GetRawStack(); - if (hookRecord->GetType() == MMAP_FILE_TYPE) { - BaseStackRawData* mmapRawData = rawData->stackContext; + if (rawData->stackConext->type == MMAP_FILE_TYPE) { + BaseStackRawData* mmapRawData = rawData->stackConext; std::string filePath(reinterpret_cast(rawData->data)); - COMMON::AdaptSandboxPath(filePath, rawData->stackContext->pid); + COMMON::AdaptSandboxPath(filePath, rawData->stackConext->pid); PROFILER_LOG_DEBUG(LOG_CORE, "MMAP_FILE_TYPE curMmapAddr=%p, MAP_FIXED=%d, " "PROT_EXEC=%d, offset=%" PRIu64 ", filePath=%s", mmapRawData->addr, mmapRawData->mmapArgs.flags & MAP_FIXED, @@ -227,11 +249,11 @@ bool StackPreprocess::HandleNoStackEvent(HookRecordPtr& hookRecord) std::lock_guard guard(mtx_); runtime_instance->HandleMapInfo({reinterpret_cast(mmapRawData->addr), mmapRawData->mallocSize, mmapRawData->mmapArgs.flags, mmapRawData->mmapArgs.offset}, filePath, - rawData->stackContext->pid, rawData->stackContext->tid); + rawData->stackConext->pid, rawData->stackConext->tid); flushBasicData_ = true; - } else if (hookRecord->GetType() == THREAD_NAME_MSG) { + } else if (rawData->stackConext->type == THREAD_NAME_MSG) { std::string threadName = reinterpret_cast(rawData->data); - ReportThreadNameMap(rawData->stackContext->tid, threadName); + ReportThreadNameMap(rawData->stackConext->tid, threadName); } else { return false; } @@ -250,11 +272,8 @@ void StackPreprocess::TakeResultsFromShmem(const std::shared_ptr& const std::shared_ptr& shareMemoryBlock) { eventNotifier->Take(); - RawStackPtr rawData = nullptr; - std::shared_ptr hookRecord = nullptr; - if (g_director == nullptr) { - g_director = std::make_shared(&hookConfig_, runtime_instance); - } + StackDataRepeater::RawStack rawStack; + RawStackPtr rawData(&rawStack, [](StackDataRepeater::RawStack* del) {}); while (!isStopTakeData_) { bool ret = shareMemoryBlock->TakeData( [&](const int8_t data[], uint32_t size) -> bool { @@ -281,48 +300,37 @@ void StackPreprocess::TakeResultsFromShmem(const std::shared_ptr& return true; } CHECK_TRUE(size >= sizeof(BaseStackRawData), false, "stack data invalid!"); - hookRecord = factory_->GetHookRecord(data, size, false); - rawData = hookRecord->GetRawStack(); - uint16_t type = hookRecord->GetType(); + rawData->stackConext = reinterpret_cast(const_cast(data)); + rawData->data = reinterpret_cast(const_cast(data)) + sizeof(BaseStackRawData); + rawData->fpDepth = (size - sizeof(BaseStackRawData)) / sizeof(uint64_t); if (isStopTakeData_) { return false; - } else if (type == MEMORY_TAG) { + } else if (rawData->stackConext->type == MEMORY_TAG) { std::string tagName = reinterpret_cast(rawData->data); - SaveMemTag(rawData->stackContext->tagId, tagName); + SaveMemTag(rawData->stackConext->tagId, tagName); return true; - } else if (HandleNoStackEvent(hookRecord)) { + } else if (HandleNoStackEvent(rawData)) { return true; - } else if (type == MUNMAP_MSG) { + } else if (rawData->stackConext->type == MUNMAP_MSG) { std::lock_guard guard(mtx_); - runtime_instance->RemoveMaps(reinterpret_cast(hookRecord->GetAddr())); - } else if (type == NMD_MSG) { + runtime_instance->RemoveMaps(reinterpret_cast(rawData->stackConext->addr)); + } else if (rawData->stackConext->type == NMD_MSG) { const char* nmdResult = reinterpret_cast(rawData->data); lseek(nmdFd_, 0, SEEK_END); (void)write(nmdFd_, nmdResult, strlen(nmdResult)); return true; - } else if (type == END_MSG) { - endMsgCount_++; - if (endMsgCount_ == SHARED_MEMORY_NUM) { - isStopTakeData_ = true; - } - return true; - } else if (type == JS_STACK_MSG) { - SaveJsRawStack(rawData->stackContext->jsChainId, reinterpret_cast(rawData->data)); + } else if (rawData->stackConext->type == END_MSG) { + isStopTakeData_ = true; return true; } - if (rawData->stackContext->jsChainId > 0) { - rawData->jsStackData = GetJsRawStack(rawData->stackContext->jsChainId); + { + std::lock_guard guard(mtx_); + runtime_instance->UpdateThread(rawData->stackConext->pid, rawData->stackConext->tid); } - auto& callFrames = g_director->ConstructCallFrames(hookRecord); ReportOfflineSymbolizationData(); std::visit([&](auto& stackData) { - if (hookConfig_.save_file() && hookConfig_.file_name() != "" && isHookStandaloneSerialize_) { - SetHookData(hookRecord, callFrames, stackData); - } else if (hookConfig_.save_file() && hookConfig_.file_name() != "") { - WriteFrames(hookRecord, callFrames); - } else if (!hookConfig_.save_file()) { - SetHookData(hookRecord, callFrames, stackData); - } + SetHookData(rawData, stackData); + FlushCheck(stackData); }, stackData_); IntervalFlushRecordStatistics(); #ifdef PERFORMANCE_DEBUG @@ -332,7 +340,7 @@ void StackPreprocess::TakeResultsFromShmem(const std::shared_ptr& (end.tv_nsec - start.tv_nsec); if (curTimeCost >= LONG_TIME_THRESHOLD) { PROFILER_LOG_ERROR(LOG_CORE, "bigTimeCost %" PRIu64 " event=%d fpDepth=%u", - curTimeCost, type, rawData->fpDepth); + curTimeCost, rawData->stackConext->type, rawData->fpDepth); } timeCost += curTimeCost; unwindTimes++; @@ -341,10 +349,6 @@ void StackPreprocess::TakeResultsFromShmem(const std::shared_ptr& unwindTimes.load(), timeCost.load(), timeCost.load() / unwindTimes.load()); } #endif - if (hookRecord != nullptr) { - factory_->SaveHookRecord(std::move(hookRecord)); - hookRecord = nullptr; - } return true; }); if (!ret) { @@ -358,12 +362,16 @@ void StackPreprocess::TakeResults() if (!dataRepeater_) { return; } - PROFILER_LOG_INFO(LOG_CORE, "TakeResults thread %d, start!", gettid()); - if (g_director == nullptr) { - g_director = std::make_shared(&hookConfig_, runtime_instance); + + size_t minStackDepth = hookConfig_.max_stack_depth() > MIN_STACK_DEPTH + ? MIN_STACK_DEPTH : hookConfig_.max_stack_depth(); + if (hookConfig_.blocked()) { + minStackDepth = static_cast(hookConfig_.max_stack_depth()); } + minStackDepth += FILTER_STACK_DEPTH; + PROFILER_LOG_INFO(LOG_CORE, "TakeResults thread %d, start!", gettid()); while (1) { - HookRecordPtr batchRawStack[MAX_BATCH_CNT] = {nullptr}; + RawStackPtr batchRawStack[MAX_BATCH_CNT] = {nullptr}; if (isStopTakeData_) { break; } @@ -386,23 +394,23 @@ void StackPreprocess::TakeResults() break; } for (unsigned int i = 0; i < MAX_BATCH_CNT; i++) { - auto hookRecord = batchRawStack[i]; - if (!hookRecord || isStopTakeData_) { + auto rawData = batchRawStack[i]; + if (!rawData || isStopTakeData_) { break; } - uint16_t type = hookRecord->GetType(); - if (type == FREE_MSG_SIMP) { - SetFreeStatisticsData(hookRecord->GetAddr()); + if (rawData->baseStackData == nullptr) { + if (rawData->freeData) { + SetFreeStatisticsData(rawData->freeData); + } continue; } - auto rawData = hookRecord->GetRawStack(); - if (rawData->stackContext == nullptr) { - PROFILER_LOG_ERROR(LOG_CORE, "StackPreprocess take results rawData->stackContext is nullptr"); + if (rawData->stackConext == nullptr) { + PROFILER_LOG_ERROR(LOG_CORE, "StackPreprocess take results rawData->stackConext is nullptr"); continue; } - if (type == NMD_MSG) { + if (rawData->stackConext->type == NMD_MSG) { continue; - } else if (type == END_MSG) { + } else if (rawData->stackConext->type == END_MSG) { isStopTakeData_ = true; break; } @@ -410,11 +418,11 @@ void StackPreprocess::TakeResults() struct timespec start = {}; clock_gettime(CLOCK_REALTIME, &start); #endif - if (HandleNoStackEvent(hookRecord)) { + if (HandleNoStackEvent(rawData)) { continue; - } else if (type == MUNMAP_MSG) { + } else if (rawData->stackConext->type == MUNMAP_MSG) { std::lock_guard guard(mtx_); - runtime_instance->RemoveMaps(reinterpret_cast(hookRecord->GetAddr())); + runtime_instance->RemoveMaps(reinterpret_cast(rawData->stackConext->addr)); } if (!rawData->reportFlag) { @@ -429,24 +437,61 @@ void StackPreprocess::TakeResults() if (eventCnts_ % LOG_PRINT_TIMES == 0) { PROFILER_LOG_INFO(LOG_CORE, "eventCnts_ = %d quene size = %zu\n", eventCnts_, dataRepeater_->Size()); } - auto& callFrames = g_director->ConstructCallFrames(hookRecord); + callFrames_.clear(); + if (hookConfig_.fp_unwind()) { + FillFpNativeIp(rawData); + if (rawData->stackConext->jsChainId > 0 && rawData->jsStackData && hookConfig_.js_stack_report() > 0) { + FillFpJsData(rawData); + } + } else if (rawData->stackConext->type != PR_SET_VMA_MSG) { + if (rawData->stackSize == 0) { + FillDwarfErrorStack(); + } else { +#if defined(__arm__) + uint32_t *regAddrArm = reinterpret_cast(rawData->data); + u64regs_.assign(regAddrArm, regAddrArm + PERF_REG_ARM_MAX); +#else + if (memcpy_s(u64regs_.data(), sizeof(uint64_t) * PERF_REG_ARM64_MAX, rawData->data, + sizeof(uint64_t) * PERF_REG_ARM64_MAX) != EOK) { + PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s regs failed"); + } +#endif + } + } #ifdef PERFORMANCE_DEBUG - size_t realFrameDepth = callFrames.size(); + size_t realFrameDepth = callFrames_.size(); #endif + size_t stackDepth = ((size_t)hookConfig_.max_stack_depth() > MAX_CALL_FRAME_UNWIND_SIZE) + ? MAX_CALL_FRAME_UNWIND_SIZE + : hookConfig_.max_stack_depth() + FILTER_STACK_DEPTH; + if (rawData->reduceStackFlag) { + stackDepth = minStackDepth; + } + if ((hookConfig_.fp_unwind()) || rawData->stackSize > 0) { + std::lock_guard guard(mtx_); + if (rawData->stackConext->type != PR_SET_VMA_MSG) { + bool ret = runtime_instance->UnwindStack(u64regs_, rawData->stackData, rawData->stackSize, + rawData->stackConext->pid, rawData->stackConext->tid, callFrames_, stackDepth); + if (!ret) { + PROFILER_LOG_ERROR(LOG_CORE, "unwind fatal error"); + continue; + } + } + } if (((hookConfig_.fp_unwind()) || rawData->stackSize > 0) && - (type != PR_SET_VMA_MSG)) { + (rawData->stackConext->type != PR_SET_VMA_MSG)) { ReportOfflineSymbolizationData(); } std::visit([&](auto& stackData) { if (hookConfig_.save_file() && hookConfig_.file_name() != "" && isHookStandaloneSerialize_) { - SetHookData(hookRecord, callFrames, stackData); + SetHookData(rawData, callFrames_, stackData); } else if (hookConfig_.save_file() && hookConfig_.file_name() != "") { - WriteFrames(hookRecord, callFrames); + WriteFrames(rawData, callFrames_); } else if (!hookConfig_.save_file()) { if (hookConfig_.malloc_free_matching_interval() > 0) { - SetApplyAndReleaseMatchFrame(hookRecord, callFrames, stackData); + SetApplyAndReleaseMatchFrame(rawData, callFrames_, stackData); } else { - SetHookData(hookRecord, callFrames, stackData); + SetHookData(rawData, callFrames_, stackData); } } }, stackData_); @@ -459,7 +504,7 @@ void StackPreprocess::TakeResults() if (curTimeCost >= LONG_TIME_THRESHOLD) { PROFILER_LOG_ERROR(LOG_CORE, "bigTimeCost %" PRIu64 " event=%d, realFrameDepth=%zu, " "callFramesDepth=%zu\n", - curTimeCost, type, realFrameDepth, callFrames.size()); + curTimeCost, rawData->stackConext->type, realFrameDepth, callFrames_.size()); } timeCost += curTimeCost; unwindTimes++; @@ -473,7 +518,7 @@ void StackPreprocess::TakeResults() if (!batchRawStack[i]) { break; } - factory_->SaveHookRecord(std::move(batchRawStack[i])); + dataRepeater_->ReturnRawStack(std::move(batchRawStack[i])); } if (hookConfig_.save_file() && hookConfig_.file_name() != "" && !isHookStandaloneSerialize_) { continue; @@ -512,10 +557,10 @@ inline void StackPreprocess::FillOfflineCallStack(std::vector& callFr for (; idx < callFrames.size(); ++idx) { if (callFrames[idx].isJsFrame_) { ReportFrameMap(callFrames[idx], stackData); - g_callStack.push_back(callFrames[idx].callFrameId_ | JS_OFFLINE_IP_MASK); + callStack_.push_back(callFrames[idx].callFrameId_ | JS_OFFLINE_IP_MASK); continue; } - g_callStack.push_back(callFrames[idx].ip_); + callStack_.push_back(callFrames[idx].ip_); } } @@ -525,7 +570,7 @@ inline void StackPreprocess::FillCallStack(std::vector& callFrames, s for (; idx < callFrames.size(); ++idx) { ReportFrameMap(callFrames[idx], stackData); // for call stack id - g_callStack.push_back(callFrames[idx].callFrameId_); + callStack_.push_back(callFrames[idx].callFrameId_); } } @@ -544,7 +589,6 @@ inline uint32_t StackPreprocess::FindCallStackId(std::vector& callStac template inline uint32_t StackPreprocess::SetCallStackMap(T& stackData) { - std::lock_guard guard(mtx_); uint32_t stackId = 0; auto hookData = stackData.add_events(); auto stackmap = hookData->mutable_stack_map(); @@ -553,23 +597,23 @@ inline uint32_t StackPreprocess::SetCallStackMap(T& stackData) // offline symbolization use ip, other use frame_map_id if (hookConfig_.offline_symbolization()) { if constexpr (std::is_same::value) { - stackmap->add_ip(g_callStack); + stackmap->add_ip(callStack_); } else { - for (size_t i = 0; i < g_callStack.size(); i++) { - stackmap->add_ip(g_callStack[i]); + for (size_t i = 0; i < callStack_.size(); i++) { + stackmap->add_ip(callStack_[i]); } } } else { if constexpr (std::is_same::value) { - stackmap->add_frame_map_id(g_callStack); + stackmap->add_frame_map_id(callStack_); } else { - for (size_t i = 0; i < g_callStack.size(); i++) { - stackmap->add_frame_map_id(g_callStack[i]); + for (size_t i = 0; i < callStack_.size(); i++) { + stackmap->add_frame_map_id(callStack_[i]); } } } stackmap->set_pid(pid_); - callStackMap_[g_callStack] = stackId; + callStackMap_[callStack_] = stackId; return stackId; } @@ -577,36 +621,34 @@ inline uint32_t StackPreprocess::SetCallStackMap(T& stackData) * @return '0' is invalid stack id, '> 0' is valid stack id */ template -inline uint32_t StackPreprocess::GetCallStackId(const HookRecordPtr& hookRecord, std::vector& callFrames, +inline uint32_t StackPreprocess::GetCallStackId(const RawStackPtr& rawStack, std::vector& callFrames, T& stackData) { - auto rawStack = hookRecord->GetRawStack(); // ignore the first two frame if dwarf unwind size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; // if free_stack_report or munmap_stack_report is false, don't need to record. - uint16_t type = hookRecord->GetType(); - if ((type == FREE_MSG) && !hookConfig_.free_stack_report()) { + if ((rawStack->stackConext->type == FREE_MSG) && !hookConfig_.free_stack_report()) { return 0; - } else if ((type == MUNMAP_MSG) && !hookConfig_.munmap_stack_report()) { + } else if ((rawStack->stackConext->type == MUNMAP_MSG) && !hookConfig_.munmap_stack_report()) { return 0; } - g_callStack.clear(); + callStack_.clear(); bool isNapi = false; - if (type == MEMORY_USING_MSG && hookConfig_.js_stack_report() == NAPI_CALL_STACK) { + if (rawStack->stackConext->type == MEMORY_USING_MSG && hookConfig_.js_stack_report() == NAPI_CALL_STACK) { std::string tagName; - GetMemTag(rawStack->stackContext->tagId, tagName); + GetMemTag(rawStack->stackConext->tagId, tagName); if (tagName.find("napi") != std::string::npos) { - g_callStack.reserve(callFrames.size() + 1); // 1 : insert a frame + callStack_.reserve(callFrames.size() + 1); // 1 : insert a frame if (!hookConfig_.offline_symbolization()) { - g_callStack.push_back(DWARF_NAPI_CALLBACK + napiIndex_); + callStack_.push_back(DWARF_NAPI_CALLBACK + napiIndex_); } else { // just for offline symbolization - g_callStack.push_back((DWARF_NAPI_CALLBACK + napiIndex_) | JS_OFFLINE_IP_MASK); + callStack_.push_back((DWARF_NAPI_CALLBACK + napiIndex_) | JS_OFFLINE_IP_MASK); } isNapi = true; } } else { - g_callStack.reserve(callFrames.size()); + callStack_.reserve(callFrames.size()); } if (!hookConfig_.offline_symbolization()) { FillCallStack(callFrames, idx, stackData); @@ -619,13 +661,14 @@ inline uint32_t StackPreprocess::GetCallStackId(const HookRecordPtr& hookRecord, if (isNapi) { // insert a frame std::string tagName; - GetMemTag(rawStack->stackContext->tagId, tagName); + GetMemTag(rawStack->stackConext->tagId, tagName); FillNapiStack(tagName, callFrames, napiIndex_); ReportFrameMap(callFrames.back(), stackData); ++napiIndex_; } // return call stack id - uint32_t stackId = FindCallStackId(g_callStack); + std::lock_guard guard(mtx_); + uint32_t stackId = FindCallStackId(callStack_); if (stackId > 0) { return stackId; } else { @@ -660,9 +703,45 @@ void StackPreprocess::SetEventFrame(const ReportEventBaseData& rawStack, event->set_thread_name_id(rawStack.tid); } +template +void StackPreprocess::SetEventFrame(const RawStackPtr& rawStack, std::vector& callFrames, + T* event, uint32_t stackMapId, const std::string& type) +{ + // ignore the first two frame if dwarf unwind + size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; + event->set_pid(rawStack->stackConext->pid); + event->set_tid(rawStack->stackConext->tid); + event->set_addr((uint64_t)rawStack->stackConext->addr); + + if constexpr (std::is_same::value || std::is_same::value) { + event->set_type(type); + } + + if constexpr (!std::is_same::value && !std::is_same::value) { + auto size = static_cast(rawStack->stackConext->mallocSize); +#ifdef USE_JEMALLOC + if constexpr (std::is_same::value || std::is_same::value) { + size = static_cast(ComputeAlign(size)); + } +#endif + event->set_size(size); + } + + if (hookConfig_.callframe_compress() && stackMapId != 0) { + event->set_thread_name_id(rawStack->stackConext->tid); + event->set_stack_id(stackMapId); + } else { + for (; idx < callFrames.size(); ++idx) { + auto frame = event->add_frame_info(); + SetFrameInfo(*frame, callFrames[idx]); + } + event->set_thread_name_id(rawStack->stackConext->tid); + } +} + void StackPreprocess::FillNapiStack(std::string& tagName, std::vector& callFrames, uint64_t napiIndex) { - CallFrame& jsCallFrame = callFrames.emplace_back(0); + CallFrame& jsCallFrame = callFrames_.emplace_back(0); jsCallFrame.symbolName_ = tagName; jsCallFrame.isJsFrame_ = true; jsCallFrame.needReport_ |= CALL_FRAME_REPORT; @@ -675,31 +754,30 @@ void StackPreprocess::FillNapiStack(std::string& tagName, std::vector } template -void StackPreprocess::SetAllocStatisticsFrame(const HookRecordPtr& hookRecord, std::vector& callFrames, +void StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector& callFrames, T& stackData) { // ignore the first two frame if dwarf unwind - auto rawStack = hookRecord->GetRawStack(); size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; - g_callStack.clear(); + callStack_.clear(); bool isNapi = false; if (hookConfig_.js_stack_report() == NAPI_CALL_STACK) { std::string tagName; - GetMemTag(rawStack->stackContext->tagId, tagName); + GetMemTag(rawStack->stackConext->tagId, tagName); if (tagName.find("napi") != std::string::npos) { - g_callStack.reserve(callFrames.size() + FRAME_DEPTH); // insert a frame + callStack_.reserve(callFrames.size() + FRAME_DEPTH); // insert a frame if (!hookConfig_.offline_symbolization()) { - g_callStack.push_back(DWARF_NAPI_CALLBACK + napiIndex_); + callStack_.push_back(DWARF_NAPI_CALLBACK + napiIndex_); } else { // just for offline symbolization - g_callStack.push_back((DWARF_NAPI_CALLBACK + napiIndex_) | JS_OFFLINE_IP_MASK); + callStack_.push_back((DWARF_NAPI_CALLBACK + napiIndex_) | JS_OFFLINE_IP_MASK); } isNapi = true; } } else { - g_callStack.reserve(callFrames.size() + 1); + callStack_.reserve(callFrames.size() + 1); } - g_callStack.push_back(rawStack->stackContext->mallocSize | SIZE_MASK); + callStack_.push_back(rawStack->stackConext->mallocSize | SIZE_MASK); if (!hookConfig_.offline_symbolization()) { FillCallStack(callFrames, idx, stackData); } else { @@ -708,79 +786,74 @@ void StackPreprocess::SetAllocStatisticsFrame(const HookRecordPtr& hookRecord, s // insert a frame if (isNapi) { std::string tagName; - GetMemTag(rawStack->stackContext->tagId, tagName); + GetMemTag(rawStack->stackConext->tagId, tagName); FillNapiStack(tagName, callFrames, napiIndex_); ReportFrameMap(callFrames.back(), stackData); ++napiIndex_; } - spinLock_.Lock(); + std::lock_guard guard(mtx_); // by call stack id set alloc statistics data. - uint32_t stackId = FindCallStackId(g_callStack); + uint32_t stackId = FindCallStackId(callStack_); if (stackId > 0) { - SetAllocStatisticsData(hookRecord, stackId, true); + SetAllocStatisticsData(rawStack, stackId, true); } else { stackId = SetCallStackMap(stackData); statisticsModelFlushCallstack_ = true; - SetAllocStatisticsData(hookRecord, stackId); + SetAllocStatisticsData(rawStack, stackId); } - spinLock_.Unlock(); } template -void StackPreprocess::SetAllocStatisticsFrame(const HookRecordPtr& hookRecord, T& stackData) +void StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack, T& stackData) { - auto rawStack = hookRecord->GetRawStack(); - g_callStack.resize(rawStack->fpDepth + 1); - g_callStack[0] = (rawStack->stackContext->mallocSize | SIZE_MASK); + callStack_.resize(rawStack->fpDepth + 1); + callStack_[0] = (rawStack->stackConext->mallocSize | SIZE_MASK); uint64_t* fpIp = reinterpret_cast(rawStack->data); for (uint8_t idx = 0; idx < rawStack->fpDepth ; ++idx) { if (fpIp[idx] != 0) { fpIp[idx] = StripPac(fpIp[idx], 0); } } - if (memcpy_s(g_callStack.data() + 1, sizeof(uint64_t) * rawStack->fpDepth, + if (memcpy_s(callStack_.data() + 1, sizeof(uint64_t) * rawStack->fpDepth, rawStack->data, sizeof(uint64_t) * rawStack->fpDepth) != EOK) { - PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s g_callStack failed"); + PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s callStack_ failed"); return; } + std::lock_guard guard(mtx_); // by call stack id set alloc statistics data. - uint32_t stackId = FindCallStackId(g_callStack); + uint32_t stackId = FindCallStackId(callStack_); if (stackId > 0) { - SetAllocStatisticsData(hookRecord, stackId, true); + SetAllocStatisticsData(rawStack, stackId, true); } else { stackId = SetCallStackMap(stackData); statisticsModelFlushCallstack_ = true; - SetAllocStatisticsData(hookRecord, stackId); + SetAllocStatisticsData(rawStack, stackId); } } template -void StackPreprocess::SetHookData(HookRecordPtr hookRecord, T& stackData) +void StackPreprocess::SetHookData(RawStackPtr rawStack, T& stackData) { - auto rawStack = hookRecord->GetRawStack(); if (hookConfig_.statistics_interval() > 0) { // statistical reporting must is compressed and accurate. - switch (hookRecord->GetType()) { + switch (rawStack->stackConext->type) { case FREE_MSG: case MUNMAP_MSG: case MEMORY_UNUSING_MSG: { - SetFreeStatisticsData(hookRecord->GetAddr()); + SetFreeStatisticsData((uint64_t)rawStack->stackConext->addr); break; } case MALLOC_MSG: - rawStack->stackContext->mallocSize = ComputeAlign(rawStack->stackContext->mallocSize); + rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize); case MMAP_MSG: case MMAP_FILE_PAGE_MSG: case MEMORY_USING_MSG: { - SetAllocStatisticsFrame(hookRecord, stackData); + SetAllocStatisticsFrame(rawStack, stackData); break; } case PR_SET_VMA_MSG: { break; } - case JS_STACK_MSG: { - break; - } default: { PROFILER_LOG_ERROR(LOG_CORE, "statistics event type: error"); break; @@ -799,67 +872,63 @@ void StackPreprocess::ReportOfflineSymbolizationData() } template -void StackPreprocess::SetApplyAndReleaseMatchFrame(HookRecordPtr hookRecord, std::vector& callFrames, +void StackPreprocess::SetApplyAndReleaseMatchFrame(RawStackPtr rawStack, std::vector& callFrames, T& stackData) { uint32_t stackMapId = 0; - auto rawStack = hookRecord->GetRawStack(); - uint16_t type = hookRecord->GetType(); - if (type != PR_SET_VMA_MSG) { - stackMapId = GetCallStackId(hookRecord, callFrames, stackData); + if (rawStack->stackConext->type != PR_SET_VMA_MSG) { + stackMapId = GetCallStackId(rawStack, callFrames, stackData); } else { - rawStack->stackContext->tagId = prctlPeriodTags_.size(); + rawStack->stackConext->tagId = prctlPeriodTags_.size(); prctlPeriodTags_.emplace_back(reinterpret_cast(rawStack->data)); - applyAndReleaseMatchPeriodListData_.emplace_back(rawStack->stackContext); + applyAndReleaseMatchPeriodListData_.emplace_back(rawStack->stackConext); } - if (type == MALLOC_MSG) { - rawStack->stackContext->mallocSize = ComputeAlign(rawStack->stackContext->mallocSize); - } else if (type == PR_SET_VMA_MSG) { + if (rawStack->stackConext->type == MALLOC_MSG) { + rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize); + } else if (rawStack->stackConext->type == PR_SET_VMA_MSG) { return; } - uint64_t addr = reinterpret_cast(hookRecord->GetAddr()); - bool isReleasedType = ((type == FREE_MSG) || (type == MUNMAP_MSG)); + uint64_t addr = reinterpret_cast(rawStack->stackConext->addr); + bool isReleasedType = ((rawStack->stackConext->type == FREE_MSG) || (rawStack->stackConext->type == MUNMAP_MSG)); if (isReleasedType) { auto iter = applyAndReleaseMatchIntervallMap_.find(addr); if (iter != applyAndReleaseMatchIntervallMap_.end()) { applyAndReleaseMatchPeriodListData_.erase(iter->second); applyAndReleaseMatchIntervallMap_.erase(addr); } else { - releasedPeriodListData_.emplace_back(rawStack->stackContext, stackMapId); + releasedPeriodListData_.emplace_back(rawStack->stackConext, stackMapId); } } else { - applyAndReleaseMatchPeriodListData_.emplace_back(rawStack->stackContext, stackMapId); + applyAndReleaseMatchPeriodListData_.emplace_back(rawStack->stackConext, stackMapId); applyAndReleaseMatchIntervallMap_.emplace(addr, std::prev(applyAndReleaseMatchPeriodListData_.end())); } } template -void StackPreprocess::SetHookData(HookRecordPtr hookRecord, std::vector& callFrames, T& stackData) +void StackPreprocess::SetHookData(RawStackPtr rawStack, std::vector& callFrames, T& stackData) { // statistical reporting must is compressed and accurate. - auto rawStack = hookRecord->GetRawStack(); - uint16_t type = hookRecord->GetType(); if (hookConfig_.statistics_interval() > 0) { - switch (type) { + switch (rawStack->stackConext->type) { case FREE_MSG: case MUNMAP_MSG: case MEMORY_UNUSING_MSG: { - SetFreeStatisticsData(hookRecord->GetAddr()); + SetFreeStatisticsData((uint64_t)rawStack->stackConext->addr); break; } case MALLOC_MSG: - rawStack->stackContext->mallocSize = ComputeAlign(rawStack->stackContext->mallocSize); + rawStack->stackConext->mallocSize = ComputeAlign(rawStack->stackConext->mallocSize); case MMAP_MSG: case MMAP_FILE_PAGE_MSG: case MEMORY_USING_MSG: { - SetAllocStatisticsFrame(hookRecord, callFrames, stackData); + SetAllocStatisticsFrame(rawStack, callFrames, stackData); break; } case PR_SET_VMA_MSG: { break; } default: { - PROFILER_LOG_ERROR(LOG_CORE, "statistics event type:%d error", type); + PROFILER_LOG_ERROR(LOG_CORE, "statistics event type:%d error", rawStack->stackConext->type); break; } } @@ -868,8 +937,8 @@ void StackPreprocess::SetHookData(HookRecordPtr hookRecord, std::vectorstackConext->type == MEMORY_TAG || rawStack->stackConext->type == PR_SET_VMA_MSG)) { + stackMapId = GetCallStackId(rawStack, callFrames, stackData); } if ((!hookConfig_.callframe_compress() || stackMapId == 0) && hookConfig_.string_compressed()) { @@ -881,54 +950,83 @@ void StackPreprocess::SetHookData(HookRecordPtr hookRecord, std::vectorset_tv_sec(rawStack->stackContext->ts.tv_sec); - hookData->set_tv_nsec(rawStack->stackContext->ts.tv_nsec); - std::string tagName = ""; - if (type == MMAP_FILE_PAGE_MSG || type == MEMORY_USING_MSG) { - GetMemTag(rawStack->stackContext->tagId, tagName); - } - SerializeInfo hookInfo = {&callFrames, stackMapId, tagName, &hookConfig_}; - hookRecord->SerializeData(hookData, hookInfo); + hookData->set_tv_sec(rawStack->stackConext->ts.tv_sec); + hookData->set_tv_nsec(rawStack->stackConext->ts.tv_nsec); + + if (rawStack->stackConext->type == MALLOC_MSG) { + auto allocEvent = hookData->mutable_alloc_event(); + SetEventFrame(rawStack, callFrames, allocEvent, stackMapId); + } else if (rawStack->stackConext->type == FREE_MSG) { + auto freeEvent = hookData->mutable_free_event(); + SetEventFrame(rawStack, callFrames, freeEvent, stackMapId); + } else if (rawStack->stackConext->type == MMAP_MSG) { + auto mmapEvent = hookData->mutable_mmap_event(); + SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId); + } else if (rawStack->stackConext->type == MMAP_FILE_PAGE_MSG) { + auto mmapEvent = hookData->mutable_mmap_event(); + const std::string prefix = "FilePage:"; + std::string tagName; + if (GetMemTag(rawStack->stackConext->tagId, tagName)) { + tagName = prefix + tagName; + } + SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId, tagName); + } else if (rawStack->stackConext->type == MUNMAP_MSG) { + auto munmapEvent = hookData->mutable_munmap_event(); + SetEventFrame(rawStack, callFrames, munmapEvent, stackMapId); + } else if (rawStack->stackConext->type == PR_SET_VMA_MSG) { + auto tagEvent = hookData->mutable_tag_event(); + const std::string prefix = "Anonymous:"; + std::string tagName(reinterpret_cast(rawStack->data)); + tagEvent->set_addr((uint64_t)rawStack->stackConext->addr); + tagEvent->set_size(rawStack->stackConext->mallocSize); + tagEvent->set_tag(prefix + tagName); + tagEvent->set_pid(pid_); + } else if (rawStack->stackConext->type == MEMORY_USING_MSG) { + auto mmapEvent = hookData->mutable_mmap_event(); + std::string tagName; + GetMemTag(rawStack->stackConext->tagId, tagName); + SetEventFrame(rawStack, callFrames, mmapEvent, stackMapId, tagName); + } else if (rawStack->stackConext->type == MEMORY_UNUSING_MSG) { + auto munmapEvent = hookData->mutable_munmap_event(); + SetEventFrame(rawStack, callFrames, munmapEvent, stackMapId); + } } inline bool StackPreprocess::SetFreeStatisticsData(uint64_t addr) { // through the addr lookup record - auto addrIter = g_allocAddrMap.find(addr); - if (addrIter != g_allocAddrMap.end()) { - spinLock_.Lock(); + auto addrIter = allocAddrMap_.find(addr); + if (addrIter != allocAddrMap_.end()) { auto& record = addrIter->second.second; ++record->releaseCount; record->releaseSize += addrIter->second.first; statisticsPeriodData_[record->callstackId] = record; - g_allocAddrMap.erase(addr); - spinLock_.Unlock(); + allocAddrMap_.erase(addr); return true; } return false; } -inline void StackPreprocess::SetAllocStatisticsData(const HookRecordPtr& hookRecord, size_t stackId, bool isExists) +inline void StackPreprocess::SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists) { - auto rawStack = hookRecord->GetRawStack(); // if the record exists, it is updated.Otherwise Add if (isExists) { auto recordIter = recordStatisticsMap_.find(stackId); if (recordIter != recordStatisticsMap_.end()) { auto& record = recordIter->second; ++record.applyCount; - record.applySize += rawStack->stackContext->mallocSize; - g_allocAddrMap[hookRecord->GetAddr()] = - std::pair(rawStack->stackContext->mallocSize, &recordIter->second); + record.applySize += rawStack->stackConext->mallocSize; + allocAddrMap_[(uint64_t)rawStack->stackConext->addr] = + std::pair(rawStack->stackConext->mallocSize, &recordIter->second); statisticsPeriodData_[stackId] = &recordIter->second; } } else { RecordStatistic record; - record.pid = rawStack->stackContext->pid; + record.pid = rawStack->stackConext->pid; record.callstackId = stackId; record.applyCount = 1; - record.applySize = rawStack->stackContext->mallocSize; - switch (hookRecord->GetType()) { + record.applySize = rawStack->stackConext->mallocSize; + switch (rawStack->stackConext->type) { case MALLOC_MSG: { record.type = RecordStatisticsEvent::MALLOC; break; @@ -943,7 +1041,7 @@ inline void StackPreprocess::SetAllocStatisticsData(const HookRecordPtr& hookRec } case MEMORY_USING_MSG: { record.type = RecordStatisticsEvent::MEMORY_USING_MSG; - record.tagId = rawStack->stackContext->tagId; + record.tagId = rawStack->stackConext->tagId; break; } default: { @@ -953,29 +1051,27 @@ inline void StackPreprocess::SetAllocStatisticsData(const HookRecordPtr& hookRec } auto [recordIter, stat] = recordStatisticsMap_.emplace(stackId, record); - g_allocAddrMap[hookRecord->GetAddr()] = - std::pair(rawStack->stackContext->mallocSize, &recordIter->second); + allocAddrMap_[(uint64_t)rawStack->stackConext->addr] = + std::pair(rawStack->stackConext->mallocSize, &recordIter->second); statisticsPeriodData_[stackId] = &recordIter->second; } } -void StackPreprocess::WriteFrames(HookRecordPtr hookRecord, const std::vector& callFrames) +void StackPreprocess::WriteFrames(RawStackPtr rawStack, const std::vector& callFrames) { - std::lock_guard guard(mtx_); - auto rawStack = hookRecord->GetRawStack(); CHECK_TRUE(fpHookData_ != nullptr, NO_RETVAL, "fpHookData_ is nullptr, please check file_name(%s)", hookConfig_.file_name().c_str()); - if (hookRecord->GetType() == PR_SET_VMA_MSG) { + if (rawStack->stackConext->type == PR_SET_VMA_MSG) { const std::string prefix = "Anonymous:"; std::string tagName(reinterpret_cast(rawStack->data)); fprintf(fpHookData_, "prctl;%u;%u;%" PRId64 ";%ld;0x%" PRIx64 ":tag:%s\n", - rawStack->stackContext->pid, rawStack->stackContext->tid, - static_cast(rawStack->stackContext->ts.tv_sec), rawStack->stackContext->ts.tv_nsec, - hookRecord->GetAddr(), (prefix + tagName).c_str()); + rawStack->stackConext->pid, rawStack->stackConext->tid, + (int64_t)rawStack->stackConext->ts.tv_sec, rawStack->stackConext->ts.tv_nsec, + (uint64_t)rawStack->stackConext->addr, (prefix + tagName).c_str()); return; } std::string tag = ""; - switch (hookRecord->GetType()) { + switch (rawStack->stackConext->type) { case FREE_MSG: tag = "free"; break; @@ -993,9 +1089,8 @@ void StackPreprocess::WriteFrames(HookRecordPtr hookRecord, const std::vectorstackContext->pid, rawStack->stackContext->tid, - static_cast(rawStack->stackContext->ts.tv_sec), - rawStack->stackContext->ts.tv_nsec, hookRecord->GetAddr(), rawStack->stackContext->mallocSize); + rawStack->stackConext->pid, rawStack->stackConext->tid, (int64_t)rawStack->stackConext->ts.tv_sec, + rawStack->stackConext->ts.tv_nsec, (uint64_t)rawStack->stackConext->addr, rawStack->stackConext->mallocSize); size_t idx = hookConfig_.fp_unwind() ? 0 : FILTER_STACK_DEPTH; for (; idx < callFrames.size(); ++idx) { (void)fprintf(fpHookData_, "0x%" PRIx64 ";0x%" PRIx64 ";%s;%s;0x%" PRIx64 ";%" PRIu64 "\n", @@ -1065,7 +1160,6 @@ inline void StackPreprocess::ReportFrameMap(CallFrame& callFrame, T& stackData) } else if ((!hookConfig_.fp_unwind()) && callFrame.callFrameId_ == DWARF_ERROR_ID && unwindFailReport_) { unwindFailReport_ = false; } - std::lock_guard guard(mtx_); ReportSymbolNameMap(callFrame, stackData); ReportFilePathMap(callFrame, stackData); auto hookData = stackData.add_events(); @@ -1279,7 +1373,6 @@ bool StackPreprocess::FlushRecordStatistics() if (statisticsPeriodData_.empty()) { return false; } - spinLock_.Lock(); std::visit([&](auto& stackData) { FlushData(stackData); }, stackData_); @@ -1302,13 +1395,11 @@ bool StackPreprocess::FlushRecordStatistics() FlushData(stackData); }, stackData_); statisticsPeriodData_.clear(); - spinLock_.Unlock(); return true; } void StackPreprocess::SaveMemTag(uint32_t tagId, const std::string& tagName) { - std::lock_guard guard(memTagMtx_); std::string temp; bool res = memTagMap_.Find(tagId, temp); if (!res) { @@ -1318,13 +1409,11 @@ void StackPreprocess::SaveMemTag(uint32_t tagId, const std::string& tagName) bool StackPreprocess::GetMemTag(uint32_t tagId, std::string& tagName) { - std::lock_guard guard(memTagMtx_); return memTagMap_.Find(tagId, tagName); } void StackPreprocess::SaveJsRawStack(uint64_t jsChainId, const char* jsRawStack) { - std::lock_guard guard(jsMapMtx_); auto iterChainId = jsStackMap_.find(jsChainId); if (iterChainId == jsStackMap_.end()) { auto iterRawStack = jsStackSet_.find(jsRawStack); @@ -1339,7 +1428,6 @@ void StackPreprocess::SaveJsRawStack(uint64_t jsChainId, const char* jsRawStack) const char* StackPreprocess::GetJsRawStack(uint64_t jsChainId) { - std::lock_guard guard(jsMapMtx_); auto iter = jsStackMap_.find(jsChainId); if (iter != jsStackMap_.end()) { return iter->second; @@ -1347,6 +1435,65 @@ const char* StackPreprocess::GetJsRawStack(uint64_t jsChainId) return nullptr; } +unsigned StackPreprocess::LgFloor(unsigned long val) +{ + val |= (val >> RIGHT_MOVE_1); + val |= (val >> RIGHT_MOVE_2); + val |= (val >> RIGHT_MOVE_4); + val |= (val >> RIGHT_MOVE_8); + val |= (val >> RIGHT_MOVE_16); + if (sizeof(val) > 4) { // 4: sizeThreshold + int constant = sizeof(val) * 4; // 4: sizeThreshold + val |= (val >> constant); + } + val++; + if (val == 0) { + return 8 * sizeof(val) - 1; // 8: 8byte + } + return __builtin_ffsl(val) - 2; // 2: adjustment +} + +uint64_t StackPreprocess::PowCeil(uint64_t val) +{ + size_t msbIndex = LgFloor(val - 1); + return 1ULL << (msbIndex + 1); +} + +size_t StackPreprocess::ComputeAlign(size_t size) +{ + if (size == 0) { + return 0; + } + unsigned index = 0; + if (size <= (size_t(1) << SC_LG_TINY_MAXCLASS)) { + unsigned lgTmin = SC_LG_TINY_MAXCLASS - SC_NTINY + 1; + unsigned lgCeil = LgFloor(PowCeil(size)); + index = (lgCeil < lgTmin) ? 0 : lgCeil - lgTmin; + } else { + unsigned floor = LgFloor((size << 1) - 1); + unsigned shift = (floor < SC_LG_NGROUP + LG_QUANTUM) ? 0 : floor - (SC_LG_NGROUP + LG_QUANTUM); + unsigned grp = shift << SC_LG_NGROUP; + unsigned lgDelta = (floor < SC_LG_NGROUP + LG_QUANTUM + 1) ? LG_QUANTUM : floor - SC_LG_NGROUP - 1; + size_t deltaInverseMask = size_t(-1) << lgDelta; + unsigned mod = ((((size - 1) & deltaInverseMask) >> lgDelta)) & ((size_t(1) << SC_LG_NGROUP) - 1); + index = SC_NTINY + grp + mod; + } + + if (index < NTBINS) { + return (size_t(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index)); + } + size_t reducedIndex = index - NTBINS; + size_t grpVal = reducedIndex >> LG_SIZE_CLASS_GROUP; + size_t modVal = reducedIndex & ((size_t(1) << LG_SIZE_CLASS_GROUP) - 1); + size_t grpSizeMask = ~((!!grpVal) - 1); + size_t grpSize = ((size_t(1) << (LG_QUANTUM + (LG_SIZE_CLASS_GROUP - 1))) << grpVal) & grpSizeMask; + size_t shiftVal = (grpVal == 0) ? 1 : grpVal; + size_t lgDeltaVal = shiftVal + (LG_QUANTUM - 1); + size_t modSize = (modVal + 1) << lgDeltaVal; + size_t usize = grpSize + modSize; + return usize; +} + void StackPreprocess::WriteHookConfig() { const size_t configSize = hookConfig_.ByteSizeLong(); @@ -1404,6 +1551,89 @@ int32_t StackPreprocess::FinishReport() return len; } +void StackPreprocess::FillFpNativeIp(RawStackPtr& rawData) +{ + uint64_t* fpIp = reinterpret_cast(rawData->data); + for (uint8_t idx = 0; idx < rawData->fpDepth ; ++idx) { + if (fpIp[idx] == 0) { + break; + } + callFrames_.emplace_back(StripPac(fpIp[idx], 0)); + } +} + +void StackPreprocess::FillFpJsData(RawStackPtr& rawData) +{ + if (hookConfig_.statistics_interval() > 0) { + switch (rawData->stackConext->type) { + case FREE_MSG: + case MUNMAP_MSG: + case MEMORY_UNUSING_MSG: + return; + default: + break; + } + } + fpJsCallStacks_.clear(); + /** + * jsStackData: + * ts_malloc1|entry/src/main/ets/pages/Index.ets:5:5,ts_malloc2|entry/src/main/ets/pages/Index.ets:8:5 + * | | + * JS_SYMBOL_FILEPATH_SEP JS_CALL_STACK_DEPTH_SEP + * jsCallStack: + * ts_malloc1|entry/src/main/ets/pages/Index.ets:5:5 + * / \ + * | | + * jsSymbolFilePathSepPos | + * jsFilePathPos = jsSymbolFilePathSepPos + 1 + */ + AdvancedSplitString(rawData->jsStackData, JS_CALL_STACK_DEPTH_SEP, fpJsCallStacks_); + for (std::string& jsCallStack: fpJsCallStacks_) { + std::string::size_type jsSymbolFilePathSepPos = jsCallStack.find_first_of(JS_SYMBOL_FILEPATH_SEP); + if (jsSymbolFilePathSepPos == std::string::npos) { + PROFILER_LOG_ERROR(LOG_CORE, "%s: jsCallStack find FAILED!", __func__); + continue; + } + std::string::size_type jsFilePathPos = jsSymbolFilePathSepPos + 1; + jsCallStack[jsSymbolFilePathSepPos] = '\0'; // "ts_malloc1'\0'entry/src/main/ets/pages/Index.ets:5:5" + CallFrame& jsCallFrame = callFrames_.emplace_back(0, 0, true); + jsCallFrame.symbolName_ = StringViewMemoryHold::GetInstance().HoldStringView(jsCallStack.c_str()); + jsCallFrame.filePath_ = StringViewMemoryHold::GetInstance().HoldStringView(jsCallStack.c_str() + jsFilePathPos); + if (hookConfig_.offline_symbolization()) { + DfxSymbol symbol; + if (!runtime_instance->ArktsGetSymbolCache(jsCallFrame, symbol)) { + symbol.filePathId_ = runtime_instance->FillArkTsFilePath(jsCallFrame.filePath_); + symbol.symbolName_ = jsCallFrame.symbolName_; + symbol.module_ = jsCallFrame.filePath_; + symbol.symbolId_ = runtime_instance->GetJsSymbolCacheSize(); + runtime_instance->FillSymbolNameId(jsCallFrame, symbol); + runtime_instance->FillFileSet(jsCallFrame, symbol); + jsCallFrame.needReport_ |= CALL_FRAME_REPORT; + runtime_instance->FillJsSymbolCache(jsCallFrame, symbol); + } + jsCallFrame.callFrameId_ = symbol.symbolId_; + jsCallFrame.symbolNameId_ = symbol.symbolNameId_; + jsCallFrame.filePathId_ = symbol.filePathId_; + jsCallFrame.filePath_ = symbol.module_; + jsCallFrame.symbolName_ = symbol.symbolName_; + } + } +} + +void StackPreprocess::FillDwarfErrorStack() +{ + CallFrame& jsCallFrame = callFrames_.emplace_back(0); + jsCallFrame.symbolName_ = "UnwindErrorDwarf"; + jsCallFrame.isJsFrame_ = true; + jsCallFrame.needReport_ |= CALL_FRAME_REPORT; + jsCallFrame.needReport_ |= SYMBOL_NAME_ID_REPORT; + jsCallFrame.needReport_ |= FILE_PATH_ID_REPORT; + jsCallFrame.callFrameId_ = DWARF_ERROR_ID; + jsCallFrame.symbolNameId_ = DWARF_ERROR_ID; + jsCallFrame.filePathId_ = DWARF_ERROR_ID; + jsCallFrame.filePath_ = "no-file-path"; +} + void StackPreprocess::FlushRecordApplyAndReleaseMatchData() { std::lock_guard guard(mtx_); diff --git a/device/plugins/native_daemon/src/utilities.cpp b/device/plugins/native_daemon/src/utilities.cpp index 8bdff1fc2..8cf865545 100644 --- a/device/plugins/native_daemon/src/utilities.cpp +++ b/device/plugins/native_daemon/src/utilities.cpp @@ -25,19 +25,6 @@ namespace OHOS { namespace Developtools { namespace NativeDaemon { constexpr uint32_t INT_MAX_LEN = 10; -constexpr uint32_t SC_LG_TINY_MIN = 3; -constexpr uint32_t LG_QUANTUM = 4; -constexpr uint32_t SC_NTINY = LG_QUANTUM - SC_LG_TINY_MIN; -constexpr uint32_t SC_LG_TINY_MAXCLASS = (LG_QUANTUM > SC_LG_TINY_MIN ? LG_QUANTUM - 1 : -1); -constexpr uint32_t SC_LG_NGROUP = 2; -constexpr uint32_t LG_SIZE_CLASS_GROUP = 2; -constexpr uint32_t NTBINS = 1; -constexpr uint32_t LG_TINY_MAXCLASS = 3; -constexpr uint32_t RIGHT_MOVE_1 = 1; -constexpr uint32_t RIGHT_MOVE_2 = 2; -constexpr uint32_t RIGHT_MOVE_4 = 4; -constexpr uint32_t RIGHT_MOVE_8 = 8; -constexpr uint32_t RIGHT_MOVE_16 = 16; uint32_t RoundUp(uint32_t x, const int align) { @@ -218,65 +205,6 @@ bool IsHexDigits(const std::string &str) return std::all_of(effectStr.begin(), effectStr.end(), ::isxdigit); } -unsigned LgFloor(unsigned long val) -{ - val |= (val >> RIGHT_MOVE_1); - val |= (val >> RIGHT_MOVE_2); - val |= (val >> RIGHT_MOVE_4); - val |= (val >> RIGHT_MOVE_8); - val |= (val >> RIGHT_MOVE_16); - if (sizeof(val) > 4) { // 4: sizeThreshold - int constant = sizeof(val) * 4; // 4: sizeThreshold - val |= (val >> constant); - } - val++; - if (val == 0) { - return 8 * sizeof(val) - 1; // 8: 8byte - } - return __builtin_ffsl(val) - 2; // 2: adjustment -} - -uint64_t PowCeil(uint64_t val) -{ - size_t msbIndex = LgFloor(val - 1); - return 1ULL << (msbIndex + 1); -} - -size_t ComputeAlign(size_t size) -{ - if (size == 0) { - return 0; - } - unsigned index = 0; - if (size <= (static_cast(1) << SC_LG_TINY_MAXCLASS)) { - unsigned lgTmin = SC_LG_TINY_MAXCLASS - SC_NTINY + 1; - unsigned lgCeil = LgFloor(PowCeil(size)); - index = (lgCeil < lgTmin) ? 0 : lgCeil - lgTmin; - } else { - unsigned floor = LgFloor((size << 1) - 1); - unsigned shift = (floor < SC_LG_NGROUP + LG_QUANTUM) ? 0 : floor - (SC_LG_NGROUP + LG_QUANTUM); - unsigned grp = shift << SC_LG_NGROUP; - unsigned lgDelta = (floor < SC_LG_NGROUP + LG_QUANTUM + 1) ? LG_QUANTUM : floor - SC_LG_NGROUP - 1; - size_t deltaInverseMask = static_cast(-1) << lgDelta; - unsigned mod = ((((size - 1) & deltaInverseMask) >> lgDelta)) & ((static_cast(1) << SC_LG_NGROUP) - 1); - index = SC_NTINY + grp + mod; - } - - if (index < NTBINS) { - return (static_cast(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index)); - } - size_t reducedIndex = index - NTBINS; - size_t grpVal = reducedIndex >> LG_SIZE_CLASS_GROUP; - size_t modVal = reducedIndex & ((static_cast(1) << LG_SIZE_CLASS_GROUP) - 1); - size_t grpSizeMask = ~((!!grpVal) - 1); - size_t grpSize = ((static_cast(1) << (LG_QUANTUM + (LG_SIZE_CLASS_GROUP - 1))) << grpVal) & grpSizeMask; - size_t shiftVal = (grpVal == 0) ? 1 : grpVal; - size_t lgDeltaVal = shiftVal + (LG_QUANTUM - 1); - size_t modSize = (modVal + 1) << lgDeltaVal; - size_t usize = grpSize + modSize; - return usize; -} - bool IsDir(const std::string &path) { struct stat st; diff --git a/device/plugins/native_daemon/src/virtual_runtime.cpp b/device/plugins/native_daemon/src/virtual_runtime.cpp index a4bfe015e..b1d784d08 100644 --- a/device/plugins/native_daemon/src/virtual_runtime.cpp +++ b/device/plugins/native_daemon/src/virtual_runtime.cpp @@ -72,7 +72,6 @@ std::string VirtualRuntime::ReadThreadName(pid_t tid) VirtualThread &VirtualRuntime::UpdateThread(pid_t pid, pid_t tid, const std::string name) { - std::lock_guard guard(mtx_); pid_ = pid; #ifdef HIPERF_DEBUG_TIME const auto startTime = steady_clock::now(); @@ -128,9 +127,8 @@ void VirtualRuntime::MakeCallFrame(DfxSymbol &symbol, CallFrame &callFrame) } bool VirtualRuntime::GetSymbolName(pid_t pid, pid_t tid, std::vector& callFrames, int offset, bool first, - SymbolType type) + bool onlyjs) { - std::lock_guard guard(mtx_); #ifdef HIPERF_DEBUG_TIME const auto startTime = steady_clock::now(); #endif @@ -140,13 +138,10 @@ bool VirtualRuntime::GetSymbolName(pid_t pid, pid_t tid, std::vector& perf_callchain_context perfCallchainContext = PERF_CONTEXT_MAX; for (auto callFrameIt = callFrames.begin() + offset; callFrameIt != callFrames.end(); ++callFrameIt) { auto &callFrame = callFrameIt.operator*(); - if (type == SymbolType::JS_SYMBOL && !callFrame.isJsFrame_) { + if (onlyjs && !callFrame.isJsFrame_) { // only symbolize arkts frame continue; } - if (type == SymbolType::NATIVE_SYMBOL && callFrame.isJsFrame_) { - continue; - } if (callFrame.ip_ >= PERF_CONTEXT_MAX) { // dont care, this is not issue. HLOGV("%s", UpdatePerfContext(callFrame.ip_, perfCallchainContext).c_str()); @@ -220,9 +215,9 @@ bool VirtualRuntime::UnwindStack(std::vector& regs, const auto startTime = steady_clock::now(); #endif // if we have userstack ? + int offset = 0; auto &thread = UpdateThread(pid, tid); if (stack_size > 0) { - std::lock_guard guard(mtx_); callstack_.UnwindCallStack(thread, ®s[0], regs.size(), stack_addr, stack_size, callFrames, maxStackLevel, hookConfig_.js_stack_report() > 0 ? hookConfig_.max_js_stack_depth() : 0, hookConfig_.js_stack_report() > 0); @@ -231,6 +226,7 @@ bool VirtualRuntime::UnwindStack(std::vector& regs, return false; } // Do not symbolize the first two frame, cause the two frame implement by tool itself + offset = FILTER_STACK_DEPTH; #ifdef HIPERF_DEBUG_TIME unwindCallStackTimes_ += duration_cast(steady_clock::now() - startTime); #endif @@ -238,6 +234,34 @@ bool VirtualRuntime::UnwindStack(std::vector& regs, #ifdef HIPERF_DEBUG_TIME unwindFromRecordTimes_ += duration_cast(steady_clock::now() - startTime); #endif + if (hookConfig_.offline_symbolization()) { + // only get js symbol if report js frame and offline symbolization for dwarf mode + if (hookConfig_.js_stack_report() > 0 && !hookConfig_.fp_unwind()) { + GetSymbolName(pid, tid, callFrames, offset, true, true); + } + return true; + } + if (!GetSymbolName(pid, tid, callFrames, offset, true)) { +#ifdef TRY_UNWIND_TWICE + HLOGD("clear and unwind one more time"); + if (!thread.ParseMap(processMaps_, true)) { + GetSymbolName(pid, tid, callFrames, offset, false); + return false; + } + if (stack_size > 0) { + callFrames.clear(); + callstack_.UnwindCallStack(thread, ®s[0], regs.size(), stack_addr, + stack_size, callFrames, maxStackLevel, 0, hookConfig_.js_stack_report() > 0); + } + if (callFrames.size() <= FILTER_STACK_DEPTH) { + callFrames.clear(); + return false; + } + if (!GetSymbolName(pid, tid, callFrames, offset, false)) { + return false; + } +#endif + } return true; } @@ -524,7 +548,6 @@ void VirtualRuntime::FillFileSet(CallFrame& callFrame, const DfxSymbol& symbol) void VirtualRuntime::HandleMapInfo(std::vector info, const std::string& filePath, pid_t pid, pid_t tid) { - std::lock_guard guard(mtx_); if (info.size() != INFO_SIZE) { return; } diff --git a/device/plugins/native_daemon/test/BUILD.gn b/device/plugins/native_daemon/test/BUILD.gn index 73e4b78dc..f9023a39e 100644 --- a/device/plugins/native_daemon/test/BUILD.gn +++ b/device/plugins/native_daemon/test/BUILD.gn @@ -22,12 +22,10 @@ sources_base = [ "unittest/common/native/debug_logger_test.cpp", "unittest/common/native/hashlist_test.cpp", "unittest/common/native/hook_manager_test.cpp", - "unittest/common/native/hook_record_factory_test.cpp", "unittest/common/native/hook_service_test.cpp", "unittest/common/native/register_test.cpp", "unittest/common/native/stack_preprocess_test.cpp", "unittest/common/native/native_daemon_main_test.cpp", - "unittest/common/native/stack_builder_test.cpp", "unittest/common/native/symbols_file_test.cpp", "unittest/common/native/utilities_test.cpp", "unittest/common/native/virtual_thread_test.cpp", @@ -36,15 +34,12 @@ sources_base = [ "../../api/src/command_poller.cpp", "../../api/src/writer_adapter.cpp", "../src/hook_manager.cpp", - "../src/hook_record.cpp", - "../src/hook_record_factory.cpp", "../src/call_stack.cpp", "../src/debug_logger.cpp", "../src/dwarf_encoding.cpp", "../src/get_thread_id.cpp", "../src/hook_service.cpp", "../src/register.cpp", - "../src/stack_builder.cpp", "../src/stack_data_repeater.cpp", "../src/stack_preprocess.cpp", "../src/symbols_file.cpp", diff --git a/device/plugins/native_daemon/test/unittest/common/native/hook_record_factory_test.cpp b/device/plugins/native_daemon/test/unittest/common/native/hook_record_factory_test.cpp deleted file mode 100644 index cf7c550e4..000000000 --- a/device/plugins/native_daemon/test/unittest/common/native/hook_record_factory_test.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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 "hook_record_factory_test.h" -#include "native_hook_config.pb.h" -#include -#include -#include - -using namespace testing::ext; -using namespace std; - -namespace OHOS::Developtools::NativeDaemon { -class HookRecordFactoryTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - const std::size_t size_ {20}; -}; - -void HookRecordFactoryTest::SetUpTestCase(void) {} -void HookRecordFactoryTest::TearDownTestCase(void) {} -void HookRecordFactoryTest::SetUp() {} -void HookRecordFactoryTest::TearDown() {} - -/* - * @tc.name: GetFreeSimpRecord - * @tc.desc: test HookRecordFactory::GetHookRecord with free simple message. - * @tc.type: FUNC - */ -HWTEST_F(HookRecordFactoryTest, GetFreeSimpRecord, TestSize.Level1) -{ - NativeHookConfig hookConfig; - std::shared_ptr factory = std::make_shared(hookConfig); - int8_t addr = 1; - int8_t data[] = {addr}; - uint32_t dataSize = sizeof(void *); - std::shared_ptr hookRecord = factory->GetHookRecord(data, dataSize); - EXPECT_EQ(hookRecord->GetType(), FREE_MSG_SIMP); -} - -/* - * @tc.name: GetJsRecord - * @tc.desc: test HookRecordFactory::GetHookRecord with js message. - * @tc.type: FUNC - */ -HWTEST_F(HookRecordFactoryTest, GetJsRecord, TestSize.Level1) -{ - NativeHookConfig hookConfig; - std::shared_ptr factory = std::make_shared(hookConfig); - StackRawData rawdata; - rawdata.type = JS_STACK_MSG; - uint32_t dataSize = sizeof(StackRawData); - int8_t* data = new int8_t[sizeof(StackRawData)]; - if (memcpy_s(data, sizeof(StackRawData), &rawdata, sizeof(StackRawData)) == EOK) { - std::shared_ptr hookRecord = factory->GetHookRecord(data, dataSize); - EXPECT_EQ(hookRecord->GetType(), JS_STACK_MSG); - } -} - -/* - * @tc.name: GetMallocRecord - * @tc.desc: test HookRecordFactory::GetHookRecord with malloc message. - * @tc.type: FUNC - */ -HWTEST_F(HookRecordFactoryTest, GetMallocRecord, TestSize.Level1) -{ - NativeHookConfig hookConfig; - std::shared_ptr factory = std::make_shared(hookConfig); - StackRawData rawdata; - rawdata.type = MALLOC_MSG; - uint32_t dataSize = sizeof(StackRawData); - int8_t* data = new int8_t[sizeof(StackRawData)]; - if (memcpy_s(data, sizeof(StackRawData), &rawdata, sizeof(StackRawData)) == EOK) { - std::shared_ptr hookRecord = factory->GetHookRecord(data, dataSize); - EXPECT_EQ(hookRecord->GetType(), MALLOC_MSG); - } -} - -/* - * @tc.name: GetNmdRecord - * @tc.desc: test HookRecordFactory::GetHookRecord with jemalloc stats message. - * @tc.type: FUNC - */ -HWTEST_F(HookRecordFactoryTest, GetNmdRecord, TestSize.Level1) -{ - NativeHookConfig hookConfig; - std::shared_ptr factory = std::make_shared(hookConfig); - StackRawData rawdata; - rawdata.type = NMD_MSG; - uint32_t dataSize = sizeof(StackRawData); - int8_t* data = new int8_t[sizeof(StackRawData)]; - if (memcpy_s(data, sizeof(StackRawData), &rawdata, sizeof(StackRawData)) == EOK) { - std::shared_ptr hookRecord = factory->GetHookRecord(data, dataSize); - EXPECT_EQ(hookRecord->GetType(), NMD_MSG); - } -} - -/* - * @tc.name: GetFreeRecord - * @tc.desc: test HookRecordFactory::GetHookRecord with free message. - * @tc.type: FUNC - */ -HWTEST_F(HookRecordFactoryTest, GetFreeRecord, TestSize.Level1) -{ - NativeHookConfig hookConfig; - std::shared_ptr factory = std::make_shared(hookConfig); - StackRawData rawdata; - rawdata.type = FREE_MSG; - uint32_t dataSize = sizeof(StackRawData); - int8_t* data = new int8_t[sizeof(StackRawData)]; - if (memcpy_s(data, sizeof(StackRawData), &rawdata, sizeof(StackRawData)) == EOK) { - std::shared_ptr hookRecord = factory->GetHookRecord(data, dataSize); - EXPECT_EQ(hookRecord->GetType(), FREE_MSG); - } -} - -/* - * @tc.name: ReturnMallocRecord - * @tc.desc: test HookRecordFactory::SaveHookRecord with malloc message. - * @tc.type: FUNC - */ -HWTEST_F(HookRecordFactoryTest, ReturnMallocRecord, TestSize.Level1) -{ - NativeHookConfig hookConfig; - std::shared_ptr factory = std::make_shared(hookConfig); - StackRawData rawdata; - rawdata.type = MALLOC_MSG; - uint32_t dataSize = sizeof(StackRawData); - int8_t* data = new int8_t[sizeof(StackRawData)]; - if (memcpy_s(data, sizeof(StackRawData), &rawdata, sizeof(StackRawData)) == EOK) { - std::shared_ptr hookRecord = factory->GetHookRecord(data, dataSize); - EXPECT_EQ(factory->mallocRecordCache_.size(), HOOK_RECORD_CACHE_INIT_SIZE - 1); - factory->SaveHookRecord(hookRecord); - EXPECT_EQ(factory->mallocRecordCache_.size(), HOOK_RECORD_CACHE_INIT_SIZE); - } -} - -/* - * @tc.name: ReturnMmapRecord - * @tc.desc: test HookRecordFactory::SaveHookRecord with mmap message. - * @tc.type: FUNC - */ -HWTEST_F(HookRecordFactoryTest, ReturnMmapRecord, TestSize.Level1) -{ - NativeHookConfig hookConfig; - std::shared_ptr factory = std::make_shared(hookConfig); - StackRawData rawdata; - rawdata.type = MMAP_MSG; - uint32_t dataSize = sizeof(StackRawData); - int8_t* data = new int8_t[sizeof(StackRawData)]; - if (memcpy_s(data, sizeof(StackRawData), &rawdata, sizeof(StackRawData)) == EOK) { - std::shared_ptr hookRecord = factory->GetHookRecord(data, dataSize); - EXPECT_EQ(factory->mmapRecordCache_.size(), HOOK_RECORD_CACHE_INIT_SIZE - 1); - factory->SaveHookRecord(hookRecord); - EXPECT_EQ(factory->mmapRecordCache_.size(), HOOK_RECORD_CACHE_INIT_SIZE); - } -} - -/* - * @tc.name: ReturnEndRecord - * @tc.desc: test HookRecordFactory::SaveHookRecord with end message. - * @tc.type: FUNC - */ -HWTEST_F(HookRecordFactoryTest, ReturnEndRecord, TestSize.Level1) -{ - NativeHookConfig hookConfig; - std::shared_ptr factory = std::make_shared(hookConfig); - StackRawData rawdata; - rawdata.type = END_MSG; - uint32_t dataSize = sizeof(StackRawData); - int8_t* data = new int8_t[sizeof(StackRawData)]; - if (memcpy_s(data, sizeof(StackRawData), &rawdata, sizeof(StackRawData)) == EOK) { - std::shared_ptr hookRecord = factory->GetHookRecord(data, dataSize); - EXPECT_EQ(factory->mallocRecordCache_.size(), HOOK_RECORD_CACHE_INIT_SIZE); - EXPECT_EQ(factory->mmapRecordCache_.size(), HOOK_RECORD_CACHE_INIT_SIZE); - factory->SaveHookRecord(hookRecord); - EXPECT_EQ(factory->mallocRecordCache_.size(), HOOK_RECORD_CACHE_INIT_SIZE); - EXPECT_EQ(factory->mmapRecordCache_.size(), HOOK_RECORD_CACHE_INIT_SIZE); - } -} -} \ No newline at end of file diff --git a/device/plugins/native_daemon/test/unittest/common/native/include/hook_record_factory_test.h b/device/plugins/native_daemon/test/unittest/common/native/include/hook_record_factory_test.h deleted file mode 100644 index 6cf6db5a3..000000000 --- a/device/plugins/native_daemon/test/unittest/common/native/include/hook_record_factory_test.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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. - */ - -#ifndef HOOK_RECORD_FACTORY_TEST -#define HOOK_RECORD_FACTORY_TEST - -#include -#include - -#include "hook_record_factory.h" -#include "utilities.h" -#include "hook_record.h" -#include "hook_common.h" -#endif \ No newline at end of file diff --git a/device/plugins/native_daemon/test/unittest/common/native/include/stack_builder_test.h b/device/plugins/native_daemon/test/unittest/common/native/include/stack_builder_test.h deleted file mode 100644 index 3b380db9c..000000000 --- a/device/plugins/native_daemon/test/unittest/common/native/include/stack_builder_test.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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. - */ - -#ifndef STACK_BUILDER_TEST -#define STACK_BUILDER_TEST - -#include -#include - -#include "hook_record_factory.h" -#include "utilities.h" -#include "hook_record.h" -#include "hook_common.h" -#include "stack_builder.h" -#endif \ No newline at end of file diff --git a/device/plugins/native_daemon/test/unittest/common/native/stack_builder_test.cpp b/device/plugins/native_daemon/test/unittest/common/native/stack_builder_test.cpp deleted file mode 100644 index fd593b8be..000000000 --- a/device/plugins/native_daemon/test/unittest/common/native/stack_builder_test.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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 "hook_record_factory_test.h" -#include "stack_builder_test.h" -#include "native_hook_config.pb.h" -#include -#include -#include - -using namespace testing::ext; -using namespace std; - -namespace OHOS::Developtools::NativeDaemon { -class StackBuilderTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - const std::size_t size_ {20}; -}; - -void StackBuilderTest::SetUpTestCase(void) {} -void StackBuilderTest::TearDownTestCase(void) {} -void StackBuilderTest::SetUp() {} -void StackBuilderTest::TearDown() {} - -/* - * @tc.name: FpStackBuilderFillIpTest - * @tc.desc: test FpStackBuilder::FillIps normal case. - * @tc.type: FUNC - */ -HWTEST_F(StackBuilderTest, FpStackBuilderFillIpTest, TestSize.Level1) -{ - NativeHookConfig hookConfig; - hookConfig.set_offline_symbolization(true); - std::shared_ptr runtime = - std::make_shared(hookConfig); - auto builder = std::make_shared(&hookConfig, runtime); - std::vector frames; - RawStackPtr rawData = std::make_shared(); - rawData->fpDepth = 1; - uint8_t ip = 16; - rawData->data = &ip; - std::shared_ptr hookRecord = std::make_shared(rawData); - builder->FillIps(frames, hookRecord); - EXPECT_EQ(frames.size(), 1); -} - -/* - * @tc.name: FpStackBuilderFillJsSymbolsTest - * @tc.desc: test FpStackBuilder::FillJsSymbols normal case. - * @tc.type: FUNC - */ -HWTEST_F(StackBuilderTest, FpStackBuilderFillJsSymbolsTest, TestSize.Level1) -{ - NativeHookConfig hookConfig; - hookConfig.set_offline_symbolization(true); - std::shared_ptr runtime = - std::make_shared(hookConfig); - auto builder = std::make_shared(&hookConfig, runtime); - std::vector frames; - RawStackPtr rawData = std::make_shared(); - rawData->fpDepth = 1; - uint8_t ip = 16; - rawData->data = &ip; - std::shared_ptr hookRecord = std::make_shared(rawData); - builder->FillIps(frames, hookRecord); - rawData->jsStackData = "funcA|"; - BaseStackRawData baseData; - baseData.jsChainId = 1; - rawData->stackContext = &baseData; - builder->FillJsSymbols(frames, hookRecord); - EXPECT_EQ(frames.size(), 2); -} - -/* - * @tc.name: FpStackBuilderFillWrongJsSymbolsTest - * @tc.desc: test FpStackBuilder::FillJsSymbols error case. - * @tc.type: FUNC - */ -HWTEST_F(StackBuilderTest, FpStackBuilderFillWrongJsSymbolsTest, TestSize.Level1) -{ - NativeHookConfig hookConfig; - hookConfig.set_offline_symbolization(true); - std::shared_ptr runtime = - std::make_shared(hookConfig); - auto builder = std::make_shared(&hookConfig, runtime); - std::vector frames; - RawStackPtr rawData = std::make_shared(); - rawData->fpDepth = 1; - uint8_t ip = 16; - rawData->data = &ip; - std::shared_ptr hookRecord = std::make_shared(rawData); - builder->FillIps(frames, hookRecord); - rawData->jsStackData = "funcA"; - BaseStackRawData baseData; - baseData.jsChainId = 1; - rawData->stackContext = &baseData; - builder->FillJsSymbols(frames, hookRecord); - EXPECT_NE(frames.size(), 2); -} - -/* - * @tc.name: DwarfStackBuilderReplaceErrStackTest - * @tc.desc: test DwarfStackBuilder::FillIps normal case. - * @tc.type: FUNC - */ -HWTEST_F(StackBuilderTest, DwarfStackBuilderReplaceErrStackTest, TestSize.Level1) -{ - NativeHookConfig hookConfig; - hookConfig.set_offline_symbolization(true); - std::shared_ptr runtime = - std::make_shared(hookConfig); - auto builder = std::make_shared(&hookConfig, runtime); - std::vector frames; - RawStackPtr rawData = std::make_shared(); - rawData->fpDepth = 1; - uint8_t ip = 16; - rawData->data = &ip; - std::shared_ptr hookRecord = std::make_shared(rawData); - ASSERT_FALSE(builder->IsRecordInfoValid(hookRecord)); - builder->ReplaceErrStack(frames); - EXPECT_EQ(frames.size(), 1); -} - -/* - * @tc.name: DwarfStackBuilderReplaceErrStackTest - * @tc.desc: test BuildStackDirector::ConstructCallFrames normal case. - * @tc.type: FUNC - */ -HWTEST_F(StackBuilderTest, DirectorTest, TestSize.Level1) -{ - NativeHookConfig hookConfig; - hookConfig.set_offline_symbolization(true); - hookConfig.set_js_stack_report(true); - std::shared_ptr runtime = - std::make_shared(hookConfig); - auto builder = std::make_shared(&hookConfig, runtime); - auto director = std::make_shared(&hookConfig, runtime); - director->SetBuilder(builder); - RawStackPtr rawData = std::make_shared(); - rawData->fpDepth = 1; - uint8_t ip = 16; - rawData->data = &ip; - rawData->jsStackData = "funcA"; - BaseStackRawData baseData; - baseData.jsChainId = 1; - rawData->stackContext = &baseData; - std::shared_ptr hookRecord = std::make_shared(rawData); - ASSERT_TRUE(director->IsRecordUnwindable(hookRecord)); - auto& frames = director->ConstructCallFrames(hookRecord); - EXPECT_EQ(frames.size(), 1); -} - -/* - * @tc.name: DirectorTestFalse - * @tc.desc: test BuildStackDirector::IsRecordUnwindable false case. - * @tc.type: FUNC - */ -HWTEST_F(StackBuilderTest, DirectorTestFalse, TestSize.Level1) -{ - NativeHookConfig hookConfig; - hookConfig.set_offline_symbolization(true); - hookConfig.set_js_stack_report(true); - std::shared_ptr runtime = - std::make_shared(hookConfig); - auto director = std::make_shared(&hookConfig, runtime); - RawStackPtr rawData = std::make_shared(); - BaseStackRawData baseData; - baseData.type = PR_SET_VMA_MSG; - rawData->stackContext = &baseData; - std::shared_ptr hookRecord = std::make_shared(rawData); - ASSERT_FALSE(director->IsRecordUnwindable(hookRecord)); -} -} \ No newline at end of file diff --git a/device/plugins/native_daemon/test/unittest/common/native/stack_preprocess_test.cpp b/device/plugins/native_daemon/test/unittest/common/native/stack_preprocess_test.cpp index 9a206e737..99f7e521f 100644 --- a/device/plugins/native_daemon/test/unittest/common/native/stack_preprocess_test.cpp +++ b/device/plugins/native_daemon/test/unittest/common/native/stack_preprocess_test.cpp @@ -24,8 +24,8 @@ using namespace testing::ext; using namespace OHOS::Developtools::NativeDaemon; namespace { -constexpr uint32_t MAX_MATCH_INTERVAL = 3600; -constexpr uint32_t MAX_MATCH_CNT = 1000; +constexpr static uint32_t MAX_MATCH_INTERVAL = 3600; +constexpr static uint32_t MAX_MATCH_CNT = 1000; class StackPreprocessTest : public testing::Test { public: diff --git a/device/plugins/native_hook/BUILD.gn b/device/plugins/native_hook/BUILD.gn index b9ce8ff29..a802003ed 100644 --- a/device/plugins/native_hook/BUILD.gn +++ b/device/plugins/native_hook/BUILD.gn @@ -36,7 +36,6 @@ ohos_source_set("native_hook_source") { "../native_daemon/src/get_thread_id.cpp", "../native_daemon/src/register.cpp", "../native_daemon/src/utilities.cpp", - "src/address_handler.cpp", "src/hook_client.cpp", "src/hook_socket_client.cpp", "src/runtime_stack_range.cpp", diff --git a/device/plugins/native_hook/include/address_handler.h b/device/plugins/native_hook/include/address_handler.h deleted file mode 100644 index 0e55d7330..000000000 --- a/device/plugins/native_hook/include/address_handler.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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. - */ -#ifndef ADDRESS_HANDLER -#define ADDRESS_HANDLER -#include "logging.h" - -struct Bitpool { - std::atomic slot; -}; - -class AddressHandler { -public: - AddressHandler(int poolSize); - - virtual ~AddressHandler(); - - void SetSuccessor(std::unique_ptr successor) - { - successor_ = std::move(successor); - } - - virtual void AddAllocAddr(uint64_t addr) = 0; - virtual bool CheckAddr(uint64_t addr) = 0; - std::atomic count = 0; - -protected: - std::unique_ptr successor_ = nullptr; - Bitpool* addressChecker_ = nullptr; - int bitPoolSize_ = 0; -}; - -class LowAddrHandler : public AddressHandler { -public: - LowAddrHandler(); - void AddAllocAddr(uint64_t addr) override; - - bool CheckAddr(uint64_t addr) override; - - //MurmurHash - uint32_t HashFunc(uint32_t addrKey); -}; - -class MidAddrHandler : public AddressHandler { -public: - MidAddrHandler(); - void AddAllocAddr(uint64_t addr) override; - - bool CheckAddr(uint64_t addr) override; - - //Fnv1aHash - uint32_t HashFunc(uint32_t addrKey); -}; - -class WholeAddrHandler : public AddressHandler { -public: - WholeAddrHandler(); - void AddAllocAddr(uint64_t addr) override; - - bool CheckAddr(uint64_t addr) override; - - //SplitMix64 - uint64_t HashFunc(uint64_t addrKey); -}; -#endif \ No newline at end of file diff --git a/device/plugins/native_hook/include/hook_socket_client.h b/device/plugins/native_hook/include/hook_socket_client.h index e56ae4140..d6fde5237 100644 --- a/device/plugins/native_hook/include/hook_socket_client.h +++ b/device/plugins/native_hook/include/hook_socket_client.h @@ -25,24 +25,22 @@ class Sampling; class HookSocketClient : public ServiceBase { public: - HookSocketClient(int pid, ClientConfig *config, Sampling *sampler, - std::atomic* targetedRange = nullptr, - void (*disableHookCallback)() = nullptr); + HookSocketClient(int pid, ClientConfig *config, Sampling *sampler, void (*disableHookCallback)()); ~HookSocketClient(); bool Connect(const std::string addrname); bool ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf, const uint32_t size) override; - std::vector GetSmbFds() + int GetSmbFd() { - return smbFds_; + return smbFd_; } - std::vector GetEventFds() + int GetEventFd() { - return eventFds_; + return eventFd_; } void Flush(); bool SendStack(const void* data, size_t size); bool SendStackWithPayload(const void* data, size_t size, const void* payload, - size_t payloadSize, int smbIndex = 0); + size_t payloadSize); void DisableHook(); bool PeerIsConnected(); bool SendNmdInfo(); @@ -55,14 +53,13 @@ public: private: std::shared_ptr unixSocketClient_; - std::vector smbFds_; - std::vector eventFds_; + int smbFd_; + int eventFd_; int pid_; int nmdType_ = -1; ClientConfig *config_ = nullptr; Sampling *sampler_ = nullptr; - std::atomic* targetedRange_ = nullptr; - std::vector> stackWriterList_; + std::shared_ptr stackWriter_; void (*disableHookCallback_)(){nullptr}; uint32_t largestSize_ = 0; uint32_t secondLargestSize_ = 0; diff --git a/device/plugins/native_hook/include/runtime_stack_range.h b/device/plugins/native_hook/include/runtime_stack_range.h index 211cdbafe..8b19fe0f0 100644 --- a/device/plugins/native_hook/include/runtime_stack_range.h +++ b/device/plugins/native_hook/include/runtime_stack_range.h @@ -27,7 +27,6 @@ bool IsLegalSoName(const std::string &fileName); void ParseEvent(const std::string& filePath, std::vector>& filterStaLibRange, const NameData& curRawData); bool ParseSelfMaps(std::vector>& filterStaLibRange); -bool ParseTargetedMaps(std::atomic& targetedRange, std::string targetedLib); bool GetRuntimeStackRange(const uintptr_t stackPtr, uintptr_t& stackBottom, uintptr_t& stackTop, bool isMainThread); #ifdef __cplusplus diff --git a/device/plugins/native_hook/include/stack_writer.h b/device/plugins/native_hook/include/stack_writer.h index 9ae7e196f..bba6b6f08 100644 --- a/device/plugins/native_hook/include/stack_writer.h +++ b/device/plugins/native_hook/include/stack_writer.h @@ -24,7 +24,6 @@ #include "event_notifier.h" #include "share_memory_block.h" #include "writer.h" -#include class StackWriter : public Writer { public: @@ -40,7 +39,6 @@ public: long WriteWithPayloadTimeout(const void* data, size_t size, const void* payload, size_t payloadSize, const std::function& callback); bool Flush() override; - bool PrepareFlush(); private: void DoStats(long bytes); @@ -56,8 +54,6 @@ private: std::atomic bytesPending_ = 0; std::atomic writeCount_ = 0; std::atomic flushCount_ = 0; - std::atomic dataCount_ = 0; - std::mutex flushMutex_; }; diff --git a/device/plugins/native_hook/src/address_handler.cpp b/device/plugins/native_hook/src/address_handler.cpp deleted file mode 100644 index 3b04dc181..000000000 --- a/device/plugins/native_hook/src/address_handler.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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 "address_handler.h" -namespace { -constexpr int BITPOOL_SIZE_FIRST = 1000 * 1024; -constexpr int BITPOOL_SIZE_SECOND = 200 * 1024; -constexpr int BITPOOL_SIZE_TOTAL_ADDR = 1000 * 1024; -constexpr int FIRST_HASH = 16; -constexpr int SECOND_HASH = 13; -constexpr int DIVIDE_VAL = 64; -constexpr int SHIFT_VAL = 16; -constexpr int SPIN_SHIFT_FIRST = 30; -constexpr int SPIN_SHIFT_SECOND = 27; -constexpr int SPIN_SHIFT_THIRD = 31; -constexpr uint64_t SPIN_FIRST_SALT = 0x9e3779b97f4a7c15; -constexpr uint64_t SPIN_SECOND_SALT = 0xbf58476d1ce4e5b9; -constexpr uint64_t SPIN_THIRD_SALT = 0x94d049bb133111eb; -constexpr uint32_t FNV_HASH = 16777619u; -constexpr uint32_t MUR_FIRST_SALT = 0x85ebca6b; -constexpr uint32_t MUR_SECOND_SALT = 0xc2b2ae35; -} - -AddressHandler::AddressHandler(int poolSize) -{ - bitPoolSize_ = poolSize; - addressChecker_ = new Bitpool [poolSize] {{0}}; -} - -AddressHandler::~AddressHandler() -{ - delete [] addressChecker_; - addressChecker_ = nullptr; -} - -LowAddrHandler::LowAddrHandler() : AddressHandler(BITPOOL_SIZE_FIRST) {}; - -void LowAddrHandler::AddAllocAddr(uint64_t addr) -{ - if (!addressChecker_) { - return; - } - uint32_t addrKey = static_cast(addr); - uint32_t val = HashFunc(addrKey) % (bitPoolSize_ * DIVIDE_VAL); - addressChecker_[val / DIVIDE_VAL].slot |= (0x1 << (val % DIVIDE_VAL)); - if (successor_ != nullptr) { - successor_->AddAllocAddr(addr); - } -} - -bool LowAddrHandler::CheckAddr(uint64_t addr) -{ - if (!addressChecker_) { - return true; - } - uint32_t addrKey = static_cast(addr); - uint32_t val = HashFunc(addrKey) % (bitPoolSize_ * DIVIDE_VAL); - if (!(addressChecker_[val / DIVIDE_VAL].slot.load() & (0x1 << (val % DIVIDE_VAL)))) { - return false; - } - if (successor_ != nullptr) { - return successor_->CheckAddr(addr); - } - return true; -} - -uint32_t LowAddrHandler::HashFunc(uint32_t addrKey) -{ - addrKey ^= addrKey >> FIRST_HASH; - addrKey *= MUR_FIRST_SALT; - addrKey ^= addrKey >> SECOND_HASH; - addrKey *= MUR_SECOND_SALT; - addrKey ^= addrKey >> FIRST_HASH; - return addrKey; -} - -MidAddrHandler::MidAddrHandler() : AddressHandler(BITPOOL_SIZE_SECOND) {}; - -void MidAddrHandler::AddAllocAddr(uint64_t addr) -{ - if (!addressChecker_) { - return; - } - uint32_t addrKey = static_cast(addr >> SHIFT_VAL); - uint32_t val = HashFunc(addrKey) % (bitPoolSize_ * DIVIDE_VAL); - addressChecker_[val / DIVIDE_VAL].slot |= (0x1 << (val % DIVIDE_VAL)); - if (successor_ != nullptr) { - successor_->AddAllocAddr(addr); - } -} - -bool MidAddrHandler::CheckAddr(uint64_t addr) -{ - if (!addressChecker_) { - return true; - } - uint32_t addrKey = static_cast(addr >> SHIFT_VAL); - uint32_t val = HashFunc(addrKey) % (bitPoolSize_ * DIVIDE_VAL); - if (!(addressChecker_[val / DIVIDE_VAL].slot.load() & (0x1 << (val % DIVIDE_VAL)))) { - return false; - } - if (successor_ != nullptr) { - return successor_->CheckAddr(addr); - } - return true; -} - -uint32_t MidAddrHandler::HashFunc(uint32_t addrKey) -{ - uint32_t hash = 2166136261u; - //mix in the input - hash ^= addrKey; - hash *= FNV_HASH; - return hash; -} - -WholeAddrHandler::WholeAddrHandler() : AddressHandler(BITPOOL_SIZE_TOTAL_ADDR) {}; - -void WholeAddrHandler::AddAllocAddr(uint64_t addr) -{ - if (!addressChecker_) { - return; - } - uint32_t val = HashFunc(addr) % (bitPoolSize_ * DIVIDE_VAL); - addressChecker_[val / DIVIDE_VAL].slot |= (0x1 << (val % DIVIDE_VAL)); - if (successor_ != nullptr) { - successor_->AddAllocAddr(addr); - } -} - -bool WholeAddrHandler::CheckAddr(uint64_t addr) -{ - if (!addressChecker_) { - return true; - } - uint32_t val = HashFunc(addr) % (bitPoolSize_ * DIVIDE_VAL); - if (!(addressChecker_[val / DIVIDE_VAL].slot.load() & (0x1 << (val % DIVIDE_VAL)))) { - return false; - } - if (successor_ != nullptr) { - return successor_->CheckAddr(addr); - } - return true; -} - -uint64_t WholeAddrHandler::HashFunc(uint64_t addrKey) -{ - uint64_t hashval = (addrKey += SPIN_FIRST_SALT); - hashval = (hashval ^ (hashval >> SPIN_SHIFT_FIRST)) * SPIN_SECOND_SALT; - hashval = (hashval ^ (hashval >> SPIN_SHIFT_SECOND)) * SPIN_THIRD_SALT; - return hashval ^ (hashval >> SPIN_SHIFT_THIRD); -} \ No newline at end of file diff --git a/device/plugins/native_hook/src/hook_client.cpp b/device/plugins/native_hook/src/hook_client.cpp index 93b3986ed..79bb13426 100644 --- a/device/plugins/native_hook/src/hook_client.cpp +++ b/device/plugins/native_hook/src/hook_client.cpp @@ -38,7 +38,6 @@ #include #include "sampling.h" #include "hitrace/trace.h" -#include "address_handler.h" using namespace OHOS::HiviewDFX; using namespace OHOS::Developtools::NativeDaemon; @@ -94,11 +93,42 @@ constexpr int TEMP_IP = 100; static bool g_isPidChanged = false; static struct mallinfo2 g_miStart = {0}; std::vector> g_filterStaLibRange; -std::atomic targetedRange; constexpr int MAX_BITPOOL_SIZE = 1000 * 1024; -std::unique_ptr g_wholeAddrHandler = nullptr; -std::unique_ptr g_midPartHandler = nullptr; -std::unique_ptr g_addrHandler = nullptr; +struct Bitpool { + std::atomic slot; +}; +Bitpool* g_addressChecker = nullptr; + +inline static uint32_t AddrHash(uint32_t h) +{ + h ^= h >> FIRST_HASH; + h *= 0x85ebca6b; + h ^= h >> SECOND_HASH; + h *= 0xc2b2ae35; + h ^= h >> FIRST_HASH; + return h; +} + +inline void Addr2Bitpool(void* addr) +{ + if (!g_addressChecker) { + return; + } + uint32_t val = AddrHash(static_cast(reinterpret_cast(addr))) % (MAX_BITPOOL_SIZE * DIVIDE_VAL); + g_addressChecker[val / DIVIDE_VAL].slot |= (0x1 << (val % DIVIDE_VAL)); +} + +inline bool IsAddrExist(void* addr) +{ + if (!g_addressChecker) { + return true; + } + uint32_t val = AddrHash(static_cast(reinterpret_cast(addr))) % (MAX_BITPOOL_SIZE * DIVIDE_VAL); + if (g_addressChecker[val / DIVIDE_VAL].slot.load() & (0x1 << (val % DIVIDE_VAL))) { + return true; + } + return false; +} const MallocDispatchType* GetDispatch() { @@ -257,11 +287,7 @@ void* MallocHookStart(void* disableHookCallback) return nullptr; } PROFILER_LOG_INFO(LOG_CORE, "MallocHookStart begin!"); - g_wholeAddrHandler = std::make_unique(); - g_midPartHandler = std::make_unique(); - g_addrHandler = std::make_unique(); - g_midPartHandler->SetSuccessor(std::move(g_wholeAddrHandler)); - g_addrHandler->SetSuccessor(std::move(g_midPartHandler)); + g_addressChecker = new Bitpool [MAX_BITPOOL_SIZE] {{0}}; g_mallocTimes = 0; g_hookClient.reset(); g_hookPid = GetRealPid(); @@ -271,7 +297,7 @@ void* MallocHookStart(void* disableHookCallback) } else { g_ClientConfig.Reset(); g_sampler.Reset(); - g_hookClient = std::make_shared(g_hookPid.load(), &g_ClientConfig, &g_sampler, &targetedRange, + g_hookClient = std::make_shared(g_hookPid.load(), &g_ClientConfig, &g_sampler, reinterpret_cast(disableHookCallback)); } g_hookReady = true; @@ -345,9 +371,8 @@ void* ohos_release_on_end(void*) g_hookClient->SendEndMsg(); g_hookClient->Flush(); } - g_addrHandler = nullptr; - g_midPartHandler = nullptr; - g_wholeAddrHandler = nullptr; + delete [] g_addressChecker; + g_addressChecker = nullptr; g_hookClient = nullptr; g_ClientConfig.Reset(); g_hookReady = false; @@ -375,12 +400,6 @@ bool FilterStandardSoIp(uint64_t ip) return false; } -bool CheckTargetLibIp(uint64_t ip) -{ - auto range = targetedRange.load(); - return (ip >= range.start && ip < range.end); -} - #if defined(__aarch64__) static int inline __attribute__((always_inline)) FpUnwind(int maxDepth, uint64_t* ips) { @@ -398,7 +417,7 @@ static int inline __attribute__((always_inline)) FpUnwind(int maxDepth, uint64_t return depth; } uintptr_t fp = nextFp; // skip current frame - bool filterTarget = true; + int count = 0; uint64_t ip = 0; while (depth < maxDepth && (fp - startFp < MAX_UNWIND_ADDR_RANGE)) { @@ -414,9 +433,6 @@ static int inline __attribute__((always_inline)) FpUnwind(int maxDepth, uint64_t ips[depth++] = ip > 0x4 ? ip - 0x4 : ip; // adjust pc in Arm64 architecture } - if ((!g_ClientConfig.targetSoName.empty()) && CheckTargetLibIp(ip)) { - filterTarget = false; - } nextFp = *reinterpret_cast(fp); if (nextFp <= stackPtr) { depth -= 1; @@ -432,9 +448,6 @@ static int inline __attribute__((always_inline)) FpUnwind(int maxDepth, uint64_t ips[0] = ip > 0x4 ? ip - 0x4 : ip; depth = 1; } - if ((!g_ClientConfig.targetSoName.empty()) && filterTarget) { - depth = 0; - } return depth; } @@ -519,9 +532,6 @@ void* hook_malloc(void* (*fn)(size_t), size_t size) if (g_ClientConfig.fpunwind) { #ifdef __aarch64__ fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip); - if (fpStackDepth == 0) { - return ret; - } rawdata.jsChainId = getJsChainId(); #endif } else { @@ -532,8 +542,8 @@ void* hook_malloc(void* (*fn)(size_t), size_t size) rawdata.tid = static_cast(GetCurThreadId()); rawdata.mallocSize = size; rawdata.addr = ret; - if ((g_ClientConfig.sampleInterval >= THRESHOLD) && (g_addrHandler != nullptr)) { - g_addrHandler->AddAllocAddr(reinterpret_cast(ret)); + if (g_ClientConfig.sampleInterval >= THRESHOLD) { + Addr2Bitpool(ret); } int realSize = 0; if (g_ClientConfig.fpunwind) { @@ -541,8 +551,7 @@ void* hook_malloc(void* (*fn)(size_t), size_t size) } else { realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs); } - holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize); g_mallocTimes++; #ifdef PERFORMANCE_DEBUG struct timespec end = {}; @@ -613,9 +622,6 @@ void* hook_aligned_alloc(void* (*fn)(size_t, size_t), size_t align, size_t len) if (g_ClientConfig.fpunwind) { #ifdef __aarch64__ fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip); - if (fpStackDepth == 0) { - return ret; - } rawdata.jsChainId = getJsChainId(); #endif } else { @@ -627,8 +633,8 @@ void* hook_aligned_alloc(void* (*fn)(size_t, size_t), size_t align, size_t len) rawdata.tid = static_cast(GetCurThreadId()); rawdata.mallocSize = len; rawdata.addr = ret; - if ((g_ClientConfig.sampleInterval >= THRESHOLD) && (g_addrHandler != nullptr)) { - g_addrHandler->AddAllocAddr(reinterpret_cast(ret)); + if (g_ClientConfig.sampleInterval >= THRESHOLD) { + Addr2Bitpool(ret); } int realSize = 0; if (g_ClientConfig.fpunwind) { @@ -636,8 +642,7 @@ void* hook_aligned_alloc(void* (*fn)(size_t, size_t), size_t align, size_t len) } else { realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs); } - holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize); g_mallocTimes++; #ifdef PERFORMANCE_DEBUG struct timespec end = {}; @@ -713,9 +718,6 @@ void* hook_calloc(void* (*fn)(size_t, size_t), size_t number, size_t size) if (g_ClientConfig.fpunwind) { #ifdef __aarch64__ fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip); - if (fpStackDepth == 0) { - return pRet; - } rawdata.jsChainId = getJsChainId(); #endif } else { @@ -727,8 +729,8 @@ void* hook_calloc(void* (*fn)(size_t, size_t), size_t number, size_t size) rawdata.tid = static_cast(GetCurThreadId()); rawdata.mallocSize = number * size; rawdata.addr = pRet; - if ((g_ClientConfig.sampleInterval >= THRESHOLD) && (g_addrHandler != nullptr)) { - g_addrHandler->AddAllocAddr(reinterpret_cast(pRet)); + if (g_ClientConfig.sampleInterval >= THRESHOLD) { + Addr2Bitpool(pRet); } int realSize = 0; if (g_ClientConfig.fpunwind) { @@ -736,8 +738,7 @@ void* hook_calloc(void* (*fn)(size_t, size_t), size_t number, size_t size) } else { realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs); } - holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize); g_mallocTimes++; #ifdef PERFORMANCE_DEBUG struct timespec end = {}; @@ -812,9 +813,6 @@ void* hook_realloc(void* (*fn)(void*, size_t), void* ptr, size_t size) if (g_ClientConfig.fpunwind) { #ifdef __aarch64__ fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip); - if (fpStackDepth == 0) { - return pRet; - } #endif } else { stackSize = GetStackSize(stackPtr, rawdata); @@ -825,8 +823,8 @@ void* hook_realloc(void* (*fn)(void*, size_t), void* ptr, size_t size) rawdata.tid = static_cast(GetCurThreadId()); rawdata.mallocSize = size; rawdata.addr = pRet; - if ((g_ClientConfig.sampleInterval >= THRESHOLD) && (g_addrHandler != nullptr)) { - g_addrHandler->AddAllocAddr(reinterpret_cast(pRet)); + if (g_ClientConfig.sampleInterval >= THRESHOLD) { + Addr2Bitpool(pRet); } int realSize = 0; int freeRealSize = 0; @@ -843,11 +841,8 @@ void* hook_realloc(void* (*fn)(void*, size_t), void* ptr, size_t size) realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs); freeRealSize = realSize; } - // 0: Don't unwind the freeData - holder->SendStackWithPayload(&freeData, freeRealSize, nullptr, 0, - reinterpret_cast(freeData.addr) % SHARED_MEMORY_NUM); - holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&freeData, freeRealSize, nullptr, 0); // 0: Don't unwind the freeData + holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize); #ifdef PERFORMANCE_DEBUG g_mallocTimes++; struct timespec end = {}; @@ -882,33 +877,16 @@ void hook_free(void (*free_func)(void*), void* p) free_func(p); return; } -#ifdef PERFORMANCE_DEBUG - struct timespec start = {}; - clock_gettime(CLOCK_REALTIME, &start); -#endif - if ((g_ClientConfig.sampleInterval >= THRESHOLD) && (g_addrHandler != nullptr)) { - if (!g_addrHandler->CheckAddr(reinterpret_cast(p))) { + if (g_ClientConfig.sampleInterval >= THRESHOLD) { + if (!IsAddrExist(p)) { free_func(p); -#ifdef PERFORMANCE_DEBUG - g_mallocTimes++; - struct timespec end = {}; - clock_gettime(CLOCK_REALTIME, &end); - g_timeCost += (end.tv_sec - start.tv_sec) * S_TO_NS + (end.tv_nsec - start.tv_nsec); - if (g_mallocTimes % PRINT_INTERVAL == 0) { - PROFILER_LOG_ERROR(LOG_CORE, - "g_mallocTimes %" PRIu64" cost time = %" PRIu64" copy data bytes = %" PRIu64 - " mean cost = %" PRIu64"\n", g_mallocTimes.load(), g_timeCost.load(), - g_dataCounts.load(), g_timeCost.load() / g_mallocTimes.load()); - } -#endif return; } } std::weak_ptr weakClient = g_hookClient; auto holder = weakClient.lock(); if ((holder != nullptr) && p) { - holder->SendStackWithPayload(&p, sizeof(void*), nullptr, 0, - reinterpret_cast(p) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&p, sizeof(void*), nullptr, 0); } free_func(p); #ifdef PERFORMANCE_DEBUG @@ -936,8 +914,8 @@ void hook_free(void (*free_func)(void*), void* p) if (g_ClientConfig.mallocDisable || IsPidChanged()) { return; } - if ((g_ClientConfig.sampleInterval >= THRESHOLD) && (g_addrHandler != nullptr)) { - if (!g_addrHandler->CheckAddr(reinterpret_cast(p))) { + if (g_ClientConfig.sampleInterval >= THRESHOLD) { + if (!IsAddrExist(p)) { return; } } @@ -959,9 +937,6 @@ void hook_free(void (*free_func)(void*), void* p) if (g_ClientConfig.fpunwind) { #ifdef __aarch64__ fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip); - if (fpStackDepth == 0) { - return; - } rawdata.jsChainId = getJsChainId(); #endif } else { @@ -979,8 +954,7 @@ void hook_free(void (*free_func)(void*), void* p) } else { realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs); } - holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize); #ifdef PERFORMANCE_DEBUG g_mallocTimes++; struct timespec end = {}; @@ -1002,7 +976,7 @@ inline void SendMmapFileRawData(int prot, int flags, off_t offset, const std::st curRawdata.pid = static_cast(g_hookPid.load()); curRawdata.mallocSize = rawdata.mallocSize; curRawdata.mmapArgs.offset = offset; - curRawdata.type = MMAP_FILE_TYPE; + curRawdata.type = OHOS::Developtools::NativeDaemon::MMAP_FILE_TYPE; if (prot & PROT_EXEC) { curRawdata.mmapArgs.flags |= PROT_EXEC; } @@ -1012,22 +986,6 @@ inline void SendMmapFileRawData(int prot, int flags, off_t offset, const std::st std::lock_guard guard(g_FilterMapMutex); ParseEvent(filePath, g_filterStaLibRange, curRawdata); } - if ((flags & MAP_FIXED) && (IsLegalSoName(filePath)) && (!g_ClientConfig.targetSoName.empty()) && - (filePath.find(g_ClientConfig.targetSoName) != std::string::npos)) { - uint64_t soStart = reinterpret_cast(curRawdata.addr); - uint64_t soEnd = soStart + static_cast(curRawdata.mallocSize); - auto range = targetedRange.load(); - if (range.start == 0 && range.end == 0) { - range.start = soStart; - range.end = soEnd; - } - if (range.start > soStart) { - range.start = soStart; - } else if (range.end < soEnd) { - range.end = soEnd; - } - targetedRange.store(range); - } if (strncpy_s(curRawdata.name, MAX_HOOK_PATH + 1, filePath.c_str(), len) != EOK) { return; } @@ -1123,15 +1081,11 @@ void* hook_mmap(void*(*fn)(void*, size_t, int, int, int, off_t), } int realSize = 0; if (g_ClientConfig.fpunwind) { - if (fpStackDepth == 0) { - return ret; - } realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t)); } else { realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs); } - holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize); #ifdef PERFORMANCE_DEBUG g_mallocTimes++; struct timespec end = {}; @@ -1172,26 +1126,14 @@ int hook_munmap(int(*fn)(void*, size_t), void* addr, size_t length) if (holder == nullptr) { return ret; } - if (!g_ClientConfig.targetSoName.empty()) { - uint64_t addrval = reinterpret_cast(addr); - auto range = targetedRange.load(); - if (addrval < range.end && addrval >= range.start) { - range.end = 0; - range.start = 0; - targetedRange.store(range); - } - } StackRawData rawdata = {{{{0}}}}; uintptr_t stackPtr = 0; int fpStackDepth = 0; rawdata.ts = unmapTime; if (g_ClientConfig.munmapStackData) { - if (g_ClientConfig.fpunwind && g_ClientConfig.statisticsInterval == 0) { + if (g_ClientConfig.fpunwind) { #ifdef __aarch64__ fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip); - if (fpStackDepth == 0) { - return ret; - } rawdata.jsChainId = getJsChainId(); #endif } else { @@ -1210,8 +1152,7 @@ int hook_munmap(int(*fn)(void*, size_t), void* addr, size_t length) } else { realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs); } - holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize); #ifdef PERFORMANCE_DEBUG g_mallocTimes++; struct timespec end = {}; @@ -1258,8 +1199,7 @@ int hook_prctl(int(*fn)(int, ...), HILOG_BASE_ERROR(LOG_CORE, "memcpy_s tag failed"); } rawdata.name[sizeof(rawdata.name) - 1] = '\0'; - holder->SendStackWithPayload(&rawdata, sizeof(BaseStackRawData) + tagLen, nullptr, 0, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&rawdata, sizeof(BaseStackRawData) + tagLen, nullptr, 0); #ifdef PERFORMANCE_DEBUG g_mallocTimes++; struct timespec end = {}; @@ -1299,9 +1239,6 @@ void hook_memtrace(void* addr, size_t size, const char* tag, bool isUsing) if (g_ClientConfig.fpunwind) { #ifdef __aarch64__ fpStackDepth = FpUnwind(g_ClientConfig.maxStackDepth, rawdata.ip); - if (fpStackDepth == 0) { - return; - } rawdata.jsChainId = getJsChainId(); #endif } else { @@ -1320,8 +1257,7 @@ void hook_memtrace(void* addr, size_t size, const char* tag, bool isUsing) } else { realSize = sizeof(BaseStackRawData) + sizeof(rawdata.regs); } - holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize, - reinterpret_cast(rawdata.addr) % SHARED_MEMORY_NUM); + holder->SendStackWithPayload(&rawdata, realSize, reinterpret_cast(stackPtr), stackSize); #ifdef PERFORMANCE_DEBUG g_mallocTimes++; struct timespec end = {}; @@ -1481,12 +1417,8 @@ bool ohos_malloc_hook_send_hook_misc_data(uint64_t id, const char* stackPtr, siz rawdata.type = JS_STACK_MSG; std::weak_ptr weakClient = g_hookClient; auto holder = weakClient.lock(); - bool result = true; if (holder != nullptr) { - for (int i = 0; i < SHARED_MEMORY_NUM; ++i) { - result &= (holder->SendStackWithPayload(&rawdata, sizeof(BaseStackRawData), stackPtr, stackSize, i)); - } - return result; + return holder->SendStackWithPayload(&rawdata, sizeof(BaseStackRawData), stackPtr, stackSize); } } return false; diff --git a/device/plugins/native_hook/src/hook_socket_client.cpp b/device/plugins/native_hook/src/hook_socket_client.cpp index 291546073..04a5671bf 100644 --- a/device/plugins/native_hook/src/hook_socket_client.cpp +++ b/device/plugins/native_hook/src/hook_socket_client.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ #include "hook_socket_client.h" -#include "runtime_stack_range.h" + #include "common.h" #include "hook_common.h" #include "unix_socket_client.h" @@ -33,7 +33,8 @@ namespace { constexpr int FLUSH_FLAG = 20; constexpr int ONLY_NMD_TYPE = 2; constexpr int SIMP_NMD = 3; -std::atomic g_disableHook = true; +std::atomic g_flushCount = 0; +std::atomic g_disableHook = false; constexpr uint32_t MEMCHECK_DETAILINFO_MAXSIZE = 102400; struct OptArg { @@ -43,7 +44,7 @@ struct OptArg { } // namespace -using namespace OHOS::Developtools::NativeDaemon; + static std::string GetRealTime() { time_t now = time(nullptr); @@ -78,14 +79,11 @@ static void NmdWriteStat(void *arg, const char *buf) opt->pos += len; } -HookSocketClient::HookSocketClient(int pid, ClientConfig *config, Sampling *sampler, - std::atomic* targetedRange, void (*disableHookCallback)()) - : pid_(pid), config_(config), sampler_(sampler), targetedRange_(targetedRange), - disableHookCallback_(disableHookCallback) +HookSocketClient::HookSocketClient(int pid, ClientConfig *config, Sampling *sampler, void (*disableHookCallback)()) + : pid_(pid), config_(config), sampler_(sampler), disableHookCallback_(disableHookCallback) { - smbFds_.reserve(SHARED_MEMORY_NUM); - eventFds_.reserve(SHARED_MEMORY_NUM); - stackWriterList_.reserve(SHARED_MEMORY_NUM); + smbFd_ = 0; + eventFd_ = 0; unixSocketClient_ = nullptr; serviceName_ = "HookService"; Connect(DEFAULT_UNIX_SOCKET_HOOK_FULL_PATH); @@ -93,13 +91,11 @@ HookSocketClient::HookSocketClient(int pid, ClientConfig *config, Sampling *samp HookSocketClient::~HookSocketClient() { - for (size_t i = 0; i < stackWriterList_.size(); ++i) { - if (stackWriterList_[i]) { - stackWriterList_[i]->Flush(); - } - stackWriterList_[i] = nullptr; + if (stackWriter_) { + stackWriter_->Flush(); } unixSocketClient_ = nullptr; + stackWriter_ = nullptr; } bool HookSocketClient::Connect(const std::string addrname) @@ -126,16 +122,11 @@ bool HookSocketClient::ProtocolProc(SocketContext &context, uint32_t pnum, const config_->maxStackDepth = config_->maxStackDepth > MAX_UNWIND_DEPTH ? MAX_UNWIND_DEPTH : config_->maxStackDepth; std::string configStr = config_->ToString(); sampler_->InitSampling(config_->sampleInterval); - for (size_t i = 0; i < SHARED_MEMORY_NUM; ++i) { - int smbfd = context.ReceiveFileDiscriptor(); - int eventfd = context.ReceiveFileDiscriptor(); - smbFds_.push_back(smbfd); - eventFds_.push_back(eventfd); - std::string smbName = "hooknativesmb_" + std::to_string(pid_) + ":" + std::to_string(i); - std::shared_ptr stackWriter = std::make_shared(smbName, config_->shareMemorySize, - smbfd, eventfd, config_->isBlocked, config_->isSaMode); - stackWriterList_.push_back(stackWriter); - } + smbFd_ = context.ReceiveFileDiscriptor(); + eventFd_ = context.ReceiveFileDiscriptor(); + std::string smbName = "hooknativesmb_" + std::to_string(pid_); + stackWriter_ = std::make_shared(smbName, config_->shareMemorySize, + smbFd_, eventFd_, config_->isBlocked, config_->isSaMode); nmdType_ = config_->nmdType; g_disableHook = false; largestSize_ = config_->largestSize; @@ -149,15 +140,12 @@ bool HookSocketClient::ProtocolProc(SocketContext &context, uint32_t pnum, const } else if (nmdType_ == SIMP_NMD) { SendSimplifiedNmdInfo(); } - if (!config_->targetSoName.empty()) { - ParseTargetedMaps(*targetedRange_, config_->targetSoName); - } return true; } bool HookSocketClient::SendStack(const void* data, size_t size) { - if (stackWriterList_.size() == 0 || stackWriterList_[0] == nullptr || unixSocketClient_ == nullptr) { + if (stackWriter_ == nullptr || unixSocketClient_ == nullptr) { return false; } @@ -165,46 +153,41 @@ bool HookSocketClient::SendStack(const void* data, size_t size) return false; } - stackWriterList_[0]->WriteTimeout(data, size); - stackWriterList_[0]->Flush(); + stackWriter_->WriteTimeout(data, size); + stackWriter_->Flush(); return true; } bool HookSocketClient::SendStackWithPayload(const void* data, size_t size, const void* payload, - size_t payloadSize, int smbIndex) + size_t payloadSize) { - if (smbIndex + 1 > static_cast(stackWriterList_.size())) { - return false; - } - std::shared_ptr stackWriter = stackWriterList_[smbIndex]; - if (stackWriter == nullptr || unixSocketClient_ == nullptr || g_disableHook) { + if (stackWriter_ == nullptr || unixSocketClient_ == nullptr || g_disableHook) { return false; } else if (unixSocketClient_->GetClientState() == CLIENT_STAT_THREAD_EXITED) { DisableHook(); return false; } - bool ret = stackWriter->WriteWithPayloadTimeout(data, size, payload, payloadSize, - std::bind(&HookSocketClient::PeerIsConnected, this)); + bool ret = stackWriter_->WriteWithPayloadTimeout(data, size, payload, payloadSize, + std::bind(&HookSocketClient::PeerIsConnected, this)); if (!ret && config_->isBlocked) { DisableHook(); return false; } - if (stackWriter->PrepareFlush()) { - stackWriter->Flush(); + ++g_flushCount; + if (g_flushCount % FLUSH_FLAG == 0) { + stackWriter_->Flush(); } return true; } void HookSocketClient::Flush() { - for (int i = 0; i < stackWriterList_.size(); ++i) { - if (stackWriterList_[i] == nullptr || unixSocketClient_ == nullptr) { - return; - } - stackWriterList_[i]->Flush(); + if (stackWriter_ == nullptr || unixSocketClient_ == nullptr) { + return; } + stackWriter_->Flush(); } void HookSocketClient::DisableHook() @@ -225,7 +208,7 @@ bool HookSocketClient::PeerIsConnected() bool HookSocketClient::SendNmdInfo() { - if ((!config_->printNmd) || (stackWriterList_.size() == 0)) { + if (!config_->printNmd) { return false; } void* nmdBuf = malloc(MEMCHECK_DETAILINFO_MAXSIZE); @@ -236,19 +219,18 @@ bool HookSocketClient::SendNmdInfo() malloc_stats_print(NmdWriteStat, &opt, "a"); StackRawData rawdata = {{{{0}}}}; rawdata.type = NMD_MSG; - if (stackWriterList_[0]) { - stackWriterList_[0]->WriteWithPayloadTimeout(&rawdata, sizeof(BaseStackRawData), - reinterpret_cast(opt.buf), strlen(opt.buf) + 1, - std::bind(&HookSocketClient::PeerIsConnected, this)); + if (stackWriter_) { + stackWriter_->WriteWithPayloadTimeout(&rawdata, sizeof(BaseStackRawData), + reinterpret_cast(opt.buf), strlen(opt.buf) + 1, + std::bind(&HookSocketClient::PeerIsConnected, this)); } - stackWriterList_[0]->Flush(); free(nmdBuf); return true; } bool HookSocketClient::SendSimplifiedNmdInfo() { - if ((!config_->printNmd) || (stackWriterList_.size() == 0)) { + if (!config_->printNmd) { return false; } void* nmdBuf = malloc(MEMCHECK_DETAILINFO_MAXSIZE); @@ -259,12 +241,12 @@ bool HookSocketClient::SendSimplifiedNmdInfo() malloc_stats_print(NmdWriteStat, &opt, "s"); StackRawData rawdata = {{{{0}}}}; rawdata.type = NMD_MSG; - if (stackWriterList_[0]) { - stackWriterList_[0]->WriteWithPayloadTimeout(&rawdata, sizeof(BaseStackRawData), - reinterpret_cast(opt.buf), strlen(opt.buf) + 1, - std::bind(&HookSocketClient::PeerIsConnected, this)); + if (stackWriter_) { + stackWriter_->WriteWithPayloadTimeout(&rawdata, sizeof(BaseStackRawData), + reinterpret_cast(opt.buf), strlen(opt.buf) + 1, + std::bind(&HookSocketClient::PeerIsConnected, this)); } - stackWriterList_[0]->Flush(); + stackWriter_->Flush(); free(nmdBuf); return true; } @@ -273,11 +255,8 @@ bool HookSocketClient::SendEndMsg() { StackRawData rawdata = {{{{0}}}}; rawdata.type = END_MSG; - std::for_each(stackWriterList_.begin(), stackWriterList_.end(), - [&rawdata](std::shared_ptr& writer) { - if (writer) { - writer->WriteTimeout(&rawdata, sizeof(BaseStackRawData)); - } - }); + if (stackWriter_) { + stackWriter_->WriteTimeout(&rawdata, sizeof(BaseStackRawData)); + } return true; } \ No newline at end of file diff --git a/device/plugins/native_hook/src/runtime_stack_range.cpp b/device/plugins/native_hook/src/runtime_stack_range.cpp index 20fd0f309..f860c447f 100644 --- a/device/plugins/native_hook/src/runtime_stack_range.cpp +++ b/device/plugins/native_hook/src/runtime_stack_range.cpp @@ -36,7 +36,6 @@ struct StandardLibrary { }; static std::map g_stdLib; -static std::map g_targetLib; static uintptr_t g_stackMainStart = 0; static uintptr_t g_stackMainEnd = 0; } // namespace @@ -104,7 +103,7 @@ bool IsLegalSoName(const std::string &fileName) return true; } -static void GetStandardLibraryRange(std::string& line, bool targeted = false) +static void GetStandardLibraryRange(std::string& line) { line.resize(strlen(line.c_str())); std::vector mapTokens = OHOS::Developtools::NativeDaemon::StringSplit(line, " "); @@ -114,13 +113,7 @@ static void GetStandardLibraryRange(std::string& line, bool targeted = false) std::string::size_type concatPos = soRange.find('-'); uint64_t soStart = static_cast(strtoll(soRange.c_str(), nullptr, BASE_MAX)); uint64_t soEnd = static_cast(strtoll(soRange.c_str() + concatPos + 1, nullptr, BASE_MAX)); - auto iter = g_stdLib.begin(); - bool isExit = false; - if (targeted) { - std::tie(iter, isExit) = g_targetLib.try_emplace(soName, StandardLibrary(soStart, soEnd, soName)); - } else { - std::tie(iter, isExit) = g_stdLib.try_emplace(soName, StandardLibrary(soStart, soEnd, soName)); - } + auto [iter, isExit] = g_stdLib.try_emplace(soName, StandardLibrary(soStart, soEnd, soName)); if (!isExit) { if (iter->second.soBegin_ > soStart) { iter->second.soBegin_ = soStart; @@ -131,37 +124,6 @@ static void GetStandardLibraryRange(std::string& line, bool targeted = false) } } -bool ParseTargetedMaps(std::atomic& targetedRange, std::string targetedLib) -{ - FILE* fp = fopen("/proc/self/maps", "r"); - bool ret = false; - if (fp == nullptr) { - return ret; - } - char mapInfo[256] = {0}; // 256: map info size - int pos = 0; - uint64_t begin = 0; - uint64_t end = 0; - uint64_t offset = 0; - char perms[5] = {0}; // 5:rwxp - while (fgets(mapInfo, sizeof(mapInfo), fp) != nullptr) { - if (strstr(mapInfo, targetedLib.c_str()) != nullptr) { - std::string lineStr = mapInfo; - GetStandardLibraryRange(lineStr, true); - } - } - if (fclose(fp) != 0) { - printf("fclose failed.\n"); - } - auto range = targetedRange.load(); - for (const auto& [soName, stdLibrary]: g_targetLib) { - range.start = stdLibrary.soBegin_; - range.end = stdLibrary.soEnd_; - } - targetedRange.store(range); - return ret; -} - bool GetRuntimeStackRange(const uintptr_t stackPtr, uintptr_t& stackBottom, uintptr_t& stackTop, bool isMainThread) { bool ret = false; diff --git a/device/plugins/native_hook/src/stack_writer.cpp b/device/plugins/native_hook/src/stack_writer.cpp index 2efdfdbb1..94f72a09c 100644 --- a/device/plugins/native_hook/src/stack_writer.cpp +++ b/device/plugins/native_hook/src/stack_writer.cpp @@ -20,7 +20,6 @@ #include "stack_writer.h" namespace { const int WAIT_TIMEOUT_SA = 3000000; - const int FLUSH_FLAG = 20; } StackWriter::StackWriter(std::string name, uint32_t size, @@ -91,12 +90,6 @@ long StackWriter::WriteWithPayloadTimeout(const void* data, size_t size, const v } } -bool StackWriter::PrepareFlush() -{ - ++dataCount_; - return (dataCount_ % FLUSH_FLAG == 0); -} - bool StackWriter::Flush() { ++flushCount_; diff --git a/device/plugins/native_hook/test/BUILD.gn b/device/plugins/native_hook/test/BUILD.gn index 13d5cfb80..2e0881adf 100644 --- a/device/plugins/native_hook/test/BUILD.gn +++ b/device/plugins/native_hook/test/BUILD.gn @@ -35,7 +35,6 @@ ohos_unittest("nativehook_ut") { module_out_path = module_output_path sources = [ "../../memory_plugin/src/buffer_splitter.cpp", - "unittest/address_handler_test.cpp", "unittest/check_hook_data_test.cpp", "unittest/hook_client_test.cpp", "unittest/hook_socket_client_test.cpp", diff --git a/device/plugins/native_hook/test/unittest/address_handler_test.cpp b/device/plugins/native_hook/test/unittest/address_handler_test.cpp deleted file mode 100644 index 21e3513b7..000000000 --- a/device/plugins/native_hook/test/unittest/address_handler_test.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. - * 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 -#include -#include "address_handler.h" -#include "init_param.h" - -using namespace testing::ext; - -namespace { - -constexpr uint64_t TEST_ADDR = 64; -class AddressHandlerTest : public ::testing::Test { -public: - static void SetUpTestCase() {} - static void TearDownTestCase() {} - void SetUp() {} - void TearDown() {} -}; - -/** - * @tc.name: LowAddrHandlerTest - * @tc.desc: Test LowAddrHandler. - * @tc.type: FUNC - */ -HWTEST_F(AddressHandlerTest, LowAddrHandlerTest, TestSize.Level1) -{ - std::unique_ptr handler = std::make_unique(); - uint64_t noExistaddr = TEST_ADDR - 1; - handler->AddAllocAddr(TEST_ADDR); - ASSERT_TRUE(handler->CheckAddr(TEST_ADDR)); - ASSERT_FALSE(handler->CheckAddr(noExistaddr)); - handler = nullptr; -} - -/** - * @tc.name: MidAddrHandlerTest - * @tc.desc: Test MidAddrHandler. - * @tc.type: FUNC - */ -HWTEST_F(AddressHandlerTest, MidAddrHandlerTest, TestSize.Level1) -{ - std::unique_ptr handler = std::make_unique(); - uint64_t addr = 0xFF00000; - uint64_t noExistaddr = addr - 1; - handler->AddAllocAddr(addr); - ASSERT_TRUE(handler->CheckAddr(addr)); - ASSERT_FALSE(handler->CheckAddr(noExistaddr)); - addr = TEST_ADDR; - noExistaddr = addr - 1; - handler->AddAllocAddr(addr); - ASSERT_TRUE(handler->CheckAddr(addr)); - ASSERT_TRUE(handler->CheckAddr(noExistaddr)); - handler = nullptr; -} - -/** - * @tc.name: WholeAddrHandlerTest - * @tc.desc: Test WholeAddrHandler. - * @tc.type: FUNC - */ -HWTEST_F(AddressHandlerTest, WholeAddrHandlerTest, TestSize.Level1) -{ - std::unique_ptr handler = std::make_unique(); - uint64_t noExistaddr = TEST_ADDR - 1; - handler->AddAllocAddr(TEST_ADDR); - ASSERT_TRUE(handler->CheckAddr(TEST_ADDR)); - ASSERT_FALSE(handler->CheckAddr(noExistaddr)); - handler = nullptr; -} - -/** - * @tc.name: LowMidAddrHandlerTest - * @tc.desc: Test LowAddrHandler and MidAddrHandler. - * @tc.type: FUNC - */ -HWTEST_F(AddressHandlerTest, LowMidAddrHandlerTest, TestSize.Level1) -{ - std::unique_ptr handlerLow = std::make_unique(); - std::unique_ptr handlerMid = std::make_unique(); - uint64_t addr = 0xFF000000000; - uint64_t noExistaddr = 0xFE000000000; - handlerLow->AddAllocAddr(addr); - ASSERT_TRUE(handlerLow->CheckAddr(addr)); - ASSERT_TRUE(handlerLow->CheckAddr(noExistaddr)); - handlerMid->AddAllocAddr(addr); - handlerLow->SetSuccessor(std::move(handlerMid)); - ASSERT_TRUE(handlerLow->CheckAddr(addr)); - ASSERT_FALSE(handlerLow->CheckAddr(noExistaddr)); - handlerLow = nullptr; - handlerMid = nullptr; -} - -/** - * @tc.name: LowWholeAddrHandlerTest - * @tc.desc: Test LowAddrHandler and WholeAddrHandler. - * @tc.type: FUNC - */ -HWTEST_F(AddressHandlerTest, LowWholeAddrHandlerTest, TestSize.Level1) -{ - std::unique_ptr handlerLow = std::make_unique(); - std::unique_ptr handlerWhole = std::make_unique(); - uint64_t addr = 0xFF000000000; - uint64_t noExistaddr = 0xFE000000000; - handlerLow->AddAllocAddr(addr); - ASSERT_TRUE(handlerLow->CheckAddr(addr)); - ASSERT_TRUE(handlerLow->CheckAddr(noExistaddr)); - handlerWhole->AddAllocAddr(addr); - handlerLow->SetSuccessor(std::move(handlerWhole)); - ASSERT_TRUE(handlerLow->CheckAddr(addr)); - ASSERT_FALSE(handlerLow->CheckAddr(noExistaddr)); - handlerLow = nullptr; - handlerWhole = nullptr; -} - -/** - * @tc.name: MidWholeAddrHandlerTest - * @tc.desc: Test MidAddrHandler and WholeAddrHandler. - * @tc.type: FUNC - */ -HWTEST_F(AddressHandlerTest, MidWholeAddrHandlerTest, TestSize.Level1) -{ - std::unique_ptr handlerMid = std::make_unique(); - std::unique_ptr handlerWhole = std::make_unique(); - uint64_t addr = TEST_ADDR; - uint64_t noExistaddr = addr - 1; - handlerMid->AddAllocAddr(addr); - ASSERT_TRUE(handlerMid->CheckAddr(addr)); - ASSERT_TRUE(handlerMid->CheckAddr(noExistaddr)); - handlerWhole->AddAllocAddr(addr); - handlerMid->SetSuccessor(std::move(handlerWhole)); - ASSERT_TRUE(handlerMid->CheckAddr(addr)); - ASSERT_FALSE(handlerMid->CheckAddr(noExistaddr)); - handlerMid = nullptr; - handlerWhole = nullptr; -} - -/** - * @tc.name: AllAddrHandlerTest - * @tc.desc: Test LowAddrHandler, MidAddrHandler and WholeAddrHandler. - * @tc.type: FUNC - */ -HWTEST_F(AddressHandlerTest, AllAddrHandlerTest, TestSize.Level1) -{ - std::unique_ptr handlerLow = std::make_unique(); - std::unique_ptr handlerMid = std::make_unique(); - std::unique_ptr handlerWhole = std::make_unique(); - uint64_t addr = 0xFF0000000000000; - uint64_t noExistaddr = 0xEF0000000000000; - handlerLow->AddAllocAddr(addr); - handlerWhole->AddAllocAddr(addr); - handlerMid->AddAllocAddr(addr); - ASSERT_TRUE(handlerLow->CheckAddr(addr)); - ASSERT_TRUE(handlerLow->CheckAddr(noExistaddr)); - handlerMid->SetSuccessor(std::move(handlerWhole)); - handlerLow->SetSuccessor(std::move(handlerMid)); - ASSERT_TRUE(handlerLow->CheckAddr(addr)); - ASSERT_FALSE(handlerLow->CheckAddr(noExistaddr)); - handlerLow = nullptr; - handlerMid = nullptr; - handlerWhole = nullptr; -} -} \ No newline at end of file diff --git a/device/plugins/native_hook/test/unittest/check_hook_data_test.cpp b/device/plugins/native_hook/test/unittest/check_hook_data_test.cpp index bbc655b6b..2fdaa7c2a 100644 --- a/device/plugins/native_hook/test/unittest/check_hook_data_test.cpp +++ b/device/plugins/native_hook/test/unittest/check_hook_data_test.cpp @@ -22,7 +22,6 @@ #include "token_setproc.h" #include "accesstoken_kit.h" #include "buffer_splitter.h" -#include "common.h" #include "logging.h" #include "parameters.h" #include @@ -505,9 +504,6 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0080, Function | MediumTest | Lev char delimiter = ';'; Getdata(totalbuffer, hookVec, delimiter); - if (hookVec.size() < 6) { - continue; - } if (hookVec[0] == "malloc" && !isFirstHook) { for (int i = 0; i < MALLOC_GET_DATE_SIZE; i++) { EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); @@ -515,7 +511,6 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0080, Function | MediumTest | Lev delimiter = '\n'; EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); ASSERT_EQ(static_cast(hookVec.size()), MALLOC_VEC_SIZE); - ASSERT_TRUE(COMMON::IsNumeric(hookVec[4].c_str())); ASSERT_EQ(atoi(hookVec[4].c_str()), DEFAULT_MALLOC_SIZE); // 4: fifth hook data, default malloc size addr = hookVec[addrPos]; @@ -576,9 +571,6 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0090, Function | MediumTest | Lev char delimiter = ';'; Getdata(totalbuffer, hookVec, delimiter); - if (hookVec.size() < 6) { - continue; - } if (hookVec[0] == "malloc" && !isFirstHook) { for (int i = 0; i < MALLOC_GET_DATE_SIZE; i++) { EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); @@ -586,7 +578,6 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0090, Function | MediumTest | Lev delimiter = '\n'; EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); ASSERT_EQ(static_cast(hookVec.size()), MALLOC_VEC_SIZE); - ASSERT_TRUE(COMMON::IsNumeric(hookVec[4].c_str())); ASSERT_EQ(atoi(hookVec[4].c_str()), DEFAULT_CALLOC_SIZE); // 4: fifth hook data, default malloc size addr = hookVec[addrPos]; @@ -648,9 +639,6 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0100, Function | MediumTest | Lev char delimiter = ';'; Getdata(totalbuffer, hookVec, delimiter); - if (hookVec.size() < 6) { - continue; - } if (hookVec[0] == "malloc" && !isFirstHook) { for (int i = 0; i < MALLOC_GET_DATE_SIZE; i++) { EXPECT_TRUE(Getdata(totalbuffer, hookVec, delimiter)); @@ -662,14 +650,12 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0100, Function | MediumTest | Lev if (isRealloc) { reallocAddr = hookVec[addrPos]; // 4: fifth hook data, default malloc size - ASSERT_TRUE(COMMON::IsNumeric(hookVec[4].c_str())); ASSERT_GE(atoi(hookVec[4].c_str()), DEFAULT_REALLOC_SIZE); EXPECT_GE(depth, REALLOC_DEPTH); isFirstHook = false; } else { mallocAddr = hookVec[addrPos]; // 4: fifth hook data, default malloc size - ASSERT_TRUE(COMMON::IsNumeric(hookVec[4].c_str())); ASSERT_EQ(atoi(hookVec[4].c_str()), DEFAULT_MALLOC_SIZE); } @@ -725,7 +711,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0110, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; uint8_t mallocPos = 0; uint8_t mallocSizePos = 6; @@ -733,9 +719,6 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0110, Function | MediumTest | Lev while (getline(infile, buf)) { std::vector& resultVec = StringSplit(buf); - if (resultVec.size() < static_cast(mallocSizePos)) { - continue; - } if (resultVec[mallocPos] == "malloc") { if (resultVec[mallocSizePos] == std::to_string(LIBA_MALLOC_SIZE)) { std::cout << buf << std::endl; @@ -781,7 +764,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0120, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; std::string expectCallStackId; std::string statisticsCallStackId; @@ -806,12 +789,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0120, Function | MediumTest | Lev } } getline(infile, buf); // read statistics_event apply_count - if (buf.find("type") != std::string::npos) { - getline(infile, buf); - } std::vector& resultVec = StringSplit(buf, ':'); - ASSERT_FALSE(resultVec.empty()); - ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); uint16_t applyCount = std::atoi(resultVec[1].c_str()); std::cout << "applyCount: " << applyCount << std::endl; EXPECT_TRUE(applyCount > 0); @@ -840,7 +818,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0130, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; std::string symTable; std::string strTable; @@ -891,7 +869,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0140, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; bool findSymbolName; bool findfilePath; @@ -940,7 +918,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0150, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; bool findFrameInfo; bool findSymbolNameId; @@ -981,7 +959,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0160, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; bool findFrameInfo; bool findSymbolName; @@ -1023,7 +1001,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0170, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; uint16_t ipCount = 0; @@ -1069,7 +1047,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0180, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; std::string expectCallStackId; std::string statisticsCallStackId; @@ -1094,12 +1072,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0180, Function | MediumTest | Lev } } getline(infile, buf); // read statistics_event apply_count - if (buf.find("type") != std::string::npos) { - getline(infile, buf); - } std::vector& resultVec = StringSplit(buf, ':'); - ASSERT_FALSE(resultVec.empty()); - ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); uint16_t applyCount = std::atoi(resultVec[1].c_str()); std::cout << "applyCount: " << applyCount << std::endl; EXPECT_TRUE(applyCount > 0); @@ -1128,7 +1101,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0190, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; bool findSymbolName; bool findfilePath; @@ -1180,7 +1153,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0200, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; std::string expectCallStackId; std::string statisticsCallStackId; @@ -1205,12 +1178,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0200, Function | MediumTest | Lev } } getline(infile, buf); // read statistics_event apply_count - if (buf.find("type") != std::string::npos) { - getline(infile, buf); - } std::vector& resultVec = StringSplit(buf, ':'); - ASSERT_FALSE(resultVec.empty()); - ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); uint16_t applyCount = std::atoi(resultVec[1].c_str()); std::cout << "applyCount: " << applyCount << std::endl; EXPECT_TRUE(applyCount > 0); @@ -1241,7 +1209,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0210, Function | MediumTest | Lev std::ifstream infile; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; std::string expectCallStackId; std::string statisticsCallStackId; @@ -1266,12 +1234,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0210, Function | MediumTest | Lev } } getline(infile, buf); // read statistics_event apply_count - if (buf.find("type") != std::string::npos) { - getline(infile, buf); - } std::vector& resultVec = StringSplit(buf, ':'); - ASSERT_FALSE(resultVec.empty()); - ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); uint16_t applyCount = std::atoi(resultVec[1].c_str()); std::cout << "applyCount: " << applyCount << std::endl; EXPECT_TRUE(applyCount > 0); @@ -1301,7 +1264,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0220, Function | MediumTest | Lev std::ifstream infile; outFile_ = "/data/local/tmp/test_dump_file.htrace"; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; std::string expectCallStackId; std::string statisticsCallStackId; @@ -1326,12 +1289,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0220, Function | MediumTest | Lev } } getline(infile, buf); // read statistics_event apply_count - if (buf.find("type") != std::string::npos) { - getline(infile, buf); - } std::vector& resultVec = StringSplit(buf, ':'); - ASSERT_FALSE(resultVec.empty()); - ASSERT_TRUE(COMMON::IsNumeric(resultVec[1].c_str())); uint16_t applyCount = std::atoi(resultVec[1].c_str()); std::cout << "applyCount: " << applyCount << std::endl; EXPECT_TRUE(applyCount > 0); @@ -1360,7 +1318,7 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0230, Function | MediumTest | Lev std::ifstream infile; outFile_ = "/data/local/tmp/test_dump_file0.htrace"; infile.open(outFile_, std::ios::in); - ASSERT_TRUE(infile.is_open()); + EXPECT_TRUE(infile.is_open()); std::string buf; bool nmdResult = false; while (getline(infile, buf)) { diff --git a/device/plugins/native_hook/test/unittest/hook_socket_client_test.cpp b/device/plugins/native_hook/test/unittest/hook_socket_client_test.cpp index a89acf515..e0df4b150 100644 --- a/device/plugins/native_hook/test/unittest/hook_socket_client_test.cpp +++ b/device/plugins/native_hook/test/unittest/hook_socket_client_test.cpp @@ -18,7 +18,6 @@ #include "hook_socket_client.h" #include "hook_service.h" -#include "hook_common.h" #include "service_entry.h" #include "socket_context.h" #include "unix_socket_client.h" @@ -93,11 +92,11 @@ HWTEST_F(HookSocketClientTest, SendStack, TestSize.Level1) } /* - * @tc.name: FdListSize - * @tc.desc: test fd list size with normal case. + * @tc.name: GetSmbFd + * @tc.desc: test HookSocketClient::GetSmbFd with normal case. * @tc.type: FUNC */ -HWTEST_F(HookSocketClientTest, FdListSize, TestSize.Level1) +HWTEST_F(HookSocketClientTest, GetSmbFd, TestSize.Level1) { ClientConfig clientConfig; SocketContext socketContext; @@ -106,16 +105,15 @@ HWTEST_F(HookSocketClientTest, FdListSize, TestSize.Level1) auto size = sizeof(clientConfig); HookSocketClient hookClient(1, &g_ClientConfigTest, &sampler, nullptr); ASSERT_TRUE(hookClient.ProtocolProc(socketContext, 0, ptr, size)); - ASSERT_EQ(hookClient.GetSmbFds().size(), OHOS::Developtools::NativeDaemon::SHARED_MEMORY_NUM); - ASSERT_EQ(hookClient.GetEventFds().size(), OHOS::Developtools::NativeDaemon::SHARED_MEMORY_NUM); + ASSERT_EQ(hookClient.GetSmbFd(), -1); } /* - * @tc.name: GetSmbFds - * @tc.desc: test HookSocketClient::GetSmbFds with normal case. + * @tc.name: GetEventFd + * @tc.desc: test HookSocketClient::GetEventFd with normal case. * @tc.type: FUNC */ -HWTEST_F(HookSocketClientTest, GetSmbFds, TestSize.Level1) +HWTEST_F(HookSocketClientTest, GetEventFd, TestSize.Level1) { ClientConfig clientConfig; SocketContext socketContext; @@ -124,30 +122,7 @@ HWTEST_F(HookSocketClientTest, GetSmbFds, TestSize.Level1) auto size = sizeof(clientConfig); HookSocketClient hookClient(1, &g_ClientConfigTest, &sampler, nullptr); ASSERT_TRUE(hookClient.ProtocolProc(socketContext, 0, ptr, size)); - std::vector smbFds = hookClient.GetSmbFds(); - for (size_t i = 0; i < smbFds.size(); ++i) { - ASSERT_EQ(smbFds[i], -1); - } -} - -/* - * @tc.name: GetEventFds - * @tc.desc: test HookSocketClient::GetEventFds with normal case. - * @tc.type: FUNC - */ -HWTEST_F(HookSocketClientTest, GetEventFds, TestSize.Level1) -{ - ClientConfig clientConfig; - SocketContext socketContext; - Sampling sampler; - auto ptr = reinterpret_cast(&clientConfig); - auto size = sizeof(clientConfig); - HookSocketClient hookClient(1, &g_ClientConfigTest, &sampler, nullptr); - ASSERT_TRUE(hookClient.ProtocolProc(socketContext, 0, ptr, size)); - std::vector eventFds = hookClient.GetEventFds(); - for (size_t i = 0; i < eventFds.size(); ++i) { - ASSERT_EQ(eventFds[i], -1); - } + ASSERT_EQ(hookClient.GetEventFd(), -1); } /* diff --git a/device/plugins/native_hook/test/unittest/stack_writer_test.cpp b/device/plugins/native_hook/test/unittest/stack_writer_test.cpp index 590f2a1b1..30dff5599 100644 --- a/device/plugins/native_hook/test/unittest/stack_writer_test.cpp +++ b/device/plugins/native_hook/test/unittest/stack_writer_test.cpp @@ -28,8 +28,6 @@ constexpr uint32_t BUFFER_SIZE = 1024; constexpr uint32_t SMB_SIZE = 10 * 4096; const std::string SMB_NAME = "stackwritertest"; const std::string PLUGIN_NAME = "stackwriter"; -const std::string PLUGIN_NAME_SECOND = "stackwriter_second"; -const std::string PLUGIN_NAME_THIRD = "stackwriter_third"; void* g_smbAddr = nullptr; int g_smbFd = 0; @@ -253,137 +251,6 @@ HWTEST_F(StackWriterTest, WriteWithPayloadTimeoutFalseTest, TestSize.Level1) EXPECT_FALSE(write->WriteWithPayloadTimeout(nullptr, 0, nullptr, 0, nullptr)); } -/** - * @tc.name: WriteWithPayloadTimeoutTwoSmbTest - * @tc.desc: test WriteWithPayloadTimeout with two shared memory block. - * @tc.type: FUNC - */ -HWTEST_F(StackWriterTest, WriteWithPayloadTimeoutTwoSmbTest, TestSize.Level1) -{ - uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA}; - uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44}; - auto writer1 = std::make_shared(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1, true); - auto writer2 = std::make_shared(PLUGIN_NAME_SECOND, SMB_SIZE, InitShareMemory(), -1, true); - EXPECT_NE(writer1->shareMemoryBlock_, nullptr); - EXPECT_TRUE(writer1->WriteWithPayloadTimeout(reinterpret_cast(buffer1), sizeof(buffer1), - reinterpret_cast(buffer1), sizeof(buffer1), nullptr)); - EXPECT_TRUE(writer2->WriteWithPayloadTimeout(reinterpret_cast(buffer2), sizeof(buffer2), - reinterpret_cast(buffer2), sizeof(buffer2), nullptr)); - EXPECT_TRUE(CheckBuffer(buffer2, sizeof(buffer2))); -} - -/** - * @tc.name: WriteWithPayloadTimeoutMultiSmbTest - * @tc.desc: test WriteWithPayloadTimeout with three shared memory block. - * @tc.type: FUNC - */ -HWTEST_F(StackWriterTest, WriteWithPayloadTimeoutMultiSmbTest, TestSize.Level1) -{ - uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA}; - uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44}; - uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD}; - auto writer1 = std::make_shared(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1, true); - auto writer2 = std::make_shared(PLUGIN_NAME_SECOND, SMB_SIZE, InitShareMemory(), -1, true); - auto writer3 = std::make_shared(PLUGIN_NAME_THIRD, SMB_SIZE, InitShareMemory(), -1, true); - EXPECT_NE(writer1->shareMemoryBlock_, nullptr); - EXPECT_NE(writer2->shareMemoryBlock_, nullptr); - EXPECT_NE(writer3->shareMemoryBlock_, nullptr); - EXPECT_TRUE(writer1->WriteWithPayloadTimeout(reinterpret_cast(buffer1), sizeof(buffer1), - reinterpret_cast(buffer1), sizeof(buffer1), nullptr)); - EXPECT_TRUE(writer2->WriteWithPayloadTimeout(reinterpret_cast(buffer2), sizeof(buffer2), - reinterpret_cast(buffer2), sizeof(buffer2), nullptr)); - EXPECT_TRUE(writer3->WriteWithPayloadTimeout(reinterpret_cast(buffer3), sizeof(buffer3), - reinterpret_cast(buffer3), sizeof(buffer3), nullptr)); - EXPECT_TRUE(CheckBuffer(buffer3, sizeof(buffer3))); -} - -/** - * @tc.name: WriteWithPayloadTimeoutMultiSmbFalseTest - * @tc.desc: test WriteWithPayloadTimeout with three shared memory block false case. - * @tc.type: FUNC - */ -HWTEST_F(StackWriterTest, WriteWithPayloadTimeoutMultiSmbFalseTest, TestSize.Level1) -{ - uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA}; - uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44}; - uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD}; - auto writer1 = std::make_shared(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1, true); - auto writer2 = std::make_shared(PLUGIN_NAME_SECOND, SMB_SIZE, InitShareMemory(), -1, true); - auto writer3 = std::make_shared(PLUGIN_NAME_THIRD, SMB_SIZE, InitShareMemory(), -1, true); - EXPECT_FALSE(writer1->WriteWithPayloadTimeout(reinterpret_cast(buffer1), 0, nullptr, 0, nullptr)); - EXPECT_FALSE(writer1->WriteWithPayloadTimeout(nullptr, 0, nullptr, 0, nullptr)); - EXPECT_FALSE(writer2->WriteWithPayloadTimeout(reinterpret_cast(buffer2), 0, nullptr, 0, nullptr)); - EXPECT_FALSE(writer2->WriteWithPayloadTimeout(nullptr, 0, nullptr, 0, nullptr)); - EXPECT_FALSE(writer3->WriteWithPayloadTimeout(reinterpret_cast(buffer3), 0, nullptr, 0, nullptr)); - EXPECT_FALSE(writer3->WriteWithPayloadTimeout(nullptr, 0, nullptr, 0, nullptr)); - EXPECT_FALSE(CheckBuffer(buffer1, sizeof(buffer1))); - EXPECT_FALSE(CheckBuffer(buffer2, sizeof(buffer2))); - EXPECT_FALSE(CheckBuffer(buffer3, sizeof(buffer3))); -} - -/** - * @tc.name: WriteTimeoutTwoSmbTest - * @tc.desc: test WriteTimeout with two shared memory block. - * @tc.type: FUNC - */ -HWTEST_F(StackWriterTest, WriteTimeoutTwoSmbTest, TestSize.Level1) -{ - uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA}; - uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44}; - auto writer1 = std::make_shared(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1, true); - auto writer2 = std::make_shared(PLUGIN_NAME_SECOND, SMB_SIZE, InitShareMemory(), -1, true); - EXPECT_NE(writer1->shareMemoryBlock_, nullptr); - EXPECT_TRUE(writer1->WriteTimeout(reinterpret_cast(buffer1), sizeof(buffer1))); - EXPECT_TRUE(writer2->WriteTimeout(reinterpret_cast(buffer2), sizeof(buffer2))); - EXPECT_TRUE(CheckBuffer(buffer2, sizeof(buffer2))); -} - -/** - * @tc.name: WriteTimeoutMultiSmbTest - * @tc.desc: test WriteTimeout with three shared memory block. - * @tc.type: FUNC - */ -HWTEST_F(StackWriterTest, WriteTimeoutMultiSmbTest, TestSize.Level1) -{ - uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA}; - uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44}; - uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD}; - auto writer1 = std::make_shared(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1, true); - auto writer2 = std::make_shared(PLUGIN_NAME_SECOND, SMB_SIZE, InitShareMemory(), -1, true); - auto writer3 = std::make_shared(PLUGIN_NAME_THIRD, SMB_SIZE, InitShareMemory(), -1, true); - EXPECT_NE(writer1->shareMemoryBlock_, nullptr); - EXPECT_NE(writer2->shareMemoryBlock_, nullptr); - EXPECT_NE(writer3->shareMemoryBlock_, nullptr); - EXPECT_TRUE(writer1->WriteTimeout(reinterpret_cast(buffer1), sizeof(buffer1))); - EXPECT_TRUE(writer2->WriteTimeout(reinterpret_cast(buffer2), sizeof(buffer2))); - EXPECT_TRUE(writer3->WriteTimeout(reinterpret_cast(buffer3), sizeof(buffer3))); - EXPECT_TRUE(CheckBuffer(buffer3, sizeof(buffer3))); -} - -/** - * @tc.name: WriteTimeoutMultiSmbFalseTest - * @tc.desc: test WriteTimeout with three shared memory block false case. - * @tc.type: FUNC - */ -HWTEST_F(StackWriterTest, WriteTimeoutMultiSmbFalseTest, TestSize.Level1) -{ - uint8_t buffer1[] = {0x55, 0xAA, 0x55, 0xAA}; - uint8_t buffer2[] = {0x11, 0x22, 0x33, 0x44}; - uint8_t buffer3[] = {0xAA, 0xBB, 0xCC, 0xDD}; - auto writer1 = std::make_shared(PLUGIN_NAME, SMB_SIZE, g_smbFd, -1, true); - auto writer2 = std::make_shared(PLUGIN_NAME_SECOND, SMB_SIZE, InitShareMemory(), -1, true); - auto writer3 = std::make_shared(PLUGIN_NAME_THIRD, SMB_SIZE, InitShareMemory(), -1, true); - EXPECT_FALSE(writer1->WriteTimeout(reinterpret_cast(buffer1), 0)); - EXPECT_FALSE(writer1->WriteTimeout(nullptr, 0)); - EXPECT_FALSE(writer2->WriteTimeout(reinterpret_cast(buffer2), 0)); - EXPECT_FALSE(writer2->WriteTimeout(nullptr, 0)); - EXPECT_FALSE(writer3->WriteTimeout(reinterpret_cast(buffer3), 0)); - EXPECT_FALSE(writer3->WriteTimeout(nullptr, 0)); - EXPECT_FALSE(CheckBuffer(buffer1, sizeof(buffer1))); - EXPECT_FALSE(CheckBuffer(buffer2, sizeof(buffer2))); - EXPECT_FALSE(CheckBuffer(buffer3, sizeof(buffer3))); -} - /** * @tc.name: WriteTimeout * @tc.desc: Write data to shared memory through writer. diff --git a/protos/types/plugins/native_hook/native_hook_config.proto b/protos/types/plugins/native_hook/native_hook_config.proto index e0fbec047..52e3e0fbc 100644 --- a/protos/types/plugins/native_hook/native_hook_config.proto +++ b/protos/types/plugins/native_hook/native_hook_config.proto @@ -47,5 +47,4 @@ message NativeHookConfig { int32 js_stack_report = 27; uint32 max_js_stack_depth = 28; string filter_napi_name = 29; - string target_so_name = 31; } -- Gitee