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 }