• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hook_manager.h"
17 
18 #include <limits>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 
22 #include "command_poller.h"
23 #include "common.h"
24 #include "epoll_event_poller.h"
25 #include "event_notifier.h"
26 #include "hook_common.h"
27 #include "hook_service.h"
28 #include "init_param.h"
29 #include "logging.h"
30 #include "plugin_service_types.pb.h"
31 #include "share_memory_allocator.h"
32 #include "utilities.h"
33 #include "virtual_runtime.h"
34 #include "hook_common.h"
35 #include "common.h"
36 #include "native_memory_profiler_sa_service.h"
37 
38 namespace OHOS::Developtools::NativeDaemon {
39 namespace {
40 constexpr int DEFAULT_EVENT_POLLING_INTERVAL = 5000;
41 constexpr uint32_t PAGE_BYTES = 4096;
42 std::shared_ptr<Writer> g_buffWriter;
43 const std::string STARTUP = "startup:";
44 const std::string PARAM_NAME = "libc.hook_mode";
45 constexpr int SIGNAL_START_HOOK = 36;
46 constexpr int SIGNAL_STOP_HOOK = 37;
47 const std::string VERSION = "1.02";
48 constexpr int32_t RESPONSE_MAX_PID_COUNT = 8;
49 constexpr int32_t MAX_PID_COUNT = 4;
50 }
51 
CheckProcess()52 bool HookManager::CheckProcess()
53 {
54     if (hookConfig_.pid() > 0) {
55         hookConfig_.add_expand_pids(hookConfig_.pid());
56     }
57     std::set<int32_t> pidCache;
58     for (const auto& pid : hookConfig_.expand_pids()) {
59         if (pid > 0) {
60             struct stat statBuf;
61             std::string pidPath = "/proc/" + std::to_string(pid) + "/status";
62             if (stat(pidPath.c_str(), &statBuf) != 0) {
63                 PROFILER_LOG_ERROR(LOG_CORE, "%s: hook process does not exist", __func__);
64                 return false;
65             } else {
66                 auto [iter, isExist] = pidCache.emplace(pid);
67                 if (isExist) {
68                     hookCtx_.emplace_back(std::make_shared<HookManagerCtx>(pid));
69                     PROFILER_LOG_INFO(LOG_CORE, "hook context: pid: %d", pid);
70                 }
71                 continue;
72             }
73         }
74     }
75 
76     if (!hookConfig_.process_name().empty() && !CheckProcessName()) {
77         return false;
78     }
79 
80     if (hookConfig_.response_library_mode()) {
81         if (hookCtx_.size() > RESPONSE_MAX_PID_COUNT) {
82             PROFILER_LOG_ERROR(LOG_CORE, "%s: The maximum allowed is to set %d PIDs.",
83                                __func__, RESPONSE_MAX_PID_COUNT);
84             return false;
85         }
86     } else {
87         if (hookCtx_.size() > MAX_PID_COUNT) {
88             PROFILER_LOG_ERROR(LOG_CORE, "%s: The maximum allowed is to set %d PIDs.", __func__, MAX_PID_COUNT);
89             return false;
90         }
91     }
92     return true;
93 }
94 
CheckProcessName()95 bool HookManager::CheckProcessName()
96 {
97     int pidValue = -1;
98     const std::string processName = hookConfig_.process_name();
99     bool isExist = COMMON::IsProcessExist(processName, pidValue);
100     if (hookConfig_.startup_mode() || !isExist) {
101         PROFILER_LOG_INFO(LOG_CORE, "Wait process %s start or restart, set param", hookConfig_.process_name().c_str());
102         std::string cmd = STARTUP + hookConfig_.process_name();
103         int ret = SystemSetParameter(PARAM_NAME.c_str(), cmd.c_str());
104         if (ret < 0) {
105             PROFILER_LOG_ERROR(LOG_CORE, "set param failed, please manually set param and start process(%s)",
106                                hookConfig_.process_name().c_str());
107         } else {
108             PROFILER_LOG_INFO(LOG_CORE, "set param success, please start process(%s)",
109                               hookConfig_.process_name().c_str());
110             hookCtx_.emplace_back(std::make_shared<HookManagerCtx>(hookConfig_.process_name()));
111         }
112     } else if (pidValue != -1) {
113         PROFILER_LOG_INFO(LOG_CORE, "Process %s exist, pid = %d", hookConfig_.process_name().c_str(), pidValue);
114         for (const auto& item : hookCtx_) {
115             if (item->pid == pidValue) {
116                 return true;
117             }
118         }
119         hookCtx_.emplace_back(std::make_shared<HookManagerCtx>(pidValue));
120     } else {
121         PROFILER_LOG_ERROR(LOG_CORE, "The startup mode parameter is not set, name: %s",
122                            hookConfig_.process_name().c_str());
123         return false;
124     }
125     return true;
126 }
127 
SetCommandPoller(const std::shared_ptr<CommandPoller> & p)128 void HookManager::SetCommandPoller(const std::shared_ptr<CommandPoller>& p)
129 {
130     commandPoller_ = p;
131 }
132 
RegisterAgentPlugin(const std::string & pluginPath)133 bool HookManager::RegisterAgentPlugin(const std::string& pluginPath)
134 {
135     RegisterPluginRequest request;
136     request.set_request_id(commandPoller_->GetRequestId());
137     request.set_path(pluginPath);
138     request.set_sha256("");
139     request.set_name(pluginPath);
140     request.set_buffer_size_hint(0);
141     RegisterPluginResponse response;
142 
143     if (commandPoller_->RegisterPlugin(request, response)) {
144         if (response.status() == ResponseStatus::OK) {
145             PROFILER_LOG_DEBUG(LOG_CORE, "response.plugin_id() = %d", response.plugin_id());
146             agentIndex_ = response.plugin_id();
147             PROFILER_LOG_DEBUG(LOG_CORE, "RegisterPlugin OK");
148         } else {
149             PROFILER_LOG_DEBUG(LOG_CORE, "RegisterPlugin FAIL 1");
150             return false;
151         }
152     } else {
153         PROFILER_LOG_DEBUG(LOG_CORE, "RegisterPlugin FAIL 2");
154         return false;
155     }
156 
157     return true;
158 }
159 
UnregisterAgentPlugin(const std::string & pluginPath)160 bool HookManager::UnregisterAgentPlugin(const std::string& pluginPath)
161 {
162     UnregisterPluginRequest request;
163     request.set_request_id(commandPoller_->GetRequestId());
164     request.set_plugin_id(agentIndex_);
165     UnregisterPluginResponse response;
166     if (commandPoller_->UnregisterPlugin(request, response)) {
167         CHECK_TRUE(response.status() == ResponseStatus::OK, false, "UnregisterPlugin FAIL 1");
168     } else {
169         PROFILER_LOG_DEBUG(LOG_CORE, "UnregisterPlugin FAIL 2");
170         return false;
171     }
172     agentIndex_ = -1;
173 
174     return true;
175 }
176 
LoadPlugin(const std::string & pluginPath)177 bool HookManager::LoadPlugin(const std::string& pluginPath)
178 {
179     return true;
180 }
181 
UnloadPlugin(const std::string & pluginPath)182 bool HookManager::UnloadPlugin(const std::string& pluginPath)
183 {
184     return true;
185 }
186 
UnloadPlugin(const uint32_t pluginId)187 bool HookManager::UnloadPlugin(const uint32_t pluginId)
188 {
189     return true;
190 }
191 
GetClientConfig(ClientConfig & clientConfig)192 void HookManager::GetClientConfig(ClientConfig& clientConfig)
193 {
194     clientConfig.shareMemorySize = static_cast<uint32_t>(hookConfig_.smb_pages() * PAGE_BYTES);
195     clientConfig.filterSize = static_cast<int32_t>(hookConfig_.filter_size());
196     clientConfig.clockId = COMMON::GetClockId(hookConfig_.clock());
197     clientConfig.maxStackDepth = hookConfig_.max_stack_depth();
198     clientConfig.mallocDisable = hookConfig_.malloc_disable();
199     clientConfig.mmapDisable = hookConfig_.mmap_disable();
200     clientConfig.freeStackData = hookConfig_.free_stack_report();
201     clientConfig.munmapStackData = hookConfig_.munmap_stack_report();
202     clientConfig.fpunwind = hookConfig_.fp_unwind();
203     clientConfig.isBlocked = hookConfig_.blocked();
204     clientConfig.memtraceEnable = hookConfig_.memtrace_enable();
205     clientConfig.sampleInterval = hookConfig_.sample_interval();
206     clientConfig.responseLibraryMode = hookConfig_.response_library_mode();
207 }
208 
HandleHookContext(const std::shared_ptr<HookManagerCtx> & ctx)209 bool HookManager::HandleHookContext(const std::shared_ptr<HookManagerCtx>& ctx)
210 {
211     if (ctx == nullptr) {
212         return false;
213     }
214     if (ctx->pid > 0) {
215         ctx->smbName = "hooknativesmb_" + std::to_string(ctx->pid);
216     } else if (!ctx->processName.empty()) {
217         ctx->smbName = "hooknativesmb_" + ctx->processName;
218     } else {
219         PROFILER_LOG_ERROR(LOG_CORE, "HandleHookContext context error, pid: %d, process name: %s",
220             ctx->pid, ctx->processName.c_str());
221         return false;
222     }
223     // create smb and eventNotifier
224     uint32_t bufferSize = static_cast<uint32_t>(hookConfig_.smb_pages()) * PAGE_BYTES; /* bufferConfig.pages() */
225     ctx->shareMemoryBlock = ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal(ctx->smbName, bufferSize);
226     CHECK_TRUE(ctx->shareMemoryBlock != nullptr, false, "CreateMemoryBlockLocal FAIL %s", ctx->smbName.c_str());
227 
228     ctx->eventNotifier = EventNotifier::Create(0, EventNotifier::NONBLOCK);
229     CHECK_NOTNULL(ctx->eventNotifier, false, "create EventNotifier for %s failed!", ctx->smbName.c_str());
230 
231     // start event poller task
232     ctx->eventPoller = std::make_unique<EpollEventPoller>(DEFAULT_EVENT_POLLING_INTERVAL);
233     CHECK_NOTNULL(ctx->eventPoller, false, "create event poller FAILED!");
234 
235     ctx->eventPoller->Init();
236     ctx->eventPoller->Start();
237 
238     PROFILER_LOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n", ctx->shareMemoryBlock->GetfileDescriptor(),
239                       ctx->eventNotifier->GetFd());
240 
241     ctx->isRecordAccurately = hookConfig_.record_accurately();
242     PROFILER_LOG_INFO(LOG_CORE, "hookConfig filter size = %d, malloc disable = %d mmap disable = %d",
243         hookConfig_.filter_size(), hookConfig_.malloc_disable(), hookConfig_.mmap_disable());
244     PROFILER_LOG_INFO(LOG_CORE, "hookConfig fp unwind = %d, max stack depth = %d, record_accurately=%d",
245         hookConfig_.fp_unwind(), hookConfig_.max_stack_depth(), ctx->isRecordAccurately);
246     PROFILER_LOG_INFO(LOG_CORE, "hookConfig  offline_symbolization = %d", hookConfig_.offline_symbolization());
247 
248     clockid_t pluginDataClockId = COMMON::GetClockId(hookConfig_.clock());
249     if (noDataQueue_) {
250         ctx->stackPreprocess = std::make_shared<StackPreprocess>(nullptr, hookConfig_, pluginDataClockId,
251         fpHookData_, isHookStandalone_);
252         ctx->eventPoller->AddFileDescriptor(
253             ctx->eventNotifier->GetFd(),
254             std::bind(&StackPreprocess::TakeResultsFromShmem, ctx->stackPreprocess,
255             ctx->eventNotifier, ctx->shareMemoryBlock));
256     } else {
257         ctx->stackData = std::make_shared<StackDataRepeater>(STACK_DATA_SIZE);
258         CHECK_TRUE(ctx->stackData != nullptr, false, "Create StackDataRepeater FAIL");
259         ctx->stackPreprocess = std::make_shared<StackPreprocess>(ctx->stackData, hookConfig_, pluginDataClockId,
260         fpHookData_, isHookStandalone_);
261         ctx->eventPoller->AddFileDescriptor(
262             ctx->eventNotifier->GetFd(),
263             std::bind(&HookManager::ReadShareMemory, this, ctx));
264     }
265     CHECK_TRUE(ctx->stackPreprocess != nullptr, false, "Create StackPreprocess FAIL");
266     ctx->stackPreprocess->SetWriter(g_buffWriter);
267     ctx->stackPreprocess->SetSaServiceFlag(isSaService_);
268     return true;
269 }
270 
CreatePluginSession(const std::vector<ProfilerPluginConfig> & config)271 bool HookManager::CreatePluginSession(const std::vector<ProfilerPluginConfig>& config)
272 {
273     PROFILER_LOG_DEBUG(LOG_CORE, "CreatePluginSession");
274     // save config
275     if (!config.empty()) {
276         std::string cfgData = config[0].config_data();
277         if (hookConfig_.ParseFromArray(reinterpret_cast<const uint8_t*>(cfgData.c_str()), cfgData.size()) <= 0) {
278             PROFILER_LOG_ERROR(LOG_CORE, "%s: ParseFromArray failed", __func__);
279             return false;
280         }
281     }
282 
283     int32_t uShortMax = (std::numeric_limits<unsigned short>::max)();
284     if (hookConfig_.filter_size() > uShortMax) {
285         PROFILER_LOG_WARN(LOG_CORE, "%s: filter size invalid(size exceed 65535), reset to 65535!", __func__);
286         hookConfig_.set_filter_size(uShortMax);
287     }
288     if (!CheckProcess()) { // Check and initialize the context for the target process.
289         return false;
290     }
291 
292     if (hookConfig_.max_stack_depth() < DLOPEN_MIN_UNWIND_DEPTH) {
293         // set default max depth
294         hookConfig_.set_max_stack_depth(DLOPEN_MIN_UNWIND_DEPTH);
295     }
296 #if defined(__arm__)
297     hookConfig_.set_fp_unwind(false); // if OS is 32-bit,set fp_unwind false.
298     hookConfig_.set_response_library_mode(false);
299 #endif
300     if (hookConfig_.response_library_mode()) {
301         hookConfig_.set_fp_unwind(true);
302         hookConfig_.set_offline_symbolization(true);
303     }
304     // offlinem symbolization, callframe must be compressed
305     if (hookConfig_.offline_symbolization()) {
306         hookConfig_.set_callframe_compress(true);
307     }
308 
309     // statistical reporting must be callframe compressed and accurate.
310     if (hookConfig_.statistics_interval() > 0) {
311         hookConfig_.set_callframe_compress(true);
312         hookConfig_.set_record_accurately(true);
313     }
314 
315     // callframe compressed, string must be compressed.
316     if (hookConfig_.callframe_compress()) {
317         hookConfig_.set_string_compressed(true);
318     }
319 
320     if (hookCtx_.empty()) {
321         PROFILER_LOG_ERROR(LOG_CORE, "HookManager no task");
322         return false;
323     }
324     if (hookConfig_.save_file() && !hookConfig_.file_name().empty()) {
325         fpHookData_ = fopen(hookConfig_.file_name().c_str(), "wb+");
326         if (fpHookData_ == nullptr) {
327             PROFILER_LOG_INFO(LOG_CORE, "fopen file %s fail", hookConfig_.file_name().c_str());
328             return false;
329         }
330     }
331     if (hookConfig_.fp_unwind() && hookConfig_.record_accurately()
332         && hookConfig_.blocked() && hookConfig_.offline_symbolization()
333         && hookConfig_.statistics_interval() > 0
334         && hookConfig_.sample_interval() > 1) {
335         noDataQueue_ = true;
336     }
337     for (const auto& item : hookCtx_) {
338         CHECK_TRUE(HandleHookContext(item), false, "handle hook context failed"); // Create the required resources.
339     }
340 
341     if (!isSaService_) { // SA mode will start HookService in the service.
342         ClientConfig clientConfig;
343         GetClientConfig(clientConfig);
344         if (noDataQueue_) {
345             clientConfig.freeEventOnlyAddrEnable = true;
346         }
347         std::string clientConfigStr = clientConfig.ToString();
348         PROFILER_LOG_INFO(LOG_CORE, "send hook client config:%s\n", clientConfigStr.c_str());
349         hookService_ = std::make_shared<HookService>(clientConfig, shared_from_this());
350         CHECK_NOTNULL(hookService_, false, "HookService create failed!");
351     }
352 
353     return true;
354 }
355 
ReadShareMemory(const std::shared_ptr<HookManagerCtx> & hookCtx)356 void HookManager::ReadShareMemory(const std::shared_ptr<HookManagerCtx>& hookCtx)
357 {
358     CHECK_NOTNULL(hookCtx->shareMemoryBlock, NO_RETVAL, "smb is null!");
359     hookCtx->eventNotifier->Take();
360     int rawRealSize = 0;
361     while (true) {
362         auto rawStack = std::make_shared<StackDataRepeater::RawStack>();
363         bool ret = hookCtx->shareMemoryBlock->TakeData([&](const int8_t data[], uint32_t size) -> bool {
364             CHECK_TRUE(size >= sizeof(BaseStackRawData), false, "stack data invalid!");
365 
366             rawStack->baseStackData = std::make_unique<uint8_t[]>(size);
367             CHECK_TRUE(memcpy_s(rawStack->baseStackData.get(), size, data, size) == EOK, false,
368                        "memcpy_s raw data failed!");
369 
370             rawStack->stackConext = reinterpret_cast<BaseStackRawData*>(rawStack->baseStackData.get());
371             rawStack->data = rawStack->baseStackData.get() + sizeof(BaseStackRawData);
372             rawStack->reportFlag = true;
373             if (rawStack->stackConext->type == MEMORY_TAG || rawStack->stackConext->type == THREAD_NAME_MSG ||
374                 rawStack->stackConext->type == MMAP_FILE_TYPE || rawStack->stackConext->type == PR_SET_VMA_MSG) {
375                 return true;
376             }
377             rawStack->reduceStackFlag = false;
378             if (hookConfig_.fp_unwind()) {
379                 rawStack->fpDepth = (size - sizeof(BaseStackRawData)) / sizeof(uint64_t);
380                 return true;
381             } else {
382                 rawRealSize = sizeof(BaseStackRawData) + MAX_REG_SIZE * sizeof(char);
383             }
384 
385             rawStack->stackSize = size - rawRealSize;
386             if (rawStack->stackSize > 0) {
387                 rawStack->stackData = rawStack->baseStackData.get() + rawRealSize;
388             }
389             return true;
390         });
391         if (!ret) {
392             break;
393         }
394         if (rawStack->stackConext->type == MEMORY_TAG) {
395             std::string tagName = reinterpret_cast<char*>(rawStack->data);
396             hookCtx->stackPreprocess->SaveMemTag(rawStack->stackConext->tagId, tagName);
397             continue;
398         }
399         if (!hookCtx->stackData->PutRawStack(rawStack, hookCtx->isRecordAccurately)) {
400             break;
401         }
402     }
403 }
404 
DestroyPluginSession(const std::vector<uint32_t> & pluginIds)405 bool HookManager::DestroyPluginSession(const std::vector<uint32_t>& pluginIds)
406 {
407     // release hook service
408     hookService_ = nullptr;
409 
410     for (const auto& item : hookCtx_) {
411         if (item->eventPoller != nullptr) {
412             PROFILER_LOG_ERROR(LOG_CORE, "eventPoller unset!");
413             if (item->eventNotifier != nullptr) {
414                 item->eventPoller->RemoveFileDescriptor(item->eventNotifier->GetFd());
415             }
416             item->eventPoller->Stop();
417             item->eventPoller->Finalize();
418             item->eventPoller = nullptr;
419         }
420 
421         if (item->shareMemoryBlock != nullptr) {
422             ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal(item->smbName);
423             item->shareMemoryBlock = nullptr;
424         }
425         item->eventNotifier = nullptr;
426         item->stackPreprocess = nullptr;
427         item->stackData = nullptr;
428     }
429     if (fpHookData_) {
430         fclose(fpHookData_);
431         fpHookData_ = nullptr;
432     }
433     return true;
434 }
435 
StartPluginSession(const std::vector<uint32_t> & pluginIds,const std::vector<ProfilerPluginConfig> & config,PluginResult & result)436 bool HookManager::StartPluginSession(const std::vector<uint32_t>& pluginIds,
437                                      const std::vector<ProfilerPluginConfig>& config, PluginResult& result)
438 {
439     UNUSED_PARAMETER(config);
440     if (hookCtx_.empty()) {
441         return false;
442     }
443     StartPluginSession();
444     return true;
445 }
446 
StopPluginSession(const std::vector<uint32_t> & pluginIds)447 bool HookManager::StopPluginSession(const std::vector<uint32_t>& pluginIds)
448 {
449     if (hookCtx_.empty()) {
450         return false;
451     }
452     for (const auto& item : hookCtx_) {
453         if (item->pid > 0) {
454             PROFILER_LOG_INFO(LOG_CORE, "stop command : send 37 signal to process  %d", item->pid);
455             if (kill(item->pid, SIGNAL_STOP_HOOK) == -1) {
456                 const int bufSize = 256;
457                 char buf[bufSize] = {0};
458                 strerror_r(errno, buf, bufSize);
459                 PROFILER_LOG_ERROR(LOG_CORE, "send 37 signal to process %d , error = %s", item->pid, buf);
460             }
461         } else {
462             PROFILER_LOG_INFO(LOG_CORE, "StopPluginSession: pid(%d) is less or equal zero.", item->pid);
463         }
464         CHECK_TRUE(item->stackPreprocess != nullptr, false, "stop StackPreprocess FAIL");
465         item->stackPreprocess->StopTakeResults();
466         PROFILER_LOG_INFO(LOG_CORE, "StopTakeResults success");
467         if (hookConfig_.statistics_interval() > 0) {
468             item->stackPreprocess->FlushRecordStatistics();
469         }
470         if (item->stackData != nullptr) {
471             item->stackData->Close();
472         }
473     }
474 
475     ResetStartupParam();
476     return true;
477 }
478 
ResetStartupParam()479 void HookManager::ResetStartupParam()
480 {
481     const std::string resetParam = "startup:disabled";
482     if (hookConfig_.startup_mode()) {
483         int ret = SystemSetParameter(PARAM_NAME.c_str(), resetParam.c_str());
484         if (ret < 0) {
485             PROFILER_LOG_WARN(LOG_CORE, "set param failed, please reset param(%s)", PARAM_NAME.c_str());
486         } else {
487             PROFILER_LOG_INFO(LOG_CORE, "reset param success");
488         }
489     }
490 }
491 
ReportPluginBasicData(const std::vector<uint32_t> & pluginIds)492 bool HookManager::ReportPluginBasicData(const std::vector<uint32_t>& pluginIds)
493 {
494     return true;
495 }
496 
CreateWriter(std::string pluginName,uint32_t bufferSize,int smbFd,int eventFd,bool isProtobufSerialize)497 bool HookManager::CreateWriter(std::string pluginName, uint32_t bufferSize, int smbFd, int eventFd,
498                                bool isProtobufSerialize)
499 {
500     PROFILER_LOG_DEBUG(LOG_CORE, "agentIndex_ %d", agentIndex_);
501     RegisterWriter(std::make_shared<BufferWriter>(pluginName, VERSION, bufferSize, smbFd, eventFd, agentIndex_));
502     return true;
503 }
504 
ResetWriter(uint32_t pluginId)505 bool HookManager::ResetWriter(uint32_t pluginId)
506 {
507     RegisterWriter(nullptr);
508     return true;
509 }
510 
RegisterWriter(const std::shared_ptr<Writer> writer)511 void HookManager::RegisterWriter(const std::shared_ptr<Writer> writer)
512 {
513     g_buffWriter = writer;
514     return;
515 }
516 
SetHookConfig(const NativeHookConfig & hookConfig)517 void HookManager::SetHookConfig(const NativeHookConfig& hookConfig)
518 {
519     hookConfig_ = hookConfig;
520 }
521 
SethookStandalone(bool HookStandalone)522 void HookManager::SethookStandalone(bool HookStandalone)
523 {
524     isHookStandalone_ = HookStandalone;
525 }
526 
SetHookConfig(const std::shared_ptr<NativeMemoryProfilerSaConfig> & config)527 void HookManager::SetHookConfig(const std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
528 {
529     hookConfig_.set_pid(config->pid_);
530     if (!config->processName_.empty()) {
531         hookConfig_.set_process_name(config->processName_);
532     }
533     hookConfig_.set_filter_size(config->filterSize_);
534     hookConfig_.set_smb_pages(config->shareMemorySize_);
535     hookConfig_.set_max_stack_depth(config->maxStackDepth_);
536     hookConfig_.set_malloc_disable(config->mallocDisable_);
537     hookConfig_.set_mmap_disable(config->mmapDisable_);
538     hookConfig_.set_free_stack_report(config->freeStackData_);
539     hookConfig_.set_munmap_stack_report(config->munmapStackData_);
540     hookConfig_.set_malloc_free_matching_interval(config->mallocFreeMatchingInterval_);
541     hookConfig_.set_malloc_free_matching_cnt(config->mallocFreeMatchingCnt_);
542     hookConfig_.set_string_compressed(config->stringCompressed_);
543     hookConfig_.set_fp_unwind(config->fpUnwind_);
544     hookConfig_.set_blocked(config->blocked_);
545     hookConfig_.set_record_accurately(config->recordAccurately_);
546     hookConfig_.set_startup_mode(config->startupMode_);
547     hookConfig_.set_memtrace_enable(config->memtraceEnable_);
548     hookConfig_.set_offline_symbolization(config->offlineSymbolization_);
549     hookConfig_.set_callframe_compress(config->callframeCompress_);
550     hookConfig_.set_statistics_interval(config->statisticsInterval_);
551     hookConfig_.set_clock(COMMON::GetClockStr(config->clockId_));
552     hookConfig_.set_sample_interval(config->sampleInterval_);
553     hookConfig_.set_response_library_mode(config->responseLibraryMode_);
554 }
555 
CreatePluginSession()556 int32_t HookManager::CreatePluginSession()
557 {
558     if (CreatePluginSession({})) {
559         return RET_OK;
560     }
561     return RET_ERR;
562 }
563 
StartPluginSession()564 void HookManager::StartPluginSession()
565 {
566     for (const auto& item : hookCtx_) {
567         if (item->stackPreprocess == nullptr) {
568             continue;
569         }
570         PROFILER_LOG_ERROR(LOG_CORE, "StartPluginSession name: %s", item->processName.c_str());
571         if (!noDataQueue_) {
572             item->stackPreprocess->StartTakeResults();
573         }
574         if (item->pid > 0) {
575             PROFILER_LOG_INFO(LOG_CORE, "start command : send 36 signal to process  %d", item->pid);
576             if (kill(item->pid, SIGNAL_START_HOOK) == -1) {
577                 const int bufSize = 256;
578                 char buf[bufSize] = {0};
579                 strerror_r(errno, buf, bufSize);
580                 PROFILER_LOG_ERROR(LOG_CORE, "send 36 signal error = %s", buf);
581             }
582         } else {
583             PROFILER_LOG_INFO(LOG_CORE, "StartPluginSession: pid(%d) is less or equal zero.", item->pid);
584         }
585     }
586 }
587 
WriteHookConfig()588 void HookManager::WriteHookConfig()
589 {
590     for (const auto& item : hookCtx_) {
591         if (item == nullptr) {
592             PROFILER_LOG_ERROR(LOG_CORE, "HookManager WriteHookConfig failed");
593             return;
594         }
595         item->stackPreprocess->WriteHookConfig();
596     }
597 }
598 
GetFds(int32_t pid,const std::string & name)599 std::pair<int, int> HookManager::GetFds(int32_t pid, const std::string& name)
600 {
601     for (const auto& item : hookCtx_) {
602         if (item->pid == pid || item->processName == name) {
603             if (item->pid == -1) {
604                 item->pid = pid;
605             }
606             item->stackPreprocess->SetPid(pid);
607             return {item->eventNotifier->GetFd(), item->shareMemoryBlock->GetfileDescriptor()};
608         }
609     }
610     return {-1, -1};
611 }
612 }