improve native daemon sa performance

Signed-off-by: zyxzyx <zhangyixin19@huawei.com>
This commit is contained in:
zyxzyx 2024-01-02 17:14:39 +08:00
parent 23b1f9b4be
commit 69a65c2d8b
9 changed files with 282 additions and 100 deletions

View File

@ -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

View File

@ -64,7 +64,7 @@ public:
std::shared_ptr<StackPreprocess> 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<std::shared_ptr<HookManagerCtx>> hookCtx_;
bool isSaService_{false};
bool noDataQueue_{false};
};
}
#endif // AGENT_MANAGER_H

View File

@ -66,6 +66,7 @@ public:
{
isSaService_ = flag;
}
void TakeResultsFromShmem(const std::shared_ptr<EventNotifier>&, const std::shared_ptr<ShareMemoryBlock>&);
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<CallFrame>& callFrames,
BatchNativeHookData& batchNativeHookData);
void SetHookData(RawStackPtr rawStack, BatchNativeHookData& batchNativeHookData);
void WriteFrames(RawStackPtr RawStack, const std::vector<CallFrame>& 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<CallFrame>& 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<uint64_t, uint32_t> 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<uint32_t, RecordStatistic> recordStatisticsMap_ {STATISTICS_MAP_SZIE};
// Key is call stack id, value is recordstatistic data pointer

View File

@ -85,6 +85,8 @@ public:
void FillMapsCache(std::string& currentFileName, std::shared_ptr<DfxMap> 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<uint64_t>& 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<DfxMap> 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);

View File

@ -40,7 +40,6 @@ namespace {
const int DEFAULT_EVENT_POLLING_INTERVAL = 5000;
const int PAGE_BYTES = 4096;
std::shared_ptr<Writer> 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<CommandPoller>& p)
{
commandPoller_ = p;
@ -236,9 +233,6 @@ bool HookManager::HandleHookContext(const std::shared_ptr<HookManagerCtx>& 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<HookManagerCtx>& 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<StackDataRepeater>(STACK_DATA_SIZE);
CHECK_TRUE(ctx->stackData != nullptr, false, "Create StackDataRepeater FAIL");
clockid_t pluginDataClockId = COMMON::GetClockId(hookConfig_.clock());
ctx->stackPreprocess = std::make_shared<StackPreprocess>(ctx->stackData, hookConfig_, pluginDataClockId,
if (noDataQueue_) {
ctx->stackPreprocess = std::make_shared<StackPreprocess>(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<StackDataRepeater>(STACK_DATA_SIZE);
CHECK_TRUE(ctx->stackData != nullptr, false, "Create StackDataRepeater FAIL");
ctx->stackPreprocess = std::make_shared<StackPreprocess>(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<ProfilerPluginConfig>& 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<ProfilerPluginConfig>& 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<HookService>(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) {

View File

@ -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<std::mutex> 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<std::chrono::seconds>(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<char *>(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<std::mutex> guard(mtx_);
runtime_instance->HandleMapInfo(reinterpret_cast<uint64_t>(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<char*>(rawData->data);
ReportThreadNameMap(rawData->stackConext->tid, threadName, stackData);
} else {
return false;
}
return true;
}
void StackPreprocess::TakeResultsFromShmem(const std::shared_ptr<EventNotifier>& eventNotifier,
const std::shared_ptr<ShareMemoryBlock>& 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<uint64_t *>(const_cast<int8_t *>(data));
SetFreeStatisticsData(addr);
return true;
}
CHECK_TRUE(size >= sizeof(BaseStackRawData), false, "stack data invalid!");
rawData->stackConext = reinterpret_cast<BaseStackRawData *>(const_cast<int8_t *>(data));
rawData->data = reinterpret_cast<uint8_t*>(const_cast<int8_t *>(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<char*>(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<std::mutex> guard(mtx_);
runtime_instance->RemoveMaps(reinterpret_cast<uint64_t>(rawData->stackConext->addr));
}
{
std::lock_guard<std::mutex> 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<char *>(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<std::mutex> guard(mtx_);
runtime_instance->HandleMapInfo(reinterpret_cast<uint64_t>(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<std::mutex> guard(mtx_);
runtime_instance->RemoveMaps(reinterpret_cast<uint64_t>(rawData->stackConext->addr));
}
if (rawData->stackConext->type == THREAD_NAME_MSG) {
std::string threadName = reinterpret_cast<char*>(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<std::mutex> 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<std::chrono::seconds>(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<std::mutex> 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<CallFrame>& 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<ProfilerPluginData_ClockId>(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<ProfilerPluginData_ClockId>(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();
}

View File

@ -76,6 +76,37 @@ constexpr int RESPONSE_LIBRARY_MODE_DEPTH = 5;
static bool g_isPidChanged = false;
static struct mallinfo2 g_miStart = {0};
std::vector<std::pair<uint64_t, uint64_t>> g_filterStaLibRange;
constexpr int MAX_BITPOOL_SIZE = 100 * 1024;
struct Bitpool {
std::atomic<uint32_t> 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<uint32_t>(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<uint32_t>(GetCurThreadId());
rawdata.mallocSize = number * size;
rawdata.addr = pRet;
if (g_ClientConfig.sampleInterval >= 256) {
Addr2Bitpool(pRet);
}
std::weak_ptr<HookSocketClient> 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<uint32_t>(GetCurThreadId());
rawdata.mallocSize = size;
rawdata.addr = pRet;
if (g_ClientConfig.sampleInterval >= 256) {
Addr2Bitpool(pRet);
}
std::weak_ptr<HookSocketClient> 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<uint64_t>(p);
std::weak_ptr<HookSocketClient> 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;

View File

@ -22,10 +22,8 @@
#include "buffer_splitter.h"
#include "logging.h"
#include "parameters.h"
#include <fstream>
#include <iostream>
#include <thread>
#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<char*>(DEFAULT_NATIVE_DAEMON_PATH.c_str()));
command_.push_back(const_cast<char*>("-o"));
command_.push_back(const_cast<char*>(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

View File

@ -347,7 +347,6 @@ bool ShareMemoryBlock::TakeData(const DataHandler& func, bool isProtobufSerializ
CHECK_NOTNULL(header_, false, "header not ready!");
CHECK_TRUE(static_cast<bool>(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;
}
}