diff --git a/device/plugins/native_daemon/include/hook_common.h b/device/plugins/native_daemon/include/hook_common.h index 7682bd29c..4ad174589 100644 --- a/device/plugins/native_daemon/include/hook_common.h +++ b/device/plugins/native_daemon/include/hook_common.h @@ -113,6 +113,7 @@ struct alignas(8) ClientConfig { // 8 is 8 bit isBlocked = false; memtraceEnable = false; responseLibraryMode = false; + freeEventOnlyAddrEnable = false; } std::string ToString() @@ -123,7 +124,8 @@ struct alignas(8) ClientConfig { // 8 is 8 bit << ", mallocDisable:" << mallocDisable << ", mmapDisable:" << mmapDisable << ", freeStackData:" << freeStackData << ", munmapStackData:" << munmapStackData << ", fpunwind:" << fpunwind << ", isBlocked:" << isBlocked << ", memtraceEnable:" << memtraceEnable - << ", sampleInterval: " << sampleInterval << ", responseLibraryMode: " << responseLibraryMode; + << ", sampleInterval: " << sampleInterval << ", responseLibraryMode: " << responseLibraryMode + << ", freeEventOnlyAddrEnable: " << freeEventOnlyAddrEnable; return ss.str(); } @@ -140,14 +142,6 @@ struct alignas(8) ClientConfig { // 8 is 8 bit bool isBlocked = false; bool memtraceEnable = false; bool responseLibraryMode = false; + bool freeEventOnlyAddrEnable = false; }; - -struct StandaloneRawStack { - BaseStackRawData* stackConext; // points to the foundation type data - uint8_t* stackData; - int8_t* data; // fp mode data is ip, dwarf mode data is regs - uint32_t stackSize; - uint8_t fpDepth; // fp mode fpDepth is ip depth, dwarf mode is invalid -}; - #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 b3654672c..3b1f7dc5b 100644 --- a/device/plugins/native_daemon/include/hook_manager.h +++ b/device/plugins/native_daemon/include/hook_manager.h @@ -64,7 +64,7 @@ public: std::shared_ptr stackPreprocess = nullptr; bool isRecordAccurately = false; }; - HookManager(); + HookManager() = default; bool RegisterAgentPlugin(const std::string& pluginPath); bool UnregisterAgentPlugin(const std::string& pluginPath); @@ -118,6 +118,7 @@ private: FILE* fpHookData_ {nullptr}; std::vector> hookCtx_; bool isSaService_{false}; + bool noDataQueue_{false}; }; } #endif // AGENT_MANAGER_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 0c501d154..f93c57829 100644 --- a/device/plugins/native_daemon/include/stack_preprocess.h +++ b/device/plugins/native_daemon/include/stack_preprocess.h @@ -66,6 +66,7 @@ public: { isSaService_ = flag; } + void TakeResultsFromShmem(const std::shared_ptr&, const std::shared_ptr&); private: using CallFrame = OHOS::Developtools::NativeDaemon::CallFrame; @@ -78,15 +79,16 @@ private: }; enum RecordStatisticsLimit : std::size_t { - STATISTICS_MAP_SZIE = 2048, - STATISTICS_PERIOD_DATA_SIZE = 256, - ALLOC_ADDRMAMP_SIZE = 2048, + STATISTICS_MAP_SZIE = 100000, + STATISTICS_PERIOD_DATA_SIZE = 100000, + ALLOC_ADDRMAMP_SIZE = 100000, }; private: void TakeResults(); void SetHookData(RawStackPtr RawStack, std::vector& callFrames, BatchNativeHookData& batchNativeHookData); + void SetHookData(RawStackPtr rawStack, BatchNativeHookData& batchNativeHookData); void WriteFrames(RawStackPtr RawStack, const std::vector& callFrames); void SetFrameInfo(Frame& frame, CallFrame& callFrame); void ReportSymbolNameMap(CallFrame& callFrame, BatchNativeHookData& batchNativeHookData); @@ -112,8 +114,11 @@ private: BatchNativeHookData& batchNativeHookData, T* event, uint32_t stackId); void SetAllocStatisticsFrame(const RawStackPtr& rawStack, std::vector& callFrames, BatchNativeHookData& batchNativeHookData); + void SetAllocStatisticsFrame(const RawStackPtr& rawStack, BatchNativeHookData& batchNativeHookData); bool SetFreeStatisticsData(uint64_t addr); void SetAllocStatisticsData(const RawStackPtr& rawStack, size_t stackId, bool isExists = false); + void IntervalFlushRecordStatistics(BatchNativeHookData& stackData); + bool HandleNoStackEvent(RawStackPtr& rawStack, BatchNativeHookData& stackData); unsigned LgFloor(unsigned long x); uint64_t PowCeil(uint64_t x); size_t ComputeAlign(size_t size); @@ -139,7 +144,6 @@ private: // Key is ip , response_library_mode used std::unordered_map responseLibraryMap_; std::chrono::seconds statisticsInterval_ {0}; - std::chrono::steady_clock::time_point lastStatisticsTime_; // Key is call stack id, value is recordstatistic data std::unordered_map recordStatisticsMap_ {STATISTICS_MAP_SZIE}; // Key is call stack id, value is recordstatistic data pointer diff --git a/device/plugins/native_daemon/include/virtual_runtime.h b/device/plugins/native_daemon/include/virtual_runtime.h index a31baaf59..212ac7f1c 100644 --- a/device/plugins/native_daemon/include/virtual_runtime.h +++ b/device/plugins/native_daemon/include/virtual_runtime.h @@ -85,6 +85,8 @@ public: void FillMapsCache(std::string& currentFileName, std::shared_ptr mapItem); void HandleMapInfo(uint64_t begin, uint64_t length, uint32_t flags, uint64_t offset, const std::string& filePath); void RemoveMaps(uint64_t addr); + // threads + VirtualThread &UpdateThread(pid_t pid, pid_t tid, const std::string name = ""); std::vector& GetOfflineMaps() { return offlineMapAddr_; @@ -112,9 +114,6 @@ public: #endif const bool loadSymboleWhenNeeded_ = true; // thie is a feature config void UpdateSymbols(std::string filename); - // we don't know whether hap vma mapping is stand for a so - // thus we need try to parse it first - bool UpdateHapSymbols(std::shared_ptr map); bool IsSymbolExist(const std::string& fileName); void DelSymbolFile(const std::string& fileName); void UpdateMaps(pid_t pid, pid_t tid); @@ -176,8 +175,6 @@ private: // find synbols function name void MakeCallFrame(DfxSymbol &symbol, CallFrame &callFrame); - // threads - VirtualThread &UpdateThread(pid_t pid, pid_t tid, const std::string name = ""); std::string ReadThreadName(pid_t tid); VirtualThread &CreateThread(pid_t pid, pid_t tid); diff --git a/device/plugins/native_daemon/src/hook_manager.cpp b/device/plugins/native_daemon/src/hook_manager.cpp index 7eef75e5f..dcd30cc0a 100644 --- a/device/plugins/native_daemon/src/hook_manager.cpp +++ b/device/plugins/native_daemon/src/hook_manager.cpp @@ -40,7 +40,6 @@ namespace { const int DEFAULT_EVENT_POLLING_INTERVAL = 5000; const int PAGE_BYTES = 4096; std::shared_ptr g_buffWriter; -constexpr uint32_t MAX_BUFFER_SIZE = 10 * 1024; const std::string STARTUP = "startup:"; const std::string PARAM_NAME = "libc.hook_mode"; const int SIGNAL_START_HOOK = 36; @@ -99,7 +98,7 @@ bool HookManager::CheckProcessName() int pidValue = -1; const std::string processName = hookConfig_.process_name(); bool isExist = COMMON::IsProcessExist(processName, pidValue); - if (hookConfig_.startup_mode() || !isExist) { + if (hookConfig_.startup_mode() && !isExist) { HILOG_INFO(LOG_CORE, "Wait process %s start or restart, set param", hookConfig_.process_name().c_str()); std::string cmd = STARTUP + hookConfig_.process_name(); int ret = SystemSetParameter(PARAM_NAME.c_str(), cmd.c_str()); @@ -125,8 +124,6 @@ bool HookManager::CheckProcessName() return true; } -HookManager::HookManager() : buffer_(new (std::nothrow) uint8_t[MAX_BUFFER_SIZE]) { } - void HookManager::SetCommandPoller(const std::shared_ptr& p) { commandPoller_ = p; @@ -236,9 +233,6 @@ bool HookManager::HandleHookContext(const std::shared_ptr& ctx) ctx->eventPoller->Init(); ctx->eventPoller->Start(); - ctx->eventPoller->AddFileDescriptor( - ctx->eventNotifier->GetFd(), - std::bind(&HookManager::ReadShareMemory, this, ctx)); HILOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n", ctx->shareMemoryBlock->GetfileDescriptor(), ctx->eventNotifier->GetFd()); @@ -250,11 +244,23 @@ bool HookManager::HandleHookContext(const std::shared_ptr& ctx) hookConfig_.fp_unwind(), hookConfig_.max_stack_depth(), ctx->isRecordAccurately); HILOG_INFO(LOG_CORE, "hookConfig offline_symbolization = %d", hookConfig_.offline_symbolization()); - ctx->stackData = std::make_shared(STACK_DATA_SIZE); - CHECK_TRUE(ctx->stackData != nullptr, false, "Create StackDataRepeater FAIL"); clockid_t pluginDataClockId = COMMON::GetClockId(hookConfig_.clock()); - ctx->stackPreprocess = std::make_shared(ctx->stackData, hookConfig_, pluginDataClockId, + if (noDataQueue_) { + ctx->stackPreprocess = std::make_shared(nullptr, hookConfig_, pluginDataClockId, fpHookData_, isHookStandalone_); + 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_); + ctx->eventPoller->AddFileDescriptor( + ctx->eventNotifier->GetFd(), + std::bind(&HookManager::ReadShareMemory, this, ctx)); + } CHECK_TRUE(ctx->stackPreprocess != nullptr, false, "Create StackPreprocess FAIL"); ctx->stackPreprocess->SetWriter(g_buffWriter); ctx->stackPreprocess->SetSaServiceFlag(isSaService_); @@ -321,6 +327,12 @@ bool HookManager::CreatePluginSession(const std::vector& c return false; } } + if (hookConfig_.fp_unwind() && hookConfig_.record_accurately() + && hookConfig_.blocked() && hookConfig_.offline_symbolization() + && hookConfig_.statistics_interval() > 0 + && hookConfig_.sample_interval() > 1) { + noDataQueue_ = true; + } for (const auto& item : hookCtx_) { CHECK_TRUE(HandleHookContext(item), false, "handle hook context failed"); // Create the required resources. } @@ -328,6 +340,9 @@ bool HookManager::CreatePluginSession(const std::vector& c if (!isSaService_) { // SA mode will start HookService in the service. ClientConfig clientConfig; GetClientConfig(clientConfig); + if(noDataQueue_) { + clientConfig.freeEventOnlyAddrEnable = true; + } std::string clientConfigStr = clientConfig.ToString(); HILOG_INFO(LOG_CORE, "send hook client config:%s\n", clientConfigStr.c_str()); hookService_ = std::make_shared(clientConfig, shared_from_this()); @@ -554,7 +569,9 @@ void HookManager::StartPluginSession() continue; } HILOG_ERROR(LOG_CORE, "StartPluginSession name: %s", item->processName.c_str()); - item->stackPreprocess->StartTakeResults(); + if (!noDataQueue_) { + item->stackPreprocess->StartTakeResults(); + } if (item->pid > 0) { HILOG_INFO(LOG_CORE, "start command : send 36 signal to process %d", item->pid); if (kill(item->pid, SIGNAL_START_HOOK) == -1) { diff --git a/device/plugins/native_daemon/src/stack_preprocess.cpp b/device/plugins/native_daemon/src/stack_preprocess.cpp index 54c14f8f1..53aec52c4 100644 --- a/device/plugins/native_daemon/src/stack_preprocess.cpp +++ b/device/plugins/native_daemon/src/stack_preprocess.cpp @@ -132,6 +132,10 @@ bool StackPreprocess::StartTakeResults() bool StackPreprocess::StopTakeResults() { HILOG_INFO(LOG_CORE, "start StopTakeResults"); + if(!dataRepeater_) { + isStopTakeData_ = true; + return true; + } CHECK_NOTNULL(dataRepeater_, false, "data repeater null"); CHECK_TRUE(thread_.get_id() != std::thread::id(), false, "thread invalid"); @@ -146,6 +150,97 @@ bool StackPreprocess::StopTakeResults() return true; } +inline void StackPreprocess::IntervalFlushRecordStatistics(BatchNativeHookData& stackData) +{ + { + std::lock_guard guard(mtx_); + FlushData(stackData); + } + // interval reporting statistics + if (hookConfig_.statistics_interval() > 0) { + static auto lastStatisticsTime = std::chrono::steady_clock::now(); + auto currentTime = std::chrono::steady_clock::now(); + auto elapsedTime = std::chrono::duration_cast(currentTime - lastStatisticsTime); + if (elapsedTime >= statisticsInterval_) { + lastStatisticsTime = currentTime; + FlushRecordStatistics(); + } + } +} + +bool StackPreprocess::HandleNoStackEvent(RawStackPtr& rawData, BatchNativeHookData& stackData) +{ + if (rawData->stackConext->type == MMAP_FILE_TYPE) { + BaseStackRawData* mmapRawData = rawData->stackConext; + std::string filePath(reinterpret_cast(rawData->data)); + COMMON::AdaptSandboxPath(filePath, rawData->stackConext->pid); + HILOG_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, + mmapRawData->mmapArgs.flags & PROT_EXEC, mmapRawData->mmapArgs.offset, filePath.data()); + { + std::lock_guard guard(mtx_); + runtime_instance->HandleMapInfo(reinterpret_cast(mmapRawData->addr), + mmapRawData->mallocSize, mmapRawData->mmapArgs.flags, mmapRawData->mmapArgs.offset, filePath); + } + flushBasicData_ = true; + } else if (rawData->stackConext->type == THREAD_NAME_MSG) { + std::string threadName = reinterpret_cast(rawData->data); + ReportThreadNameMap(rawData->stackConext->tid, threadName, stackData); + } else { + return false; + } + return true; +} + +void StackPreprocess::TakeResultsFromShmem(const std::shared_ptr& eventNotifier, + const std::shared_ptr& shareMemoryBlock) +{ + eventNotifier->Take(); + StackDataRepeater::RawStack rawStack; + RawStackPtr rawData(&rawStack, [](StackDataRepeater::RawStack* del) {}); + while (!isStopTakeData_) { + BatchNativeHookData stackData; + bool ret = shareMemoryBlock->TakeData( + [&](const int8_t data[], uint32_t size) -> bool { + if (size == sizeof(uint64_t)) { + uint64_t addr = *reinterpret_cast(const_cast(data)); + SetFreeStatisticsData(addr); + return true; + } + CHECK_TRUE(size >= sizeof(BaseStackRawData), false, "stack data invalid!"); + 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 (rawData->stackConext->type == MEMORY_TAG) { + std::string tagName = reinterpret_cast(rawData->data); + SaveMemTag(rawData->stackConext->tagId, tagName); + return true; + } else if(HandleNoStackEvent(rawData, stackData)) { + if(rawData->stackConext->type == THREAD_NAME_MSG) { + FlushData(stackData); + } + return true; + } else if (rawData->stackConext->type == MUNMAP_MSG) { + std::lock_guard guard(mtx_); + runtime_instance->RemoveMaps(reinterpret_cast(rawData->stackConext->addr)); + } + { + std::lock_guard guard(mtx_); + runtime_instance->UpdateThread(rawData->stackConext->pid, rawData->stackConext->tid); + } + SetHookData(rawData, stackData); + IntervalFlushRecordStatistics(stackData); + return true; + }); + if (!ret) { + break; + } + } +} + void StackPreprocess::TakeResults() { if (!dataRepeater_) { @@ -172,30 +267,12 @@ void StackPreprocess::TakeResults() if (!rawData || isStopTakeData_) { break; } - if (rawData->stackConext->type == MMAP_FILE_TYPE) { - BaseStackRawData* mmapRawData = rawData->stackConext; - std::string filePath(reinterpret_cast(rawData->data)); - COMMON::AdaptSandboxPath(filePath, rawData->stackConext->pid); - HILOG_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, - mmapRawData->mmapArgs.flags & PROT_EXEC, mmapRawData->mmapArgs.offset, filePath.data()); - { - std::lock_guard guard(mtx_); - runtime_instance->HandleMapInfo(reinterpret_cast(mmapRawData->addr), - mmapRawData->mallocSize, mmapRawData->mmapArgs.flags, mmapRawData->mmapArgs.offset, filePath); - } - flushBasicData_ = true; + if (HandleNoStackEvent(rawData, stackData)) { continue; } else if (rawData->stackConext->type == MUNMAP_MSG) { std::lock_guard guard(mtx_); runtime_instance->RemoveMaps(reinterpret_cast(rawData->stackConext->addr)); } - if (rawData->stackConext->type == THREAD_NAME_MSG) { - std::string threadName = reinterpret_cast(rawData->data); - ReportThreadNameMap(rawData->stackConext->tid, threadName, stackData); - continue; - } if (!rawData->reportFlag) { ignoreCnts_++; @@ -282,20 +359,7 @@ void StackPreprocess::TakeResults() if (hookConfig_.save_file() && hookConfig_.file_name() != "" && !isHookStandaloneSerialize_) { continue; } - { - std::lock_guard guard(mtx_); - FlushData(stackData); - } - - // interval reporting statistics - if (hookConfig_.statistics_interval() > 0) { - auto currentTime = std::chrono::steady_clock::now(); - auto elapsedTime = std::chrono::duration_cast(currentTime - lastStatisticsTime_); - if (elapsedTime >= statisticsInterval_) { - lastStatisticsTime_ = currentTime; - FlushRecordStatistics(); - } - } + IntervalFlushRecordStatistics(stackData); } HILOG_INFO(LOG_CORE, "TakeResults thread %d, exit!", gettid()); } @@ -465,6 +529,58 @@ void StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack, } } +void StackPreprocess::SetAllocStatisticsFrame(const RawStackPtr& rawStack, + BatchNativeHookData& batchNativeHookData) +{ + callStack_.resize(rawStack->fpDepth); + if (memcpy_s(callStack_.data(), sizeof(uint64_t) * rawStack->fpDepth, + rawStack->data, sizeof(uint64_t) * rawStack->fpDepth) != EOK) { + HILOG_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(callStack_); + if (stackId > 0) { + SetAllocStatisticsData(rawStack, stackId, true); + } else { + stackId = SetCallStackMap(batchNativeHookData); + SetAllocStatisticsData(rawStack, stackId); + } +} + +void StackPreprocess::SetHookData(RawStackPtr rawStack, BatchNativeHookData& batchNativeHookData) +{ + if (flushBasicData_) { + SetMapsInfo(rawStack->stackConext->pid); + flushBasicData_ = false; + } + // statistical reporting must is compressed and accurate. + switch (rawStack->stackConext->type) { + case FREE_MSG: + case MUNMAP_MSG: + case MEMORY_UNUSING_MSG: { + SetFreeStatisticsData((uint64_t)rawStack->stackConext->addr); + break; + } + case MALLOC_MSG: + case MMAP_MSG: + case MMAP_FILE_PAGE_MSG: + case MEMORY_USING_MSG: { + SetAllocStatisticsFrame(rawStack, batchNativeHookData); + break; + } + case PR_SET_VMA_MSG: { + break; + } + default: { + HILOG_ERROR(LOG_CORE, "statistics event type: error"); + break; + } + } + return; +} + void StackPreprocess::SetHookData(RawStackPtr rawStack, std::vector& callFrames, BatchNativeHookData& batchNativeHookData) { @@ -489,6 +605,9 @@ void StackPreprocess::SetHookData(RawStackPtr rawStack, SetAllocStatisticsFrame(rawStack, callFrames, batchNativeHookData); break; } + case PR_SET_VMA_MSG: { + break; + } default: { HILOG_ERROR(LOG_CORE, "statistics event type:%d error", rawStack->stackConext->type); break; @@ -823,22 +942,19 @@ void StackPreprocess::Flush(const uint8_t* src, size_t size) HILOG_ERROR(LOG_CORE, "Flush src is nullptr"); return; } - if (isSaService_) { - ProfilerPluginData pluginData; - pluginData.set_name("nativehook"); - pluginData.set_version("1.02"); - pluginData.set_status(0); - pluginData.set_data(src, size); - struct timespec ts; - clock_gettime(pluginDataClockId_, &ts); - pluginData.set_clock_id(static_cast(pluginDataClockId_)); - pluginData.set_tv_sec(ts.tv_sec); - pluginData.set_tv_nsec(ts.tv_nsec); - pluginData.SerializeToArray(buffer_.get(), pluginData.ByteSizeLong()); - size = pluginData.ByteSizeLong(); - } + ProfilerPluginData pluginData; + pluginData.set_name("nativehook"); + pluginData.set_version("1.02"); + pluginData.set_status(0); + pluginData.set_data(src, size); + struct timespec ts; + clock_gettime(pluginDataClockId_, &ts); + pluginData.set_clock_id(static_cast(pluginDataClockId_)); + pluginData.set_tv_sec(ts.tv_sec); + pluginData.set_tv_nsec(ts.tv_nsec); + pluginData.SerializeToArray(buffer_.get(), pluginData.ByteSizeLong()); - writer_->Write(buffer_.get(), size); + writer_->Write(buffer_.get(), pluginData.ByteSizeLong()); writer_->Flush(); } diff --git a/device/plugins/native_hook/src/hook_client.cpp b/device/plugins/native_hook/src/hook_client.cpp index 8205ae9cb..01cd5ed5e 100644 --- a/device/plugins/native_hook/src/hook_client.cpp +++ b/device/plugins/native_hook/src/hook_client.cpp @@ -76,6 +76,37 @@ constexpr int RESPONSE_LIBRARY_MODE_DEPTH = 5; static bool g_isPidChanged = false; static struct mallinfo2 g_miStart = {0}; std::vector> g_filterStaLibRange; +constexpr int MAX_BITPOOL_SIZE = 100 * 1024; +struct Bitpool { + std::atomic slot; +}; +Bitpool addressChecker[MAX_BITPOOL_SIZE] = {{0}}; + +inline static uint32_t addrHash(uint32_t h) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; +} + +inline void Addr2Bitpool(void* addr) +{ + uint32_t val = addrHash((uint32_t)(uint64_t)addr) % (MAX_BITPOOL_SIZE * 32); + addressChecker[val / 32].slot |= (0x1 << (val % 32)); +} + +inline bool IsAddrExist(void* addr) +{ + uint32_t val = addrHash((uint32_t)(uint64_t)addr) % (MAX_BITPOOL_SIZE * 32); + if (addressChecker[val / 32].slot.load() & (0x1 << (val % 32))) { + return true; + } + return false; +} + const MallocDispatchType* GetDispatch() { return g_dispatch.load(std::memory_order_relaxed); @@ -357,6 +388,9 @@ 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 >= 256) { + Addr2Bitpool(ret); + } int realSize = 0; if (g_ClientConfig.fpunwind) { realSize = sizeof(BaseStackRawData) + (fpStackDepth * sizeof(uint64_t)); @@ -431,6 +465,9 @@ 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 >= 256) { + Addr2Bitpool(pRet); + } std::weak_ptr weakClient = g_hookClient; auto holder = weakClient.lock(); if (holder != nullptr) { @@ -507,6 +544,9 @@ 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 >= 256) { + Addr2Bitpool(pRet); + } std::weak_ptr weakClient = g_hookClient; auto holder = weakClient.lock(); if (holder != nullptr) { @@ -546,6 +586,20 @@ void hook_free(void (*free_func)(void*), void* p) if (g_ClientConfig.mallocDisable || IsPidChanged()) { return; } + if (g_ClientConfig.sampleInterval >= 256) { + if (!IsAddrExist(p)) { + return; + } + } + if (g_ClientConfig.freeEventOnlyAddrEnable) { + uint64_t addr = reinterpret_cast(p); + std::weak_ptr weakClient = g_hookClient; + auto holder = weakClient.lock(); + if (holder != nullptr) { + holder->SendStackWithPayload(&addr, sizeof(addr), nullptr, 0); + } + return; + } StackRawData rawdata = {{{{0}}}}; const char* stackptr = nullptr; const char* stackendptr = nullptr; 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 71fbcea7e..6ea05fdb0 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,10 +22,8 @@ #include "buffer_splitter.h" #include "logging.h" -#include "parameters.h" #include #include -#include #pragma clang optimize off @@ -73,9 +71,6 @@ public: outFile_ = DEFAULT_PATH + "hooktest_"+ outFileType_ + mode_[modeIndex_] + ".txt"; int processNum = fork(); if (processNum == 0) { - int waitProcMills = 300; - OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "0"); - std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills)); command_.push_back(const_cast(DEFAULT_NATIVE_DAEMON_PATH.c_str())); command_.push_back(const_cast("-o")); command_.push_back(const_cast(outFile_.c_str())); @@ -901,11 +896,12 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0160, Function | MediumTest | Lev */ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0170, Function | MediumTest | Level3) { - for (size_t i = 1; i < 2; ++i) { // 1 is fp mode, response_library_mode only fp mode is used + for (size_t i = 0; i < 2; ++i) { // 2: 0 is dwarf, 1 is fp mode unwindDepth_ = 6; outFileType_ = "responseLibraryMode"; modeIndex_ = i; responseLibraryMode_ = true; + offlineSymbolization_ = true; StartMallocProcess(); StartAndStopHook(); @@ -913,24 +909,19 @@ HWTEST_F(CheckHookDataTest, DFX_DFR_Hiprofiler_0170, Function | MediumTest | Lev infile.open(outFile_, std::ios::in); EXPECT_TRUE(infile.is_open()); std::string buf; - uint16_t ipCount = 0; + bool foundSymbolTab = false; + bool foundMapsInfo = false; while (getline(infile, buf)) { - if (buf.find("stack_map") != std::string::npos) { - while (getline(infile, buf)) { - if (buf.find("ip") != std::string::npos) { - ++ipCount; - continue; - } else if (buf.find("}") != std::string::npos) { - break; - } - } + if (buf.find("symbol_tab") != std::string::npos) { + foundSymbolTab = true; } - if (ipCount > 0) { - break; + if (buf.find("maps_info") != std::string::npos) { + foundMapsInfo = true; } } - EXPECT_TRUE(ipCount == 1); // response_library_mode callstack depth only is 1 + EXPECT_TRUE(foundSymbolTab); + EXPECT_TRUE(foundMapsInfo); } } #endif diff --git a/device/services/shared_memory/src/share_memory_block.cpp b/device/services/shared_memory/src/share_memory_block.cpp index 116dab416..9af89a184 100644 --- a/device/services/shared_memory/src/share_memory_block.cpp +++ b/device/services/shared_memory/src/share_memory_block.cpp @@ -347,7 +347,6 @@ bool ShareMemoryBlock::TakeData(const DataHandler& func, bool isProtobufSerializ CHECK_NOTNULL(header_, false, "header not ready!"); CHECK_TRUE(static_cast(func), false, "func invalid!"); - PthreadLocker locker(header_->info.mutex_); auto size = GetDataSize(); if (size == 0) { return false; @@ -443,6 +442,15 @@ bool ShareMemoryBlock::PutWithPayloadSync(const int8_t* header, uint32_t headerS pthread_mutex_unlock(&header_->info.mutex_); return true; } +void ShareMemoryBlock::ClearShareMemoryBlock() +{ + // clear header infos + PthreadLocker locker(header_->info.mutex_); + header_->info.readOffset_ = 0; + header_->info.writeOffset_ = 0; + header_->info.bytesCount_ = 0; + header_->info.chunkCount_ = 0; +} void ShareMemoryBlock::UseMemory(int32_t size) { @@ -541,4 +549,4 @@ bool ShareMemoryBlock::Seek(uint32_t pos) void ShareMemoryBlock::ResetPos() { messageWriteOffset_ = PIECE_HEAD_LEN; -} +} \ No newline at end of file