1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
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 #include "hook_standalone.h"
16
17 #include <csignal>
18 #include <functional>
19 #include <linux/types.h>
20 #include <sys/mman.h>
21
22 #include "common.h"
23 #include "epoll_event_poller.h"
24 #include "event_notifier.h"
25 #include "hook_common.h"
26 #include "hook_manager.h"
27 #include "hook_service.h"
28 #include "logging.h"
29 #include "native_hook_config.pb.h"
30 #include "share_memory_allocator.h"
31 #include "stack_data_repeater.h"
32 #include "stack_preprocess.h"
33 #include "virtual_runtime.h"
34 #include "hook_manager.h"
35 #include "utilities.h"
36
37 using namespace OHOS::Developtools::NativeDaemon;
38 namespace OHOS {
39 namespace Developtools {
40 namespace Profiler {
41 namespace Hook {
42 const int DEFAULT_EVENT_POLLING_INTERVAL = 5000;
43 const int MOVE_BIT_16 = 16;
44 const int MOVE_BIT_32 = 32;
45 std::string g_smbName = "hooknativesmb";
46 std::unique_ptr<EpollEventPoller> g_eventPoller_;
47 std::shared_ptr<ShareMemoryBlock> g_shareMemoryBlock;
48 std::shared_ptr<EventNotifier> g_eventNotifier;
49 std::shared_ptr<HookService> g_hookService;
50 std::shared_ptr<HookManager> g_hookManager;
51 std::shared_ptr<StackDataRepeater> g_stackDataRepeater;
52 std::shared_ptr<StackPreprocess> g_stackpreprocess;
53 uint32_t g_maxStackDepth;
54 bool g_unwindErrorFlag = false;
55 bool g_fpUnwind = false;
56 uint32_t g_statisticsinterval;
57 std::unique_ptr<FILE, decltype(&fclose)> g_fpHookFile(nullptr, nullptr);
58
SignalHandl(int signo)59 static void SignalHandl(int signo)
60 {
61 HILOG_ERROR(LOG_CORE, "recv signal %d", signo);
62 g_stackpreprocess->StopTakeResults();
63 if (g_statisticsinterval > 0) {
64 g_stackpreprocess->FlushRecordStatistics();
65 }
66 exit(-1);
67 }
68
GetClientConfig(const HookData & hookData,ClientConfig & clientConfig)69 void GetClientConfig(const HookData& hookData, ClientConfig& clientConfig)
70 {
71 clientConfig.shareMemroySize = hookData.smbSize;
72 clientConfig.filterSize = hookData.filterSize;
73 clientConfig.maxStackDepth = hookData.maxStackDepth;
74 clientConfig.mallocDisable = hookData.mallocDisable;
75 clientConfig.mmapDisable = hookData.mmapDisable;
76 clientConfig.freeStackData = hookData.freemsgstack;
77 clientConfig.munmapStackData = hookData.munmapmsgstack;
78 clientConfig.fpunwind = hookData.fpUnwind;
79 clientConfig.isBlocked = true;
80 }
81
StartHook(HookData & hookData)82 bool StartHook(HookData& hookData)
83 {
84 // create smb and eventNotifier
85 g_shareMemoryBlock = ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal(g_smbName, hookData.smbSize);
86 g_eventNotifier = EventNotifier::Create(0, EventNotifier::NONBLOCK);
87 g_stackDataRepeater = std::make_shared<StackDataRepeater>(STACK_DATA_SIZE);
88 CHECK_TRUE(g_stackDataRepeater != nullptr, false, "Create StackDataRepeater FAIL");
89 g_hookManager = std::make_shared<HookManager>(g_shareMemoryBlock, g_eventNotifier, g_stackDataRepeater);
90 // start event poller task
91 g_eventPoller_ = std::make_unique<EpollEventPoller>(DEFAULT_EVENT_POLLING_INTERVAL);
92 g_eventPoller_->Init();
93 g_eventPoller_->Start();
94 g_eventPoller_->AddFileDescriptor(g_eventNotifier->GetFd(),
95 std::bind(&HookManager::ReadShareMemory, g_hookManager.get()));
96
97 HILOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n", g_shareMemoryBlock->GetfileDescriptor(),
98 g_eventNotifier->GetFd());
99
100 #if defined(__arm__)
101 hookData.fpUnwind = false;
102 #endif
103 if (hookData.maxStackDepth < DLOPEN_MIN_UNWIND_DEPTH) {
104 // set default max depth
105 hookData.maxStackDepth = DLOPEN_MIN_UNWIND_DEPTH;
106 }
107
108 HILOG_INFO(LOG_CORE, "hookservice smbFd = %d, eventFd = %d\n",
109 g_shareMemoryBlock->GetfileDescriptor(), g_eventNotifier->GetFd());
110
111 ClientConfig clientConfig;
112 GetClientConfig(hookData, clientConfig);
113 std::string clientConfigStr = clientConfig.ToString();
114 HILOG_INFO(LOG_CORE, "send hook client config:%s\n", clientConfigStr.c_str());
115 g_hookService = std::make_shared<HookService>(g_shareMemoryBlock->GetfileDescriptor(),
116 g_eventNotifier->GetFd(), hookData.pid, hookData.processName, clientConfig);
117
118 g_maxStackDepth = hookData.maxStackDepth;
119 g_fpUnwind = hookData.fpUnwind;
120 g_statisticsinterval = hookData.statisticsInterval;
121
122 NativeHookConfig nativeConfig;
123 nativeConfig.set_fp_unwind(hookData.fpUnwind);
124 nativeConfig.set_max_stack_depth(hookData.maxStackDepth);
125 nativeConfig.set_filter_size(hookData.filterSize);
126 nativeConfig.set_save_file(true);
127 nativeConfig.set_file_name(hookData.fileName);
128 nativeConfig.set_statistics_interval(hookData.statisticsInterval);
129 nativeConfig.set_offline_symbolization(hookData.offlineSymbolization);
130 nativeConfig.set_callframe_compress(hookData.callframeCompress);
131 nativeConfig.set_string_compressed(hookData.stringCompressed);
132 #if defined(__arm__)
133 nativeConfig.set_fp_unwind(false); // if OS is 32-bit,set fp_unwind false.
134 #endif
135 bool isHookStandaloneSerialize = false;
136 // statistical reporting must be callframe compressed and accurate.
137 if (nativeConfig.statistics_interval() > 0) {
138 nativeConfig.set_callframe_compress(true);
139 nativeConfig.set_record_accurately(true);
140 }
141 // offlinem symbolization, callframe must be compressed
142 if (nativeConfig.offline_symbolization()) {
143 nativeConfig.set_callframe_compress(true);
144 }
145
146 // callframe compressed, string must be compressed.
147 if (nativeConfig.callframe_compress()) {
148 nativeConfig.set_string_compressed(true);
149 }
150
151 if (nativeConfig.string_compressed() || hookData.rawString) {
152 isHookStandaloneSerialize = true;
153 }
154 HILOG_INFO(LOG_CORE, "fp_unwind = %d", nativeConfig.fp_unwind());
155 HILOG_INFO(LOG_CORE, "offline_symbolization = %d", nativeConfig.offline_symbolization());
156 HILOG_INFO(LOG_CORE, "callframe_compress; = %d", nativeConfig.callframe_compress());
157 HILOG_INFO(LOG_CORE, "string_compressed; = %d", nativeConfig.string_compressed());
158 HILOG_INFO(LOG_CORE, "statistics_interval = %u", nativeConfig.statistics_interval());
159 HILOG_INFO(LOG_CORE, "isHookStandaloneSerialize = %d", isHookStandaloneSerialize);
160 HILOG_INFO(LOG_CORE, "rawString = %d", hookData.rawString);
161 clockid_t pluginDataClockId = COMMON::GetClockId("realtime");
162 g_stackpreprocess = std::make_shared<StackPreprocess>(g_stackDataRepeater, nativeConfig,
163 pluginDataClockId, isHookStandaloneSerialize);
164 CHECK_TRUE(g_stackpreprocess != nullptr, false, "Create StackPreprocess FAIL");
165 g_hookManager->SetHookConfig(nativeConfig);
166 g_stackpreprocess->StartTakeResults();
167 signal(SIGINT, SignalHandl);
168 return true;
169 }
170 } // namespace Hook
171 } // namespace Profiler
172 } // namespace Developtools
173 } // namespace OHOS
174